diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 817626d228..643b4d6e64 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -414,10 +414,17 @@ Regarding sprites & sounds, you must credit the artist and possibly the codebase
Do not add any of the following in a Pull Request or risk getting the PR closed:
* National Socialist Party of Germany content, National Socialist Party of Germany related content, or National Socialist Party of Germany references
* Code where one line of code is split across mutiple lines (except for multiple, separate strings and comments; in those cases, existing longer lines must not be split up)
-* Code adding, removing, or updating the availability of alien races/species/human mutants without prior approval. Pull requests attempting to add or remove features from said races/species/mutants require prior approval as well.
Just because something isn't on this list doesn't mean that it's acceptable. Use common sense above all else.
+## Content requiring prior approval
+Certain types of changes may require prior approval from maintainers. This currently includes:
+
+* Code adding, removing, or updating the availability of alien races/species/human mutants. This includes pull requests attempting to add or remove features from said races/species/mutants. (Requires approval from at least one maintainer)
+* Code adding, removing, or modifying the functionality of adult-oriented features (such as, but not limited to: vore, genitals, MKUltra, and more). This also includes pull requests attempting to add or remove these features outright. (Requires approval from at least half of the formal maintainer team)
+
+The above content requires approval from the specified amount of maintainers prior to PR creation. Seeking approval must be done via a @Maintainer ping in a relevant development/code or staff channel on the Discord, otherwise it will be considered insufficient. If a PR contains any of the above content, but the creator does not have sufficient approval prior to the PR's creation, then the PR may be closed by any maintainer, at any time, for any reason.
+
## A word on Git
Yes, we know that the files have a tonne of mixed Windows and Linux line endings. Attempts to fix this have been met with less than stellar success, and as such we have decided to give up caring until there comes a time when it matters.
diff --git a/_maps/RandomRuins/IceRuins/icemoon_surface_mining_site.dmm b/_maps/RandomRuins/IceRuins/icemoon_surface_mining_site.dmm
index 969acdd871..23abc4b731 100644
--- a/_maps/RandomRuins/IceRuins/icemoon_surface_mining_site.dmm
+++ b/_maps/RandomRuins/IceRuins/icemoon_surface_mining_site.dmm
@@ -16,7 +16,7 @@
/turf/open/floor/wood,
/area/ruin/unpowered)
"d" = (
-/turf/open/openspace/icemoon,
+/turf/open/transparent/openspace/icemoon,
/area/icemoon/surface/outdoors)
"e" = (
/obj/item/clothing/suit/hooded/explorer,
diff --git a/_maps/RandomRuins/StationRuins/Box/Engine/engine_teg.dmm b/_maps/RandomRuins/StationRuins/Box/Engine/engine_teg.dmm
index f8d701debe..2d66300953 100644
--- a/_maps/RandomRuins/StationRuins/Box/Engine/engine_teg.dmm
+++ b/_maps/RandomRuins/StationRuins/Box/Engine/engine_teg.dmm
@@ -71,8 +71,9 @@
/turf/closed/wall/r_wall,
/area/engine/engineering)
"di" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/turf/closed/wall,
+/obj/structure/reagent_dispensers/fueltank,
+/obj/effect/turf_decal/delivery,
+/turf/open/floor/plasteel,
/area/engine/engineering)
"dl" = (
/obj/structure/cable{
@@ -304,12 +305,6 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
-/obj/effect/turf_decal/tile/yellow{
- dir = 1
- },
-/obj/effect/turf_decal/tile/yellow{
- dir = 8
- },
/turf/open/floor/plasteel,
/area/engine/engineering)
"kH" = (
@@ -523,6 +518,9 @@
/obj/machinery/light{
dir = 4
},
+/obj/structure/sign/warning/enginesafety{
+ pixel_x = 32
+ },
/turf/open/floor/plasteel,
/area/engine/engineering)
"qv" = (
@@ -543,7 +541,13 @@
dir = 4
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/turf/closed/wall,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/turf/open/floor/plasteel,
/area/engine/engineering)
"qN" = (
/obj/structure/table/reinforced,
@@ -848,6 +852,10 @@
/obj/machinery/igniter{
id = "TEG_igniter"
},
+/mob/living/carbon/monkey{
+ name = "Mumkey Jones"
+ },
+/obj/item/clothing/head/hardhat/atmos,
/turf/open/floor/engine/vacuum,
/area/engine/engineering)
"An" = (
@@ -882,14 +890,6 @@
/obj/machinery/atmospherics/pipe/simple/orange/visible{
dir = 1
},
-/obj/machinery/camera{
- c_tag = "TEG - North Center";
- dir = 8
- },
-/obj/effect/turf_decal/tile/yellow{
- dir = 4
- },
-/obj/effect/turf_decal/tile/yellow,
/turf/open/floor/plasteel,
/area/engine/engineering)
"AX" = (
@@ -1042,12 +1042,6 @@
},
/turf/open/floor/plasteel,
/area/engine/engineering)
-"EI" = (
-/obj/effect/turf_decal/delivery,
-/obj/structure/reagent_dispensers/fueltank,
-/obj/machinery/atmospherics/pipe/simple/orange/visible,
-/turf/open/floor/plasteel,
-/area/engine/engineering)
"EL" = (
/turf/closed/wall,
/area/engine/engineering)
@@ -1082,6 +1076,11 @@
/obj/structure/window/reinforced,
/turf/open/floor/plasteel,
/area/engine/engineering)
+"Fs" = (
+/obj/structure/rack,
+/obj/item/pipe_dispenser,
+/turf/open/floor/plasteel,
+/area/engine/engineering)
"FG" = (
/obj/machinery/atmospherics/pipe/simple/orange/visible{
dir = 10
@@ -1218,11 +1217,6 @@
/turf/open/floor/plasteel,
/area/engine/engineering)
"Jd" = (
-/obj/machinery/light,
-/obj/effect/turf_decal/tile/yellow{
- dir = 8
- },
-/obj/effect/turf_decal/tile/yellow,
/obj/machinery/atmospherics/pipe/manifold/orange/visible,
/turf/open/floor/plasteel,
/area/engine/engineering)
@@ -1312,15 +1306,6 @@
dir = 4
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/obj/machinery/light{
- dir = 1
- },
-/obj/effect/turf_decal/tile/yellow{
- dir = 1
- },
-/obj/effect/turf_decal/tile/yellow{
- dir = 4
- },
/turf/open/floor/plasteel,
/area/engine/engineering)
"LD" = (
@@ -1372,6 +1357,7 @@
/obj/machinery/atmospherics/pipe/manifold/cyan/visible{
dir = 4
},
+/obj/machinery/meter,
/turf/open/floor/plasteel,
/area/engine/engineering)
"Nz" = (
@@ -1429,12 +1415,10 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{
dir = 4
},
-/obj/machinery/airalarm{
- dir = 1;
- locked = 0;
- pixel_y = -22
- },
/obj/machinery/light,
+/obj/structure/sign/nanotrasen{
+ pixel_y = -32
+ },
/turf/open/floor/plasteel,
/area/engine/engineering)
"Pz" = (
@@ -1452,6 +1436,9 @@
/obj/machinery/light{
dir = 1
},
+/obj/structure/sign/warning/nosmoking{
+ pixel_y = 30
+ },
/turf/open/floor/plasteel,
/area/engine/engineering)
"PK" = (
@@ -1522,12 +1509,11 @@
/turf/open/space,
/area/space/nearstation)
"Rl" = (
-/obj/machinery/atmospherics/components/binary/pump{
- dir = 1
- },
/obj/effect/turf_decal/stripes/line{
dir = 1
},
+/obj/machinery/atmospherics/pipe/simple/cyan/visible,
+/obj/machinery/meter,
/turf/open/floor/plasteel,
/area/engine/engineering)
"Rz" = (
@@ -1602,7 +1588,13 @@
/turf/open/floor/plating,
/area/engine/engineering)
"TE" = (
-/obj/structure/closet/crate/internals,
+/obj/structure/closet/crate{
+ icon_state = "crateopen"
+ },
+/obj/effect/spawner/lootdrop/maintenance{
+ lootcount = 2;
+ name = "2maintenance loot spawner"
+ },
/turf/open/floor/plasteel,
/area/engine/engineering)
"TH" = (
@@ -1648,6 +1640,10 @@
dir = 4
},
/obj/effect/turf_decal/tile/yellow,
+/obj/machinery/camera{
+ c_tag = "TEG - North Center";
+ dir = 8
+ },
/turf/open/floor/plasteel,
/area/engine/engineering)
"Uq" = (
@@ -1671,18 +1667,15 @@
/area/engine/engineering)
"UT" = (
/obj/machinery/atmospherics/pipe/simple/orange/visible,
-/obj/effect/turf_decal/tile/yellow{
- dir = 1
- },
-/obj/effect/turf_decal/tile/yellow{
- dir = 8
- },
/turf/open/floor/plasteel,
/area/engine/engineering)
"UY" = (
/obj/machinery/atmospherics/components/unary/vent_pump/on{
dir = 8
},
+/obj/machinery/airalarm{
+ pixel_y = 23
+ },
/turf/open/floor/plasteel,
/area/engine/engineering)
"Vi" = (
@@ -1811,10 +1804,6 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 5
},
-/obj/structure/extinguisher_cabinet{
- dir = 4;
- pixel_y = -27
- },
/turf/open/floor/plasteel,
/area/engine/engineering)
"YC" = (
@@ -1837,9 +1826,10 @@
/turf/open/floor/plasteel,
/area/engine/engineering)
"YP" = (
-/obj/structure/rack,
-/obj/machinery/atmospherics/pipe/simple/scrubbers/visible,
-/obj/item/pipe_dispenser,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow,
/turf/open/floor/plasteel,
/area/engine/engineering)
"YQ" = (
@@ -1878,7 +1868,9 @@
/turf/open/floor/plasteel,
/area/engine/engineering)
"Zu" = (
-/obj/machinery/atmospherics/pipe/manifold/cyan/visible,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{
+ dir = 6
+ },
/obj/machinery/meter,
/turf/open/floor/plasteel,
/area/engine/engineering)
@@ -1887,13 +1879,6 @@
dir = 4
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/obj/structure/sign/warning/securearea{
- pixel_y = -32
- },
-/obj/effect/turf_decal/tile/yellow{
- dir = 8
- },
-/obj/effect/turf_decal/tile/yellow,
/turf/open/floor/plasteel,
/area/engine/engineering)
"ZC" = (
@@ -2170,7 +2155,7 @@ iD
MP
MP
MP
-ij
+MP
yX
qn
qn
@@ -2251,11 +2236,11 @@ ME
QS
uB
Ok
-Ok
-Ok
+di
+di
Ok
Bz
-Zu
+lI
Wc
Ok
zG
@@ -2307,8 +2292,8 @@ iP
wk
go
fF
-EI
-EI
+UT
+UT
sn
qc
Nh
@@ -2367,7 +2352,7 @@ KA
KA
Ok
dZ
-bO
+Zu
ev
tl
qb
@@ -2477,7 +2462,7 @@ IP
Zs
sD
Jd
-EL
+YP
YG
AX
PK
@@ -2505,7 +2490,7 @@ SX
ou
vG
Zv
-di
+Xe
qJ
Lw
Xe
@@ -2595,7 +2580,7 @@ PK
Dv
Dv
bO
-YP
+sH
As
yN
yN
@@ -2651,7 +2636,7 @@ eh
zx
XW
ST
-Ok
+Fs
MP
tw
tw
diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm
index 264fdb1058..c0b4e6a88a 100644
--- a/_maps/map_files/BoxStation/BoxStation.dmm
+++ b/_maps/map_files/BoxStation/BoxStation.dmm
@@ -1257,6 +1257,16 @@
/turf/open/floor/plating,
/area/maintenance/fore/secondary)
"acV" = (
+/obj/structure/cable{
+ icon_state = "1-4"
+ },
+/obj/structure/cable{
+ icon_state = "2-4"
+ },
+/obj/structure/lattice/catwalk,
+/turf/open/space,
+/area/solar/port/fore)
+"acW" = (
/obj/structure/cable{
icon_state = "0-2"
},
@@ -1266,11 +1276,6 @@
},
/turf/open/floor/plasteel/airless/solarpanel,
/area/solar/port/fore)
-"acW" = (
-/obj/structure/cable,
-/obj/structure/lattice/catwalk,
-/turf/open/space,
-/area/solar/port/fore)
"acX" = (
/obj/effect/spawner/structure/window/reinforced,
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
@@ -1489,7 +1494,12 @@
/obj/structure/lattice/catwalk,
/turf/open/space,
/area/solar/starboard/fore)
-"adu" = (
+"adw" = (
+/obj/structure/cable,
+/obj/structure/lattice/catwalk,
+/turf/open/space,
+/area/solar/port/fore)
+"adx" = (
/obj/structure/cable{
icon_state = "4-8"
},
@@ -1502,56 +1512,17 @@
/obj/structure/lattice/catwalk,
/turf/open/space,
/area/solar/port/fore)
-"adv" = (
-/obj/structure/cable{
- icon_state = "1-4"
- },
-/obj/structure/cable{
- icon_state = "2-4"
- },
-/obj/structure/lattice/catwalk,
-/turf/open/space,
-/area/solar/port/fore)
-"adw" = (
-/obj/structure/cable{
- icon_state = "0-8"
- },
-/obj/structure/lattice/catwalk,
-/turf/open/space,
-/area/solar/port/fore)
-"adx" = (
-/obj/structure/cable{
- icon_state = "0-4"
- },
-/obj/structure/lattice/catwalk,
-/turf/open/space,
-/area/solar/port/fore)
"ady" = (
/obj/structure/lattice/catwalk,
/turf/open/space,
/area/solar/port/fore)
-"adz" = (
-/obj/structure/cable{
- icon_state = "4-8"
- },
-/obj/structure/cable{
- icon_state = "2-8"
- },
-/obj/structure/cable{
- icon_state = "1-8"
- },
-/obj/structure/lattice/catwalk,
-/turf/open/space,
-/area/solar/port/fore)
"adA" = (
-/obj/structure/cable{
- icon_state = "2-8"
+/obj/structure/cable,
+/obj/machinery/power/solar{
+ id = "auxsolareast";
+ name = "Port Auxiliary Solar Array"
},
-/obj/structure/cable{
- icon_state = "1-8"
- },
-/obj/structure/lattice/catwalk,
-/turf/open/space,
+/turf/open/floor/plasteel/airless/solarpanel,
/area/solar/port/fore)
"adB" = (
/obj/structure/cable{
@@ -1817,12 +1788,11 @@
/turf/open/space,
/area/solar/starboard/fore)
"adZ" = (
-/obj/structure/cable,
-/obj/machinery/power/solar{
- id = "auxsolareast";
- name = "Port Auxiliary Solar Array"
+/obj/structure/cable{
+ icon_state = "0-8"
},
-/turf/open/floor/plasteel/airless/solarpanel,
+/obj/structure/lattice/catwalk,
+/turf/open/space,
/area/solar/port/fore)
"aea" = (
/obj/machinery/portable_atmospherics/canister/nitrous_oxide,
@@ -5054,12 +5024,16 @@
/turf/open/floor/plasteel/dark,
/area/security/courtroom)
"ajq" = (
-/obj/structure/lattice/catwalk,
+/obj/machinery/door/airlock/external{
+ name = "Solar Maintenance";
+ req_access_txt = "10; 13"
+ },
/obj/structure/cable{
icon_state = "1-2"
},
-/turf/open/space,
-/area/solar/port/fore)
+/obj/effect/mapping_helpers/airlock/cyclelink_helper,
+/turf/open/floor/plating,
+/area/maintenance/solars/port/fore)
"ajr" = (
/obj/structure/table/wood,
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
@@ -5417,16 +5391,12 @@
/turf/open/floor/plating,
/area/maintenance/solars/port/fore)
"ajW" = (
-/obj/machinery/door/airlock/external{
- name = "Solar Maintenance";
- req_access_txt = "10; 13"
- },
/obj/structure/cable{
- icon_state = "1-2"
+ icon_state = "0-4"
},
-/obj/effect/mapping_helpers/airlock/cyclelink_helper,
-/turf/open/floor/plating,
-/area/maintenance/solars/port/fore)
+/obj/structure/lattice/catwalk,
+/turf/open/space,
+/area/solar/port/fore)
"ajX" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
@@ -6668,15 +6638,17 @@
/area/security/courtroom)
"amv" = (
/obj/structure/cable{
- icon_state = "1-2"
+ icon_state = "4-8"
},
-/obj/effect/mapping_helpers/airlock/cyclelink_helper,
-/obj/machinery/door/airlock/external{
- name = "Solar Maintenance";
- req_access_txt = "10; 13"
+/obj/structure/cable{
+ icon_state = "2-8"
},
-/turf/open/floor/plating,
-/area/maintenance/solars/starboard/fore)
+/obj/structure/cable{
+ icon_state = "1-8"
+ },
+/obj/structure/lattice/catwalk,
+/turf/open/space,
+/area/solar/port/fore)
"amw" = (
/obj/effect/spawner/structure/window/reinforced,
/turf/open/floor/plating,
@@ -8572,13 +8544,15 @@
/turf/open/floor/plasteel,
/area/security/processing)
"aqJ" = (
-/obj/effect/mapping_helpers/airlock/cyclelink_helper,
-/obj/machinery/door/airlock/external{
- name = "External Access";
- req_access_txt = "13"
+/obj/structure/cable{
+ icon_state = "2-8"
},
-/turf/open/floor/plating,
-/area/maintenance/port/fore)
+/obj/structure/cable{
+ icon_state = "1-8"
+ },
+/obj/structure/lattice/catwalk,
+/turf/open/space,
+/area/solar/port/fore)
"aqK" = (
/obj/structure/chair/stool,
/turf/open/floor/plasteel,
@@ -42345,15 +42319,9 @@
/turf/open/floor/plasteel,
/area/science/circuit)
"bXv" = (
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 4
- },
-/obj/machinery/door/airlock/external{
- name = "External Access";
- req_access_txt = "13"
- },
-/turf/open/floor/plating,
-/area/maintenance/port/aft)
+/obj/item/stack/rods,
+/turf/open/space,
+/area/space)
"bXw" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/visible,
/turf/open/floor/plasteel,
@@ -45067,7 +45035,7 @@
dir = 4
},
/turf/closed/wall/r_wall,
-/area/engine/engineering)
+/area/engine/atmos)
"cez" = (
/obj/machinery/atmospherics/pipe/simple/cyan/visible,
/turf/open/floor/plasteel,
@@ -45521,9 +45489,12 @@
/turf/open/floor/plasteel,
/area/engine/engineering)
"cfK" = (
-/obj/structure/sign/warning/securearea,
-/turf/closed/wall,
-/area/engine/engineering)
+/obj/structure/lattice/catwalk,
+/obj/structure/cable{
+ icon_state = "0-2"
+ },
+/turf/open/space,
+/area/solar/port/fore)
"cfL" = (
/obj/machinery/firealarm{
pixel_y = 24
@@ -46323,18 +46294,11 @@
/turf/open/floor/plating,
/area/maintenance/solars/port/aft)
"chO" = (
-/obj/structure/cable{
- icon_state = "4-8"
- },
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 4
- },
/obj/machinery/door/airlock/external{
- name = "Solar Maintenance";
- req_access_txt = "10; 13"
+ req_access_txt = "13"
},
/turf/open/floor/plating,
-/area/maintenance/solars/port/aft)
+/area/maintenance/fore/secondary)
"chP" = (
/obj/structure/cable{
icon_state = "4-8"
@@ -49352,15 +49316,16 @@
/turf/open/space,
/area/maintenance/aft)
"csg" = (
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 1
+/obj/structure/cable{
+ icon_state = "1-2"
},
+/obj/effect/mapping_helpers/airlock/cyclelink_helper,
/obj/machinery/door/airlock/external{
- name = "Engineering External Access";
- req_access_txt = "10;13"
+ name = "Solar Maintenance";
+ req_access_txt = "10; 13"
},
/turf/open/floor/plating,
-/area/engine/engineering)
+/area/maintenance/solars/starboard/fore)
"csi" = (
/obj/structure/transit_tube/curved/flipped{
dir = 1
@@ -51153,13 +51118,10 @@
/turf/open/floor/plasteel,
/area/security/processing)
"cxW" = (
-/obj/effect/mapping_helpers/airlock/cyclelink_helper,
-/obj/machinery/door/airlock/external{
- name = "External Access";
- req_access_txt = "13"
- },
-/turf/open/floor/plating,
-/area/maintenance/starboard/fore)
+/obj/structure/lattice,
+/obj/structure/lattice/catwalk,
+/turf/open/space,
+/area/space/nearstation)
"cxY" = (
/obj/machinery/camera{
c_tag = "Arrivals Escape Pod 1";
@@ -51258,14 +51220,13 @@
/turf/open/floor/plating,
/area/hallway/secondary/entry)
"cyC" = (
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 8
- },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper,
/obj/machinery/door/airlock/external{
+ name = "External Access";
req_access_txt = "13"
},
/turf/open/floor/plating,
-/area/maintenance/starboard)
+/area/maintenance/port/fore)
"cyD" = (
/obj/effect/mapping_helpers/airlock/cyclelink_helper{
dir = 8
@@ -51287,15 +51248,13 @@
/turf/open/floor/plating,
/area/maintenance/port/aft)
"cyG" = (
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 8
- },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper,
/obj/machinery/door/airlock/external{
- name = "Atmospherics External Airlock";
- req_access_txt = "24"
+ name = "External Access";
+ req_access_txt = "13"
},
/turf/open/floor/plating,
-/area/engine/atmos)
+/area/maintenance/starboard/fore)
"cyK" = (
/obj/structure/cable{
icon_state = "4-8"
@@ -51341,18 +51300,14 @@
/turf/open/space/basic,
/area/space)
"cyU" = (
-/obj/structure/cable{
- icon_state = "1-2"
- },
/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 1
+ dir = 8
},
/obj/machinery/door/airlock/external{
- name = "Solar Maintenance";
- req_access_txt = "10; 13"
+ req_access_txt = "13"
},
/turf/open/floor/plating,
-/area/maintenance/solars/starboard/aft)
+/area/maintenance/starboard)
"czg" = (
/obj/effect/mapping_helpers/airlock/cyclelink_helper{
dir = 8
@@ -52258,10 +52213,9 @@
/turf/open/space,
/area/space/nearstation)
"cCS" = (
-/obj/machinery/atmospherics/pipe/simple/orange/visible,
/obj/structure/lattice,
-/turf/open/space,
-/area/space/nearstation)
+/turf/closed/wall/r_wall,
+/area/engine/atmos)
"cCT" = (
/obj/machinery/atmospherics/components/unary/vent_pump/on{
dir = 4
@@ -52328,12 +52282,15 @@
/turf/closed/wall,
/area/engine/engineering)
"cDY" = (
-/obj/structure/lattice,
-/obj/machinery/atmospherics/pipe/simple/orange/visible{
- dir = 9
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 4
},
-/turf/open/space,
-/area/space/nearstation)
+/obj/machinery/door/airlock/external{
+ name = "External Access";
+ req_access_txt = "13"
+ },
+/turf/open/floor/plating,
+/area/maintenance/port/aft)
"cDZ" = (
/obj/structure/cable{
icon_state = "1-2"
@@ -53612,6 +53569,11 @@
dir = 8
},
/area/crew_quarters/fitness/pool)
+"dCt" = (
+/obj/machinery/atmospherics/pipe/simple/orange/visible,
+/obj/structure/lattice,
+/turf/open/space,
+/area/space/nearstation)
"dCV" = (
/obj/structure/cable{
icon_state = "1-4"
@@ -54280,6 +54242,12 @@
},
/turf/open/floor/plasteel,
/area/security/range)
+"fty" = (
+/obj/structure/lattice,
+/obj/machinery/atmospherics/pipe/simple/orange/visible,
+/obj/structure/lattice,
+/turf/open/space,
+/area/space/nearstation)
"ftE" = (
/obj/item/radio/intercom{
pixel_y = 25
@@ -54838,10 +54806,6 @@
dir = 8
},
/area/medical/sleeper)
-"haL" = (
-/obj/structure/lattice,
-/turf/open/space/basic,
-/area/space)
"haM" = (
/obj/item/radio/intercom{
name = "Station Intercom (General)";
@@ -55122,6 +55086,13 @@
},
/turf/open/floor/plasteel,
/area/hallway/primary/starboard)
+"imk" = (
+/obj/structure/lattice,
+/obj/machinery/atmospherics/pipe/simple/orange/visible{
+ dir = 9
+ },
+/turf/open/space/basic,
+/area/space/nearstation)
"imH" = (
/obj/structure/falsewall,
/turf/open/floor/plating,
@@ -55417,6 +55388,10 @@
},
/turf/open/floor/wood,
/area/crew_quarters/bar)
+"jiK" = (
+/obj/structure/sign/warning/securearea,
+/turf/closed/wall,
+/area/engine/engineering)
"jjC" = (
/obj/structure/table/wood,
/obj/item/toy/cards/deck,
@@ -56729,6 +56704,19 @@
/obj/structure/table/wood,
/turf/open/floor/wood,
/area/maintenance/bar)
+"mQp" = (
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 1
+ },
+/obj/machinery/door/airlock/external{
+ name = "Solar Maintenance";
+ req_access_txt = "10; 13"
+ },
+/turf/open/floor/plating,
+/area/maintenance/solars/starboard/aft)
"mQS" = (
/obj/machinery/light{
dir = 8;
@@ -58858,14 +58846,10 @@
/turf/open/floor/plasteel,
/area/crew_quarters/fitness/pool)
"tAH" = (
-/obj/machinery/door/airlock/external{
- req_access_txt = "13"
- },
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 8
- },
-/turf/open/floor/plating,
-/area/maintenance/fore/secondary)
+/obj/machinery/atmospherics/pipe/simple/orange/visible,
+/obj/structure/lattice,
+/turf/open/space/basic,
+/area/space/nearstation)
"tCa" = (
/obj/structure/table/wood,
/obj/item/instrument/guitar{
@@ -58888,6 +58872,19 @@
},
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
+"tEK" = (
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 4
+ },
+/obj/machinery/door/airlock/external{
+ name = "Solar Maintenance";
+ req_access_txt = "10; 13"
+ },
+/turf/open/floor/plating,
+/area/maintenance/solars/port/aft)
"tHh" = (
/obj/machinery/disposal/bin,
/obj/effect/turf_decal/tile/red,
@@ -59258,7 +59255,7 @@
"uDO" = (
/obj/structure/lattice/catwalk,
/obj/structure/cable{
- icon_state = "0-2"
+ icon_state = "1-2"
},
/turf/open/space,
/area/solar/port/fore)
@@ -60002,6 +59999,16 @@
/obj/machinery/holopad,
/turf/open/floor/plasteel/showroomfloor,
/area/security/main)
+"wmu" = (
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 1
+ },
+/obj/machinery/door/airlock/external{
+ name = "Engineering External Access";
+ req_access_txt = "10;13"
+ },
+/turf/open/floor/plating,
+/area/engine/engineering)
"woR" = (
/obj/machinery/cryopod{
dir = 1
@@ -60161,6 +60168,16 @@
/obj/item/hand_labeler,
/turf/open/floor/plasteel,
/area/hallway/secondary/service)
+"wWi" = (
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 8
+ },
+/obj/machinery/door/airlock/external{
+ name = "Atmospherics External Airlock";
+ req_access_txt = "24"
+ },
+/turf/open/floor/plating,
+/area/engine/atmos)
"wWT" = (
/obj/effect/landmark/start/roboticist,
/turf/open/floor/plasteel/white,
@@ -67551,7 +67568,7 @@ gXs
gXs
gJi
gJi
-haL
+gXs
aag
gJi
aaa
@@ -68305,7 +68322,7 @@ aaa
aaa
aaa
aae
-ktS
+aaa
gXs
aaa
aaa
@@ -68562,7 +68579,7 @@ aaa
aaa
aaa
aaa
-ktS
+aaa
gXs
aaa
aaa
@@ -68819,7 +68836,7 @@ aaa
aaa
aaa
aaa
-ktS
+aaa
gXs
aaa
aaa
@@ -69076,7 +69093,7 @@ aaa
aaa
aaa
aaa
-ktS
+aaa
gXs
aaa
cqq
@@ -69333,7 +69350,7 @@ aaf
aaf
aaf
aaa
-ktS
+aaa
arB
asE
cyb
@@ -73695,11 +73712,11 @@ aaa
aae
aaa
aaa
-aaa
aag
alU
alU
alU
+alU
aCW
amC
asK
@@ -73952,9 +73969,9 @@ aaa
aaa
aaa
aaa
-aaa
aag
-aqJ
+cyC
+amC
amC
gLH
ase
@@ -74209,7 +74226,7 @@ aaa
aaa
aaa
aaa
-aaa
+gJi
alU
alU
alU
@@ -74958,7 +74975,6 @@ aaa
aaa
aaa
aaa
-aaa
aaS
aaS
aaS
@@ -74977,6 +74993,7 @@ aaS
aaf
aaf
aaf
+aaf
aaa
aaa
aaa
@@ -75215,7 +75232,6 @@ aaa
aaa
aaa
aaa
-aaa
abY
aaa
aaf
@@ -75228,7 +75244,7 @@ acy
aaa
aaf
aaa
-aiS
+bXv
aaa
aaS
aaa
@@ -75237,6 +75253,7 @@ aaa
aaa
aaa
aaa
+aaa
alU
aoR
apO
@@ -75472,25 +75489,25 @@ aaa
aaa
aaa
aaa
-aaa
abY
aaa
+acW
acV
-adv
-adZ
+adA
aaa
+acW
acV
-adv
-adZ
+adA
aaa
+acW
acV
-adv
-adZ
+adA
aaa
aaS
aaf
aaf
aaf
+aaf
aaa
aaa
aaa
@@ -75726,23 +75743,22 @@ aaa
aaa
aaa
aaa
-aaa
aae
aaa
aaa
abY
aaf
-acV
-adu
-adZ
+acW
+adx
+adA
aaa
-acV
-adu
-adZ
+acW
+adx
+adA
aaa
-acV
-adu
-adZ
+acW
+adx
+adA
aaf
aaf
aaa
@@ -75751,6 +75767,7 @@ aaa
aaa
aaa
aaa
+aaa
alU
alU
alU
@@ -75986,20 +76003,19 @@ aaa
aaa
aaa
aaa
-aaa
abY
aaa
-acV
-adu
-adZ
+acW
+adx
+adA
aaf
-acV
-adu
-adZ
+acW
+adx
+adA
aaf
-acV
-adu
-adZ
+acW
+adx
+adA
aaa
aaf
aaa
@@ -76008,6 +76024,7 @@ aaa
aaa
aaa
aaa
+aaa
aaf
aaa
ali
@@ -76243,20 +76260,20 @@ aaa
aaa
aaa
aaa
-aaa
aaf
aaf
-acV
-adu
-adZ
+acW
+adx
+adA
aaa
-acV
-adu
-adZ
+acW
+adx
+adA
aaa
-acV
-adu
-adZ
+acW
+adx
+adA
+aaf
aaf
aaf
aaf
@@ -76497,26 +76514,26 @@ aaa
aaa
aaa
aaa
-aaa
aaS
aaS
aaS
aaf
aaa
-acV
-adu
-adZ
+acW
+adx
+adA
aaa
-acV
-adu
-adZ
+acW
+adx
+adA
aaa
-acV
-adu
-adZ
+acW
+adx
+adA
aaa
aaf
aaa
+aaa
ajV
alR
alR
@@ -76754,27 +76771,27 @@ aaa
aaa
aaa
aaa
-aaa
aaS
aaa
aaf
aaa
aaa
aaa
-adw
+adZ
aaa
aaa
aaa
-adw
+adZ
aaa
aaa
aaa
-adw
+adZ
aaa
aaa
ajV
ajV
ajV
+ajV
alQ
amy
ang
@@ -77011,13 +77028,12 @@ aaa
aaa
aaa
aaa
-aaa
aaS
aaf
abs
abZ
abZ
-acW
+adw
ady
ady
ady
@@ -77027,9 +77043,10 @@ ady
ady
ady
ady
+cfK
uDO
ajq
-ajW
+akB
akB
alh
alT
@@ -77268,27 +77285,27 @@ aaa
aaa
aaa
aaa
-aaa
aaS
aaa
aaf
aaa
aaa
aaa
-adx
+ajW
aaa
aaa
aaa
-adx
+ajW
aaa
aaa
aaa
-adx
+ajW
aaa
aaa
ajV
ajV
ajV
+ajV
alS
amz
anh
@@ -77525,26 +77542,26 @@ aaa
aaa
aaa
aaa
-aaa
aaS
aba
aaS
aaf
aaa
-acV
-adz
-adZ
+acW
+amv
+adA
aaa
-acV
-adz
-adZ
+acW
+amv
+adA
aaa
-acV
-adz
-adZ
+acW
+amv
+adA
aaa
aaf
aaa
+aaa
ajV
alR
alR
@@ -77785,22 +77802,22 @@ aaa
aaa
aaa
aaa
+aaf
+aaf
+acW
+amv
+adA
aaa
-aaf
-aaf
-acV
-adz
-adZ
+acW
+amv
+adA
aaa
-acV
-adz
-adZ
+acW
+amv
+adA
+aaf
+aaf
aaa
-acV
-adz
-adZ
-aaf
-aaf
aaa
aaa
aaa
@@ -78042,24 +78059,24 @@ aaa
aaa
aaa
aaa
-aaa
aaS
aaa
-acV
-adz
-adZ
+acW
+amv
+adA
aaf
-acV
-adz
-adZ
+acW
+amv
+adA
aaf
-acV
-adz
-adZ
+acW
+amv
+adA
aaa
aaf
aaf
aaf
+aaf
gXs
alU
alF
@@ -78299,25 +78316,25 @@ aaa
aaa
aaa
aaa
-aaa
aaS
aaf
-acV
-adz
-adZ
+acW
+amv
+adA
aaa
-acV
-adz
-adZ
+acW
+amv
+adA
aaa
-acV
-adz
-adZ
+acW
+amv
+adA
aaf
aaf
aaa
aaa
aaa
+aaa
alU
alU
ank
@@ -78556,22 +78573,22 @@ aaa
aaa
aaa
aaa
+aaS
+aaa
+acW
+aqJ
+adA
+aaa
+acW
+aqJ
+adA
+aaa
+acW
+aqJ
+adA
aaa
aaS
aaa
-acV
-adA
-adZ
-aaa
-acV
-adA
-adZ
-aaa
-acV
-adA
-adZ
-aaa
-aaS
aaa
aaa
aaa
@@ -78658,9 +78675,9 @@ aaf
aaa
aaf
aaa
-aaa
+aaf
hrF
-aaa
+aaf
aaa
aaf
aaa
@@ -78813,7 +78830,6 @@ aaa
aaa
aaa
aaa
-aaa
aaS
aaa
aaf
@@ -78831,6 +78847,7 @@ aaa
aaS
aaf
aaf
+aaf
gXs
alU
amC
@@ -78915,9 +78932,9 @@ aaf
aaf
aaf
aaf
-aaf
-hrF
-aaf
+cfx
+tEK
+cfx
aaf
aaf
aaf
@@ -79070,7 +79087,6 @@ aaa
aaa
aaa
aaa
-aaa
aaS
aaS
aaS
@@ -79089,6 +79105,7 @@ aaS
aaa
aaa
aaa
+aaa
alU
amE
ann
@@ -79173,7 +79190,7 @@ aaf
aaa
aaa
cfx
-chO
+chN
cfx
aaa
aaf
@@ -79421,8 +79438,8 @@ caf
aoV
aag
aaf
-aaa
-aaa
+gXs
+gXs
aaf
aaa
aaa
@@ -79675,9 +79692,9 @@ bLv
bCq
aoV
cbj
-aoV
-aag
-aaf
+bLv
+cDY
+bLv
aaf
bCq
bCq
@@ -79933,7 +79950,7 @@ bCq
bCq
cbj
bLv
-bXv
+bHE
bLv
aaf
bCq
@@ -79949,7 +79966,7 @@ ciQ
cfw
aaa
aaa
-aaa
+gXs
aaf
aaf
aaa
@@ -80204,9 +80221,9 @@ cgC
chR
ciS
cfw
-aaa
-aaa
-aaa
+aag
+aag
+aag
aaa
aaf
aaf
@@ -80461,9 +80478,9 @@ cgB
chQ
ciR
cfw
-aag
-aag
-aag
+bCq
+cDY
+bCq
aaa
aaa
aaf
@@ -80719,7 +80736,7 @@ chS
cfw
cfw
bCq
-bXv
+bHE
bCq
aaa
aaa
@@ -90215,7 +90232,7 @@ bUE
bWM
bXJ
bMK
-bMK
+bYH
bYH
bYH
bVg
@@ -92531,10 +92548,10 @@ bWQ
bWQ
caD
bWQ
-ccw
-ccw
+bLK
+bLK
cey
-ccw
+bLK
ccw
ccw
ccw
@@ -92810,14 +92827,14 @@ ckF
cpE
cjR
crW
-csg
+ciZ
+wmu
aag
aaa
aaa
aaa
aaa
aaa
-aaa
ctv
ctv
ctv
@@ -93067,14 +93084,14 @@ crw
cjO
ccw
crX
-cfK
+ciZ
+jiK
aag
aaa
aaa
aaa
aaa
aaa
-aaa
aaT
aaT
aaT
@@ -93325,7 +93342,7 @@ cjm
ccw
ccw
cig
-aag
+cig
aag
aag
aag
@@ -95003,10 +95020,10 @@ aaa
aaa
aaa
aaa
-aaa
acw
abp
abp
+abp
adR
abp
lJC
@@ -95259,10 +95276,10 @@ aaa
aaa
aaa
aaa
-aaa
aaf
aag
acU
+anF
adr
sXy
aeC
@@ -95517,12 +95534,12 @@ aaa
aaa
aaa
aaa
-aaa
aag
abp
abp
abp
abp
+abp
mxn
abp
abp
@@ -96045,7 +96062,7 @@ aaa
ahn
ahn
ahn
-tAH
+anF
ahn
eMs
anG
@@ -96301,8 +96318,8 @@ aaa
aaa
aaa
aaa
-gJi
-gJi
+ahn
+chO
ahn
ahn
khB
@@ -96390,10 +96407,10 @@ bQA
bPj
bOh
cCQ
-bLK
-cyG
-bLK
-aoV
+cCS
+chg
+cCS
+aaf
aoV
aoV
aaf
@@ -96558,8 +96575,8 @@ aaa
aaa
aaa
aaa
-aaa
-aaa
+gJi
+gJi
dFX
wWW
dqb
@@ -96646,21 +96663,21 @@ cbI
ccC
cdD
bOh
-cCG
+cCQ
cCS
+wWi
cCS
-cCI
-cCI
-cCI
-cCI
-cCI
-cCI
-cCI
-cCI
-cCI
-cCI
-cCI
-cDY
+aaa
+aaa
+aaa
+gXs
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
+cCQ
aaf
aaf
aaf
@@ -96903,21 +96920,21 @@ cbH
ccB
cbH
bOh
-aaf
-aaa
-aoV
-aaf
-aoV
-aoV
-aoV
-aaf
-aoV
-aoV
-aoV
-aoV
-aoV
-aoV
-gXs
+cCG
+tAH
+dCt
+fty
+dCt
+dCt
+dCt
+fty
+dCt
+dCt
+dCt
+dCt
+dCt
+dCt
+imk
aoV
aaa
aaa
@@ -97161,11 +97178,11 @@ ccD
cbH
bOh
aaf
-aaf
-aaf
-aaf
-aaf
-aoV
+aaa
+aaa
+aaa
+aaa
+aaa
aoV
aaf
aoV
@@ -100424,7 +100441,7 @@ aaa
aaa
aaa
aaa
-aaa
+gXs
aaf
aaf
alO
@@ -100680,8 +100697,8 @@ aaa
aaa
aaa
aaa
-aaa
-aag
+gJi
+alO
alO
arp
alO
@@ -100937,9 +100954,9 @@ aaa
aaa
aaa
aaa
-aaa
-aag
-cxW
+gJi
+cyG
+anf
anf
aqv
ayf
@@ -101194,10 +101211,10 @@ aaf
aaf
aaf
aaf
-aaf
-aag
+cxW
alO
anf
+anf
alO
mAH
jaF
@@ -101703,7 +101720,7 @@ aaa
aaa
aaf
aaa
-aaa
+amw
amw
amw
amw
@@ -101960,8 +101977,8 @@ eaR
jIs
jIs
jIs
-acx
-amv
+csg
+ane
ane
cxN
aog
@@ -102217,7 +102234,7 @@ aaa
aaa
aaf
aaa
-aaa
+amw
amw
amw
amw
@@ -110535,7 +110552,7 @@ cmw
cnj
cnj
cnj
-aaa
+cnj
aaa
aaf
aaa
@@ -110742,7 +110759,7 @@ aaf
aaf
aaf
bky
-cyC
+btp
bns
boF
bqe
@@ -110791,8 +110808,8 @@ clx
cmv
cnk
cnK
-cyU
-cpi
+cnK
+mQp
cpi
cpi
cqJ
@@ -110997,9 +111014,9 @@ aQE
aNa
aaa
aaf
-aaa
-aaf
-aaa
+gXs
+bky
+cyU
bns
boF
bqe
@@ -111049,7 +111066,7 @@ cmx
cnj
cnj
cnj
-aaa
+cnj
aaa
aaf
aaa
@@ -111254,7 +111271,7 @@ afE
aNa
aaa
aaa
-aaa
+gXs
aaf
aaa
bns
@@ -112836,7 +112853,7 @@ aaa
aaa
aaf
cNW
-cPI
+cOe
cNW
aaf
aaf
@@ -113092,9 +113109,9 @@ aaa
aaa
aaa
aaf
-aag
-aag
-aag
+cNW
+cPI
+cNW
aaf
aaa
aaa
@@ -113348,11 +113365,11 @@ aaa
aaa
aaa
aaa
-aaa
-aaa
+gXs
aag
-aaa
-aaa
+aag
+aag
+gXs
aaa
aaa
aaa
@@ -113607,7 +113624,7 @@ aaa
aaa
aaa
aaa
-aaf
+aag
aaa
aaa
aaa
diff --git a/_maps/map_files/CogStation/CogStation.dmm b/_maps/map_files/CogStation/CogStation.dmm
index 8bf6d0e32b..40a57135fd 100644
--- a/_maps/map_files/CogStation/CogStation.dmm
+++ b/_maps/map_files/CogStation/CogStation.dmm
@@ -1848,9 +1848,6 @@
dir = 8
},
/obj/effect/turf_decal/tile/neutral,
-/obj/machinery/light_switch{
- pixel_y = -24
- },
/turf/open/floor/plasteel/dark,
/area/crew_quarters/observatory)
"aez" = (
@@ -2177,6 +2174,9 @@
dir = 4
},
/obj/effect/turf_decal/tile/neutral,
+/obj/machinery/light_switch{
+ pixel_x = 24
+ },
/turf/open/floor/plasteel/dark,
/area/crew_quarters/observatory)
"afl" = (
@@ -2722,10 +2722,6 @@
dir = 1;
pixel_y = -22
},
-/obj/machinery/camera{
- c_tag = "Observatory Viewing Area";
- dir = 4
- },
/obj/machinery/light/small{
dir = 8
},
@@ -3188,6 +3184,9 @@
/obj/machinery/atmospherics/pipe/manifold/cyan/hidden{
dir = 1
},
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
/turf/open/floor/plating,
/area/maintenance/starboard/fore)
"ahL" = (
@@ -3327,15 +3326,12 @@
/turf/open/floor/plasteel/dark,
/area/crew_quarters/observatory)
"aif" = (
-/obj/machinery/firealarm{
- pixel_y = 26
- },
-/obj/structure/cable{
- icon_state = "2-4"
- },
/obj/machinery/atmospherics/pipe/simple/cyan/hidden{
dir = 4
},
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
/turf/open/floor/plating,
/area/maintenance/starboard/fore)
"aig" = (
@@ -4483,17 +4479,8 @@
/turf/open/floor/plasteel,
/area/hallway/secondary/entry)
"akN" = (
-/obj/structure/plasticflaps,
-/obj/structure/fans/tiny,
-/obj/machinery/door/poddoor/preopen{
- id = "secblock";
- name = "Security Router"
- },
-/obj/machinery/conveyor/auto{
- id = "sec"
- },
-/turf/open/floor/plating,
-/area/router/sec)
+/turf/open/space/basic,
+/area/router/aux)
"akO" = (
/obj/effect/turf_decal/stripes/line{
dir = 8
@@ -6200,12 +6187,20 @@
/turf/open/floor/grass,
/area/hydroponics)
"aoJ" = (
-/obj/machinery/atmospherics/pipe/simple/supply/visible,
-/obj/machinery/space_heater,
-/turf/open/floor/plasteel,
-/area/engine/engineering{
- name = "Engine Room"
- })
+/obj/machinery/firealarm{
+ pixel_y = 26
+ },
+/obj/structure/cable{
+ icon_state = "2-4"
+ },
+/obj/machinery/atmospherics/pipe/simple/cyan/hidden{
+ dir = 4
+ },
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/turf/open/floor/plating,
+/area/maintenance/starboard/fore)
"aoK" = (
/turf/closed/wall/r_wall,
/area/router/service)
@@ -6300,7 +6295,7 @@
/obj/machinery/conveyor{
id = "serv_off"
},
-/obj/machinery/door/poddoor/preopen{
+/obj/machinery/door/poddoor{
id = "servblock";
name = "Service Router"
},
@@ -6309,7 +6304,7 @@
"aoT" = (
/obj/structure/plasticflaps,
/obj/structure/fans/tiny,
-/obj/machinery/door/poddoor/preopen{
+/obj/machinery/door/poddoor{
id = "servblock";
name = "Service Router"
},
@@ -8607,7 +8602,7 @@
/obj/effect/turf_decal/tile/bar{
dir = 1
},
-/obj/item/storage/pill_bottle/dice,
+/obj/item/storage/box/dice,
/obj/item/toy/cards/deck,
/turf/open/floor/plasteel,
/area/crew_quarters/bar)
@@ -15009,13 +15004,19 @@
/turf/open/floor/plasteel/stairs/medium,
/area/hallway/secondary/entry)
"aHa" = (
-/obj/structure/disposalpipe/junction/yjunction,
-/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{
- dir = 8
+/obj/structure/cable,
+/obj/machinery/power/apc{
+ areastring = "/area/crew_quarters/locker";
+ dir = 8;
+ name = "Locker Room APC";
+ pixel_x = -24
},
/obj/machinery/atmospherics/pipe/simple/orange/hidden,
-/turf/open/floor/plasteel,
-/area/hallway/primary/port/fore)
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/turf/open/floor/plating,
+/area/maintenance/fore)
"aHb" = (
/obj/structure/chair,
/obj/machinery/firealarm{
@@ -15163,12 +15164,12 @@
/turf/open/floor/plasteel,
/area/tcommsat/computer)
"aHp" = (
-/obj/structure/disposalpipe/segment{
- dir = 9
+/obj/machinery/atmospherics/pipe/simple/orange/hidden,
+/obj/structure/cable{
+ icon_state = "1-2"
},
-/obj/machinery/atmospherics/pipe/manifold4w/supplymain/hidden,
-/turf/open/floor/plasteel,
-/area/hallway/primary/port/fore)
+/turf/open/floor/plating,
+/area/maintenance/fore)
"aHq" = (
/obj/effect/turf_decal/bot,
/obj/structure/disposalpipe/segment,
@@ -15841,12 +15842,16 @@
/turf/open/floor/carpet/royalblue,
/area/bridge)
"aIJ" = (
-/obj/effect/turf_decal/tile/neutral,
-/obj/effect/turf_decal/tile/neutral{
- dir = 8
+/obj/machinery/door/firedoor,
+/obj/machinery/door/airlock/maintenance{
+ name = "Fore Maintenance";
+ req_one_access_txt = "12;46"
},
-/obj/machinery/atmospherics/pipe/simple/supplymain/hidden,
-/turf/open/floor/plasteel,
+/obj/machinery/atmospherics/pipe/simple/orange/hidden,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/turf/open/floor/plating,
/area/hallway/primary/port/fore)
"aIK" = (
/obj/structure/table/wood,
@@ -16804,7 +16809,7 @@
/area/bridge)
"aKw" = (
/obj/structure/table,
-/obj/item/storage/pill_bottle/dice,
+/obj/item/storage/box/dice,
/obj/item/toy/cards/deck,
/obj/structure/disposalpipe/segment{
dir = 4
@@ -17089,13 +17094,22 @@
/turf/open/floor/plating,
/area/maintenance/fore)
"aLc" = (
-/obj/machinery/door/firedoor,
-/obj/machinery/door/airlock/maintenance{
- name = "Central Maintenance";
- req_one_access_txt = "12"
+/obj/structure/disposalpipe/segment{
+ dir = 4
},
-/obj/machinery/atmospherics/pipe/simple/supplymain/hidden,
-/turf/open/floor/plating,
+/obj/effect/turf_decal/tile/neutral{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/neutral{
+ dir = 4
+ },
+/obj/machinery/atmospherics/pipe/manifold/orange/hidden{
+ dir = 8
+ },
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/turf/open/floor/plasteel,
/area/hallway/primary/port/fore)
"aLd" = (
/obj/machinery/atmospherics/pipe/simple/supplymain/hidden,
@@ -17721,14 +17735,16 @@
/turf/closed/wall,
/area/maintenance/department/chapel)
"aMo" = (
-/obj/structure/disposalpipe/segment{
- dir = 6
+/obj/structure/disposalpipe/junction/yjunction,
+/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{
+ dir = 8
},
+/obj/machinery/atmospherics/pipe/simple/orange/hidden,
/obj/structure/cable{
- icon_state = "1-2"
+ icon_state = "1-4"
},
-/turf/open/floor/plating,
-/area/maintenance/starboard/central)
+/turf/open/floor/plasteel,
+/area/hallway/primary/port/fore)
"aMp" = (
/obj/effect/landmark/event_spawn,
/obj/machinery/atmospherics/pipe/simple/orange/hidden,
@@ -17880,18 +17896,15 @@
},
/area/chapel/main)
"aMG" = (
-/obj/structure/disposalpipe/segment,
+/obj/structure/disposalpipe/segment{
+ dir = 9
+ },
+/obj/machinery/atmospherics/pipe/manifold4w/supplymain/hidden,
/obj/structure/cable{
- icon_state = "1-2"
+ icon_state = "2-8"
},
-/obj/machinery/camera{
- c_tag = "Central Starboard Maintenance";
- dir = 8;
- pixel_y = -22
- },
-/mob/living/simple_animal/hostile/retaliate/bat,
-/turf/open/floor/plating,
-/area/maintenance/starboard/central)
+/turf/open/floor/plasteel,
+/area/hallway/primary/port/fore)
"aMH" = (
/obj/structure/cable{
icon_state = "2-8"
@@ -19880,9 +19893,16 @@
/turf/open/floor/plasteel/white,
/area/crew_quarters/fitness/cogpool)
"aQS" = (
+/obj/effect/turf_decal/tile/neutral,
+/obj/effect/turf_decal/tile/neutral{
+ dir = 8
+ },
/obj/machinery/atmospherics/pipe/simple/supplymain/hidden,
-/turf/open/floor/plating,
-/area/maintenance/central)
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/turf/open/floor/plasteel,
+/area/hallway/primary/port/fore)
"aQT" = (
/obj/machinery/door/airlock/engineering{
name = "Thermo-Electric Generator";
@@ -22384,6 +22404,18 @@
/obj/effect/spawner/lootdrop/maintenance,
/turf/open/floor/plating,
/area/maintenance/department/eva)
+"aWr" = (
+/obj/machinery/door/firedoor,
+/obj/machinery/door/airlock/maintenance{
+ name = "Central Maintenance";
+ req_one_access_txt = "12"
+ },
+/obj/machinery/atmospherics/pipe/simple/supplymain/hidden,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/turf/open/floor/plating,
+/area/hallway/primary/port/fore)
"aWs" = (
/obj/machinery/light{
dir = 8;
@@ -22411,16 +22443,10 @@
/turf/open/floor/plating,
/area/maintenance/central)
"aWu" = (
-/obj/structure/cable{
- icon_state = "0-2"
- },
-/obj/machinery/power/apc{
- areastring = "/area/crew_quarters/fitness/cogpool";
- dir = 4;
- name = "Pool APC";
- pixel_x = 24
- },
/obj/machinery/atmospherics/pipe/simple/supplymain/hidden,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/plating,
/area/maintenance/central)
"aWv" = (
@@ -22787,9 +22813,9 @@
/turf/open/floor/carpet,
/area/library)
"aXg" = (
-/obj/structure/bookcase/random/reference,
-/turf/open/floor/wood,
-/area/library)
+/obj/machinery/vending/coffee,
+/turf/open/floor/plasteel,
+/area/hallway/primary/central)
"aXh" = (
/obj/machinery/atmospherics/pipe/simple/supply/visible{
dir = 6
@@ -22837,6 +22863,12 @@
},
/turf/open/floor/plasteel,
/area/hallway/primary/central)
+"aXm" = (
+/obj/machinery/atmospherics/pipe/manifold/cyan/hidden{
+ dir = 1
+ },
+/turf/closed/wall/r_wall,
+/area/tcommsat/computer)
"aXn" = (
/obj/effect/turf_decal/tile/bar,
/obj/effect/turf_decal/tile/bar{
@@ -22876,6 +22908,15 @@
"aXr" = (
/turf/open/floor/plasteel,
/area/ai_monitored/storage/eva)
+"aXs" = (
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 1
+ },
+/turf/open/floor/plating,
+/area/tcommsat/computer)
"aXt" = (
/obj/effect/spawner/structure/window/reinforced,
/obj/structure/sign/warning/securearea,
@@ -24424,10 +24465,12 @@
/turf/open/floor/plasteel/dark,
/area/security/checkpoint/customs)
"baE" = (
-/obj/structure/disposalpipe/segment{
- dir = 9
+/obj/structure/bookcase/random/reference,
+/obj/effect/turf_decal/tile/neutral,
+/obj/effect/turf_decal/tile/neutral{
+ dir = 1
},
-/turf/open/floor/wood,
+/turf/open/floor/plasteel/dark,
/area/library)
"baF" = (
/obj/structure/chair/office/dark{
@@ -24976,18 +25019,21 @@
/turf/open/floor/plating,
/area/security/checkpoint/customs)
"bbQ" = (
-/obj/structure/sign/warning/vacuum/external{
- pixel_x = -32;
- pixel_y = 32
+/obj/structure/cable{
+ icon_state = "0-2"
},
+/obj/machinery/power/apc{
+ areastring = "/area/crew_quarters/fitness/cogpool";
+ dir = 4;
+ name = "Pool APC";
+ pixel_x = 24
+ },
+/obj/machinery/atmospherics/pipe/simple/supplymain/hidden,
/obj/structure/cable{
icon_state = "1-2"
},
-/obj/machinery/atmospherics/pipe/simple/supplymain/hidden,
-/turf/open/floor/plasteel,
-/area/engine/engineering{
- name = "Engine Room"
- })
+/turf/open/floor/plating,
+/area/maintenance/central)
"bbR" = (
/obj/structure/closet/crate/hydroponics,
/obj/effect/turf_decal/tile/green,
@@ -27393,19 +27439,16 @@
/turf/open/floor/wood,
/area/medical/medbay/lobby)
"bhy" = (
-/obj/structure/closet/crate/science,
-/obj/item/stack/sheet/metal/ten,
-/obj/item/stack/sheet/glass/five,
-/obj/item/stack/rods/twentyfive,
-/obj/item/target/syndicate,
-/obj/item/target/alien,
-/obj/item/target,
-/obj/item/target/clown,
-/obj/machinery/atmospherics/pipe/simple/orange/hidden{
- dir = 10
+/obj/structure/plasticflaps,
+/obj/structure/fans/tiny,
+/obj/machinery/conveyor/auto{
+ id = "sec"
},
-/turf/open/floor/plasteel,
-/area/science/mixing)
+/obj/machinery/door/poddoor{
+ name = "Security Router"
+ },
+/turf/open/floor/plating,
+/area/router/sec)
"bhz" = (
/obj/structure/disposalpipe/segment,
/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{
@@ -27774,8 +27817,15 @@
/turf/open/floor/plating,
/area/quartermaster/storage)
"bim" = (
-/turf/open/space/basic,
-/area/space/nearstation)
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/button/massdriver{
+ id = "router_in";
+ name = "mass driver button (Router)";
+ pixel_x = 24;
+ pixel_y = -8
+ },
+/turf/open/floor/plating,
+/area/maintenance/disposal)
"bin" = (
/obj/machinery/computer/mecha{
dir = 4
@@ -30316,6 +30366,18 @@
},
/turf/open/floor/plasteel,
/area/science/mixing)
+"bnl" = (
+/obj/structure/cable{
+ icon_state = "1-4"
+ },
+/obj/structure/cable{
+ icon_state = "2-4"
+ },
+/obj/machinery/atmospherics/pipe/manifold/cyan/hidden{
+ dir = 8
+ },
+/turf/open/floor/plating,
+/area/maintenance/starboard/central)
"bnm" = (
/obj/machinery/atmospherics/pipe/manifold/orange/hidden{
dir = 4
@@ -31910,7 +31972,7 @@
/obj/effect/turf_decal/tile/green{
dir = 4
},
-/obj/item/storage/pill_bottle/dice,
+/obj/item/storage/box/dice,
/obj/item/toy/cards/deck,
/turf/open/floor/plasteel/white/corner{
dir = 1
@@ -33867,9 +33929,18 @@
/area/janitor)
"bvb" = (
/obj/structure/disposalpipe/segment,
-/obj/effect/landmark/blobstart,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/obj/machinery/door/airlock/engineering{
+ name = "Electrical Substation";
+ req_access_txt = "10"
+ },
+/obj/structure/fans/tiny,
/turf/open/floor/plating,
-/area/maintenance/starboard/central)
+/area/engine/storage_shared{
+ name = "Electrical Substation"
+ })
"bvc" = (
/obj/machinery/computer/cargo/request,
/obj/machinery/airalarm{
@@ -34423,10 +34494,13 @@
/turf/open/floor/plating,
/area/maintenance/starboard/central)
"bwp" = (
-/obj/structure/disposalpipe/segment,
-/obj/structure/cable{
- icon_state = "1-8"
+/obj/structure/disposalpipe/segment{
+ dir = 6
},
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/obj/machinery/atmospherics/pipe/simple/cyan/hidden,
/turf/open/floor/plating,
/area/maintenance/starboard/central)
"bwq" = (
@@ -34650,6 +34724,20 @@
},
/turf/open/floor/plating,
/area/router)
+"bwM" = (
+/obj/structure/disposalpipe/segment,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/obj/machinery/camera{
+ c_tag = "Central Starboard Maintenance";
+ dir = 8;
+ pixel_y = -22
+ },
+/obj/machinery/atmospherics/pipe/simple/cyan/hidden,
+/mob/living/simple_animal/hostile/retaliate/bat,
+/turf/open/floor/plating,
+/area/maintenance/starboard/central)
"bwN" = (
/obj/machinery/atmospherics/pipe/simple/general/visible{
dir = 4
@@ -34921,11 +35009,16 @@
/turf/open/floor/plating,
/area/maintenance/department/chapel)
"bxq" = (
+/obj/structure/disposalpipe/segment,
/obj/structure/cable{
- icon_state = "4-8"
+ icon_state = "1-2"
},
+/obj/structure/cable{
+ icon_state = "1-4"
+ },
+/obj/machinery/atmospherics/pipe/simple/cyan/hidden,
/turf/open/floor/plating,
-/area/tcommsat/computer)
+/area/maintenance/starboard/central)
"bxr" = (
/obj/structure/table,
/obj/effect/turf_decal/tile/purple,
@@ -35428,32 +35521,29 @@
/turf/open/floor/plasteel,
/area/router/eva)
"byt" = (
+/obj/structure/disposalpipe/segment,
+/obj/structure/cable{
+ icon_state = "1-8"
+ },
+/obj/machinery/atmospherics/pipe/simple/cyan/hidden,
+/turf/open/floor/plating,
+/area/maintenance/starboard/central)
+"byu" = (
+/obj/structure/disposalpipe/segment,
+/obj/effect/landmark/blobstart,
+/obj/machinery/atmospherics/pipe/simple/cyan/hidden,
+/turf/open/floor/plating,
+/area/maintenance/starboard/central)
+"byv" = (
/obj/structure/disposalpipe/segment{
dir = 4
},
/obj/machinery/camera{
c_tag = "Central Starboard Exterior Access"
},
-/turf/open/floor/plating,
-/area/maintenance/starboard/central)
-"byu" = (
-/obj/machinery/door/firedoor,
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 8
- },
-/obj/structure/disposalpipe/segment{
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
dir = 4
},
-/obj/machinery/door/airlock/external{
- name = "Central Starboard Exterior Access";
- req_access_txt = "13"
- },
-/turf/open/floor/plating,
-/area/maintenance/starboard/central)
-"byv" = (
-/obj/structure/disposalpipe/junction/flip{
- dir = 1
- },
/turf/open/floor/plating,
/area/maintenance/starboard/central)
"byw" = (
@@ -36136,14 +36226,19 @@
/turf/open/floor/plasteel,
/area/gateway)
"bAd" = (
-/obj/structure/cable{
- icon_state = "1-4"
+/obj/machinery/door/firedoor,
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 8
},
-/obj/structure/cable{
- icon_state = "2-4"
+/obj/structure/disposalpipe/segment{
+ dir = 4
+ },
+/obj/machinery/door/airlock/external{
+ name = "Central Starboard Exterior Access";
+ req_access_txt = "13"
},
/obj/machinery/atmospherics/pipe/simple/cyan/hidden{
- dir = 5
+ dir = 4
},
/turf/open/floor/plating,
/area/maintenance/starboard/central)
@@ -36375,6 +36470,15 @@
/area/medical/medbay/zone2{
name = "Medbay Treatment Center"
})
+"bAz" = (
+/obj/structure/disposalpipe/junction/flip{
+ dir = 1
+ },
+/obj/machinery/atmospherics/pipe/simple/cyan/hidden{
+ dir = 9
+ },
+/turf/open/floor/plating,
+/area/maintenance/starboard/central)
"bAA" = (
/obj/structure/lattice,
/obj/structure/cable{
@@ -36532,6 +36636,19 @@
/area/medical/medbay/zone2{
name = "Medbay Treatment Center"
})
+"bAN" = (
+/obj/structure/rack,
+/obj/item/clothing/suit/space/fragile,
+/obj/item/clothing/head/helmet/space/fragile,
+/obj/item/tank/internals/air,
+/obj/item/flashlight,
+/obj/machinery/airalarm{
+ dir = 1;
+ locked = 0;
+ pixel_y = -22
+ },
+/turf/open/floor/plating,
+/area/maintenance/starboard/central)
"bAO" = (
/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{
dir = 4
@@ -38158,16 +38275,20 @@
},
/area/crew_quarters/heads/captain)
"bEr" = (
-/obj/structure/cable,
-/obj/machinery/power/apc{
- areastring = "/area/crew_quarters/locker";
- dir = 8;
- name = "Locker Room APC";
- pixel_x = -24
+/obj/structure/sign/warning/vacuum/external{
+ pixel_x = -32;
+ pixel_y = 32
},
-/obj/machinery/atmospherics/pipe/simple/orange/hidden,
-/turf/open/floor/plating,
-/area/maintenance/fore)
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/obj/machinery/atmospherics/pipe/manifold/supplymain/hidden{
+ dir = 8
+ },
+/turf/open/floor/plasteel,
+/area/engine/engineering{
+ name = "Engine Room"
+ })
"bEs" = (
/obj/machinery/portable_atmospherics/canister/oxygen,
/obj/effect/turf_decal/tile/yellow{
@@ -38355,9 +38476,15 @@
/turf/open/floor/plasteel/dark,
/area/crew_quarters/bar)
"bEK" = (
-/obj/machinery/atmospherics/pipe/simple/orange/hidden,
-/turf/open/floor/plating,
-/area/maintenance/fore)
+/obj/machinery/atmospherics/pipe/simple/supply/visible,
+/obj/machinery/space_heater,
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 8
+ },
+/turf/open/floor/plasteel,
+/area/engine/engineering{
+ name = "Engine Room"
+ })
"bEL" = (
/obj/structure/disposalpipe/segment{
dir = 4
@@ -38591,9 +38718,19 @@
/turf/open/floor/plasteel,
/area/ai_monitored/turret_protected/ai)
"bFg" = (
-/obj/effect/turf_decal/tile/brown,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/visible,
+/obj/machinery/suit_storage_unit/engine,
+/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{
+ dir = 4
+ },
+/obj/machinery/airalarm{
+ dir = 4;
+ pixel_x = -23
+ },
/turf/open/floor/plasteel,
-/area/quartermaster/miningoffice)
+/area/engine/engineering{
+ name = "Engine Room"
+ })
"bFh" = (
/obj/effect/turf_decal/tile/brown,
/obj/machinery/light,
@@ -39247,14 +39384,15 @@
/turf/open/floor/plasteel,
/area/hallway/primary/central)
"bGu" = (
-/obj/machinery/door/firedoor,
-/obj/machinery/door/airlock/maintenance{
- name = "Fore Maintenance";
- req_one_access_txt = "12;46"
+/obj/structure/cable{
+ icon_state = "1-4"
},
-/obj/machinery/atmospherics/pipe/simple/orange/hidden,
-/turf/open/floor/plating,
-/area/hallway/primary/port/fore)
+/obj/machinery/atmospherics/pipe/simple/supplymain/hidden,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/turf/open/floor/plasteel/freezer,
+/area/crew_quarters/toilet/restrooms)
"bGv" = (
/obj/machinery/door/firedoor,
/obj/machinery/door/airlock/public/glass{
@@ -39621,20 +39759,15 @@
/turf/open/floor/plasteel,
/area/security/main)
"bHi" = (
-/obj/structure/disposalpipe/segment{
- dir = 4
- },
-/obj/effect/turf_decal/tile/neutral{
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
dir = 1
},
-/obj/effect/turf_decal/tile/neutral{
- dir = 4
+/obj/effect/landmark/event_spawn,
+/obj/structure/cable{
+ icon_state = "1-2"
},
-/obj/machinery/atmospherics/pipe/manifold/orange/hidden{
- dir = 8
- },
-/turf/open/floor/plasteel,
-/area/hallway/primary/port/fore)
+/turf/open/floor/plasteel/freezer,
+/area/crew_quarters/toilet/restrooms)
"bHj" = (
/obj/structure/table,
/obj/structure/bedsheetbin/towel,
@@ -40740,7 +40873,11 @@
/obj/machinery/airalarm{
pixel_y = 24
},
-/turf/open/floor/wood,
+/obj/effect/turf_decal/tile/neutral,
+/obj/effect/turf_decal/tile/neutral{
+ dir = 1
+ },
+/turf/open/floor/plasteel/dark,
/area/library)
"bJD" = (
/obj/machinery/disposal/bin{
@@ -40891,15 +41028,11 @@
/turf/open/floor/plasteel/white,
/area/science/mixing)
"bJU" = (
-/obj/effect/turf_decal/tile/brown,
-/obj/machinery/light{
- dir = 4
+/obj/structure/cable{
+ icon_state = "1-2"
},
-/obj/effect/turf_decal/tile/purple{
- dir = 4
- },
-/turf/open/floor/plasteel,
-/area/quartermaster/miningoffice)
+/turf/open/floor/plasteel/freezer,
+/area/crew_quarters/toilet/restrooms)
"bJV" = (
/obj/machinery/atmospherics/components/unary/thermomachine/freezer/on{
dir = 1;
@@ -41361,7 +41494,11 @@
/area/science/robotics/lab)
"bKR" = (
/obj/structure/bookcase/random/religion,
-/turf/open/floor/wood,
+/obj/effect/turf_decal/tile/neutral,
+/obj/effect/turf_decal/tile/neutral{
+ dir = 1
+ },
+/turf/open/floor/plasteel/dark,
/area/library)
"bKS" = (
/obj/machinery/door/firedoor,
@@ -42981,22 +43118,30 @@
/turf/open/floor/plasteel,
/area/hallway/secondary/exit)
"bOn" = (
-/obj/machinery/door/airlock/external/glass{
- name = "Shuttle Maintenance Access"
+/obj/machinery/door/firedoor,
+/obj/machinery/door/airlock/maintenance{
+ name = "Bathroom Maintenance";
+ req_access_txt = "12"
},
-/turf/open/floor/plasteel,
-/area/hallway/secondary/exit)
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/turf/open/floor/plating,
+/area/crew_quarters/toilet/restrooms)
"bOo" = (
/obj/effect/spawner/structure/window/reinforced,
/obj/structure/sign/warning/docking,
/turf/open/floor/plating,
/area/hallway/secondary/exit)
"bOp" = (
-/obj/machinery/door/airlock/external/glass{
- name = "Departures Shuttle Dock"
+/obj/structure/cable{
+ icon_state = "2-8"
},
-/turf/open/floor/plasteel,
-/area/hallway/secondary/exit)
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/turf/open/floor/plating,
+/area/maintenance/aft)
"bOq" = (
/obj/machinery/power/tracker,
/obj/structure/cable,
@@ -44925,8 +45070,12 @@
/turf/open/floor/plasteel/dark,
/area/science/robotics/lab)
"bRZ" = (
-/obj/structure/bookcase/random/fiction,
-/turf/open/floor/wood,
+/obj/structure/bookcase/random/nonfiction,
+/obj/effect/turf_decal/tile/neutral,
+/obj/effect/turf_decal/tile/neutral{
+ dir = 1
+ },
+/turf/open/floor/plasteel/dark,
/area/library)
"bSa" = (
/obj/structure/closet/secure_closet/medical3,
@@ -46569,15 +46718,15 @@
/turf/open/floor/plasteel,
/area/quartermaster/sorting)
"bVt" = (
-/obj/structure/disposalpipe/segment,
-/obj/structure/cable{
- icon_state = "1-2"
+/obj/effect/turf_decal/tile/brown{
+ dir = 1
},
-/obj/structure/cable{
- icon_state = "1-4"
+/obj/effect/turf_decal/tile/purple{
+ dir = 4
},
-/turf/open/floor/plating,
-/area/maintenance/starboard/central)
+/obj/machinery/atmospherics/pipe/simple/cyan/hidden,
+/turf/open/floor/plasteel,
+/area/quartermaster/miningoffice)
"bVu" = (
/obj/effect/decal/cleanable/dirt,
/obj/item/radio/intercom{
@@ -47901,11 +48050,9 @@
/turf/open/floor/plating,
/area/router)
"bXN" = (
-/obj/structure/cable{
- icon_state = "2-8"
- },
-/turf/open/floor/plating,
-/area/maintenance/aft)
+/obj/machinery/smartfridge/organ/preloaded,
+/turf/closed/wall,
+/area/medical/morgue)
"bXO" = (
/obj/structure/table/glass,
/obj/machinery/reagentgrinder,
@@ -47922,7 +48069,7 @@
/obj/structure/cable{
icon_state = "0-4"
},
-/turf/open/floor/plating,
+/turf/open/floor/plating/airless,
/area/space/nearstation)
"bXQ" = (
/obj/structure/closet/l3closet/scientist,
@@ -47979,7 +48126,7 @@
/obj/structure/cable{
icon_state = "4-8"
},
-/turf/open/floor/plating,
+/turf/open/floor/plating/airless,
/area/space/nearstation)
"bXW" = (
/obj/structure/disposalpipe/segment{
@@ -48671,8 +48818,10 @@
/turf/open/floor/plasteel/freezer,
/area/crew_quarters/toilet/restrooms)
"bZo" = (
-/turf/open/floor/plasteel/freezer,
-/area/crew_quarters/toilet/restrooms)
+/obj/effect/turf_decal/tile/brown,
+/obj/machinery/atmospherics/pipe/simple/cyan/hidden,
+/turf/open/floor/plasteel,
+/area/quartermaster/miningoffice)
"bZp" = (
/obj/structure/lattice/catwalk,
/obj/structure/cable{
@@ -48706,13 +48855,13 @@
/turf/open/floor/plating,
/area/hallway/primary/central)
"bZs" = (
-/obj/machinery/door/firedoor,
-/obj/machinery/door/airlock/maintenance{
- name = "Bathroom Maintenance";
- req_access_txt = "12"
+/obj/effect/turf_decal/tile/brown,
+/obj/effect/turf_decal/tile/purple{
+ dir = 4
},
-/turf/open/floor/plating,
-/area/crew_quarters/toilet/restrooms)
+/obj/machinery/atmospherics/pipe/simple/cyan/hidden,
+/turf/open/floor/plasteel,
+/area/quartermaster/miningoffice)
"bZt" = (
/turf/closed/wall,
/area/maintenance/starboard/aft)
@@ -48859,8 +49008,11 @@
/turf/open/floor/carpet,
/area/library)
"bZK" = (
-/obj/structure/bookcase/random/nonfiction,
-/turf/open/floor/wood,
+/obj/effect/turf_decal/tile/neutral,
+/obj/effect/turf_decal/tile/neutral{
+ dir = 1
+ },
+/turf/open/floor/plasteel/dark,
/area/library)
"bZL" = (
/obj/machinery/air_sensor/atmos/nitrous_tank,
@@ -52612,9 +52764,8 @@
/turf/open/floor/plasteel,
/area/engine/teg_hot)
"chC" = (
-/obj/effect/decal/cleanable/dirt,
-/turf/open/floor/plating,
-/area/maintenance/disposal)
+/turf/closed/wall/r_wall/rust,
+/area/space/nearstation)
"chD" = (
/obj/effect/turf_decal/stripes/line{
dir = 1
@@ -53089,6 +53240,17 @@
},
/turf/open/floor/plating,
/area/maintenance/port/fore)
+"ciA" = (
+/obj/effect/turf_decal/tile/brown,
+/obj/machinery/light{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/purple{
+ dir = 4
+ },
+/obj/machinery/atmospherics/pipe/simple/cyan/hidden,
+/turf/open/floor/plasteel,
+/area/quartermaster/miningoffice)
"ciB" = (
/obj/structure/frame/computer,
/obj/structure/disposalpipe/segment,
@@ -54655,18 +54817,15 @@
/turf/open/floor/circuit/telecomms/mainframe,
/area/tcommsat/server)
"clO" = (
-/obj/structure/disposalpipe/segment,
-/obj/structure/cable{
- icon_state = "1-2"
+/obj/effect/turf_decal/tile/brown,
+/obj/effect/turf_decal/tile/purple{
+ dir = 4
},
-/obj/machinery/door/airlock/engineering{
- name = "Electrical Substation";
- req_access_txt = "10"
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 1
},
-/turf/open/floor/plating,
-/area/engine/storage_shared{
- name = "Electrical Substation"
- })
+/turf/open/floor/plasteel,
+/area/quartermaster/miningoffice)
"clP" = (
/obj/structure/table,
/obj/item/stock_parts/subspace/amplifier,
@@ -55625,6 +55784,29 @@
icon_state = "panelscorched"
},
/area/maintenance/port/fore)
+"cnG" = (
+/obj/machinery/door/airlock/external/glass{
+ name = "Shuttle Maintenance Access"
+ },
+/obj/structure/fans/tiny,
+/turf/open/floor/plasteel,
+/area/hallway/secondary/exit)
+"cnH" = (
+/obj/machinery/door/airlock/external/glass{
+ name = "Departures Shuttle Dock"
+ },
+/obj/structure/fans/tiny,
+/turf/open/floor/plasteel,
+/area/hallway/secondary/exit)
+"cnI" = (
+/turf/open/floor/plating{
+ icon_state = "platingdmg3"
+ },
+/area/space/nearstation)
+"cnJ" = (
+/obj/structure/girder,
+/turf/open/floor/plating/airless,
+/area/space/nearstation)
"cnK" = (
/obj/effect/turf_decal/stripes/line{
dir = 8
@@ -55634,10 +55816,47 @@
},
/turf/open/floor/plasteel,
/area/engine/teg_hot)
+"cnL" = (
+/obj/structure/closet/crate/science,
+/obj/item/stack/sheet/metal/ten,
+/obj/item/stack/sheet/glass/five,
+/obj/item/stack/rods/twentyfive,
+/obj/item/target/syndicate,
+/obj/item/target/alien,
+/obj/item/target,
+/obj/item/target/clown,
+/turf/open/floor/plasteel,
+/area/science/mixing)
+"cnM" = (
+/obj/machinery/mass_driver{
+ dir = 8;
+ id = "pb_in";
+ name = "Router Driver"
+ },
+/turf/open/floor/plating/airless,
+/area/router/aux)
+"cnN" = (
+/obj/structure/bookcase/random/fiction,
+/obj/effect/turf_decal/tile/neutral,
+/obj/effect/turf_decal/tile/neutral{
+ dir = 1
+ },
+/turf/open/floor/plasteel/dark,
+/area/library)
"cnO" = (
/obj/effect/landmark/event_spawn,
/turf/open/floor/engine,
/area/science/storage)
+"cnP" = (
+/obj/structure/disposalpipe/segment{
+ dir = 9
+ },
+/obj/item/kirbyplants{
+ icon_state = "plant-21";
+ pixel_y = 3
+ },
+/turf/open/floor/wood,
+/area/library)
"cnS" = (
/obj/structure/cable{
icon_state = "0-2"
@@ -61156,18 +61375,6 @@
/obj/machinery/atmospherics/pipe/simple/cyan/hidden,
/turf/open/floor/plasteel,
/area/quartermaster/miningoffice)
-"cyd" = (
-/obj/effect/turf_decal/tile/brown{
- dir = 1
- },
-/obj/effect/turf_decal/tile/purple{
- dir = 4
- },
-/obj/machinery/atmospherics/pipe/simple/cyan/hidden{
- dir = 5
- },
-/turf/open/floor/plasteel,
-/area/quartermaster/miningoffice)
"cye" = (
/obj/structure/disposalpipe/segment{
dir = 5
@@ -67714,13 +67921,6 @@
/obj/machinery/atmospherics/pipe/simple/supplymain/hidden,
/turf/open/floor/plasteel/freezer,
/area/crew_quarters/toilet/restrooms)
-"cJg" = (
-/obj/structure/cable{
- icon_state = "1-4"
- },
-/obj/machinery/atmospherics/pipe/simple/supplymain/hidden,
-/turf/open/floor/plasteel/freezer,
-/area/crew_quarters/toilet/restrooms)
"cJh" = (
/obj/structure/table,
/obj/structure/bedsheetbin/towel,
@@ -67819,16 +68019,6 @@
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/closed/wall/r_wall,
-/area/engine/engineering{
- name = "Engine Room"
- })
-"cJq" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/visible,
-/obj/machinery/suit_storage_unit/engine,
-/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{
- dir = 4
- },
-/turf/open/floor/plasteel,
/area/engine/engineering{
name = "Engine Room"
})
@@ -69803,13 +69993,6 @@
"cNB" = (
/turf/open/floor/plating,
/area/quartermaster/miningdock/airless)
-"cNC" = (
-/obj/machinery/atmospherics/components/unary/vent_pump/on{
- dir = 1
- },
-/obj/effect/landmark/event_spawn,
-/turf/open/floor/plasteel/freezer,
-/area/crew_quarters/toilet/restrooms)
"cND" = (
/obj/effect/landmark/event_spawn,
/turf/open/floor/plasteel,
@@ -85536,8 +85719,8 @@ aaU
aaa
aaU
aEa
-cMK
-bxq
+aXm
+aXs
bxC
akI
bxK
@@ -92528,7 +92711,7 @@ aaa
aaa
aaa
aaa
-aaU
+aaa
bcy
bed
boJ
@@ -93042,11 +93225,11 @@ aaa
aaa
aaa
aaa
-aaa
+aaU
+bQe
+aaU
aaU
aaU
-aaa
-aaa
bcw
bdf
bdf
@@ -93299,13 +93482,13 @@ aaa
aaa
aaa
aaa
-aaa
-bim
+aaU
+aye
+aaU
aaU
aaU
-aaa
bcw
-bhy
+cnL
bdf
bpR
bJw
@@ -93557,10 +93740,10 @@ aaa
aaa
aaa
aaU
-aaa
-aaa
-aaU
-aaU
+chC
+abp
+abp
+abp
bcy
biK
bdf
@@ -93814,10 +93997,10 @@ aaa
aaa
aaa
aaU
-aaa
-aaa
-aaa
-aaU
+brs
+brs
+brs
+brs
bcw
biT
bdf
@@ -94071,8 +94254,8 @@ aaU
aaU
aaU
aaU
-aaa
-aaa
+cnI
+cnJ
bgW
bgW
bgW
@@ -97834,16 +98017,16 @@ aaa
aaa
aaa
aaa
-aak
-aak
-aak
+aaU
+aaa
+aaU
aaa
aaa
aaa
aaa
aaa
aaa
-akN
+bhy
alq
alq
apn
@@ -98169,7 +98352,7 @@ aZy
aZy
aZy
aZy
-beJ
+aXg
bfd
bjg
bUt
@@ -98348,9 +98531,9 @@ aaa
aaa
aaa
aaa
-aWj
-aWj
-aWj
+aaU
+aaa
+aaU
aaa
aaa
aaa
@@ -98598,16 +98781,16 @@ aaU
aar
abM
ace
-aWj
-aWj
-aWj
-aWj
-aWj
-aWj
-aWj
-aWj
+aaU
+aaU
+aaU
+aaU
+aaU
+aaU
+aaU
+aaU
abp
-aWj
+aaU
aaU
aaU
aaU
@@ -98855,16 +99038,16 @@ aaU
aar
abR
ace
-aWj
+aaU
aaa
aaa
aaa
aaa
aaa
aaa
-aWj
-aWj
-aWj
+aaU
+aaa
+aaU
aaa
aaa
aaa
@@ -99112,7 +99295,7 @@ aaU
aar
abM
acf
-aWj
+aaU
aaa
aaa
aaa
@@ -99368,8 +99551,8 @@ aaa
aaU
aaa
acM
-aWj
-aWj
+aaa
+aaU
aaa
aaa
aaa
@@ -99454,8 +99637,8 @@ bWi
aWh
cmN
aZy
-aXg
-bZK
+baE
+bRZ
bZF
csH
bay
@@ -99625,7 +99808,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
aaa
aaa
@@ -99712,7 +99895,7 @@ baS
bbr
aZy
bJC
-bZF
+bZK
bZF
cjx
bay
@@ -99882,7 +100065,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
aaa
aaa
@@ -99969,10 +100152,10 @@ cdE
bbs
aZy
bKR
-bRZ
+cnN
bZF
cCJ
-baE
+cnP
bZS
bZS
bGI
@@ -100139,7 +100322,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
add
adC
@@ -100396,7 +100579,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
adf
aad
@@ -100653,7 +100836,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
adf
aad
@@ -100910,7 +101093,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
adf
aad
@@ -101167,7 +101350,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
adf
aad
@@ -101424,7 +101607,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
adf
aad
@@ -101681,7 +101864,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
adh
adC
@@ -101938,7 +102121,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
aaa
aaa
@@ -102193,9 +102376,9 @@ aaa
aaa
aaa
aaU
-aar
aaU
-aWj
+aaU
+aaU
aaU
aaU
aaU
@@ -102450,9 +102633,9 @@ aaa
aaa
aaa
abp
-aar
+akN
aTd
-aWj
+aaa
abp
aaa
aaU
@@ -102707,9 +102890,9 @@ aaa
aaa
aaa
aaU
-aar
aaU
-aWj
+aaU
+aaU
aaU
aaU
aaU
@@ -102966,7 +103149,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
aaa
aaa
@@ -103223,7 +103406,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaU
aaa
adj
@@ -103480,7 +103663,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaU
adj
adj
@@ -103737,7 +103920,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaU
adj
adF
@@ -103994,7 +104177,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaU
adj
adF
@@ -104251,7 +104434,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaU
adj
adF
@@ -104285,12 +104468,12 @@ aJF
aJF
aJF
aJF
-bEr
-bEK
-bEK
-bGu
-bHi
aHa
+aHp
+aHp
+aIJ
+aLc
+aMo
cBj
cBw
cBF
@@ -104508,7 +104691,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaU
adj
adF
@@ -104547,15 +104730,15 @@ aim
aim
aEh
aEq
-aHp
-aIJ
-aLc
-aQS
-aQS
-aQS
-aQS
+aMG
aQS
+aWr
aWu
+aWu
+aWu
+aWu
+aWu
+bbQ
aWA
aXd
bre
@@ -104765,7 +104948,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaU
adj
adF
@@ -105022,7 +105205,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaU
adj
adj
@@ -105279,7 +105462,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaU
adj
@@ -105536,7 +105719,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaa
@@ -105660,7 +105843,7 @@ cbm
byQ
bHK
cGU
-byQ
+bXN
bHK
bIu
bJh
@@ -105793,7 +105976,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaa
@@ -106050,7 +106233,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaa
@@ -106307,7 +106490,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaa
@@ -106564,7 +106747,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaa
@@ -106821,7 +107004,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaa
@@ -107078,7 +107261,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaa
@@ -107191,11 +107374,11 @@ cIA
cIP
cIY
cJf
-cJg
-cNC
-bZo
-bZs
-bXN
+bGu
+bHi
+bJU
+bOn
+bOp
bJp
bJp
cyT
@@ -107335,7 +107518,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaa
@@ -107592,7 +107775,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaU
@@ -107849,7 +108032,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaa
@@ -108104,9 +108287,9 @@ aaa
aaa
aaa
aaU
-aar
+aaU
aTd
-aWj
+aaU
aaU
aaU
aaU
@@ -108363,7 +108546,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaa
@@ -108620,7 +108803,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaa
@@ -108877,7 +109060,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaa
@@ -109013,7 +109196,7 @@ bme
bme
bme
bme
-bOn
+cnG
bme
bOo
aaa
@@ -109134,7 +109317,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaa
@@ -109272,7 +109455,7 @@ bOe
bOi
cnd
bOl
-bOp
+cnH
aaa
aaa
aaa
@@ -109391,7 +109574,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaa
@@ -109648,7 +109831,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aae
aaa
aaa
@@ -109786,7 +109969,7 @@ bme
bOh
cne
bOm
-bOp
+cnH
aaa
aaa
aaa
@@ -109905,7 +110088,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaa
@@ -110162,7 +110345,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaa
@@ -110242,7 +110425,7 @@ bsz
aej
agc
agT
-cJq
+bFg
apm
aqS
arP
@@ -110419,7 +110602,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaa
@@ -110480,7 +110663,7 @@ bpH
ang
coh
cfy
-clO
+bvb
aRu
aSv
aSy
@@ -110498,7 +110681,7 @@ cxa
bPr
sVC
aNH
-bbQ
+bEr
cJA
aqO
anE
@@ -110676,7 +110859,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaa
@@ -110755,7 +110938,7 @@ cxb
bsz
aej
agC
-aoJ
+bEK
cJB
apm
aqT
@@ -110933,7 +111116,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaa
@@ -111188,9 +111371,9 @@ aaa
aaa
aaa
aaU
-aav
+aaU
aTd
-aWj
+aaU
aaU
aaU
aaU
@@ -111328,7 +111511,7 @@ bme
bOi
bOj
bOl
-bOp
+cnH
cnE
aaa
aaa
@@ -111447,7 +111630,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaa
@@ -111704,7 +111887,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaU
@@ -111842,7 +112025,7 @@ bOe
bOh
cnc
bOm
-bOp
+cnH
aaa
aaa
aaa
@@ -111961,7 +112144,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaa
@@ -111982,7 +112165,7 @@ afm
apT
adS
bEu
-ahN
+aif
afa
aha
ahx
@@ -112097,7 +112280,7 @@ bme
bme
bme
bme
-bOn
+cnG
bme
bOo
aaa
@@ -112218,7 +112401,7 @@ aaa
aaa
aaa
aaU
-aWj
+aaa
aaa
aaa
aaa
@@ -112239,7 +112422,7 @@ aiV
anv
aec
axS
-ahN
+aif
afK
ahb
ahx
@@ -112288,7 +112471,7 @@ bxP
arE
aMI
cgX
-chC
+bim
cik
bwW
bsT
@@ -112475,7 +112658,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
aaa
aaa
@@ -112496,7 +112679,7 @@ aja
aoM
aec
agi
-ahN
+aif
afK
ahc
ahx
@@ -112730,9 +112913,9 @@ aaa
aaa
aaa
aaU
-aav
aaU
-aWj
+aaU
+aaU
aaU
aaU
aaU
@@ -112753,7 +112936,7 @@ bEp
bEp
bEp
bEp
-ahN
+aif
afK
ahd
ahx
@@ -112798,8 +112981,8 @@ arE
att
cqr
arE
-byt
-bzo
+byv
+bAN
aMI
cgZ
cif
@@ -112987,9 +113170,9 @@ aaa
aaa
aaa
abp
-aav
+aaa
aTd
-aWj
+aaa
abp
aaa
aaa
@@ -113010,7 +113193,7 @@ ajS
aHj
bvm
ahP
-ahN
+aif
afK
afK
ahT
@@ -113055,7 +113238,7 @@ att
btP
bwo
arE
-byu
+bAd
arE
aMI
cha
@@ -113244,19 +113427,19 @@ aaa
aaa
aaa
aaU
-aav
aaU
-aWj
-aWj
-aWj
-aWj
-aWj
-aWj
-aWj
-aWj
-aWj
-aWj
-aWj
+aaU
+aaU
+aaU
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
+aaU
aaV
aaU
aaU
@@ -113267,7 +113450,7 @@ ahP
ahP
bzp
ahP
-ahN
+aif
aiB
afK
ahU
@@ -113306,13 +113489,13 @@ aYF
beQ
bjw
bwu
-bAd
-aMo
-aMG
-bVt
+bnl
bwp
-bvb
-byv
+bwM
+bxq
+byt
+byu
+bAz
ceQ
cgT
chc
@@ -113503,7 +113686,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
aaa
aaa
@@ -113524,7 +113707,7 @@ akn
aJR
bEg
ahP
-aif
+aoJ
ass
afK
afK
@@ -113760,7 +113943,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
aaa
aaa
@@ -114017,7 +114200,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
aaa
aaa
@@ -114274,7 +114457,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
aaa
aaa
@@ -114531,7 +114714,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
aaa
aaa
@@ -114788,7 +114971,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
aaa
aaa
@@ -115045,7 +115228,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
aaa
aaa
@@ -115302,7 +115485,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
aaa
aaa
@@ -115559,7 +115742,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
aaa
aaa
@@ -115816,7 +115999,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
aaa
aaa
@@ -116073,7 +116256,7 @@ aaa
aaU
aaa
aaU
-aWj
+aaa
aaU
aaa
aaa
@@ -116330,7 +116513,7 @@ aaa
aaU
aaa
ahv
-aWj
+aaa
aaU
aaa
aaa
@@ -116585,7 +116768,7 @@ aaa
aaa
aaa
aaU
-aav
+cnM
abM
acj
aaU
@@ -119537,13 +119720,13 @@ cjb
cxV
cyb
cyc
-cyd
-bFg
-bHR
-bHR
-bHR
-bJU
-bHR
+bVt
+bZo
+bZs
+bZs
+bZs
+ciA
+clO
bHR
bLb
boK
diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index 1b7b9c7414..53ca9a72b0 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -1464,19 +1464,7 @@
/obj/structure/cable{
icon_state = "4-8"
},
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 8
- },
-/obj/machinery/door/airlock/external{
- name = "External Solar Access";
- req_access_txt = "10; 13"
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 8
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 4
- },
+/obj/effect/turf_decal/delivery,
/turf/open/floor/plasteel,
/area/maintenance/solars/starboard/fore)
"acQ" = (
@@ -17256,19 +17244,7 @@
/obj/structure/cable{
icon_state = "4-8"
},
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 4
- },
-/obj/machinery/door/airlock/external{
- name = "External Solar Access";
- req_one_access_txt = "13; 24; 10"
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 8
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 4
- },
+/obj/effect/turf_decal/delivery,
/turf/open/floor/plasteel,
/area/maintenance/solars/port/fore)
"aIk" = (
@@ -25107,14 +25083,8 @@
/turf/open/floor/plasteel/dark,
/area/security/execution/education)
"aUK" = (
-/obj/effect/mapping_helpers/airlock/cyclelink_helper,
-/obj/machinery/door/airlock/external{
- name = "Security External Airlock";
- req_access_txt = "63"
- },
-/obj/effect/turf_decal/stripes/line,
-/obj/effect/turf_decal/stripes/line{
- dir = 1
+/obj/structure/sign/warning/vacuum/external{
+ pixel_x = 32
},
/turf/open/floor/plating,
/area/security/prison)
@@ -43327,21 +43297,16 @@
/turf/open/floor/plasteel/dark,
/area/ai_monitored/turret_protected/ai)
"bzd" = (
-/obj/effect/decal/cleanable/dirt,
-/obj/effect/decal/cleanable/cobweb,
-/obj/structure/closet/emcloset/anchored,
-/obj/effect/turf_decal/delivery,
-/turf/open/floor/plasteel,
-/area/engine/gravity_generator)
+/obj/structure/lattice,
+/turf/closed/wall,
+/area/construction/mining/aux_base)
"bze" = (
-/obj/effect/decal/cleanable/dirt,
/obj/effect/turf_decal/bot,
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
"bzf" = (
-/obj/machinery/light/small{
- dir = 4
- },
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/closet/emcloset/anchored,
/obj/effect/turf_decal/delivery,
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
@@ -44447,122 +44412,83 @@
/turf/open/floor/plasteel/dark,
/area/engine/gravity_generator)
"bAI" = (
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 6
- },
-/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
- },
-/turf/open/floor/plasteel/dark,
-/area/engine/gravity_generator)
-"bAJ" = (
-/obj/structure/cable/white{
- icon_state = "0-2"
- },
-/obj/effect/spawner/structure/window/reinforced,
-/obj/structure/sign/warning/electricshock{
- pixel_y = 32
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
-/turf/open/floor/plating,
-/area/engine/gravity_generator)
-"bAK" = (
-/obj/effect/decal/cleanable/dirt,
-/obj/machinery/light{
- dir = 1
- },
-/obj/machinery/status_display/evac{
- pixel_y = 32
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 9
- },
-/turf/open/floor/plasteel,
-/area/engine/gravity_generator)
-"bAL" = (
-/obj/machinery/power/apc/highcap/five_k{
- areastring = "/area/engine/gravity_generator";
- dir = 1;
- name = "Gravity Generator APC";
- pixel_y = 24
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
-/obj/structure/cable{
- icon_state = "0-2"
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 1
- },
-/turf/open/floor/plasteel,
-/area/engine/gravity_generator)
-"bAM" = (
-/obj/machinery/power/terminal{
- dir = 4
- },
-/obj/item/radio/intercom{
- name = "Station Intercom";
- pixel_y = 26
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 10
- },
-/obj/structure/cable/white{
- icon_state = "0-2"
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 5
- },
-/turf/open/floor/plasteel,
-/area/engine/gravity_generator)
-"bAN" = (
-/obj/effect/decal/cleanable/dirt,
-/obj/effect/decal/cleanable/cobweb/cobweb2,
-/obj/machinery/power/smes{
- charge = 5e+006
- },
-/obj/structure/sign/nanotrasen{
- pixel_y = 32
- },
-/obj/structure/extinguisher_cabinet{
- pixel_x = 26
- },
-/obj/structure/cable{
- icon_state = "0-2"
- },
+/obj/structure/closet/firecloset,
/obj/effect/turf_decal/bot,
/turf/open/floor/plasteel,
-/area/engine/gravity_generator)
-"bAO" = (
-/turf/closed/wall,
-/area/engine/gravity_generator)
-"bAP" = (
-/obj/machinery/door/firedoor,
+/area/construction/mining/aux_base)
+"bAJ" = (
+/obj/structure/reagent_dispensers/watertank,
+/obj/effect/turf_decal/bot,
+/turf/open/floor/plasteel,
+/area/construction/mining/aux_base)
+"bAK" = (
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 1
+ dir = 8
},
/obj/machinery/door/airlock/external{
- name = "External Airlock";
- req_access_txt = "13"
+ name = "External Solar Access";
+ req_access_txt = "10; 13"
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 8
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/maintenance/solars/starboard/fore)
+"bAL" = (
+/obj/structure/lattice/catwalk,
+/obj/structure/cable{
+ icon_state = "0-4"
+ },
+/turf/open/space,
+/area/solar/port/fore)
+"bAM" = (
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 4
+ },
+/obj/machinery/door/airlock/external{
+ name = "External Solar Access";
+ req_one_access_txt = "13; 24; 10"
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 8
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/maintenance/solars/port/fore)
+"bAN" = (
+/obj/effect/mapping_helpers/airlock/cyclelink_helper,
+/obj/machinery/door/airlock/external{
+ name = "Security External Airlock";
+ req_access_txt = "63"
},
-/obj/effect/decal/cleanable/dirt,
/obj/effect/turf_decal/stripes/line,
/obj/effect/turf_decal/stripes/line{
dir = 1
},
+/turf/open/floor/plating,
+/area/security/prison)
+"bAO" = (
+/obj/machinery/light/small{
+ dir = 4
+ },
+/obj/effect/turf_decal/delivery,
+/obj/structure/reagent_dispensers/fueltank,
+/turf/open/floor/plasteel,
+/area/engine/gravity_generator)
+"bAP" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/bot,
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
"bAQ" = (
@@ -45609,7 +45535,7 @@
},
/turf/open/floor/circuit/green,
/area/ai_monitored/turret_protected/ai)
-"bCw" = (
+"bCx" = (
/obj/effect/turf_decal/bot_white/right,
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -45623,37 +45549,9 @@
},
/turf/open/floor/plasteel/dark,
/area/engine/gravity_generator)
-"bCx" = (
-/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
- },
-/turf/open/floor/plasteel/dark,
-/area/engine/gravity_generator)
-"bCy" = (
-/obj/effect/turf_decal/bot_white/left,
-/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
- },
-/turf/open/floor/plasteel/dark,
-/area/engine/gravity_generator)
"bCz" = (
-/obj/machinery/atmospherics/components/unary/vent_pump/on{
- dir = 1
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 6
},
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -45668,26 +45566,91 @@
/turf/open/floor/plasteel/dark,
/area/engine/gravity_generator)
"bCA" = (
-/obj/structure/cable/white,
/obj/structure/cable/white{
icon_state = "0-2"
},
/obj/effect/spawner/structure/window/reinforced,
+/obj/structure/sign/warning/electricshock{
+ pixel_y = 32
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
/turf/open/floor/plating,
/area/engine/gravity_generator)
"bCB" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/light{
+ dir = 1
+ },
+/obj/machinery/status_display/evac{
+ pixel_y = 32
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
/obj/effect/turf_decal/stripes/line{
- dir = 8
+ dir = 9
},
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
"bCC" = (
-/obj/machinery/atmospherics/components/unary/vent_pump/on{
+/obj/machinery/power/apc/highcap/five_k{
+ areastring = "/area/engine/gravity_generator";
+ dir = 1;
+ name = "Gravity Generator APC";
+ pixel_y = 24
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
/obj/structure/cable{
- icon_state = "1-4"
+ icon_state = "0-2"
},
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/turf/open/floor/plasteel,
+/area/engine/gravity_generator)
+"bCD" = (
+/obj/machinery/power/terminal{
+ dir = 4
+ },
+/obj/item/radio/intercom{
+ name = "Station Intercom";
+ pixel_y = 26
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 10
+ },
+/obj/structure/cable/white{
+ icon_state = "0-2"
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 5
+ },
+/turf/open/floor/plasteel,
+/area/engine/gravity_generator)
+"bCE" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/cobweb/cobweb2,
+/obj/machinery/power/smes{
+ charge = 5e+006
+ },
+/obj/structure/sign/nanotrasen{
+ pixel_y = 32
+ },
+/obj/structure/extinguisher_cabinet{
+ pixel_x = 26
+ },
+/obj/structure/cable{
+ icon_state = "0-2"
+ },
+/obj/effect/turf_decal/bot,
+/turf/open/floor/plasteel,
+/area/engine/gravity_generator)
+"bCF" = (
+/obj/effect/turf_decal/bot_white/left,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -45698,80 +45661,26 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
-/turf/open/floor/plasteel,
-/area/engine/gravity_generator)
-"bCD" = (
-/obj/effect/decal/cleanable/dirt,
-/obj/machinery/atmospherics/pipe/manifold/supply/hidden,
-/obj/structure/cable{
- icon_state = "4-8"
- },
-/obj/structure/cable/white{
- icon_state = "1-2"
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 4
- },
-/turf/open/floor/plasteel,
-/area/engine/gravity_generator)
-"bCE" = (
-/obj/effect/decal/cleanable/dirt,
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
-/obj/structure/cable{
- icon_state = "1-8"
- },
-/obj/effect/turf_decal/bot,
-/turf/open/floor/plasteel,
-/area/engine/gravity_generator)
-"bCF" = (
-/obj/structure/sign/warning/radiation,
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
-/turf/closed/wall/r_wall,
-/area/engine/gravity_generator)
-"bCG" = (
-/obj/effect/decal/cleanable/dirt,
-/obj/machinery/airalarm{
- pixel_y = 23
- },
-/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
- dir = 1
- },
-/obj/machinery/camera{
- c_tag = "Engineering - Gravity Generator Foyer";
- dir = 4;
- name = "engineering camera"
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 9
- },
-/turf/open/floor/plasteel,
+/turf/open/floor/plasteel/dark,
/area/engine/gravity_generator)
"bCH" = (
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
+/obj/machinery/door/firedoor,
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 1
+ },
+/obj/machinery/door/airlock/external{
+ name = "External Airlock";
+ req_access_txt = "13"
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/stripes/line,
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
},
-/obj/effect/turf_decal/delivery,
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
"bCI" = (
-/obj/structure/closet/radiation,
-/obj/machinery/light/small{
- dir = 1
- },
-/obj/structure/extinguisher_cabinet{
- pixel_x = 26
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 5
- },
-/turf/open/floor/plasteel,
+/turf/closed/wall,
/area/engine/gravity_generator)
"bCJ" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
@@ -45784,9 +45693,6 @@
icon_state = "0-4"
},
/obj/effect/spawner/structure/window/reinforced,
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
/turf/open/floor/plating,
/area/engine/break_room)
"bCL" = (
@@ -45801,13 +45707,13 @@
/obj/structure/cable/white{
icon_state = "2-8"
},
-/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
- dir = 1
- },
/obj/effect/turf_decal/stripes/line,
/obj/effect/turf_decal/stripes/line{
dir = 1
},
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 6
+ },
/turf/open/floor/plasteel,
/area/engine/break_room)
"bCM" = (
@@ -47193,11 +47099,8 @@
/turf/open/floor/circuit/green,
/area/ai_monitored/turret_protected/ai)
"bEn" = (
-/obj/machinery/light{
- dir = 8
- },
-/obj/structure/sign/warning/radiation{
- pixel_x = -32
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 1
},
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -47212,112 +47115,124 @@
/turf/open/floor/plasteel/dark,
/area/engine/gravity_generator)
"bEo" = (
-/turf/open/floor/circuit/green,
-/area/engine/gravity_generator)
-"bEp" = (
-/obj/machinery/door/firedoor,
-/obj/machinery/door/airlock/command/glass{
- name = "Gravity Generator Chamber";
- req_access_txt = "19; 61"
+/obj/effect/turf_decal/bot_white,
+/obj/effect/turf_decal/tile/neutral{
+ dir = 1
},
-/obj/effect/turf_decal/stripes/line{
- dir = 8
- },
-/obj/effect/turf_decal/stripes/line{
+/obj/effect/turf_decal/tile/neutral,
+/obj/effect/turf_decal/tile/neutral{
dir = 4
},
-/obj/structure/cable/white{
- icon_state = "1-4"
+/obj/effect/turf_decal/tile/neutral{
+ dir = 8
},
-/obj/structure/cable/white{
- icon_state = "2-4"
- },
-/turf/open/floor/plasteel,
+/turf/open/floor/plasteel/dark,
/area/engine/gravity_generator)
"bEq" = (
/obj/effect/turf_decal/stripes/line{
dir = 8
},
-/obj/structure/cable/white{
- icon_state = "4-8"
- },
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
"bEr" = (
-/obj/machinery/holopad,
-/obj/effect/decal/cleanable/dirt,
-/obj/effect/turf_decal/bot,
-/obj/structure/cable/white{
- icon_state = "4-8"
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 4
+ },
+/obj/structure/cable{
+ icon_state = "1-4"
+ },
+/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
},
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
"bEs" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/pipe/manifold/supply/hidden,
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
/obj/structure/cable/white{
- icon_state = "1-4"
+ icon_state = "1-2"
},
/obj/effect/turf_decal/stripes/line{
dir = 4
},
-/obj/structure/cable/white{
- icon_state = "1-8"
- },
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
"bEt" = (
/obj/effect/decal/cleanable/dirt,
-/obj/structure/cable/white{
- icon_state = "4-8"
- },
-/obj/effect/turf_decal/delivery,
-/turf/open/floor/plasteel,
-/area/engine/gravity_generator)
-"bEu" = (
-/obj/machinery/door/firedoor,
-/obj/machinery/door/airlock/highsecurity{
- name = "Gravity Generator Room";
- req_access_txt = "19;23"
- },
-/obj/structure/cable/white{
- icon_state = "4-8"
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 8
- },
-/obj/effect/turf_decal/stripes/line{
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
-/turf/open/floor/plasteel,
-/area/engine/gravity_generator)
-"bEv" = (
-/obj/structure/cable/white{
- icon_state = "2-4"
- },
-/obj/structure/cable/white{
- icon_state = "2-8"
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/obj/effect/turf_decal/delivery,
-/turf/open/floor/plasteel,
-/area/engine/gravity_generator)
-"bEw" = (
-/obj/machinery/holopad,
-/obj/effect/decal/cleanable/dirt,
-/obj/structure/cable/white{
- icon_state = "4-8"
+/obj/structure/cable{
+ icon_state = "1-8"
},
/obj/effect/turf_decal/bot,
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
-"bEx" = (
+"bEu" = (
+/obj/structure/sign/warning/radiation,
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
+/turf/closed/wall/r_wall,
+/area/engine/gravity_generator)
+"bEv" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/airalarm{
+ pixel_y = 23
+ },
+/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
+ dir = 1
+ },
+/obj/machinery/camera{
+ c_tag = "Engineering - Gravity Generator Foyer";
+ dir = 4;
+ name = "engineering camera"
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 9
+ },
+/obj/structure/cable/white{
+ icon_state = "2-4"
+ },
+/turf/open/floor/plasteel,
+/area/engine/gravity_generator)
+"bEw" = (
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
+/obj/effect/turf_decal/delivery,
/obj/structure/cable/white{
icon_state = "4-8"
},
-/obj/effect/decal/cleanable/dirt,
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 6
+/turf/open/floor/plasteel,
+/area/engine/gravity_generator)
+"bEx" = (
+/obj/structure/closet/radiation,
+/obj/machinery/light/small{
+ dir = 1
+ },
+/obj/structure/extinguisher_cabinet{
+ pixel_x = 26
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 5
+ },
+/obj/structure/cable/white{
+ icon_state = "4-8"
},
-/obj/effect/turf_decal/delivery,
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
"bEy" = (
@@ -47330,9 +47245,6 @@
req_access_txt = "10"
},
/obj/effect/decal/cleanable/dirt,
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 4
- },
/obj/effect/turf_decal/stripes/line{
dir = 8
},
@@ -47342,18 +47254,21 @@
/obj/effect/mapping_helpers/airlock/cyclelink_helper{
dir = 4
},
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
/turf/open/floor/plasteel,
/area/engine/break_room)
"bEz" = (
/obj/structure/cable/white{
icon_state = "4-8"
},
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 4
- },
/obj/effect/turf_decal/stripes/end{
dir = 8
},
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
/turf/open/floor/plasteel,
/area/engine/break_room)
"bEA" = (
@@ -47363,27 +47278,26 @@
/obj/structure/cable/white{
icon_state = "4-8"
},
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 4
- },
/obj/effect/turf_decal/stripes/line,
/obj/effect/turf_decal/stripes/line{
dir = 1
},
+/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
+ dir = 4
+ },
/turf/open/floor/plasteel,
/area/engine/break_room)
"bEB" = (
/obj/structure/cable/white{
icon_state = "4-8"
},
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 4
- },
/obj/effect/turf_decal/stripes/line,
/obj/effect/turf_decal/stripes/line{
dir = 1
},
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 6
+ },
/turf/open/floor/plasteel,
/area/engine/break_room)
"bEC" = (
@@ -47393,25 +47307,25 @@
/obj/structure/cable/white{
icon_state = "4-8"
},
-/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
- dir = 1
- },
/obj/effect/turf_decal/stripes/line,
/obj/effect/turf_decal/stripes/line{
dir = 1
},
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
/turf/open/floor/plasteel,
/area/engine/break_room)
"bED" = (
+/obj/effect/turf_decal/stripes/end{
+ dir = 4
+ },
/obj/structure/cable/white{
icon_state = "4-8"
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
-/obj/effect/turf_decal/stripes/end{
- dir = 4
- },
/turf/open/floor/plasteel,
/area/engine/break_room)
"bEE" = (
@@ -48446,22 +48360,15 @@
/turf/open/floor/plasteel/dark,
/area/aisat)
"bFW" = (
-/obj/machinery/gravity_generator/main/station,
-/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
- },
-/turf/open/floor/plasteel/dark,
+/turf/open/floor/circuit/green,
/area/engine/gravity_generator)
"bFX" = (
-/obj/machinery/atmospherics/components/unary/vent_scrubber/on,
+/obj/machinery/light{
+ dir = 8
+ },
+/obj/structure/sign/warning/radiation{
+ pixel_x = -32
+ },
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -48475,89 +48382,89 @@
/turf/open/floor/plasteel/dark,
/area/engine/gravity_generator)
"bFY" = (
-/obj/effect/decal/cleanable/dirt,
/obj/effect/turf_decal/stripes/line{
dir = 8
},
+/obj/structure/cable/white{
+ icon_state = "4-8"
+ },
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
"bFZ" = (
-/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
- dir = 4
- },
-/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/machinery/holopad,
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/bot,
+/obj/structure/cable/white{
+ icon_state = "4-8"
},
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
"bGa" = (
-/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
- dir = 1
+/obj/structure/cable/white{
+ icon_state = "1-4"
},
/obj/effect/turf_decal/stripes/line{
dir = 4
},
+/obj/structure/cable/white{
+ icon_state = "1-8"
+ },
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
"bGb" = (
/obj/effect/decal/cleanable/dirt,
-/obj/machinery/power/port_gen/pacman,
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 4
- },
-/obj/effect/turf_decal/bot,
-/turf/open/floor/plasteel,
-/area/engine/gravity_generator)
-"bGc" = (
-/obj/structure/sign/warning/radiation,
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 4
- },
-/turf/closed/wall/r_wall,
-/area/engine/gravity_generator)
-"bGd" = (
/obj/structure/cable/white{
- icon_state = "1-2"
- },
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 4
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/obj/effect/turf_decal/stripes/line{
- dir = 10
- },
-/turf/open/floor/plasteel,
-/area/engine/gravity_generator)
-"bGe" = (
-/obj/machinery/status_display/evac{
- pixel_x = 32;
- pixel_y = -32
- },
-/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
- dir = 1
+ icon_state = "4-8"
},
/obj/effect/turf_decal/delivery,
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
-"bGf" = (
-/obj/structure/closet/radiation,
-/obj/effect/decal/cleanable/dirt,
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 9
+"bGc" = (
+/obj/machinery/door/firedoor,
+/obj/machinery/door/airlock/highsecurity{
+ name = "Gravity Generator Room";
+ req_access_txt = "19;23"
+ },
+/obj/structure/cable/white{
+ icon_state = "4-8"
},
-/obj/machinery/light/small,
/obj/effect/turf_decal/stripes/line{
+ dir = 8
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/engine/gravity_generator)
+"bGd" = (
+/obj/structure/cable/white{
+ icon_state = "2-8"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/obj/effect/turf_decal/delivery,
+/obj/structure/cable/white{
+ icon_state = "1-8"
+ },
+/turf/open/floor/plasteel,
+/area/engine/gravity_generator)
+"bGe" = (
+/obj/machinery/holopad,
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/bot,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 6
},
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
+"bGf" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/delivery,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
+/obj/machinery/light/small,
+/turf/open/floor/plasteel,
+/area/engine/gravity_generator)
"bGg" = (
/obj/machinery/firealarm{
dir = 4;
@@ -48565,6 +48472,9 @@
},
/obj/item/kirbyplants/random,
/obj/effect/turf_decal/delivery,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
/turf/open/floor/plasteel,
/area/engine/break_room)
"bGh" = (
@@ -48579,6 +48489,9 @@
/obj/effect/turf_decal/tile/yellow{
dir = 8
},
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
/turf/open/floor/plasteel/dark/corner,
/area/engine/break_room)
"bGi" = (
@@ -48586,15 +48499,16 @@
/obj/effect/turf_decal/tile/yellow{
dir = 8
},
+/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden,
/turf/open/floor/plasteel/dark/corner,
/area/engine/break_room)
"bGj" = (
-/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
- dir = 1
- },
/obj/effect/turf_decal/tile/yellow{
dir = 8
},
+/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
+ dir = 8
+ },
/turf/open/floor/plasteel/dark/corner,
/area/engine/break_room)
"bGk" = (
@@ -49624,9 +49538,7 @@
/turf/open/floor/plasteel/dark,
/area/ai_monitored/turret_protected/ai)
"bHN" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 5
- },
+/obj/machinery/atmospherics/components/unary/vent_scrubber/on,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -49641,68 +49553,50 @@
/area/engine/gravity_generator)
"bHO" = (
/obj/structure/cable/white,
+/obj/structure/cable/white{
+ icon_state = "0-2"
+ },
/obj/effect/spawner/structure/window/reinforced,
-/obj/structure/sign/warning/electricshock{
- pixel_y = -32
- },
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 4
- },
/turf/open/floor/plating,
/area/engine/gravity_generator)
"bHP" = (
-/obj/machinery/light,
-/obj/machinery/status_display/evac{
- pixel_y = -32
- },
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 4
- },
-/obj/machinery/camera{
- c_tag = "Engineering - Gravity Generator";
- dir = 1;
- name = "engineering camera"
- },
+/obj/effect/decal/cleanable/dirt,
/obj/effect/turf_decal/stripes/line{
- dir = 10
+ dir = 8
},
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
"bHQ" = (
-/obj/effect/decal/cleanable/dirt,
-/obj/machinery/airalarm{
- dir = 1;
- pixel_y = -22
- },
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
dir = 4
},
-/obj/effect/turf_decal/stripes/line,
+/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
+ },
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
"bHR" = (
-/obj/machinery/newscaster{
- pixel_y = -32
- },
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 9
+/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
+ dir = 1
},
/obj/effect/turf_decal/stripes/line{
- dir = 6
+ dir = 4
},
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
"bHS" = (
-/obj/machinery/firealarm{
- dir = 8;
- pixel_x = 24
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/power/port_gen/pacman,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
},
-/obj/machinery/light_switch{
- pixel_y = -26
- },
-/obj/structure/table/reinforced,
-/obj/item/stack/sheet/plasteel/twenty,
-/obj/item/wrench,
/obj/effect/turf_decal/bot,
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
@@ -49710,27 +49604,23 @@
/obj/structure/cable/white{
icon_state = "1-2"
},
-/obj/machinery/door/poddoor/preopen{
- id = "transitlock";
- name = "Transit Tube Lockdown Door"
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/obj/effect/turf_decal/stripes/line,
/obj/effect/turf_decal/stripes/line{
- dir = 1
+ dir = 10
},
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
"bHU" = (
-/obj/effect/decal/cleanable/dirt,
-/obj/machinery/door/poddoor/preopen{
- id = "transitlock";
- name = "Transit Tube Lockdown Door"
+/obj/machinery/status_display/evac{
+ pixel_x = 32;
+ pixel_y = -32
},
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/obj/effect/turf_decal/stripes/line,
-/obj/effect/turf_decal/stripes/line{
- dir = 1
+/obj/effect/turf_decal/delivery,
+/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
+ dir = 4
},
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
@@ -51017,27 +50907,30 @@
/obj/structure/cable/white{
icon_state = "1-2"
},
-/obj/machinery/door/airlock/hatch{
- name = "MiniSat Transit Tube Access";
- req_one_access_txt = "32;19"
+/obj/machinery/door/poddoor/preopen{
+ id = "transitlock";
+ name = "Transit Tube Lockdown Door"
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/obj/effect/turf_decal/tile/neutral{
+/obj/effect/turf_decal/stripes/line,
+/obj/effect/turf_decal/stripes/line{
dir = 1
},
-/obj/effect/turf_decal/tile/neutral,
-/obj/effect/turf_decal/tile/neutral{
- dir = 4
- },
-/obj/effect/turf_decal/tile/neutral{
- dir = 8
- },
-/turf/open/floor/plasteel/dark,
-/area/engine/transit_tube)
+/turf/open/floor/plasteel,
+/area/engine/gravity_generator)
"bJP" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/door/poddoor/preopen{
+ id = "transitlock";
+ name = "Transit Tube Lockdown Door"
+ },
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/turf/closed/wall/r_wall,
-/area/engine/transit_tube)
+/obj/effect/turf_decal/stripes/line,
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/turf/open/floor/plasteel,
+/area/engine/gravity_generator)
"bJQ" = (
/obj/item/kirbyplants/random,
/obj/effect/turf_decal/tile/neutral{
@@ -52186,50 +52079,54 @@
/turf/closed/wall/r_wall,
/area/engine/transit_tube)
"bLG" = (
-/obj/structure/closet/emcloset/anchored,
-/obj/effect/turf_decal/tile/neutral{
- dir = 1
+/obj/machinery/door/firedoor,
+/obj/machinery/door/airlock/command/glass{
+ name = "Gravity Generator Chamber";
+ req_access_txt = "19; 61"
},
-/obj/effect/turf_decal/tile/neutral,
-/obj/effect/turf_decal/tile/neutral{
- dir = 4
- },
-/obj/effect/turf_decal/tile/neutral{
+/obj/effect/turf_decal/stripes/line{
dir = 8
},
-/turf/open/floor/plasteel/dark,
-/area/engine/transit_tube)
-"bLH" = (
-/obj/machinery/status_display/evac,
-/turf/closed/wall,
-/area/engine/transit_tube)
-"bLI" = (
-/obj/machinery/power/apc/highcap/five_k{
- areastring = "/area/engine/transit_tube";
- dir = 1;
- name = "Transit Tube Access APC";
- pixel_y = 24
- },
-/obj/machinery/atmospherics/components/unary/vent_pump/on,
-/obj/effect/turf_decal/tile/neutral{
- dir = 1
- },
-/obj/effect/turf_decal/tile/neutral,
-/obj/effect/turf_decal/tile/neutral{
+/obj/effect/turf_decal/stripes/line{
dir = 4
},
-/obj/effect/turf_decal/tile/neutral{
- dir = 8
- },
/obj/structure/cable/white{
- icon_state = "0-4"
+ icon_state = "1-4"
+ },
+/obj/structure/cable/white{
+ icon_state = "2-4"
+ },
+/turf/open/floor/plasteel,
+/area/engine/gravity_generator)
+"bLH" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
+/turf/closed/wall,
+/area/engine/break_room)
+"bLI" = (
+/obj/machinery/gravity_generator/main/station,
+/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
},
/turf/open/floor/plasteel/dark,
-/area/engine/transit_tube)
+/area/engine/gravity_generator)
"bLJ" = (
/obj/structure/cable/white{
icon_state = "1-2"
},
+/obj/machinery/door/airlock/hatch{
+ name = "MiniSat Transit Tube Access";
+ req_one_access_txt = "32;19"
+ },
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -52241,35 +52138,11 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
-/obj/structure/cable/white{
- icon_state = "1-8"
- },
/turf/open/floor/plasteel/dark,
/area/engine/transit_tube)
"bLK" = (
-/obj/item/kirbyplants/random,
-/obj/machinery/firealarm{
- dir = 8;
- pixel_x = 24
- },
-/obj/machinery/button/door{
- id = "transitlock";
- name = "Transit Tube Lockdown Control";
- pixel_y = 26;
- req_access_txt = "39; 19"
- },
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/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
- },
-/turf/open/floor/plasteel/dark,
+/turf/closed/wall/r_wall,
/area/engine/transit_tube)
"bLL" = (
/obj/item/kirbyplants/random,
@@ -53595,29 +53468,14 @@
/turf/open/space,
/area/space/nearstation)
"bNH" = (
-/obj/structure/lattice/catwalk,
-/obj/structure/cable/white{
- icon_state = "2-4"
+/obj/structure/sign/warning/radiation,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
},
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 6
- },
-/turf/open/space,
-/area/space/nearstation)
+/turf/closed/wall/r_wall,
+/area/engine/gravity_generator)
"bNI" = (
-/obj/structure/cable/white{
- icon_state = "4-8"
- },
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 4
- },
-/obj/machinery/door/airlock/hatch{
- name = "MiniSat Exterior Access";
- req_one_access_txt = "32;19"
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
+/obj/structure/closet/emcloset/anchored,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -53631,12 +53489,6 @@
/turf/open/floor/plasteel/dark,
/area/engine/transit_tube)
"bNJ" = (
-/obj/structure/cable/white{
- icon_state = "4-8"
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -53647,39 +53499,21 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
+/obj/structure/closet/firecloset,
/turf/open/floor/plasteel/dark,
/area/engine/transit_tube)
"bNK" = (
-/obj/structure/cable/white{
- icon_state = "4-8"
- },
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 8
- },
-/obj/machinery/door/airlock/hatch{
- name = "MiniSat Exterior Access";
- req_one_access_txt = "32;19"
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
-/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
- },
-/turf/open/floor/plasteel/dark,
+/obj/machinery/status_display/evac,
+/turf/closed/wall,
/area/engine/transit_tube)
"bNL" = (
-/obj/structure/cable/white{
- icon_state = "4-8"
+/obj/machinery/power/apc/highcap/five_k{
+ areastring = "/area/engine/transit_tube";
+ dir = 1;
+ name = "Transit Tube Access APC";
+ pixel_y = 24
},
-/obj/machinery/atmospherics/pipe/manifold/supply/hidden,
+/obj/machinery/atmospherics/components/unary/vent_pump/on,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -53690,15 +53524,16 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
+/obj/structure/cable/white{
+ icon_state = "0-4"
+ },
/turf/open/floor/plasteel/dark,
/area/engine/transit_tube)
"bNM" = (
/obj/structure/cable/white{
- icon_state = "1-8"
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 9
+ icon_state = "1-2"
},
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -53709,11 +53544,22 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
+/obj/structure/cable/white{
+ icon_state = "1-8"
+ },
/turf/open/floor/plasteel/dark,
/area/engine/transit_tube)
"bNN" = (
-/obj/machinery/light/small{
- dir = 4
+/obj/item/kirbyplants/random,
+/obj/machinery/firealarm{
+ dir = 8;
+ pixel_x = 24
+ },
+/obj/machinery/button/door{
+ id = "transitlock";
+ name = "Transit Tube Lockdown Control";
+ pixel_y = 26;
+ req_access_txt = "39; 19"
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/effect/turf_decal/tile/neutral{
@@ -54901,9 +54747,38 @@
/turf/open/space,
/area/space/nearstation)
"bPL" = (
+/obj/structure/cable/white{
+ icon_state = "4-8"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
+/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/machinery/light/small,
-/obj/structure/sign/warning/vacuum{
- pixel_x = -32
+/turf/open/floor/plasteel/dark,
+/area/engine/transit_tube)
+"bPM" = (
+/obj/structure/cable/white{
+ icon_state = "4-8"
+ },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 8
+ },
+/obj/machinery/door/airlock/hatch{
+ name = "MiniSat Exterior Access";
+ req_one_access_txt = "32;19"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
},
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -54917,20 +54792,11 @@
},
/turf/open/floor/plasteel/dark,
/area/engine/transit_tube)
-"bPM" = (
-/turf/closed/wall,
-/area/engine/transit_tube)
"bPN" = (
-/obj/item/kirbyplants/random,
-/obj/machinery/airalarm{
- dir = 4;
- pixel_x = -23
- },
-/obj/machinery/flasher{
- id = "AI";
- pixel_x = -26;
- pixel_y = -26
+/obj/structure/cable/white{
+ icon_state = "4-8"
},
+/obj/machinery/atmospherics/pipe/manifold/supply/hidden,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -54944,6 +54810,9 @@
/turf/open/floor/plasteel/dark,
/area/engine/transit_tube)
"bPO" = (
+/obj/structure/cable/white{
+ icon_state = "1-8"
+ },
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -54954,15 +54823,16 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
+/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
+ dir = 4
+ },
/turf/open/floor/plasteel/dark,
/area/engine/transit_tube)
"bPP" = (
-/obj/item/kirbyplants/random,
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/obj/machinery/light_switch{
- pixel_x = 22;
- pixel_y = -10
+/obj/machinery/light/small{
+ dir = 4
},
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -56192,13 +56062,15 @@
/turf/open/space,
/area/space/nearstation)
"bRV" = (
-/obj/effect/spawner/structure/window/reinforced,
-/turf/open/floor/plating,
-/area/engine/transit_tube)
-"bRW" = (
-/obj/machinery/door/airlock/hatch{
- name = "MiniSat Transit Tube Access";
- req_one_access_txt = "32;19"
+/obj/item/kirbyplants/random,
+/obj/machinery/airalarm{
+ dir = 4;
+ pixel_x = -23
+ },
+/obj/machinery/flasher{
+ id = "AI";
+ pixel_x = -26;
+ pixel_y = -26
},
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -56212,10 +56084,38 @@
},
/turf/open/floor/plasteel/dark,
/area/engine/transit_tube)
+"bRW" = (
+/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/machinery/atmospherics/pipe/simple/supply/hidden,
+/turf/open/floor/plasteel/dark,
+/area/engine/transit_tube)
"bRX" = (
-/obj/effect/spawner/structure/window/reinforced,
+/obj/item/kirbyplants/random,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/turf/open/floor/plating,
+/obj/machinery/light_switch{
+ pixel_x = 22;
+ pixel_y = -10
+ },
+/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
+ },
+/turf/open/floor/plasteel/dark,
/area/engine/transit_tube)
"bRY" = (
/obj/machinery/keycard_auth{
@@ -57376,22 +57276,9 @@
/turf/open/space,
/area/space/nearstation)
"bTL" = (
-/obj/structure/window/reinforced{
- dir = 8
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 5
},
-/obj/structure/table/reinforced,
-/obj/machinery/light/small{
- dir = 1
- },
-/obj/machinery/camera{
- c_tag = "AI Satellite - Transit Tube";
- name = "ai camera";
- network = list("minisat");
- start_active = 1
- },
-/obj/item/clipboard,
-/obj/item/folder/blue,
-/obj/item/pen,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -57403,30 +57290,16 @@
dir = 8
},
/turf/open/floor/plasteel/dark,
-/area/engine/transit_tube)
+/area/engine/gravity_generator)
"bTM" = (
-/obj/structure/chair/office/dark{
- dir = 8
- },
-/obj/machinery/flasher{
- id = "AI";
- pixel_x = -26;
- pixel_y = 26
- },
-/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
- },
-/turf/open/floor/plasteel/dark,
+/obj/effect/spawner/structure/window/reinforced,
+/turf/open/floor/plating,
/area/engine/transit_tube)
"bTN" = (
-/obj/machinery/atmospherics/components/unary/vent_scrubber/on,
+/obj/machinery/door/airlock/hatch{
+ name = "MiniSat Transit Tube Access";
+ req_one_access_txt = "32;19"
+ },
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -57437,22 +57310,13 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel/dark,
/area/engine/transit_tube)
"bTO" = (
-/obj/item/kirbyplants/random,
+/obj/effect/spawner/structure/window/reinforced,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/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
- },
-/turf/open/floor/plasteel/dark,
+/turf/open/floor/plating,
/area/engine/transit_tube)
"bTP" = (
/obj/machinery/computer/station_alert{
@@ -59145,9 +59009,6 @@
/turf/open/floor/plasteel/dark,
/area/engine/transit_tube)
"bWc" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 4
- },
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -59158,10 +59019,15 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
+/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
+ dir = 1
+ },
+/obj/structure/chair/office/light{
+ dir = 8
+ },
/turf/open/floor/plasteel/dark,
/area/engine/transit_tube)
"bWd" = (
-/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -59172,6 +59038,12 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 1
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
/turf/open/floor/plasteel/dark,
/area/engine/transit_tube)
"bWe" = (
@@ -60847,6 +60719,9 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
+/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
+ dir = 1
+ },
/turf/open/floor/plasteel/dark,
/area/engine/transit_tube)
"bYp" = (
@@ -72264,7 +72139,7 @@
pixel_y = 32
},
/turf/open/space,
-/area/space/nearstation)
+/area/space)
"crE" = (
/obj/structure/window/reinforced,
/obj/structure/window/reinforced{
@@ -83035,22 +82910,16 @@
/turf/open/floor/plasteel,
/area/crew_quarters/fitness/recreation)
"cJI" = (
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+/obj/structure/cable/white,
+/obj/effect/spawner/structure/window/reinforced,
+/obj/structure/sign/warning/electricshock{
+ pixel_y = -32
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
-/obj/machinery/door/airlock/external{
- name = "External Airlock";
- req_access_txt = "13"
- },
-/obj/effect/decal/cleanable/dirt,
-/obj/effect/turf_decal/stripes/line{
- dir = 8
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 4
- },
-/turf/open/floor/plasteel,
-/area/maintenance/port)
+/turf/open/floor/plating,
+/area/engine/gravity_generator)
"cJJ" = (
/obj/effect/mapping_helpers/airlock/cyclelink_helper{
dir = 8
@@ -108364,19 +108233,7 @@
/obj/structure/cable{
icon_state = "4-8"
},
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 8
- },
-/obj/machinery/door/airlock/external{
- name = "External Solar Access";
- req_access_txt = "10; 13"
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 8
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 4
- },
+/obj/effect/turf_decal/delivery,
/turf/open/floor/plasteel,
/area/maintenance/solars/starboard/aft)
"dBN" = (
@@ -115581,6 +115438,10 @@
/turf/open/floor/plasteel,
/area/maintenance/port/aft)
"dOc" = (
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plasteel,
+/area/maintenance/port/aft)
+"dOd" = (
/obj/effect/mapping_helpers/airlock/cyclelink_helper{
dir = 8
},
@@ -115597,11 +115458,6 @@
},
/turf/open/floor/plasteel,
/area/maintenance/port/aft)
-"dOd" = (
-/obj/effect/decal/cleanable/dirt,
-/obj/effect/turf_decal/delivery,
-/turf/open/floor/plasteel,
-/area/maintenance/port/aft)
"dOe" = (
/obj/effect/decal/cleanable/dirt,
/obj/effect/turf_decal/tile/neutral{
@@ -115610,6 +115466,7 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
+/obj/effect/turf_decal/delivery,
/turf/open/floor/plasteel{
heat_capacity = 1e+006
},
@@ -122648,19 +122505,7 @@
/obj/structure/cable{
icon_state = "4-8"
},
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 4
- },
-/obj/machinery/door/airlock/external{
- name = "External Solar Access";
- req_access_txt = "10; 13"
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 8
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 4
- },
+/obj/effect/turf_decal/delivery,
/turf/open/floor/plasteel,
/area/maintenance/solars/port/aft)
"ebE" = (
@@ -124004,14 +123849,16 @@
/turf/open/floor/plasteel/grimy,
/area/chapel/office)
"edX" = (
-/obj/machinery/door/airlock/maintenance_hatch{
- name = "Maintenance Hatch";
- req_access_txt = "12"
- },
/obj/effect/turf_decal/stripes/line,
/obj/effect/turf_decal/stripes/line{
dir = 1
},
+/obj/machinery/door/airlock/external{
+ name = "External Airlock";
+ req_access_txt = "13"
+ },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper,
+/obj/machinery/door/firedoor,
/turf/open/floor/plasteel,
/area/hallway/secondary/exit/departure_lounge)
"edY" = (
@@ -124731,16 +124578,6 @@
/turf/open/floor/carpet,
/area/chapel/office)
"eft" = (
-/obj/machinery/door/firedoor,
-/obj/effect/mapping_helpers/airlock/cyclelink_helper,
-/obj/machinery/door/airlock/external{
- name = "External Airlock";
- req_access_txt = "13"
- },
-/obj/effect/turf_decal/stripes/line,
-/obj/effect/turf_decal/stripes/line{
- dir = 1
- },
/turf/open/floor/plasteel,
/area/hallway/secondary/exit/departure_lounge)
"efu" = (
@@ -125581,6 +125418,24 @@
/obj/machinery/chem_dispenser/apothecary,
/turf/open/floor/plasteel/dark,
/area/medical/medbay/central)
+"eMb" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/closet/crate{
+ icon_state = "crateopen"
+ },
+/obj/item/flashlight,
+/obj/effect/spawner/lootdrop/maintenance,
+/obj/effect/turf_decal/tile/neutral{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/neutral{
+ dir = 4
+ },
+/obj/effect/turf_decal/bot,
+/turf/open/floor/plasteel{
+ heat_capacity = 1e+006
+ },
+/area/maintenance/port)
"eMD" = (
/obj/effect/decal/cleanable/dirt,
/obj/structure/cable/white{
@@ -125733,6 +125588,9 @@
},
/turf/closed/wall/r_wall,
/area/maintenance/disposal/incinerator)
+"fMf" = (
+/turf/closed/wall,
+/area/engine/transit_tube)
"fRK" = (
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -126016,6 +125874,24 @@
/obj/item/reagent_containers/glass/beaker,
/turf/open/floor/plating,
/area/crew_quarters/abandoned_gambling_den)
+"ikq" = (
+/obj/machinery/light,
+/obj/machinery/status_display/evac{
+ pixel_y = -32
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
+/obj/machinery/camera{
+ c_tag = "Engineering - Gravity Generator";
+ dir = 1;
+ name = "engineering camera"
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 10
+ },
+/turf/open/floor/plasteel,
+/area/engine/gravity_generator)
"imI" = (
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden,
/obj/effect/turf_decal/tile/neutral{
@@ -126143,6 +126019,25 @@
},
/turf/open/floor/plasteel/dark,
/area/science/mixing)
+"iUc" = (
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 4
+ },
+/obj/machinery/door/airlock/external{
+ name = "External Solar Access";
+ req_access_txt = "10; 13"
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 8
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/maintenance/solars/port/aft)
"jdx" = (
/obj/structure/lattice,
/obj/structure/grille,
@@ -126344,6 +126239,9 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plating,
/area/science/mixing)
+"jUu" = (
+/turf/closed/wall/r_wall,
+/area/space/nearstation)
"jYx" = (
/obj/effect/turf_decal/bot,
/obj/machinery/portable_atmospherics/canister/carbon_dioxide,
@@ -126736,6 +126634,20 @@
},
/turf/open/floor/plasteel/dark,
/area/science/mixing)
+"mte" = (
+/obj/machinery/firealarm{
+ dir = 8;
+ pixel_x = 24
+ },
+/obj/machinery/light_switch{
+ pixel_y = -26
+ },
+/obj/structure/table/reinforced,
+/obj/item/stack/sheet/plasteel/twenty,
+/obj/item/wrench,
+/obj/effect/turf_decal/bot,
+/turf/open/floor/plasteel,
+/area/engine/gravity_generator)
"mvm" = (
/obj/effect/decal/cleanable/dirt,
/obj/structure/cable/white{
@@ -126877,6 +126789,18 @@
},
/turf/open/floor/plasteel,
/area/maintenance/port/fore)
+"nYv" = (
+/obj/machinery/newscaster{
+ pixel_y = -32
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 9
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 6
+ },
+/turf/open/floor/plasteel,
+/area/engine/gravity_generator)
"odz" = (
/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
dir = 1
@@ -127171,6 +127095,25 @@
dir = 9
},
/area/science/circuit)
+"qhB" = (
+/obj/structure/cable/white{
+ icon_state = "4-8"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
+/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
+ },
+/turf/open/floor/plasteel/dark,
+/area/engine/transit_tube)
"qnx" = (
/obj/machinery/atmospherics/components/unary/outlet_injector/atmos/toxins_mixing_input,
/turf/open/floor/engine/vacuum,
@@ -127408,6 +127351,25 @@
},
/turf/open/floor/plasteel/grimy,
/area/library)
+"tML" = (
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 8
+ },
+/obj/machinery/door/airlock/external{
+ name = "External Solar Access";
+ req_access_txt = "10; 13"
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 8
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/maintenance/solars/starboard/aft)
"tNT" = (
/obj/effect/landmark/carpspawn,
/turf/open/space,
@@ -127653,6 +127615,32 @@
/obj/machinery/atmospherics/pipe/simple/green/visible,
/turf/open/floor/plasteel/dark,
/area/engine/atmos)
+"vFT" = (
+/obj/structure/cable/white{
+ icon_state = "4-8"
+ },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 4
+ },
+/obj/machinery/door/airlock/hatch{
+ name = "MiniSat Exterior Access";
+ req_one_access_txt = "32;19"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
+/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
+ },
+/turf/open/floor/plasteel/dark,
+/area/engine/transit_tube)
"vHN" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/effect/turf_decal/tile/neutral{
@@ -127688,6 +127676,18 @@
},
/turf/open/floor/plasteel,
/area/maintenance/port/aft)
+"vYo" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/airalarm{
+ dir = 1;
+ pixel_y = -22
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
+/obj/effect/turf_decal/stripes/line,
+/turf/open/floor/plasteel,
+/area/engine/gravity_generator)
"wei" = (
/obj/effect/turf_decal/stripes/line,
/turf/open/floor/plasteel,
@@ -127750,6 +127750,16 @@
/obj/effect/turf_decal/tile/purple,
/turf/open/floor/plasteel/white,
/area/science/misc_lab)
+"wFK" = (
+/obj/structure/lattice/catwalk,
+/obj/structure/cable/white{
+ icon_state = "2-4"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 6
+ },
+/turf/open/space,
+/area/space/nearstation)
"wZT" = (
/obj/effect/turf_decal/tile/neutral{
dir = 8
@@ -127972,6 +127982,23 @@
},
/turf/open/floor/plating,
/area/engine/atmos)
+"yja" = (
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 4
+ },
+/obj/machinery/door/airlock/external{
+ name = "External Airlock";
+ req_access_txt = "13"
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/stripes/line{
+ dir = 8
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/maintenance/port)
"yjc" = (
/obj/machinery/power/apc{
areastring = "/area/science/research/abandoned";
@@ -145314,12 +145341,12 @@ aaa
aaa
aaa
aaa
+aaa
ajr
ajr
aad
ajr
ajr
-ajr
aad
ajr
ajr
@@ -145571,11 +145598,11 @@ aaa
aaa
aaa
aaa
+aaa
ajr
aaa
aaa
aad
-aaa
aad
aaa
aad
@@ -145828,11 +145855,11 @@ aaa
aaa
aaa
aaa
+aaa
ajr
aad
ajr
ajr
-aad
ajr
ajr
ajr
@@ -146085,6 +146112,7 @@ aaa
aaa
aaa
aaa
+aaa
ajr
aaa
ajr
@@ -146096,7 +146124,6 @@ aad
aad
aad
aad
-aad
ajr
aaa
bNF
@@ -146342,6 +146369,7 @@ aaa
aaa
aaa
aaa
+aaa
aad
aaa
ajr
@@ -146352,12 +146380,11 @@ bxC
bxC
bxC
bxC
-bxC
-aad
+jUu
aad
aad
bNF
-aad
+qgU
bVZ
aad
aad
@@ -146599,20 +146626,20 @@ aaa
aaa
aaa
aaa
-ajr
-aad
-ajr
-aad
-bxC
-bAH
-bAH
-bEn
-bAH
-bAH
-bxC
-aad
-ajr
aaa
+ajr
+aad
+ajr
+aad
+bxC
+bAH
+bAH
+bFX
+bAH
+bAH
+jUu
+aad
+ajr
bNF
aaa
bVZ
@@ -146856,20 +146883,20 @@ aaa
aaa
aaa
aaa
+aaa
ajr
aaa
aad
aad
bxC
bAH
-bCw
bCx
-bCy
+bEo
+bCF
bAH
-bxC
+jUu
aad
ajr
-aaa
bNF
aaa
bVZ
@@ -146896,8 +146923,8 @@ cdB
cdB
cdB
car
-aad
-abj
+caE
+yja
caE
caE
cOj
@@ -147090,7 +147117,7 @@ aAP
aAP
avY
ask
-ask
+bAL
aad
abj
abj
@@ -147113,22 +147140,22 @@ aaa
aaa
aaa
aaa
+aaa
ajr
aad
ajr
aad
bxC
bAH
-bCx
bEo
bFW
+bLI
bAH
-bxC
-aad
+jUu
aad
aad
bNF
-aad
+qgU
bVY
aad
aad
@@ -147153,8 +147180,8 @@ car
car
car
car
-caE
-cJI
+eMb
+cqI
caE
cme
cOk
@@ -147346,9 +147373,9 @@ aad
aad
aad
aad
-aad
-apK
-aad
+aFp
+bAM
+aFp
aLb
aad
aaa
@@ -147370,20 +147397,20 @@ aaa
aaa
aaa
aaa
+aaa
aad
aaa
ajr
aad
bxC
bAH
-bCy
+bCF
+bEo
bCx
-bCw
bAH
-bxC
+jUu
aad
ajr
-aaa
bNF
aaa
bVZ
@@ -147628,19 +147655,19 @@ ajr
ajr
aad
ajr
+ajr
aad
ajr
aad
bxC
-bAI
bCz
+bEn
bAH
-bFX
bHN
-bxC
+bTL
+jUu
aad
aad
-aaa
bNF
aaa
bVZ
@@ -147888,18 +147915,18 @@ aad
aaa
aaa
aad
+aad
bxC
-bAJ
-bCA
-bEp
bCA
bHO
-bxC
+bLG
+bHO
+cJI
+jUu
aad
-bNH
-bPK
+wFK
bRU
-aad
+qgU
bVZ
aad
car
@@ -148145,18 +148172,18 @@ ajr
ajr
aad
aad
+aad
bxC
-bAK
bCB
bEq
bFY
bHP
-bxC
-aad
-bNF
-aad
-aad
-aad
+ikq
+bLF
+bLF
+vFT
+bLF
+qgU
bVZ
aad
car
@@ -148402,18 +148429,18 @@ aad
aad
aad
aad
+aad
bxC
-bAL
bCC
bEr
bFZ
bHQ
-bxC
+vYo
bLF
bNI
+qhB
bLF
-bLF
-aad
+qgU
bVZ
aad
car
@@ -148659,18 +148686,18 @@ aRF
aRF
aad
aad
+aad
bxC
-bAM
bCD
bEs
bGa
bHR
-bxC
-bLG
+nYv
+bLF
bNJ
bPL
bLF
-bTK
+qgU
bWa
bTK
car
@@ -148916,18 +148943,18 @@ bpO
aRF
aad
aad
+aad
bxC
-bAN
bCE
bEt
bGb
bHS
-bxC
-bLH
+mte
+bLF
bNK
bPM
+fMf
bLF
-bTL
bWb
bYn
car
@@ -149172,15 +149199,15 @@ bpO
btK
aRF
aad
+qgU
+qgU
bxC
bxC
-bxC
-bCF
bEu
bGc
+bNH
bxC
-bxC
-bLI
+bLF
bNL
bPN
bRV
@@ -149430,9 +149457,9 @@ btL
aRF
abj
bxC
-bzd
-bAO
-bCG
+bxC
+bxC
+bCI
bEv
bGd
bHT
@@ -150203,9 +150230,9 @@ aMG
bxE
bzg
bzg
-bCJ
-bEy
bzg
+bEy
+bLH
bHV
bJQ
bLL
@@ -154660,7 +154687,7 @@ aaa
aad
aad
aad
-ajr
+qgU
aad
ebC
aad
@@ -154918,9 +154945,9 @@ ajr
aad
aad
aad
-aad
-ebC
-aad
+eak
+iUc
+eak
aad
aaa
aac
@@ -169915,8 +169942,8 @@ aaa
aaa
aaa
aad
-aad
abi
+bAI
abR
abi
acp
@@ -170172,9 +170199,9 @@ aaa
aaa
aaa
abj
-abj
abH
abS
+abS
acd
acq
acH
@@ -170428,9 +170455,9 @@ aaa
aaa
aaa
aaa
-aaa
-aad
+qgU
abi
+bAJ
abT
abi
acr
@@ -170684,9 +170711,9 @@ aaa
aaa
aaa
aaa
-aaa
-aac
+jdx
aad
+bzd
abi
abi
ace
@@ -170941,8 +170968,8 @@ aaa
aaa
aaa
aaa
-aaa
-aac
+jdx
+aad
aad
aad
aad
@@ -171198,7 +171225,7 @@ aaa
aaa
aaa
aaa
-aaa
+aac
aac
aac
aad
@@ -172489,9 +172516,9 @@ aac
aaa
aad
aad
-aad
-acQ
-aad
+acf
+bAK
+acf
aad
aaa
abi
@@ -172745,7 +172772,7 @@ aaa
aac
aac
aad
-aac
+aad
aad
aaj
aad
@@ -182646,9 +182673,9 @@ aaA
aaa
aaa
aad
-aaa
-dBN
-aad
+dyV
+tML
+dyV
aad
aaa
aad
@@ -182902,9 +182929,9 @@ aci
aaA
aaa
aaa
-ajr
-aad
-dBO
+qgU
+qgU
+dBN
aad
aaa
dFy
@@ -184873,7 +184900,7 @@ aaa
ajr
ajr
ajr
-aaa
+qgU
aKZ
aKZ
aKZ
@@ -185130,9 +185157,9 @@ aaa
aaa
aaa
aaa
-aaa
-aaa
+qgU
abj
+bAN
aUK
aWs
aXT
@@ -185388,11 +185415,11 @@ aaa
aaa
aaa
aaa
-aaa
aad
aKV
aKV
aKV
+aKV
aZK
bbt
aNJ
diff --git a/_maps/map_files/KiloStation/KiloStation.dmm b/_maps/map_files/KiloStation/KiloStation.dmm
index e848fd87d1..518fa4e81e 100644
--- a/_maps/map_files/KiloStation/KiloStation.dmm
+++ b/_maps/map_files/KiloStation/KiloStation.dmm
@@ -2134,14 +2134,11 @@
/turf/open/floor/plasteel/dark,
/area/maintenance/port)
"adM" = (
-/obj/machinery/door/airlock/external{
- name = "Abandoned External Airlock"
- },
-/obj/effect/mapping_helpers/airlock/cyclelink_helper,
/obj/structure/cable{
icon_state = "1-2"
},
-/turf/open/floor/plasteel/dark,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plasteel,
/area/maintenance/fore)
"adN" = (
/obj/effect/turf_decal/loading_area{
@@ -2160,11 +2157,16 @@
/turf/open/floor/engine,
/area/ai_monitored/storage/satellite)
"adO" = (
+/obj/machinery/door/airlock/external{
+ name = "Satellite External Airlock";
+ req_one_access_txt = "32;19"
+ },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper,
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/structure/cable{
icon_state = "1-2"
},
-/turf/open/floor/engine,
+/turf/open/floor/plasteel/dark,
/area/ai_monitored/turret_protected/aisat/atmos)
"adP" = (
/obj/machinery/status_display/ai,
@@ -2513,6 +2515,9 @@
/turf/open/floor/plating,
/area/security/execution/education)
"aeD" = (
+/obj/structure/cable{
+ icon_state = "2-8"
+ },
/obj/structure/disposalpipe/segment,
/turf/open/floor/plating/airless,
/area/space/nearstation)
@@ -2598,13 +2603,20 @@
},
/obj/machinery/light/small,
/turf/open/floor/plating/airless,
-/area/maintenance/starboard/fore)
+/area/space/nearstation)
"aeL" = (
+/obj/machinery/door/airlock/external{
+ name = "Abandoned External Airlock"
+ },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper,
/obj/structure/cable{
- icon_state = "2-8"
+ icon_state = "1-2"
+ },
+/obj/structure/cable{
+ icon_state = "1-2"
},
/obj/structure/disposalpipe/segment,
-/turf/open/floor/plating/airless,
+/turf/open/floor/plasteel/dark,
/area/maintenance/starboard/fore)
"aeM" = (
/obj/machinery/photocopier,
@@ -5704,13 +5716,6 @@
/turf/open/floor/plasteel/dark,
/area/security/courtroom)
"ajI" = (
-/obj/machinery/door/airlock/external{
- name = "Abandoned External Airlock"
- },
-/obj/effect/mapping_helpers/airlock/cyclelink_helper,
-/obj/structure/cable{
- icon_state = "1-2"
- },
/obj/structure/cable{
icon_state = "1-2"
},
@@ -6935,7 +6940,6 @@
dir = 4
},
/obj/structure/closet/emcloset/anchored,
-/obj/effect/decal/cleanable/cobweb,
/obj/machinery/light/small{
dir = 8
},
@@ -9658,12 +9662,19 @@
/turf/open/floor/plasteel/showroomfloor,
/area/medical/genetics)
"aqp" = (
+/obj/machinery/door/airlock/external{
+ name = "Solar Maintenance";
+ req_access_txt = "10; 13"
+ },
/obj/structure/cable{
icon_state = "4-8"
},
-/obj/structure/lattice/catwalk,
-/turf/open/floor/plating/airless,
-/area/solar/port/fore)
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 4
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plating,
+/area/maintenance/solars/port/fore)
"aqq" = (
/obj/machinery/status_display/ai{
pixel_x = -32
@@ -12462,12 +12473,18 @@
/turf/open/floor/plasteel,
/area/bridge)
"auN" = (
+/obj/machinery/door/airlock/external{
+ name = "Solar Maintenance";
+ req_access_txt = "10; 13"
+ },
/obj/structure/cable{
icon_state = "4-8"
},
-/obj/structure/lattice/catwalk,
-/turf/open/floor/plating/airless,
-/area/solar/starboard/fore)
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 8
+ },
+/turf/open/floor/plating,
+/area/maintenance/solars/starboard/fore)
"auO" = (
/obj/effect/decal/cleanable/dirt,
/obj/structure/cable{
@@ -64779,11 +64796,15 @@
/turf/open/floor/plasteel/dark,
/area/hallway/primary/starboard)
"bZG" = (
-/obj/structure/sign/warning/vacuum/external{
- pixel_y = 32
+/obj/machinery/door/airlock/external{
+ name = "Abandoned External Airlock"
},
-/turf/open/floor/plating/airless,
-/area/space/nearstation)
+/obj/effect/mapping_helpers/airlock/cyclelink_helper,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/turf/open/floor/plasteel/dark,
+/area/maintenance/fore)
"bZH" = (
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -64902,9 +64923,18 @@
/turf/open/floor/plasteel,
/area/hallway/primary/starboard)
"bZP" = (
-/obj/structure/cable,
-/turf/open/floor/plating/airless,
-/area/space/nearstation)
+/obj/machinery/door/airlock/external{
+ name = "Prison External Airlock";
+ req_access_txt = "2"
+ },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 1
+ },
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/turf/open/floor/plasteel/dark,
+/area/security/prison)
"bZQ" = (
/obj/structure/closet/l3closet/janitor,
/obj/structure/window/reinforced,
@@ -67690,11 +67720,6 @@
},
/area/ai_monitored/turret_protected/ai)
"ceA" = (
-/obj/machinery/door/airlock/external{
- name = "Satellite External Airlock";
- req_one_access_txt = "32;19"
- },
-/obj/effect/mapping_helpers/airlock/cyclelink_helper,
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/structure/cable{
icon_state = "1-2"
@@ -69610,15 +69635,12 @@
/turf/open/floor/plasteel,
/area/engine/atmos)
"chO" = (
-/obj/structure/sign/warning/vacuum/external,
-/turf/closed/wall,
+/obj/structure/reagent_dispensers/fueltank,
+/turf/open/floor/plasteel/dark,
/area/ai_monitored/turret_protected/aisat/atmos)
"chP" = (
-/obj/structure/reagent_dispensers/watertank,
-/obj/structure/reagent_dispensers/watertank,
-/obj/effect/turf_decal/delivery,
-/obj/machinery/light,
-/turf/open/floor/plasteel/dark,
+/obj/structure/sign/warning/vacuum/external,
+/turf/closed/wall,
/area/ai_monitored/turret_protected/aisat/atmos)
"chQ" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
@@ -69697,12 +69719,19 @@
/turf/open/floor/plasteel,
/area/engine/engineering)
"chU" = (
+/obj/machinery/door/airlock/external{
+ name = "Solar Maintenance";
+ req_access_txt = "10; 13"
+ },
/obj/structure/cable{
icon_state = "4-8"
},
-/obj/structure/lattice/catwalk,
-/turf/open/floor/plating/airless,
-/area/solar/port/aft)
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 4
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plating,
+/area/maintenance/solars/port/aft)
"chW" = (
/obj/machinery/door/firedoor,
/obj/machinery/door/airlock/hatch{
@@ -71343,16 +71372,9 @@
/turf/open/floor/plating,
/area/engine/engineering)
"ckJ" = (
-/obj/machinery/door/airlock/external{
- name = "Solar Maintenance";
- req_access_txt = "10; 13"
- },
/obj/structure/cable{
icon_state = "4-8"
},
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 8
- },
/turf/open/floor/plating,
/area/maintenance/solars/starboard/aft)
"ckK" = (
@@ -71763,16 +71785,9 @@
/turf/open/space/basic,
/area/space/nearstation)
"clx" = (
-/obj/machinery/door/airlock/external{
- name = "Solar Maintenance";
- req_access_txt = "10; 13"
- },
/obj/structure/cable{
icon_state = "4-8"
},
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 4
- },
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plating,
/area/maintenance/solars/port/aft)
@@ -74873,6 +74888,9 @@
dir = 8
},
/obj/effect/decal/cleanable/dirt,
+/obj/structure/cable{
+ icon_state = "1-4"
+ },
/turf/open/floor/plating{
icon_state = "platingdmg1"
},
@@ -74942,6 +74960,9 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
/turf/open/floor/plasteel/dark,
/area/maintenance/disposal)
"crg" = (
@@ -76410,14 +76431,12 @@
/turf/open/floor/plating/airless,
/area/solar/starboard/aft)
"ctO" = (
-/obj/machinery/door/airlock/external{
- name = "External Airlock";
- req_access_txt = "13"
- },
/obj/structure/cable{
icon_state = "1-2"
},
-/turf/open/floor/plasteel/dark,
+/turf/open/floor/plating{
+ icon_state = "platingdmg1"
+ },
/area/maintenance/disposal)
"ctP" = (
/obj/structure/cable{
@@ -76438,16 +76457,9 @@
/turf/open/floor/plating/airless,
/area/solar/starboard/aft)
"ctS" = (
-/obj/machinery/door/airlock/external{
- name = "Solar Maintenance";
- req_access_txt = "10; 13"
- },
/obj/structure/cable{
icon_state = "4-8"
},
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 4
- },
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plating,
/area/maintenance/solars/port/fore)
@@ -77673,12 +77685,18 @@
/turf/open/floor/plating,
/area/maintenance/disposal)
"cwb" = (
+/obj/machinery/door/airlock/external{
+ name = "Solar Maintenance";
+ req_access_txt = "10; 13"
+ },
/obj/structure/cable{
icon_state = "4-8"
},
-/obj/structure/lattice/catwalk,
-/turf/open/floor/plating/airless,
-/area/solar/starboard/aft)
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 8
+ },
+/turf/open/floor/plating,
+/area/maintenance/solars/starboard/aft)
"cwc" = (
/obj/machinery/atmospherics/components/binary/pump/on,
/obj/machinery/airlock_sensor/incinerator_atmos{
@@ -77774,9 +77792,9 @@
/area/maintenance/starboard/aft)
"cwk" = (
/obj/structure/cable{
- icon_state = "1-2"
+ icon_state = "2-8"
},
-/turf/open/floor/plating/asteroid/airless,
+/turf/open/floor/plating/airless,
/area/space/nearstation)
"cwl" = (
/obj/structure/cable{
@@ -77954,13 +77972,6 @@
/turf/open/floor/plating,
/area/maintenance/starboard)
"cwD" = (
-/obj/machinery/door/airlock/external{
- name = "External Airlock";
- req_access_txt = "13"
- },
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 8
- },
/turf/open/floor/plasteel/dark,
/area/maintenance/starboard)
"cwE" = (
@@ -78131,6 +78142,9 @@
icon_state = "1-8"
},
/obj/effect/decal/cleanable/blood/old,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/plating,
/area/maintenance/disposal)
"cwQ" = (
@@ -78244,6 +78258,9 @@
dir = 4
},
/obj/effect/decal/cleanable/dirt,
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
/turf/open/floor/plating{
icon_state = "platingdmg3"
},
@@ -78301,6 +78318,9 @@
},
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/cleanable/blood/old,
+/obj/structure/cable{
+ icon_state = "2-8"
+ },
/turf/open/floor/plating,
/area/maintenance/disposal)
"cxh" = (
@@ -78340,6 +78360,9 @@
/area/maintenance/disposal)
"cxj" = (
/obj/effect/decal/cleanable/dirt,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/plating{
icon_state = "platingdmg3"
},
@@ -78387,17 +78410,21 @@
},
/area/maintenance/port/fore)
"cxp" = (
-/obj/structure/cable{
- icon_state = "1-4"
+/obj/machinery/door/airlock/external{
+ name = "External Airlock";
+ req_access_txt = "13"
},
-/turf/open/floor/plating/airless,
-/area/space/nearstation)
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/turf/open/floor/plasteel/dark,
+/area/maintenance/disposal)
"cxq" = (
-/obj/structure/cable{
- icon_state = "2-8"
+/obj/effect/decal/cleanable/cobweb,
+/turf/open/floor/plating{
+ icon_state = "platingdmg1"
},
-/turf/open/floor/plating/airless,
-/area/space/nearstation)
+/area/maintenance/fore)
"cxr" = (
/obj/structure/sign/poster/contraband/clown,
/turf/closed/wall/rust,
@@ -83810,16 +83837,9 @@
},
/area/maintenance/starboard)
"cMH" = (
-/obj/machinery/door/airlock/external{
- name = "Solar Maintenance";
- req_access_txt = "10; 13"
- },
/obj/structure/cable{
icon_state = "4-8"
},
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 8
- },
/turf/open/floor/plating,
/area/maintenance/solars/starboard/fore)
"cMI" = (
@@ -84487,13 +84507,6 @@
/turf/open/space/basic,
/area/space/nearstation)
"cUD" = (
-/obj/machinery/door/airlock/external{
- name = "Prison External Airlock";
- req_access_txt = "2"
- },
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 1
- },
/obj/structure/cable{
icon_state = "1-2"
},
@@ -84511,6 +84524,10 @@
icon_state = "wood-broken"
},
/area/security/vacantoffice)
+"dky" = (
+/obj/structure/cable,
+/turf/open/floor/plating/airless,
+/area/space/nearstation)
"dlg" = (
/obj/machinery/light,
/turf/open/floor/wood,
@@ -84662,6 +84679,12 @@
/obj/effect/decal/cleanable/cobweb/cobweb2,
/turf/closed/mineral/random/labormineral,
/area/space/nearstation)
+"fAn" = (
+/obj/structure/sign/warning/vacuum/external{
+ pixel_y = 32
+ },
+/turf/open/floor/plating/airless,
+/area/space/nearstation)
"fXq" = (
/obj/effect/turf_decal/tile/neutral{
dir = 8
@@ -85114,6 +85137,16 @@
/obj/structure/sign/poster/ripped,
/turf/closed/wall,
/area/crew_quarters/fitness/recreation)
+"lqz" = (
+/obj/machinery/door/airlock/external{
+ name = "External Airlock";
+ req_access_txt = "13"
+ },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 8
+ },
+/turf/open/floor/plasteel/dark,
+/area/maintenance/starboard)
"lKu" = (
/obj/structure/table/wood,
/obj/item/reagent_containers/food/drinks/soda_cans/thirteenloko,
@@ -85171,6 +85204,9 @@
},
/turf/open/floor/plasteel/dark,
/area/science/research)
+"mKj" = (
+/turf/closed/wall/rust,
+/area/security/execution/education)
"mKp" = (
/obj/structure/cable{
icon_state = "1-2"
@@ -85537,6 +85573,12 @@
icon_state = "wood-broken4"
},
/area/maintenance/port/fore)
+"yaV" = (
+/obj/structure/cable{
+ icon_state = "1-4"
+ },
+/turf/open/floor/plating/airless,
+/area/space/nearstation)
"ydo" = (
/obj/structure/cable{
icon_state = "4-8"
@@ -99350,9 +99392,9 @@ bTK
bVs
hNk
bXG
+abp
cZm
-bZG
-aeU
+fAn
aeU
aeU
aeU
@@ -99609,7 +99651,7 @@ cTF
bXH
cUD
bZP
-aeU
+dky
coy
aeU
aeU
@@ -99862,19 +99904,19 @@ aaG
aez
cIj
aeB
-cZm
+mKj
+aez
aez
aez
cko
cko
-cko
-aeU
aeU
aeU
aeU
aeU
+cnS
chU
-aeU
+cnS
aUz
aeU
aeu
@@ -100317,9 +100359,9 @@ aeu
aeU
aeU
aeU
-aeU
+ctH
aqp
-aeU
+ctH
aeu
aeu
aeu
@@ -112391,7 +112433,7 @@ aaa
aaa
aeU
aUz
-aeu
+adH
adH
adH
adH
@@ -112648,8 +112690,8 @@ aaa
aaa
acm
aeU
-aeU
adQ
+cxq
alN
chj
aoc
@@ -112905,7 +112947,7 @@ aeR
aeR
aes
aes
-aes
+bZG
adM
alO
amL
@@ -113162,7 +113204,7 @@ aaa
aaa
acm
aaa
-aaa
+adH
adH
adH
adQ
@@ -120603,9 +120645,9 @@ aaa
aaa
aaa
aaa
-aeU
aeK
baH
+baH
afb
baH
baH
@@ -124312,9 +124354,9 @@ cpb
crf
cnu
cnu
+cnu
cko
aeu
-aeu
aaa
aaa
aaa
@@ -124570,7 +124612,7 @@ cxg
cxj
ctO
cxp
-aeU
+yaV
ciQ
aeU
aaa
@@ -124826,7 +124868,7 @@ cnu
cnd
cnu
cnu
-cxq
+cnu
cwk
cxu
aeU
@@ -126360,9 +126402,9 @@ bzG
bzG
aeu
aeu
-aeU
+ckz
cwb
-aeU
+ckz
aeU
aUz
aeU
@@ -129382,9 +129424,9 @@ aaQ
aeo
aeo
acm
-acm
-acK
-acm
+bkd
+lqz
+bkd
aaa
aaa
aaa
@@ -129617,9 +129659,9 @@ aeu
aeu
aeu
aeu
-aeU
+cLM
auN
-aeU
+cLM
aeu
aeu
aeu
diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm
index 16659f3e7a..fdc313c30a 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -793,10 +793,16 @@
/turf/open/floor/plating,
/area/security/prison)
"abN" = (
-/turf/open/floor/plating{
- icon_state = "platingdmg3"
+/obj/machinery/door/airlock/external{
+ name = "Solar Maintenance";
+ req_access_txt = "10; 13"
},
-/area/security/prison)
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper,
+/turf/open/floor/plating,
+/area/maintenance/solars/port/fore)
"abO" = (
/obj/structure/cable{
icon_state = "1-4"
@@ -954,6 +960,9 @@
/area/security/prison)
"acg" = (
/obj/machinery/light/small,
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
+ },
/turf/open/floor/plating{
icon_state = "panelscorched"
},
@@ -962,18 +971,22 @@
/obj/effect/turf_decal/stripes/line{
dir = 4
},
-/turf/open/floor/plating,
-/area/security/prison)
-"aci" = (
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 4
+ },
/obj/machinery/door/airlock/external{
name = "Security External Airlock";
req_access_txt = "1"
},
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 4
- },
/turf/open/floor/plating,
/area/security/prison)
+"aci" = (
+/obj/structure/lattice/catwalk,
+/obj/machinery/door/airlock/external{
+ req_one_access_txt = "13,8"
+ },
+/turf/open/space,
+/area/maintenance/starboard/fore)
"acj" = (
/obj/machinery/light/small{
dir = 1
@@ -2047,14 +2060,12 @@
/turf/open/floor/plating,
/area/maintenance/solars/port/fore)
"aef" = (
-/obj/machinery/door/airlock/external{
- name = "Solar Maintenance";
- req_access_txt = "10; 13"
- },
/obj/structure/cable{
icon_state = "1-2"
},
-/obj/effect/mapping_helpers/airlock/cyclelink_helper,
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
/turf/open/floor/plating,
/area/maintenance/solars/port/fore)
"aeg" = (
@@ -2310,9 +2321,6 @@
/obj/structure/cable{
icon_state = "1-2"
},
-/obj/effect/turf_decal/stripes/line{
- dir = 1
- },
/turf/open/floor/plating,
/area/maintenance/solars/port/fore)
"aeH" = (
@@ -7006,15 +7014,6 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/closed/wall,
/area/crew_quarters/fitness/recreation)
-"amG" = (
-/obj/machinery/light/small{
- dir = 8
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 6
- },
-/turf/open/floor/plating,
-/area/maintenance/starboard/fore)
"amH" = (
/obj/machinery/door/airlock/external{
req_one_access_txt = "13,8"
@@ -11553,19 +11552,15 @@
/turf/open/floor/plating/airless,
/area/space/nearstation)
"avJ" = (
-/obj/machinery/door/airlock/external,
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 4
+/obj/structure/sign/warning/vacuum/external{
+ pixel_x = 32
},
/turf/open/floor/plating,
-/area/maintenance/port/fore)
+/area/maintenance/starboard/fore)
"avK" = (
/obj/structure/sign/warning/vacuum/external{
pixel_y = 32
},
-/obj/effect/turf_decal/stripes/line{
- dir = 8
- },
/turf/open/floor/plating,
/area/maintenance/port/fore)
"avL" = (
@@ -37959,12 +37954,8 @@
/turf/open/floor/wood,
/area/crew_quarters/heads/hop)
"bwl" = (
-/obj/machinery/door/airlock/hatch{
- name = "MiniSat Space Access Airlock";
- req_one_access_txt = "32;19"
- },
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 8
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
},
/turf/open/floor/plasteel/dark,
/area/engine/break_room)
@@ -38524,9 +38515,6 @@
/obj/machinery/light/small{
dir = 1
},
-/obj/effect/turf_decal/stripes/line{
- dir = 4
- },
/turf/open/floor/plasteel/dark,
/area/engine/break_room)
"bxn" = (
@@ -44779,7 +44767,7 @@
dir = 8
},
/turf/open/space,
-/area/aisat)
+/area/space/nearstation)
"bKR" = (
/obj/structure/window/reinforced{
dir = 8
@@ -46796,11 +46784,11 @@
/turf/open/floor/plasteel/showroomfloor,
/area/crew_quarters/kitchen)
"bOY" = (
-/obj/structure/sign/warning/vacuum/external{
- pixel_x = 32
+/obj/machinery/door/airlock/external{
+ req_access_txt = "13"
},
-/obj/effect/turf_decal/stripes/line{
- dir = 1
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 8
},
/turf/open/floor/plating,
/area/maintenance/starboard/fore)
@@ -53609,9 +53597,6 @@
/obj/machinery/light/small{
dir = 1
},
-/obj/effect/turf_decal/stripes/line{
- dir = 4
- },
/turf/open/floor/plating,
/area/engine/atmos)
"ccY" = (
@@ -54894,17 +54879,12 @@
/turf/open/space,
/area/solar/port/aft)
"cfA" = (
-/obj/structure/cable/yellow{
- icon_state = "4-8"
- },
-/obj/machinery/door/airlock/external{
- req_access_txt = "13"
- },
+/obj/machinery/door/airlock/external,
/obj/effect/mapping_helpers/airlock/cyclelink_helper{
dir = 4
},
/turf/open/floor/plating,
-/area/maintenance/port/aft)
+/area/maintenance/port/fore)
"cfB" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/structure/cable/yellow{
@@ -63173,12 +63153,9 @@
/turf/open/space,
/area/solar/port/aft)
"cvj" = (
-/obj/structure/closet/emcloset,
-/obj/structure/sign/warning/vacuum/external{
- pixel_x = -32
- },
-/turf/open/floor/plating,
-/area/maintenance/port/aft)
+/obj/structure/lattice,
+/turf/closed/wall/r_wall,
+/area/engine/break_room)
"cvk" = (
/obj/structure/closet/crate,
/obj/item/crowbar/red,
@@ -63664,7 +63641,10 @@
/turf/open/floor/plasteel,
/area/science/circuit)
"cwc" = (
-/obj/effect/turf_decal/stripes/line,
+/obj/machinery/door/airlock/external{
+ name = "Auxiliary Escape Airlock"
+ },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper,
/turf/open/floor/plating,
/area/maintenance/aft)
"cwd" = (
@@ -63693,9 +63673,14 @@
/obj/structure/cable/yellow{
icon_state = "4-8"
},
-/obj/structure/lattice/catwalk,
-/turf/open/space,
-/area/space/nearstation)
+/obj/machinery/door/airlock/external{
+ req_access_txt = "13"
+ },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 4
+ },
+/turf/open/floor/plating,
+/area/maintenance/port/aft)
"cwh" = (
/obj/structure/cable/yellow{
icon_state = "4-8"
@@ -70269,7 +70254,7 @@
pixel_x = -32
},
/turf/open/space,
-/area/space/nearstation)
+/area/space)
"cIz" = (
/obj/structure/disposalpipe/segment,
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
@@ -70553,18 +70538,20 @@
/obj/structure/cable/yellow{
icon_state = "4-8"
},
-/obj/effect/turf_decal/stripes/line{
- dir = 4
- },
/turf/open/floor/plating,
/area/maintenance/starboard/aft)
"cJf" = (
/obj/structure/cable/yellow{
- icon_state = "0-8"
+ icon_state = "4-8"
},
-/obj/structure/lattice/catwalk,
-/turf/open/space,
-/area/space/nearstation)
+/obj/machinery/door/airlock/external{
+ req_access_txt = "13"
+ },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 8
+ },
+/turf/open/floor/plating,
+/area/maintenance/starboard/aft)
"cJg" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/item/bedsheet/medical,
@@ -71813,6 +71800,7 @@
/obj/effect/turf_decal/stripes/line{
dir = 1
},
+/obj/effect/landmark/blobstart,
/turf/open/floor/plating,
/area/maintenance/aft)
"cLA" = (
@@ -72157,15 +72145,12 @@
/turf/open/floor/plasteel,
/area/hallway/secondary/exit/departure_lounge)
"cMk" = (
-/obj/machinery/power/apc/highcap/five_k{
- areastring = "/area/maintenance/aft";
- name = "Aft Maintenance APC";
- pixel_y = -24
+/obj/structure/window/reinforced{
+ dir = 1;
+ pixel_y = 1
},
-/obj/structure/cable/yellow,
-/obj/effect/turf_decal/stripes/line,
-/turf/open/floor/plating,
-/area/maintenance/aft)
+/turf/open/space,
+/area/space)
"cMl" = (
/obj/structure/table,
/obj/item/stack/sheet/glass/fifty{
@@ -72750,10 +72735,6 @@
/turf/open/floor/plasteel,
/area/hallway/secondary/exit/departure_lounge)
"cNe" = (
-/obj/machinery/door/airlock/external{
- name = "Auxiliary Escape Airlock"
- },
-/obj/effect/mapping_helpers/airlock/cyclelink_helper,
/turf/open/floor/plating,
/area/maintenance/aft)
"cNf" = (
@@ -76631,9 +76612,6 @@
/obj/structure/cable{
icon_state = "4-8"
},
-/obj/effect/turf_decal/stripes/line{
- dir = 4
- },
/turf/open/floor/plating,
/area/maintenance/solars/starboard/aft)
"dbR" = (
@@ -81171,10 +81149,6 @@
/obj/machinery/vr_sleeper,
/turf/open/floor/plasteel,
/area/crew_quarters/fitness/recreation)
-"evy" = (
-/obj/effect/spawner/structure/window/reinforced,
-/turf/open/floor/plating,
-/area/space)
"eEe" = (
/obj/machinery/atmospherics/components/unary/vent_pump/on{
dir = 8
@@ -81313,6 +81287,19 @@
},
/turf/open/floor/plating,
/area/maintenance/starboard/aft)
+"gsT" = (
+/obj/machinery/door/airlock/external{
+ name = "Solar Maintenance";
+ req_access_txt = "10; 13"
+ },
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 8
+ },
+/turf/open/floor/plating,
+/area/solar/starboard/aft)
"gEk" = (
/obj/structure/cable/yellow{
icon_state = "2-8"
@@ -81350,9 +81337,7 @@
/turf/open/floor/plasteel,
/area/science/misc_lab)
"gNe" = (
-/obj/machinery/light/small{
- dir = 8
- },
+/obj/effect/turf_decal/stripes/line,
/turf/open/floor/plating,
/area/maintenance/aft)
"gRS" = (
@@ -81526,13 +81511,6 @@
/obj/structure/cable{
icon_state = "1-2"
},
-/obj/machinery/door/airlock/external{
- name = "Solar Maintenance";
- req_access_txt = "10; 13"
- },
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 1
- },
/turf/open/floor/plating,
/area/maintenance/solars/port/aft)
"jAj" = (
@@ -81656,17 +81634,15 @@
/turf/open/floor/plasteel,
/area/hallway/secondary/exit/departure_lounge)
"kDM" = (
-/obj/structure/cable/yellow{
- icon_state = "4-8"
- },
-/obj/machinery/door/airlock/external{
- req_access_txt = "13"
+/obj/machinery/door/airlock/hatch{
+ name = "MiniSat Space Access Airlock";
+ req_one_access_txt = "32;19"
},
/obj/effect/mapping_helpers/airlock/cyclelink_helper{
dir = 8
},
-/turf/open/floor/plating,
-/area/maintenance/starboard/aft)
+/turf/open/floor/plasteel/dark,
+/area/engine/break_room)
"kJW" = (
/obj/machinery/atmospherics/components/binary/pump{
dir = 1;
@@ -81775,14 +81751,9 @@
/turf/open/space/basic,
/area/space/nearstation)
"lNZ" = (
-/obj/machinery/door/airlock/external{
- req_access_txt = "13"
- },
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 8
- },
-/turf/open/floor/plating,
-/area/maintenance/starboard/fore)
+/obj/structure/lattice/catwalk,
+/turf/closed/wall/r_wall,
+/area/engine/atmos)
"lOi" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
@@ -81902,6 +81873,12 @@
},
/turf/open/floor/plating,
/area/maintenance/port)
+"mSd" = (
+/obj/structure/cable/yellow{
+ icon_state = "4-8"
+ },
+/turf/open/floor/plating,
+/area/maintenance/port/aft)
"mWg" = (
/obj/structure/girder,
/obj/structure/grille,
@@ -82477,8 +82454,9 @@
/turf/open/floor/plasteel,
/area/science/circuit)
"sdw" = (
-/turf/open/space/basic,
-/area/space/nearstation)
+/obj/structure/window/reinforced,
+/turf/open/space,
+/area/space)
"siF" = (
/obj/structure/grille,
/turf/open/floor/plating/airless,
@@ -82576,6 +82554,12 @@
},
/turf/open/floor/plasteel/dark,
/area/crew_quarters/cryopod)
+"sUM" = (
+/obj/structure/sign/warning/vacuum/external{
+ pixel_x = -32
+ },
+/turf/open/floor/plating,
+/area/maintenance/port/aft)
"sZN" = (
/obj/structure/closet/firecloset,
/turf/open/floor/plating,
@@ -82662,6 +82646,13 @@
/obj/machinery/cryopod,
/turf/open/floor/plasteel/dark,
/area/crew_quarters/cryopod)
+"uim" = (
+/obj/structure/cable/yellow{
+ icon_state = "0-8"
+ },
+/obj/structure/lattice/catwalk,
+/turf/open/space,
+/area/space/nearstation)
"uku" = (
/obj/machinery/atmospherics/pipe/manifold4w/general/visible,
/turf/open/floor/plasteel,
@@ -82853,12 +82844,8 @@
/turf/open/floor/plating,
/area/maintenance/port/aft)
"wxc" = (
-/obj/machinery/door/airlock/external{
- name = "Atmospherics External Airlock";
- req_access_txt = "24"
- },
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 8
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
},
/turf/open/floor/plating,
/area/engine/atmos)
@@ -82869,10 +82856,13 @@
/turf/open/floor/plating,
/area/crew_quarters/cryopod)
"wFH" = (
-/obj/structure/cable/yellow{
- icon_state = "1-2"
+/obj/machinery/power/apc/highcap/five_k{
+ areastring = "/area/maintenance/aft";
+ name = "Aft Maintenance APC";
+ pixel_y = -24
},
-/obj/effect/landmark/blobstart,
+/obj/structure/cable/yellow,
+/obj/effect/turf_decal/stripes/line,
/turf/open/floor/plating,
/area/maintenance/starboard/aft)
"wKo" = (
@@ -82880,8 +82870,15 @@
/turf/closed/wall,
/area/science/circuit)
"wOE" = (
+/obj/machinery/door/airlock/external{
+ name = "Atmospherics External Airlock";
+ req_access_txt = "24"
+ },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 8
+ },
/turf/open/floor/plating,
-/area/maintenance/aft)
+/area/engine/atmos)
"wOY" = (
/obj/structure/fans/tiny/invisible,
/turf/open/space/basic,
@@ -82940,15 +82937,11 @@
/turf/open/floor/plasteel,
/area/hallway/primary/port)
"xse" = (
-/obj/machinery/door/airlock/external{
- name = "Solar Maintenance";
- req_access_txt = "10; 13"
- },
/obj/structure/cable{
icon_state = "4-8"
},
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 8
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
},
/turf/open/floor/plating,
/area/maintenance/solars/starboard/aft)
@@ -83056,6 +83049,19 @@
},
/turf/open/floor/plating,
/area/maintenance/port/aft)
+"yfW" = (
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/obj/machinery/door/airlock/external{
+ name = "Solar Maintenance";
+ req_access_txt = "10; 13"
+ },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 1
+ },
+/turf/open/floor/plating,
+/area/maintenance/solars/port/aft)
"ygk" = (
/obj/effect/turf_decal/stripes/line{
dir = 8
@@ -95238,9 +95244,9 @@ anS
anS
aaf
aaf
-aqB
-anS
-aaf
+dne
+cfA
+dne
aaf
aaf
aaf
@@ -95496,7 +95502,7 @@ aaa
aaa
aaf
dne
-avJ
+avL
dne
aaf
aaa
@@ -96581,7 +96587,7 @@ bXt
bYC
bYC
bYC
-aaa
+bYC
aaa
aaf
aaa
@@ -96838,8 +96844,8 @@ bXu
bYD
bZN
jyQ
+yfW
cda
-cej
cfz
cED
chY
@@ -97095,7 +97101,7 @@ bXv
bYC
bYC
bYC
-aaa
+bYC
aaa
aaf
aaa
@@ -99168,7 +99174,7 @@ ckN
aaa
aaf
aaf
-aaa
+lMJ
aaa
aaf
aaa
@@ -99423,7 +99429,7 @@ ckQ
cjt
ckN
aaf
-aaf
+ack
cwf
ack
aaf
@@ -99680,10 +99686,10 @@ cjt
diJ
dux
dux
-ack
+dux
cwg
-ack
-ack
+dux
+dux
aaf
aaa
aaa
@@ -99937,9 +99943,9 @@ crh
dxv
ctn
dux
-dux
-cfA
-dux
+sUM
+cwh
+dyw
dux
aaf
aaf
@@ -100194,8 +100200,8 @@ dvt
csf
cto
dux
-cvj
-cwh
+cfF
+mSd
cxb
dux
aaa
@@ -101647,7 +101653,7 @@ aaa
aaa
acT
aaa
-aaf
+aee
aee
aee
aee
@@ -101904,7 +101910,7 @@ aaf
aaf
acU
aak
-aak
+abN
aef
aeG
afE
@@ -102161,7 +102167,7 @@ aaa
aaa
aaf
aaa
-aaf
+aee
aee
aee
aee
@@ -108580,7 +108586,7 @@ aaa
aaa
aaa
wOY
-abN
+abe
ach
aax
acN
@@ -108838,7 +108844,7 @@ urv
abe
abe
abe
-aci
+abL
aax
acO
adh
@@ -112806,7 +112812,7 @@ cFh
cKH
cLz
wFH
-cMk
+bTs
bTs
bTs
bTs
@@ -113063,8 +113069,8 @@ cJN
cCq
cgN
cMl
-wOE
bTs
+lMJ
aaf
aaf
aaf
@@ -113321,7 +113327,7 @@ cCq
cLA
bTs
bTs
-bTs
+lMJ
aaf
aaa
aaa
@@ -119485,7 +119491,7 @@ aaf
aaa
aaf
dvY
-kDM
+cJd
dvY
aaa
dbN
@@ -119741,13 +119747,13 @@ cEA
aaf
aaa
aaa
-ack
+dvY
cJf
-ack
-aaa
-aaf
-dbR
+dvY
aaa
+dbN
+gsT
+dbN
aaa
aaa
aaa
@@ -119893,7 +119899,7 @@ aaf
aaa
aaa
aaa
-sdw
+aaa
aaa
acP
acP
@@ -119998,9 +120004,9 @@ blx
aaa
aaa
aaa
-aaa
-aaf
-aaa
+ack
+uim
+ack
aaa
aaf
dbR
@@ -121266,7 +121272,7 @@ ciL
cgs
csc
dvY
-evy
+dxk
krD
lsv
txj
@@ -121523,7 +121529,7 @@ cpK
ciL
csc
dvY
-vLD
+lMJ
krD
jyv
ohj
@@ -121780,7 +121786,7 @@ cpL
crb
csd
dvY
-vLD
+lMJ
krD
krD
noG
@@ -123501,7 +123507,7 @@ aaa
aaa
aaf
dni
-amG
+asB
amH
anN
dnS
@@ -123758,7 +123764,7 @@ aaf
aaf
aaf
dnh
-amH
+avG
dnh
apd
dnS
@@ -124014,8 +124020,8 @@ aaa
aaf
aaa
aaf
-aaa
-ack
+dnh
+aci
dnh
ape
dnS
@@ -127140,8 +127146,8 @@ aaa
aaf
bpw
aaf
-aaf
-ack
+cvj
+kDM
bxc
bzg
bAP
@@ -127398,7 +127404,7 @@ aaf
bpw
aaa
aaf
-aaf
+ack
bxc
bzh
bAQ
@@ -128190,9 +128196,9 @@ gJs
bFZ
bAR
aaf
-bxc
+lNZ
wxc
-bxc
+lNZ
aaf
aaa
aaf
@@ -128447,9 +128453,9 @@ bVN
bXr
bAR
aaf
-aMr
-ccY
-bBb
+lNZ
+wOE
+lNZ
aaf
aaa
aaf
@@ -128704,7 +128710,7 @@ bVO
bUJ
bAR
aaf
-aMq
+sdw
ccY
bgo
aTQ
@@ -129161,8 +129167,8 @@ aaa
ack
ack
atn
-bOY
-avG
+anN
+dnS
dqT
aaf
aaa
@@ -129218,7 +129224,7 @@ bAR
bAR
bAR
aaf
-aMq
+sdw
ccY
aVk
aNC
@@ -129418,8 +129424,8 @@ aaf
aaf
aaf
dnh
-dnh
-lNZ
+avJ
+avG
dqT
aaf
aaa
@@ -129674,9 +129680,9 @@ aaa
aaa
aaf
aaa
-aaa
-aaf
-ack
+dnh
+dnh
+bOY
dqT
aaf
anT
@@ -135878,7 +135884,7 @@ blA
bnu
bpH
brU
-aOV
+cMk
aaa
aMq
bzm
@@ -136120,7 +136126,7 @@ aOU
aOY
aOY
aOY
-aTT
+aNC
aaa
aaa
aaa
@@ -136138,7 +136144,7 @@ brV
aRy
aaa
aaa
-aTT
+aNC
aOY
aOY
aOY
@@ -136377,7 +136383,7 @@ aOV
aaa
aaa
aaa
-aTU
+aaf
aaa
aRy
aRy
@@ -136402,7 +136408,7 @@ aaa
aaa
aaa
aaa
-aTU
+aaf
aaa
aaa
aaa
@@ -139461,7 +139467,7 @@ aOV
aaa
aaa
aaa
-aTU
+aaf
aaa
aRy
aRy
@@ -139479,14 +139485,14 @@ bsh
aRy
bvt
aaa
-aTU
+aaf
aaa
aaa
aaa
aaa
aaa
aaa
-aTU
+aaf
aaa
aaa
aaa
@@ -139718,7 +139724,7 @@ aOX
aNw
aNw
aNw
-aTY
+bJl
aaa
aaa
aaa
@@ -139736,14 +139742,14 @@ bsi
aRy
aaa
aaa
-aTY
+bJl
aNw
aNw
aNw
aNw
aNw
aNw
-aTY
+bJl
aNw
aNw
aNw
diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm
index e07873089a..db44dfb92a 100644
--- a/_maps/map_files/OmegaStation/OmegaStation.dmm
+++ b/_maps/map_files/OmegaStation/OmegaStation.dmm
@@ -1244,15 +1244,7 @@
/turf/closed/wall,
/area/maintenance/starboard/fore)
"abM" = (
-/obj/effect/turf_decal/stripes/line,
-/obj/machinery/door/airlock/external{
- name = "External Airlock";
- req_access_txt = "13"
- },
-/obj/effect/mapping_helpers/airlock/cyclelink_helper,
-/obj/effect/turf_decal/stripes/line{
- dir = 1
- },
+/obj/effect/turf_decal/delivery,
/turf/open/floor/plasteel,
/area/maintenance/starboard/fore)
"abN" = (
@@ -23608,22 +23600,9 @@
/turf/open/floor/engine,
/area/engine/supermatter)
"aKB" = (
-/obj/effect/turf_decal/stripes/line{
- dir = 8
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 4
- },
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
-/obj/machinery/door/airlock/external{
- name = "External Airlock";
- req_access_txt = "13"
- },
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 8
- },
/turf/open/floor/plasteel,
/area/maintenance/port/aft)
"aKC" = (
@@ -23645,14 +23624,23 @@
/turf/open/floor/plasteel/dark,
/area/engine/engineering)
"aKF" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 8
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
+ },
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
-/obj/structure/sign/warning/vacuum{
- pixel_x = -32;
- pixel_y = 32
+/obj/machinery/door/airlock/external{
+ name = "External Airlock";
+ req_access_txt = "13"
},
-/turf/open/floor/plating,
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 8
+ },
+/turf/open/floor/plasteel,
/area/maintenance/port/aft)
"aKG" = (
/obj/structure/cable/white{
@@ -39608,9 +39596,17 @@
/turf/open/floor/plasteel,
/area/engine/atmos)
"edA" = (
-/obj/structure/lattice,
-/turf/open/space/basic,
-/area/space)
+/obj/effect/turf_decal/stripes/line,
+/obj/machinery/door/airlock/external{
+ name = "External Airlock";
+ req_access_txt = "13"
+ },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper,
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/turf/open/floor/plasteel,
+/area/maintenance/starboard/fore)
"eew" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/structure/cable{
@@ -42876,9 +42872,6 @@
/obj/structure/sign/warning/securearea,
/turf/closed/wall/rust,
/area/maintenance/starboard)
-"sIO" = (
-/turf/open/space/basic,
-/area/space/nearstation)
"sIP" = (
/obj/machinery/vending/cola/random,
/obj/effect/turf_decal/bot,
@@ -71461,7 +71454,7 @@ aaa
aaa
aaa
aaa
-aaa
+sdX
uhz
uhz
oxn
@@ -71718,7 +71711,7 @@ aac
aac
aac
aac
-aaa
+sdX
uhz
iye
mJP
@@ -91220,7 +91213,7 @@ aaa
aae
aaa
aaa
-aac
+bxZ
abL
bxZ
swz
@@ -91477,7 +91470,7 @@ aaa
aae
aad
aac
-bvg
+edA
abM
acu
adt
@@ -91734,7 +91727,7 @@ aad
aah
aad
aad
-aad
+bxZ
bxZ
adq
bxZ
@@ -93059,7 +93052,7 @@ aRz
sIc
sIv
sFs
-sIO
+aaa
sIU
sJe
sIU
@@ -98477,9 +98470,9 @@ aac
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aac
aac
aac
@@ -98734,9 +98727,9 @@ aac
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aac
aaa
@@ -98991,9 +98984,9 @@ aaa
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -99248,9 +99241,9 @@ aaa
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -99505,9 +99498,9 @@ aaa
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -99762,9 +99755,9 @@ aaa
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -100019,9 +100012,9 @@ jFP
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -100276,9 +100269,9 @@ jFP
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -100533,9 +100526,9 @@ jFP
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -100790,9 +100783,9 @@ jFP
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -101047,9 +101040,9 @@ jFP
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -101304,9 +101297,9 @@ jFP
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -101561,9 +101554,9 @@ jFP
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -101818,9 +101811,9 @@ jFP
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -102075,9 +102068,9 @@ jFP
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -102332,9 +102325,9 @@ jFP
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -102589,9 +102582,9 @@ jFP
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -102846,9 +102839,9 @@ jFP
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -103103,9 +103096,9 @@ jFP
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -103360,9 +103353,9 @@ jFP
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -103617,9 +103610,9 @@ jFP
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -103874,9 +103867,9 @@ jFP
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -104131,9 +104124,9 @@ jFP
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -104388,9 +104381,9 @@ jFP
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -104645,9 +104638,9 @@ jFP
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -104902,9 +104895,9 @@ aaa
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -105159,9 +105152,9 @@ aaa
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
@@ -105416,9 +105409,9 @@ aaa
aaa
aaa
aaa
-edA
+sdX
aaa
-edA
+sdX
aaa
aaa
aaa
diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm
index e6f14badd9..263cb44144 100644
--- a/_maps/map_files/PubbyStation/PubbyStation.dmm
+++ b/_maps/map_files/PubbyStation/PubbyStation.dmm
@@ -1846,7 +1846,7 @@
network = list("minisat")
},
/turf/open/space,
-/area/ai_monitored/turret_protected/AIsatextAS)
+/area/ai_monitored/turret_protected/AIsatextAP)
"aeA" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 6
@@ -2622,9 +2622,6 @@
/obj/machinery/light/small{
dir = 8
},
-/obj/structure/sign/warning/vacuum/external{
- pixel_x = 32
- },
/obj/structure/sign/warning/vacuum/external{
pixel_x = -32
},
@@ -2744,12 +2741,8 @@
/turf/open/floor/plating,
/area/security/main)
"agR" = (
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 1
- },
-/obj/machinery/door/airlock/external{
- name = "MiniSat External Access";
- req_access_txt = "65"
+/obj/structure/sign/warning/vacuum/external{
+ pixel_x = 32
},
/turf/open/floor/plating,
/area/ai_monitored/turret_protected/aisat_interior)
@@ -2821,12 +2814,15 @@
/turf/open/floor/plasteel/showroomfloor,
/area/security/main)
"ahh" = (
-/obj/structure/lattice/catwalk,
-/obj/structure/showcase/cyborg/old{
- pixel_y = 20
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 1
},
-/turf/open/space,
-/area/space/nearstation)
+/obj/machinery/door/airlock/external{
+ name = "MiniSat External Access";
+ req_access_txt = "65"
+ },
+/turf/open/floor/plating,
+/area/ai_monitored/turret_protected/aisat_interior)
"ahi" = (
/obj/structure/lattice/catwalk,
/turf/open/space,
@@ -2927,13 +2923,15 @@
/turf/open/floor/plasteel/showroomfloor,
/area/security/main)
"ahr" = (
-/obj/structure/lattice,
-/obj/machinery/camera/motion{
- c_tag = "MiniSat Entrance";
- network = list("minisat")
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 8
},
-/turf/open/space,
-/area/space/nearstation)
+/obj/machinery/door/airlock/external{
+ name = "Security External Airlock";
+ req_access_txt = "63"
+ },
+/turf/open/floor/plating,
+/area/maintenance/fore)
"ahs" = (
/obj/structure/lattice/catwalk,
/obj/structure/transit_tube,
@@ -4690,8 +4688,12 @@
/turf/open/space/basic,
/area/space/nearstation)
"alb" = (
-/turf/open/floor/wood,
-/area/maintenance/department/crew_quarters/dorms)
+/obj/structure/lattice/catwalk,
+/obj/structure/showcase/cyborg/old{
+ pixel_y = 20
+ },
+/turf/open/space,
+/area/space/nearstation)
"alc" = (
/obj/structure/table,
/obj/item/storage/fancy/cigarettes/cigars,
@@ -6634,13 +6636,6 @@
/turf/open/floor/plating,
/area/maintenance/fore)
"apn" = (
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 8
- },
-/obj/machinery/door/airlock/external{
- name = "Security External Airlock";
- req_access_txt = "63"
- },
/turf/open/floor/plating,
/area/maintenance/fore)
"apo" = (
@@ -8703,13 +8698,18 @@
/turf/closed/wall,
/area/bridge)
"atZ" = (
-/obj/effect/mapping_helpers/airlock/cyclelink_helper,
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 8
+ },
/obj/machinery/door/airlock/external{
- name = "Bridge External Access";
- req_access_txt = "10;13"
+ name = "Solar Maintenance";
+ req_access_txt = "10; 13"
},
/turf/open/floor/plating,
-/area/ai_monitored/turret_protected/aisat_interior)
+/area/maintenance/solars/starboard)
"aua" = (
/obj/structure/closet/secure_closet/freezer/money,
/obj/item/reagent_containers/food/drinks/bottle/vodka/badminka,
@@ -9124,9 +9124,6 @@
/obj/structure/sign/warning/vacuum/external{
pixel_x = -32
},
-/obj/machinery/light/small{
- dir = 1
- },
/turf/open/floor/plating,
/area/bridge)
"auV" = (
@@ -13689,14 +13686,13 @@
/turf/open/floor/plating,
/area/maintenance/department/cargo)
"aFj" = (
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 8
+/obj/structure/lattice,
+/obj/machinery/camera/motion{
+ c_tag = "MiniSat Entrance";
+ network = list("minisat")
},
-/obj/machinery/door/airlock/external{
- req_access_txt = "13"
- },
-/turf/open/floor/plating,
-/area/maintenance/department/cargo)
+/turf/open/space,
+/area/space/nearstation)
"aFk" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/effect/spawner/lootdrop/minor/bowler_or_that,
@@ -22864,11 +22860,13 @@
/turf/closed/wall,
/area/maintenance/solars/starboard)
"baH" = (
-/obj/structure/rack,
-/obj/item/clothing/mask/gas,
-/obj/item/multitool,
+/obj/effect/mapping_helpers/airlock/cyclelink_helper,
+/obj/machinery/door/airlock/external{
+ name = "Bridge External Access";
+ req_access_txt = "10;13"
+ },
/turf/open/floor/plating,
-/area/maintenance/solars/starboard)
+/area/ai_monitored/turret_protected/aisat_interior)
"baI" = (
/obj/structure/cable{
icon_state = "0-8"
@@ -23315,13 +23313,6 @@
/turf/open/floor/plasteel,
/area/quartermaster/miningdock)
"bbL" = (
-/obj/machinery/power/smes,
-/obj/structure/cable{
- icon_state = "0-2"
- },
-/turf/open/floor/plating,
-/area/maintenance/solars/starboard)
-"bbM" = (
/obj/machinery/power/terminal{
dir = 8
},
@@ -23333,17 +23324,10 @@
},
/turf/open/floor/plating,
/area/maintenance/solars/starboard)
-"bbO" = (
-/obj/structure/cable{
- icon_state = "4-8"
- },
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 4
- },
-/obj/machinery/door/airlock/external{
- name = "Solar Maintenance";
- req_access_txt = "10; 13"
- },
+"bbM" = (
+/obj/structure/rack,
+/obj/item/clothing/mask/gas,
+/obj/item/multitool,
/turf/open/floor/plating,
/area/maintenance/solars/starboard)
"bbP" = (
@@ -23757,16 +23741,6 @@
/turf/open/floor/plating,
/area/maintenance/department/cargo)
"bcJ" = (
-/obj/structure/cable{
- icon_state = "4-8"
- },
-/obj/machinery/door/airlock/engineering{
- name = "Starboard Solar Access";
- req_access_txt = "10"
- },
-/turf/open/floor/plating,
-/area/maintenance/solars/starboard)
-"bcK" = (
/obj/structure/cable{
icon_state = "1-2"
},
@@ -23775,27 +23749,35 @@
},
/turf/open/floor/plating,
/area/maintenance/solars/starboard)
-"bcL" = (
+"bcK" = (
/obj/structure/cable{
icon_state = "1-4"
},
/turf/open/floor/plating,
/area/maintenance/solars/starboard)
-"bcN" = (
-/obj/machinery/power/solar_control{
- dir = 8;
- id = "starboardsolar";
- name = "Starboard Solar Control"
+"bcL" = (
+/obj/structure/cable{
+ icon_state = "2-4"
},
-/obj/structure/cable,
-/turf/open/floor/plating,
-/area/maintenance/solars/starboard)
-"bcO" = (
/obj/structure/cable{
icon_state = "4-8"
},
/turf/open/floor/plating,
/area/maintenance/solars/starboard)
+"bcN" = (
+/obj/machinery/light/small{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/cobweb,
+/turf/open/floor/plating,
+/area/bridge)
+"bcO" = (
+/obj/structure/lattice/catwalk,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{
+ dir = 9
+ },
+/turf/open/space,
+/area/space/nearstation)
"bcQ" = (
/obj/structure/lattice/catwalk,
/obj/structure/cable{
@@ -24156,17 +24138,17 @@
},
/area/maintenance/department/cargo)
"bdR" = (
-/obj/structure/cable,
-/obj/machinery/power/apc{
- dir = 8;
- name = "Starboard Solar APC";
- pixel_x = -24
- },
+/obj/structure/chair/stool,
+/obj/item/cigbutt/cigarbutt,
/turf/open/floor/plating,
/area/maintenance/solars/starboard)
"bdS" = (
-/obj/structure/chair/stool,
-/obj/item/cigbutt/cigarbutt,
+/obj/machinery/power/solar_control{
+ dir = 8;
+ id = "starboardsolar";
+ name = "Starboard Solar Control"
+ },
+/obj/structure/cable,
/turf/open/floor/plating,
/area/maintenance/solars/starboard)
"bdU" = (
@@ -27986,7 +27968,7 @@
dir = 8
},
/turf/open/floor/plasteel/white,
-/area/storage/emergency/port)
+/area/medical/medbay/zone3)
"bny" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/machinery/firealarm{
@@ -28005,7 +27987,7 @@
dir = 4
},
/turf/open/floor/plasteel/white,
-/area/storage/emergency/port)
+/area/medical/medbay/zone3)
"bnz" = (
/obj/structure/table,
/obj/item/folder/white,
@@ -39909,12 +39891,6 @@
/area/science/mixing)
"bMp" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/visible,
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 1
- },
-/obj/machinery/door/airlock/external{
- req_access_txt = "8"
- },
/turf/open/floor/plating,
/area/science/mixing)
"bMq" = (
@@ -40394,11 +40370,10 @@
/turf/open/floor/engine/vacuum,
/area/science/mixing)
"bNq" = (
-/obj/structure/lattice/catwalk,
-/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{
- dir = 6
+/obj/machinery/atmospherics/components/unary/outlet_injector/on{
+ dir = 1
},
-/turf/open/space,
+/turf/open/floor/plating/airless,
/area/science/mixing)
"bNr" = (
/obj/structure/window/reinforced{
@@ -40834,10 +40809,11 @@
/turf/open/floor/engine/vacuum,
/area/science/mixing)
"bOu" = (
-/obj/machinery/atmospherics/components/unary/outlet_injector/on{
- dir = 1
+/obj/structure/lattice/catwalk,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{
+ dir = 6
},
-/turf/open/floor/plating/airless,
+/turf/open/space,
/area/science/mixing)
"bOv" = (
/obj/structure/window/reinforced{
@@ -41125,12 +41101,15 @@
/turf/open/floor/engine/n2o,
/area/engine/atmos)
"bPl" = (
-/obj/structure/lattice/catwalk,
-/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{
- dir = 9
+/obj/machinery/atmospherics/pipe/simple/scrubbers/visible,
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 1
},
-/turf/open/space,
-/area/space/nearstation)
+/obj/machinery/door/airlock/external{
+ req_access_txt = "8"
+ },
+/turf/open/floor/plating,
+/area/science/mixing)
"bPn" = (
/obj/machinery/door/airlock/grunge{
name = "Chapel"
@@ -43266,7 +43245,7 @@
/obj/structure/closet/firecloset,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plasteel,
-/area/engine/atmos)
+/area/engine/break_room)
"bTR" = (
/obj/machinery/atmospherics/pipe/simple/yellow/visible{
dir = 4
@@ -43455,7 +43434,7 @@
/obj/effect/turf_decal/delivery,
/obj/structure/closet/firecloset,
/turf/open/floor/plasteel,
-/area/engine/atmos)
+/area/engine/break_room)
"bUp" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/visible,
/turf/open/floor/plasteel,
@@ -43848,7 +43827,7 @@
/obj/effect/turf_decal/delivery,
/obj/machinery/atmospherics/pipe/manifold4w/scrubbers,
/turf/open/floor/plasteel,
-/area/engine/atmos)
+/area/engine/break_room)
"bVd" = (
/obj/machinery/door/airlock/atmos{
name = "Atmospherics";
@@ -45016,10 +44995,6 @@
/turf/open/floor/plating,
/area/chapel/asteroid/monastery)
"bXN" = (
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 8
- },
-/obj/machinery/door/airlock/external,
/turf/open/floor/plating,
/area/chapel/asteroid/monastery)
"bXS" = (
@@ -45926,12 +45901,21 @@
/obj/machinery/atmospherics/components/unary/outlet_injector/atmos/incinerator_input{
dir = 8
},
+/obj/machinery/air_sensor/atmos/incinerator_tank{
+ pixel_x = 32;
+ pixel_y = -32
+ },
/turf/open/floor/engine,
/area/maintenance/disposal/incinerator)
"bZV" = (
-/obj/structure/sign/warning/fire,
-/turf/closed/wall/r_wall,
-/area/maintenance/disposal/incinerator)
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 8
+ },
+/obj/machinery/door/airlock/external{
+ req_access_txt = "13"
+ },
+/turf/open/floor/plating,
+/area/maintenance/department/cargo)
"bZY" = (
/turf/closed/wall,
/area/chapel/office)
@@ -46149,13 +46133,15 @@
icon_state = "4-8"
},
/obj/machinery/igniter/incinerator_atmos,
-/obj/machinery/air_sensor/atmos/incinerator_tank{
- pixel_x = 32;
- pixel_y = -32
- },
/turf/open/floor/engine,
/area/maintenance/disposal/incinerator)
"caP" = (
+/obj/structure/cable/yellow{
+ icon_state = "4-8"
+ },
+/turf/open/floor/engine,
+/area/maintenance/disposal/incinerator)
+"caQ" = (
/obj/structure/cable/yellow{
icon_state = "0-8"
},
@@ -46167,13 +46153,9 @@
dir = 8;
luminosity = 2
},
-/obj/machinery/camera{
- c_tag = "Turbine Chamber";
- network = list("turbine")
- },
/turf/open/floor/engine,
/area/maintenance/disposal/incinerator)
-"caQ" = (
+"caR" = (
/obj/structure/cable/yellow{
icon_state = "0-8"
},
@@ -46183,10 +46165,6 @@
},
/turf/open/floor/engine,
/area/maintenance/disposal/incinerator)
-"caR" = (
-/obj/machinery/door/poddoor/incinerator_atmos_main,
-/turf/open/floor/engine/vacuum,
-/area/maintenance/disposal/incinerator)
"caS" = (
/turf/closed/wall,
/area/chapel/asteroid/monastery)
@@ -46611,9 +46589,9 @@
/turf/open/floor/plasteel/dark,
/area/maintenance/disposal/incinerator)
"ccs" = (
-/obj/machinery/door/poddoor/incinerator_atmos_aux,
-/turf/open/floor/engine/vacuum,
-/area/maintenance/disposal/incinerator)
+/obj/structure/lattice,
+/turf/closed/wall,
+/area/maintenance/department/cargo)
"ccu" = (
/obj/structure/flora/ausbushes/leafybush,
/turf/open/floor/plating/asteroid,
@@ -46786,13 +46764,6 @@
/turf/open/floor/plating,
/area/maintenance/disposal/incinerator)
"cdl" = (
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 8
- },
-/obj/machinery/door/airlock/external{
- name = "Atmospherics External Access";
- req_access_txt = "24"
- },
/turf/open/floor/plating,
/area/maintenance/disposal/incinerator)
"cdm" = (
@@ -47328,6 +47299,9 @@
/obj/structure/cable{
icon_state = "1-2"
},
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
/turf/open/floor/plasteel/dark,
/area/engine/engineering)
"cfu" = (
@@ -47446,14 +47420,12 @@
/turf/open/floor/plasteel/dark,
/area/engine/engineering)
"cfQ" = (
-/obj/structure/chair{
- dir = 8
+/obj/machinery/power/smes,
+/obj/structure/cable{
+ icon_state = "0-2"
},
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 9
- },
-/turf/open/floor/plasteel/dark,
-/area/engine/engineering)
+/turf/open/floor/plating,
+/area/maintenance/solars/starboard)
"cfS" = (
/obj/structure/table/reinforced,
/obj/item/tank/internals/emergency_oxygen/engi,
@@ -47579,14 +47551,12 @@
/turf/open/floor/plating,
/area/engine/engineering)
"cgs" = (
-/obj/effect/mapping_helpers/airlock/cyclelink_helper,
-/obj/machinery/door/airlock/external{
- name = "Engineering External Access";
- req_access_txt = "61"
- },
/obj/structure/cable{
icon_state = "1-2"
},
+/obj/machinery/light/small{
+ dir = 8
+ },
/turf/open/floor/plating,
/area/engine/engineering)
"cgu" = (
@@ -47678,9 +47648,6 @@
/turf/open/floor/plating/airless,
/area/space/nearstation)
"cgQ" = (
-/obj/machinery/light/small{
- dir = 8
- },
/obj/structure/sign/warning/vacuum/external{
pixel_x = -32
},
@@ -49453,7 +49420,7 @@
/obj/structure/lattice,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/space/basic,
-/area/ai_monitored/turret_protected/AIsatextAS)
+/area/ai_monitored/turret_protected/AIsatextAP)
"cnJ" = (
/obj/effect/turf_decal/delivery,
/obj/machinery/vending/wardrobe/sec_wardrobe,
@@ -50434,6 +50401,15 @@
/turf/open/floor/plating,
/area/maintenance/department/engine)
"crB" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4
+ },
+/obj/machinery/light/small{
+ dir = 1
+ },
+/turf/open/floor/plating,
+/area/maintenance/department/engine)
+"crC" = (
/obj/effect/mapping_helpers/airlock/cyclelink_helper{
dir = 8
},
@@ -50445,15 +50421,6 @@
},
/turf/open/floor/plating,
/area/maintenance/department/engine)
-"crC" = (
-/obj/machinery/light/small{
- dir = 1
- },
-/obj/structure/disposalpipe/segment{
- dir = 4
- },
-/turf/open/floor/plating,
-/area/maintenance/department/engine)
"crD" = (
/obj/structure/table/wood/fancy,
/obj/item/storage/box/bodybags,
@@ -53580,13 +53547,15 @@
/turf/open/floor/plating,
/area/maintenance/department/engine)
"dWp" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 4
+/obj/effect/mapping_helpers/airlock/cyclelink_helper,
+/obj/machinery/door/airlock/external{
+ name = "Engineering External Access";
+ req_access_txt = "61"
},
/obj/structure/cable{
icon_state = "1-2"
},
-/turf/open/floor/plasteel/dark,
+/turf/open/floor/plating,
/area/engine/engineering)
"dYe" = (
/obj/structure/cable{
@@ -53959,6 +53928,9 @@
/obj/effect/turf_decal/arrows{
dir = 8
},
+/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
+ dir = 4
+ },
/turf/open/floor/plasteel/dark,
/area/engine/engineering)
"eWi" = (
@@ -54360,6 +54332,9 @@
},
/turf/open/floor/plasteel,
/area/engine/engineering)
+"fRr" = (
+/turf/open/floor/engine/vacuum,
+/area/maintenance/disposal/incinerator)
"fRs" = (
/turf/closed/wall,
/area/crew_quarters/heads/hor)
@@ -54572,6 +54547,16 @@
},
/turf/open/floor/plasteel,
/area/hallway/secondary/exit/departure_lounge)
+"gmZ" = (
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 8
+ },
+/obj/machinery/door/airlock/external{
+ name = "Atmospherics External Access";
+ req_access_txt = "24"
+ },
+/turf/open/floor/plating,
+/area/maintenance/disposal/incinerator)
"gna" = (
/turf/open/floor/plasteel/stairs/medium,
/area/maintenance/department/crew_quarters/dorms)
@@ -54932,6 +54917,10 @@
/obj/effect/turf_decal/stripes/line,
/turf/open/floor/plasteel,
/area/engine/engineering)
+"hbl" = (
+/obj/machinery/door/poddoor/incinerator_atmos_main,
+/turf/open/floor/engine/vacuum,
+/area/space)
"heC" = (
/obj/machinery/power/apc/highcap/five_k{
dir = 8;
@@ -55279,14 +55268,15 @@
/turf/open/floor/engine,
/area/engine/engineering)
"hSM" = (
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 8
+/obj/structure/cable{
+ icon_state = "4-8"
},
-/obj/machinery/door/airlock/external{
- req_access_txt = "13"
+/obj/machinery/door/airlock/engineering{
+ name = "Starboard Solar Access";
+ req_access_txt = "10"
},
/turf/open/floor/plating,
-/area/maintenance/department/science)
+/area/maintenance/solars/starboard)
"hTl" = (
/obj/structure/sink{
dir = 4;
@@ -55395,6 +55385,13 @@
/obj/effect/turf_decal/stripes/line,
/turf/open/floor/engine,
/area/engine/engineering)
+"igB" = (
+/obj/machinery/camera{
+ c_tag = "Turbine Chamber";
+ network = list("turbine")
+ },
+/turf/open/floor/engine,
+/area/maintenance/disposal/incinerator)
"igE" = (
/obj/structure/table/reinforced,
/obj/machinery/button/door{
@@ -55667,7 +55664,7 @@
dir = 9
},
/turf/open/floor/plasteel/white,
-/area/storage/emergency/port)
+/area/medical/medbay/zone3)
"iJi" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 5
@@ -57269,6 +57266,15 @@
},
/turf/open/floor/plasteel,
/area/science/xenobiology)
+"mvm" = (
+/obj/structure/cable,
+/obj/machinery/power/apc{
+ dir = 8;
+ name = "Starboard Solar APC";
+ pixel_x = -24
+ },
+/turf/open/floor/plating,
+/area/maintenance/solars/starboard)
"mwg" = (
/obj/structure/closet/crate{
icon_state = "crateopen"
@@ -57459,6 +57465,10 @@
/obj/effect/landmark/start/paramedic,
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
+"nbu" = (
+/obj/structure/sign/warning/fire,
+/turf/closed/wall/r_wall,
+/area/space)
"ncm" = (
/obj/machinery/atmospherics/pipe/simple/cyan/visible{
dir = 4
@@ -58035,6 +58045,10 @@
},
/turf/open/floor/plasteel/dark,
/area/tcommsat/computer)
+"ore" = (
+/obj/structure/closet/firecloset,
+/turf/open/floor/plating,
+/area/engine/engineering)
"ost" = (
/obj/structure/table/glass,
/obj/item/paper_bin{
@@ -58146,13 +58160,6 @@
/obj/structure/cable{
icon_state = "4-8"
},
-/obj/effect/mapping_helpers/airlock/cyclelink_helper{
- dir = 8
- },
-/obj/machinery/door/airlock/external{
- name = "Solar Maintenance";
- req_access_txt = "10; 13"
- },
/turf/open/floor/plating,
/area/maintenance/solars/starboard)
"oDP" = (
@@ -58221,6 +58228,12 @@
/obj/item/stack/sheet/mineral/wood,
/turf/open/floor/plasteel,
/area/maintenance/department/engine)
+"oGw" = (
+/obj/item/clothing/mask/gas,
+/turf/open/floor/plating{
+ icon_state = "platingdmg3"
+ },
+/area/maintenance/disposal/incinerator)
"oHa" = (
/obj/machinery/power/emitter/anchored{
dir = 8;
@@ -59255,6 +59268,10 @@
},
/turf/open/floor/plasteel,
/area/hallway/secondary/exit/departure_lounge)
+"qVk" = (
+/obj/machinery/door/poddoor/incinerator_atmos_aux,
+/turf/open/space/basic,
+/area/maintenance/disposal/incinerator)
"qVP" = (
/obj/machinery/door/firedoor,
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
@@ -59563,6 +59580,13 @@
icon_state = "panelscorched"
},
/area/maintenance/department/engine)
+"rzF" = (
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 8
+ },
+/obj/machinery/door/airlock/external,
+/turf/open/floor/plating,
+/area/chapel/asteroid/monastery)
"rBh" = (
/obj/structure/mopbucket,
/obj/item/mop,
@@ -60877,12 +60901,16 @@
/turf/open/floor/plasteel,
/area/science/xenobiology)
"uXH" = (
-/obj/structure/cable{
- icon_state = "2-4"
- },
/obj/structure/cable{
icon_state = "4-8"
},
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 4
+ },
+/obj/machinery/door/airlock/external{
+ name = "Solar Maintenance";
+ req_access_txt = "10; 13"
+ },
/turf/open/floor/plating,
/area/maintenance/solars/starboard)
"uZb" = (
@@ -61180,6 +61208,15 @@
},
/turf/open/floor/plating,
/area/maintenance/department/engine)
+"vHf" = (
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 8
+ },
+/obj/machinery/door/airlock/external{
+ req_access_txt = "13"
+ },
+/turf/open/floor/plating,
+/area/maintenance/department/science)
"vIc" = (
/obj/structure/cable{
icon_state = "2-4"
@@ -62245,7 +62282,9 @@
/obj/structure/chair{
dir = 8
},
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 9
+ },
/turf/open/floor/plasteel/dark,
/area/engine/engineering)
@@ -77500,9 +77539,9 @@ rLi
tlc
aiu
aht
-aaa
-azH
-aaa
+axB
+rKr
+axB
aaa
aaa
aaa
@@ -77758,9 +77797,9 @@ aiu
aiu
axC
axB
-rKr
+azN
axB
-axC
+aaa
aaa
aaa
aaa
@@ -78017,7 +78056,7 @@ axC
ayz
azN
axB
-axC
+aaa
aaa
aaa
aaa
@@ -81853,7 +81892,7 @@ ahB
ahZ
aiB
ajc
-agy
+ajM
akB
alq
alZ
@@ -82110,7 +82149,7 @@ ahC
aia
aiC
ajc
-agy
+ajM
akC
alr
ama
@@ -82367,7 +82406,7 @@ ahD
aib
aiD
ajc
-agy
+ajM
akD
als
amb
@@ -82458,9 +82497,9 @@ aht
aaa
aaa
abI
-aaa
-bSZ
-ahi
+bGI
+bNs
+rzF
bNs
bOw
bOw
@@ -82624,7 +82663,7 @@ ahB
aic
aiE
agy
-agy
+ajM
akE
alt
amc
@@ -82716,7 +82755,7 @@ abI
abI
abI
aaa
-aht
+bSZ
ahi
bNs
bNs
@@ -84536,8 +84575,8 @@ aaa
aaa
aaa
aaa
-kSb
-kSb
+fon
+fon
aht
aht
nKo
@@ -88120,7 +88159,7 @@ bDi
bDi
bDi
bIZ
-mZE
+aaa
aaa
aaa
aaa
@@ -88377,8 +88416,8 @@ wNq
bva
gMO
bBX
-mZE
-mZE
+aaa
+aaa
aaa
aaa
aaa
@@ -88635,7 +88674,7 @@ bBX
fdS
bBX
bBX
-mZE
+aaa
aaa
aaa
aaa
@@ -90436,7 +90475,7 @@ gnq
bXk
ceU
eVy
-cfP
+bXk
bXk
bXk
bXk
@@ -90597,9 +90636,9 @@ aaa
aaa
aaa
aaa
-aaa
-ahi
-ahi
+aoz
+ahr
+aoz
aqG
arD
asO
@@ -90855,8 +90894,8 @@ aaa
aaa
aaa
aaa
-aaa
-aaa
+cdm
+cdm
aqG
arE
arA
@@ -90950,8 +90989,8 @@ cdM
bXq
xmE
ymb
-cfQ
bXk
+ore
qWG
bXk
paU
@@ -94698,7 +94737,7 @@ ags
adX
adX
adX
-aaa
+adX
aaa
aaa
aaa
@@ -94954,8 +94993,8 @@ cnC
adX
adX
adX
-ahh
-aaa
+adX
+alb
aaa
aaa
aaa
@@ -94970,9 +95009,9 @@ aaa
aaa
aaa
aaa
-aaa
ahi
atY
+bcN
auU
atY
lQQ
@@ -95211,6 +95250,7 @@ bIK
agt
agD
agR
+ahh
ahi
aaa
aaa
@@ -95218,7 +95258,6 @@ aaa
aaa
aaa
aaa
-aaa
aht
amC
aht
@@ -95227,9 +95266,9 @@ aaa
aaa
aaa
aaa
-aaa
ahi
-atZ
+baH
+auV
auV
awc
axg
@@ -95468,8 +95507,8 @@ agg
adX
adX
adX
-ahh
-aaa
+adX
+alb
aaa
aaa
aaa
@@ -95484,11 +95523,11 @@ aaa
aaa
aaa
aaa
-aaa
ahi
atY
atY
atY
+atY
axh
axh
axh
@@ -95726,8 +95765,8 @@ ags
adX
adX
adX
-ahr
-aht
+adX
+aFj
aht
aht
aht
@@ -98814,7 +98853,7 @@ iqc
ngp
cBr
cBs
-alb
+tap
gna
klV
xbJ
@@ -99584,7 +99623,7 @@ aju
ajt
alQ
mnG
-alb
+tap
tap
aiS
anY
@@ -99842,7 +99881,7 @@ alc
alR
amF
pzF
-alb
+tap
anm
ajv
ajv
@@ -101740,7 +101779,7 @@ caN
bZT
bYw
cdl
-bYw
+oGw
bYw
aaa
mau
@@ -101995,9 +102034,9 @@ bYw
bZU
caO
cbF
-ccs
-cdm
-cdm
+bYw
+gmZ
+bYw
bYw
aht
fon
@@ -102249,13 +102288,13 @@ bVo
bJP
aht
bYw
-bYw
+igB
caP
+fRr
+qVk
+cdm
+cdm
bYw
-bYw
-aaa
-aaa
-aaa
aaa
aaa
aaa
@@ -102505,11 +102544,11 @@ bWg
bVo
bJP
aaa
-aaa
+bYw
bYw
caQ
bYw
-aaa
+bYw
aaa
aaa
aaa
@@ -102762,10 +102801,10 @@ bJP
bJP
bJP
abI
-abI
-bZV
+aaa
+bYw
caR
-bZV
+bYw
aaa
aaa
aaa
@@ -103019,10 +103058,10 @@ aaa
aaa
abI
aaa
-aaa
-aaa
-aaa
-aaa
+abI
+nbu
+hbl
+nbu
aaa
aaa
aaa
@@ -105574,9 +105613,9 @@ bIN
dAF
bCV
bCV
-bNq
+bCV
bOu
-aht
+bNq
aaa
aaa
aaa
@@ -105832,8 +105871,8 @@ bJT
wOS
bMp
bPl
-mZE
-aht
+bcO
+aaa
aaa
aaa
aaa
@@ -106088,9 +106127,9 @@ fBz
bCV
bCV
bCV
+bCV
ahi
aht
-aht
abI
abI
abI
@@ -106822,7 +106861,7 @@ aEl
aEj
aEj
aht
-aht
+ccs
aEj
aEl
aEl
@@ -107079,10 +107118,10 @@ aTu
aUB
aEl
aaa
-aaa
-aEl
+aEj
aZv
aUC
+aUC
bcH
aUC
aZw
@@ -107337,8 +107376,8 @@ aGO
aEj
aEj
aEj
-aEj
aTx
+aFi
aGO
bcI
aFi
@@ -107574,10 +107613,10 @@ aaa
aaa
aaa
aaa
+aEl
+aFi
aEj
-aFj
-aEj
-aEj
+aaa
aEj
aEl
aEj
@@ -107594,12 +107633,12 @@ aUC
aVE
aUC
aUC
-aUC
aZw
-aFi
-bcI
-aFi
-aFi
+aEj
+aEj
+hSM
+aEj
+aEj
kIo
bfN
aEj
@@ -107831,9 +107870,9 @@ aaa
aaa
aaa
aaa
-ahi
-ahi
-ahi
+aEj
+bZV
+aEj
aaa
aaa
aaa
@@ -107853,9 +107892,9 @@ aEj
aEj
aYC
baG
-baG
+cfQ
bcJ
-baG
+mvm
baG
aEj
aEj
@@ -108088,9 +108127,9 @@ aaa
aaa
aaa
aaa
-aaa
-aaa
-aaa
+ahi
+ahi
+ahi
aaa
aaa
aaa
@@ -108624,9 +108663,9 @@ aFi
aFi
aYD
baG
-baH
+rWE
uXH
-bcN
+rWE
baG
eZA
tDn
@@ -108882,7 +108921,7 @@ aXC
aYE
baG
rWE
-bbO
+oCX
rWE
baG
vzT
@@ -109139,7 +109178,7 @@ aXC
aYF
baG
sut
-bcO
+oCX
rWE
baG
dsv
@@ -109396,7 +109435,7 @@ aEl
aEl
baG
rWE
-oCX
+atZ
rWE
baG
aEj
@@ -109902,7 +109941,7 @@ aaa
aaa
aaa
aaa
-mZE
+aaa
aaa
aaa
aaa
@@ -112504,7 +112543,7 @@ qcH
bnd
nNN
bwm
-hSM
+lWy
bwm
bwm
aaa
@@ -112760,10 +112799,10 @@ riW
jtf
bnd
aht
-ahi
-ahi
-ahi
-aht
+bwm
+vHf
+bwm
+aaa
aht
aby
aht
@@ -113017,9 +113056,9 @@ cOp
lGS
bnd
aaa
-aaa
-aaa
-aaa
+ahi
+ahi
+ahi
aht
aaa
aed
diff --git a/_maps/map_files/Snaxi/Snaxi.dmm b/_maps/map_files/Snaxi/Snaxi.dmm
index f7aca9baf2..45e6e4dee0 100644
--- a/_maps/map_files/Snaxi/Snaxi.dmm
+++ b/_maps/map_files/Snaxi/Snaxi.dmm
@@ -210,7 +210,8 @@
"aap" = (
/obj/machinery/quantumpad{
map_pad_id = "5";
- map_pad_link_id = "6"
+ map_pad_link_id = "6";
+ name = "South Sector Pad"
},
/obj/structure/sign/directions/evac{
pixel_y = 40
@@ -221,6 +222,13 @@
/obj/structure/sign/directions/command{
pixel_y = 24
},
+/obj/structure/sign/directions/science{
+ dir = 8;
+ icon_state = "pad_s";
+ layer = 4.1;
+ name = "south sector";
+ pixel_y = 13
+ },
/turf/open/floor/plasteel,
/area/hallway/primary/aft)
"aaq" = (
@@ -519,7 +527,8 @@
/obj/machinery/atmospherics/components/unary/vent_pump/on,
/obj/machinery/quantumpad{
map_pad_id = "1";
- map_pad_link_id = "2"
+ map_pad_link_id = "2";
+ name = "Northwest Sector Pad"
},
/obj/structure/sign/directions/medical{
dir = 8;
@@ -531,6 +540,13 @@
icon_state = "direction_sci";
pixel_y = 28
},
+/obj/structure/sign/directions/science{
+ dir = 8;
+ icon_state = "pad_nw";
+ layer = 4.1;
+ name = "northwest sector";
+ pixel_y = 13
+ },
/turf/open/floor/plasteel,
/area/quartermaster/miningdock)
"aaO" = (
@@ -730,13 +746,12 @@
/obj/machinery/light{
dir = 4
},
-/obj/structure/reagent_dispensers/watertank,
-/obj/item/radio/intercom{
- pixel_y = -26
- },
/obj/structure/sign/departments/xenobio{
pixel_x = 32
},
+/obj/structure/closet/bombcloset{
+ anchored = 1
+ },
/turf/open/floor/plasteel/white,
/area/science/misc_lab)
"abi" = (
@@ -1242,11 +1257,8 @@
/turf/open/floor/plasteel/dark,
/area/security/main)
"acb" = (
-/obj/structure/sign/poster/official/science{
- pixel_y = -32
- },
-/turf/open/floor/plasteel/white,
-/area/science/mixing)
+/turf/open/floor/plasteel/dark,
+/area/hydroponics)
"acc" = (
/obj/structure/sign/poster/contraband/lusty_xenomorph{
pixel_x = -32;
@@ -1640,8 +1652,8 @@
"aiS" = (
/obj/structure/closet/secure_closet/CMO,
/obj/machinery/keycard_auth{
- pixel_y = 4;
- pixel_x = -24
+ pixel_x = -24;
+ pixel_y = 4
},
/obj/effect/turf_decal/tile/blue{
dir = 4
@@ -3147,8 +3159,8 @@
dir = 4
},
/obj/machinery/conveyor{
- id = "packageSort2";
- dir = 1
+ dir = 1;
+ id = "packageSort2"
},
/obj/machinery/disposal/deliveryChute,
/obj/structure/window/reinforced{
@@ -4061,9 +4073,9 @@
/area/crew_quarters/dorms)
"aNS" = (
/obj/machinery/turnstile{
+ dir = 4;
name = "Genpop Entrance Turnstile";
- req_access_txt = "69";
- dir = 4
+ req_access_txt = "69"
},
/obj/machinery/door/poddoor/preopen{
id = "permacell1";
@@ -4554,9 +4566,9 @@
/area/maintenance/solars/port/fore)
"bcc" = (
/obj/machinery/door/window/brigdoor/security/cell{
+ dir = 1;
id = "Cell 2";
- name = "Cell 2";
- dir = 1
+ name = "Cell 2"
},
/obj/effect/turf_decal/vg_decals/numbers/two,
/obj/machinery/door/poddoor/preopen{
@@ -5031,9 +5043,9 @@
"brE" = (
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden,
/obj/machinery/door/window/southleft{
+ dir = 1;
name = "Court Cell";
- req_access_txt = "2";
- dir = 1
+ req_access_txt = "2"
},
/obj/structure/window/reinforced{
dir = 8
@@ -5169,7 +5181,7 @@
/turf/open/floor/plasteel/dark,
/area/hallway/secondary/exit/departure_lounge)
"bum" = (
-/turf/open/openspace/icemoon,
+/turf/open/transparent/openspace/icemoon,
/area/icemoon/surface/outdoors)
"buF" = (
/obj/machinery/light,
@@ -5209,7 +5221,15 @@
"buO" = (
/obj/machinery/quantumpad{
map_pad_id = "3";
- map_pad_link_id = "4"
+ map_pad_link_id = "4";
+ name = "Northeast Sector Pad"
+ },
+/obj/structure/sign/directions/science{
+ dir = 8;
+ icon_state = "pad_ne";
+ layer = 4.1;
+ name = "northeast sector";
+ pixel_y = 13
},
/turf/open/floor/plasteel,
/area/hallway/primary/port)
@@ -5284,9 +5304,9 @@
dir = 1
},
/obj/machinery/turnstile{
+ dir = 4;
name = "Genpop Entrance Turnstile";
- req_access_txt = "69";
- dir = 4
+ req_access_txt = "69"
},
/turf/open/floor/plasteel/dark,
/area/security/brig)
@@ -6957,9 +6977,9 @@
name = "west facing firelock"
},
/obj/machinery/door/window/southleft{
+ dir = 8;
name = "Test Chamber";
- req_access_txt = "55";
- dir = 8
+ req_access_txt = "55"
},
/obj/machinery/door/poddoor/preopen{
id = "xenobio2";
@@ -6975,9 +6995,9 @@
dir = 10
},
/obj/machinery/door/window/southleft{
+ dir = 4;
name = "Test Chamber";
- req_access_txt = "55";
- dir = 4
+ req_access_txt = "55"
},
/turf/open/floor/plasteel,
/area/science/xenobiology)
@@ -7072,9 +7092,9 @@
dir = 4
},
/obj/machinery/door/window/brigdoor{
+ dir = 1;
name = "Reception Desk";
- req_access_txt = "63";
- dir = 1
+ req_access_txt = "63"
},
/obj/machinery/door/window/brigdoor{
dir = 8;
@@ -7186,9 +7206,6 @@
dir = 5
},
/obj/machinery/atmospherics/components/unary/portables_connector/visible,
-/obj/machinery/firealarm{
- pixel_y = 24
- },
/turf/open/floor/plasteel,
/area/science/mixing)
"bKO" = (
@@ -7475,8 +7492,8 @@
},
/obj/structure/table/wood,
/obj/machinery/recharger{
- pixel_y = 4;
- pixel_x = -7
+ pixel_x = -7;
+ pixel_y = 4
},
/obj/item/book/manual/wiki/security_space_law{
pixel_x = 6;
@@ -8958,7 +8975,15 @@
"cpC" = (
/obj/machinery/quantumpad{
map_pad_id = "2";
- map_pad_link_id = "1"
+ map_pad_link_id = "1";
+ name = "South Sector Pad"
+ },
+/obj/structure/sign/directions/science{
+ dir = 8;
+ icon_state = "pad_s";
+ layer = 4.1;
+ name = "south sector";
+ pixel_y = 13
},
/turf/open/floor/plasteel,
/area/hallway/primary/port)
@@ -9296,8 +9321,8 @@
},
/obj/machinery/camera{
c_tag = "Medbay West";
- network = list("ss13","medbay");
- dir = 4
+ dir = 4;
+ network = list("ss13","medbay")
},
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
@@ -9414,9 +9439,9 @@
req_access_txt = "10"
},
/obj/machinery/door/window/northright{
+ dir = 4;
name = "Engineering Delivery";
- req_access_txt = "10";
- dir = 4
+ req_access_txt = "10"
},
/obj/effect/turf_decal/delivery,
/turf/open/floor/plasteel/dark,
@@ -9818,7 +9843,15 @@
"cQa" = (
/obj/machinery/quantumpad{
map_pad_id = "6";
- map_pad_link_id = "5"
+ map_pad_link_id = "5";
+ name = "Northeast Sector Pad"
+ },
+/obj/structure/sign/directions/science{
+ dir = 8;
+ icon_state = "pad_ne";
+ layer = 4.1;
+ name = "northeast sector";
+ pixel_y = 13
},
/turf/open/floor/plasteel,
/area/quartermaster/miningdock)
@@ -10387,8 +10420,8 @@
dir = 4
},
/obj/machinery/shower{
- pixel_y = 20;
- pixel_x = 11
+ pixel_x = 11;
+ pixel_y = 20
},
/obj/structure/disposalpipe/segment{
dir = 4
@@ -10760,8 +10793,8 @@
/obj/structure/table/wood,
/obj/item/book/manual/wiki/security_space_law,
/obj/item/flashlight/lamp/green{
- pixel_y = 1;
- pixel_x = -7
+ pixel_x = -7;
+ pixel_y = 1
},
/turf/open/floor/wood,
/area/security/courtroom)
@@ -11054,6 +11087,13 @@
"dAV" = (
/turf/closed/wall/r_wall,
/area/ai_monitored/turret_protected/ai_upload_foyer)
+"dBA" = (
+/obj/machinery/portable_atmospherics/pump,
+/obj/item/radio/intercom{
+ pixel_y = -26
+ },
+/turf/open/floor/plasteel/white,
+/area/science/mixing)
"dBL" = (
/obj/structure/closet/secure_closet/medical1,
/obj/structure/extinguisher_cabinet{
@@ -11207,9 +11247,9 @@
dir = 4
},
/obj/machinery/turnstile{
+ dir = 8;
name = "Genpop Exit Turnstile";
- req_access_txt = "70";
- dir = 8
+ req_access_txt = "70"
},
/turf/open/floor/plasteel/dark,
/area/security/brig)
@@ -12173,8 +12213,8 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/machinery/button/flasher{
id = "PCell 1";
- pixel_y = 9;
- pixel_x = -37
+ pixel_x = -37;
+ pixel_y = 9
},
/turf/open/floor/plasteel/dark,
/area/security/brig)
@@ -12356,9 +12396,9 @@
dir = 4
},
/obj/machinery/turnstile{
+ dir = 8;
name = "Genpop Exit Turnstile";
- req_access_txt = "70";
- dir = 8
+ req_access_txt = "70"
},
/obj/effect/turf_decal/tile/red{
dir = 1
@@ -12388,7 +12428,7 @@
/turf/open/floor/plasteel,
/area/hallway/primary/port)
"esY" = (
-/turf/open/openspace/icemoon,
+/turf/open/transparent/openspace/icemoon,
/area/engine/atmos)
"ets" = (
/obj/machinery/atmospherics/components/unary/vent_pump/on{
@@ -13510,9 +13550,9 @@
icon_state = "1-4"
},
/obj/machinery/door/window/brigdoor/security/cell{
+ dir = 8;
id = "Cell 1";
- name = "Cell 1";
- dir = 8
+ name = "Cell 1"
},
/obj/effect/turf_decal/vg_decals/numbers/one,
/obj/machinery/door/poddoor/preopen{
@@ -13766,7 +13806,6 @@
dir = 4;
pixel_x = -24
},
-/obj/structure/closet/crate/bin,
/turf/open/floor/plasteel/white,
/area/science/misc_lab)
"fjS" = (
@@ -14345,8 +14384,8 @@
name = "Door Bolt Control";
normaldoorcontrol = 1;
pixel_x = 24;
- specialfunctions = 4;
- pixel_y = -5
+ pixel_y = -5;
+ specialfunctions = 4
},
/obj/machinery/light/small{
dir = 8
@@ -14836,8 +14875,8 @@
/obj/structure/table/wood,
/obj/item/book/manual/wiki/security_space_law,
/obj/item/flashlight/lamp/green{
- pixel_y = 1;
- pixel_x = -7
+ pixel_x = -7;
+ pixel_y = 1
},
/turf/open/floor/wood,
/area/security/courtroom)
@@ -15167,7 +15206,15 @@
"gct" = (
/obj/machinery/quantumpad{
map_pad_id = "4";
- map_pad_link_id = "3"
+ map_pad_link_id = "3";
+ name = "Northwest Sector Pad"
+ },
+/obj/structure/sign/directions/science{
+ dir = 8;
+ icon_state = "pad_nw";
+ layer = 4.1;
+ name = "northwest sector";
+ pixel_y = 13
},
/turf/open/floor/plasteel,
/area/hallway/primary/aft)
@@ -15538,9 +15585,9 @@
/obj/machinery/button/door{
id = "Secure Gate";
name = "Cell Shutters";
+ pixel_x = 3;
pixel_y = 24;
- req_access_txt = "2";
- pixel_x = 3
+ req_access_txt = "2"
},
/turf/open/floor/plasteel/dark,
/area/security/brig)
@@ -15934,8 +15981,6 @@
/obj/machinery/atmospherics/components/unary/vent_pump/on{
dir = 4
},
-/obj/machinery/portable_atmospherics/scrubber,
-/obj/item/storage/firstaid/toxin,
/obj/structure/disposalpipe/segment{
dir = 4
},
@@ -16444,6 +16489,9 @@
/area/storage/atmos)
"gPE" = (
/obj/machinery/portable_atmospherics/pump,
+/obj/machinery/firealarm{
+ pixel_y = 24
+ },
/turf/open/floor/plasteel/white,
/area/science/mixing)
"gPF" = (
@@ -16835,9 +16883,9 @@
/obj/machinery/button/door{
id = "kitchen";
name = "Kitchen Shutters Control";
- req_access_txt = "28";
pixel_x = 24;
- pixel_y = -4
+ pixel_y = -4;
+ req_access_txt = "28"
},
/turf/open/floor/plasteel/cafeteria,
/area/crew_quarters/kitchen)
@@ -17096,8 +17144,8 @@
dir = 8
},
/obj/machinery/computer/monitor{
- name = "bridge power monitoring console";
- dir = 1
+ dir = 1;
+ name = "bridge power monitoring console"
},
/obj/structure/cable{
icon_state = "0-2"
@@ -17235,8 +17283,8 @@
/obj/item/folder/blue,
/obj/item/stamp/law,
/obj/item/flashlight/lamp/green{
- pixel_y = 1;
- pixel_x = -7
+ pixel_x = -7;
+ pixel_y = 1
},
/turf/open/floor/plasteel/cult,
/area/lawoffice)
@@ -18346,9 +18394,8 @@
/turf/open/floor/carpet,
/area/security/detectives_office)
"hTL" = (
-/obj/effect/spawner/structure/window/plasma/reinforced,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/turf/open/floor/plating,
+/turf/open/floor/plasteel/white,
/area/science/mixing)
"hTO" = (
/obj/structure/cable{
@@ -18426,9 +18473,9 @@
/area/engine/engineering)
"hVH" = (
/obj/machinery/atmospherics/components/unary/vent_pump/siphon/on{
+ dir = 1;
external_pressure_bound = 120;
- name = "killroom vent";
- dir = 1
+ name = "killroom vent"
},
/turf/open/floor/circuit/telecomms,
/area/science/xenobiology)
@@ -18466,8 +18513,8 @@
},
/obj/machinery/camera{
c_tag = "Surgery Observation";
- network = list("ss13","medbay");
- dir = 8
+ dir = 8;
+ network = list("ss13","medbay")
},
/turf/open/floor/plasteel/dark,
/area/medical/surgery)
@@ -18616,8 +18663,8 @@
/area/security/main)
"iam" = (
/obj/machinery/computer/slot_machine{
- pixel_y = 2;
- pixel_x = -7
+ pixel_x = -7;
+ pixel_y = 2
},
/turf/open/floor/wood,
/area/maintenance/bar)
@@ -19811,8 +19858,8 @@
/obj/machinery/button/door{
id = "hos";
name = "HoS Office Shutters";
- pixel_y = -26;
- pixel_x = -6
+ pixel_x = -6;
+ pixel_y = -26
},
/turf/open/floor/carpet,
/area/crew_quarters/heads/hos)
@@ -21387,8 +21434,8 @@
pixel_y = -22
},
/obj/machinery/button/door/incinerator_vent_toxmix{
- pixel_y = -22;
- pixel_x = 9
+ pixel_x = 9;
+ pixel_y = -22
},
/obj/machinery/meter,
/turf/open/floor/plasteel/white,
@@ -22646,6 +22693,8 @@
c_tag = "Testing Lab East";
network = list("ss13","rd")
},
+/obj/machinery/portable_atmospherics/scrubber,
+/obj/item/storage/firstaid/toxin,
/turf/open/floor/plasteel/white,
/area/science/misc_lab)
"kxI" = (
@@ -24585,8 +24634,8 @@
"lMF" = (
/obj/machinery/camera{
c_tag = "Virology Module";
- network = list("ss13","medbay");
- dir = 1
+ dir = 1;
+ network = list("ss13","medbay")
},
/obj/structure/disposalpipe/segment{
dir = 4
@@ -26020,8 +26069,8 @@
/obj/machinery/button/door{
id = "engsm";
name = "Radiation Shutters Control";
- req_access_txt = "10";
- pixel_y = 25
+ pixel_y = 25;
+ req_access_txt = "10"
},
/obj/machinery/atmospherics/pipe/manifold/cyan/visible,
/obj/effect/turf_decal/stripes/line{
@@ -26167,9 +26216,9 @@
dir = 4
},
/obj/machinery/turnstile{
+ dir = 8;
name = "Genpop Exit Turnstile";
- req_access_txt = "70";
- dir = 8
+ req_access_txt = "70"
},
/obj/structure/cable{
icon_state = "4-8"
@@ -27624,8 +27673,8 @@
/area/bridge)
"nFM" = (
/obj/machinery/atmospherics/components/binary/pump{
- name = "Port Mix to Engine";
- dir = 1
+ dir = 1;
+ name = "Port Mix to Engine"
},
/turf/open/floor/plasteel,
/area/engine/atmos)
@@ -27746,9 +27795,9 @@
"nJI" = (
/obj/structure/table/reinforced,
/obj/machinery/door/window/southleft{
+ dir = 4;
name = "Reception Desk";
- req_access_txt = "63";
- dir = 4
+ req_access_txt = "63"
},
/obj/structure/cable{
icon_state = "1-2"
@@ -27997,8 +28046,8 @@
/area/engine/engineering)
"nSX" = (
/obj/machinery/atmospherics/components/binary/pump/on{
- name = "Gas to Cooling Loop";
- dir = 1
+ dir = 1;
+ name = "Gas to Cooling Loop"
},
/turf/open/floor/plating,
/area/engine/atmospherics_engine)
@@ -28299,6 +28348,12 @@
/obj/effect/landmark/event_spawn,
/turf/open/floor/plasteel,
/area/maintenance/starboard)
+"odf" = (
+/obj/structure/closet/bombcloset{
+ anchored = 1
+ },
+/turf/open/floor/plasteel/white,
+/area/science/mixing)
"odg" = (
/obj/machinery/atmospherics/pipe/heat_exchanging/simple{
dir = 4
@@ -30144,8 +30199,8 @@
/area/quartermaster/storage)
"pfb" = (
/obj/machinery/atmospherics/components/binary/pump/on{
- name = "Gas to Cooling Loop";
- dir = 1
+ dir = 1;
+ name = "Gas to Cooling Loop"
},
/obj/effect/turf_decal/stripes/line{
dir = 9
@@ -30853,10 +30908,10 @@
/area/ai_monitored/security/armory)
"pvY" = (
/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 1;
external_pressure_bound = 140;
name = "killroom vent";
- pressure_checks = 0;
- dir = 1
+ pressure_checks = 0
},
/turf/open/floor/circuit/telecomms,
/area/science/xenobiology)
@@ -31393,9 +31448,9 @@
dir = 4
},
/obj/machinery/turnstile{
+ dir = 8;
name = "Genpop Exit Turnstile";
- req_access_txt = "70";
- dir = 8
+ req_access_txt = "70"
},
/obj/machinery/door/firedoor/border_only{
dir = 8;
@@ -32573,8 +32628,8 @@
},
/obj/machinery/button/ignition{
id = "testigniter";
- pixel_y = -30;
- pixel_x = -1
+ pixel_x = -1;
+ pixel_y = -30
},
/obj/structure/disposalpipe/trunk{
dir = 1
@@ -32758,9 +32813,9 @@
/area/maintenance/bar)
"qEz" = (
/obj/machinery/door/window/brigdoor/security/cell{
+ dir = 1;
id = "Cell 3";
- name = "Cell 3";
- dir = 1
+ name = "Cell 3"
},
/obj/effect/turf_decal/vg_decals/numbers/three,
/obj/machinery/door/poddoor/preopen{
@@ -33692,8 +33747,8 @@
"rgQ" = (
/obj/machinery/camera{
c_tag = "Xenobiology Test Chamber";
- network = list("xeno","rd");
- dir = 4
+ dir = 4;
+ network = list("xeno","rd")
},
/turf/open/floor/engine,
/area/science/xenobiology)
@@ -34114,7 +34169,6 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
-/obj/structure/reagent_dispensers/fueltank,
/turf/open/floor/plasteel/white,
/area/science/misc_lab)
"rqE" = (
@@ -34459,8 +34513,8 @@
},
/obj/machinery/camera{
c_tag = "AI Chamber - Core";
- network = list("aicore");
- dir = 4
+ dir = 4;
+ network = list("aicore")
},
/turf/open/floor/circuit/off,
/area/ai_monitored/turret_protected/ai)
@@ -34550,9 +34604,9 @@
dir = 4
},
/obj/machinery/turnstile{
+ dir = 8;
name = "Genpop Exit Turnstile";
- req_access_txt = "70";
- dir = 8
+ req_access_txt = "70"
},
/obj/machinery/door/firedoor/border_only{
dir = 4;
@@ -34787,6 +34841,10 @@
},
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
+"rQB" = (
+/obj/structure/reagent_dispensers/fueltank,
+/turf/open/floor/plasteel/white,
+/area/science/mixing)
"rQH" = (
/obj/effect/spawner/structure/window/reinforced,
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
@@ -34891,7 +34949,7 @@
/turf/open/floor/plasteel,
/area/engine/engineering)
"rUd" = (
-/turf/open/openspace/icemoon,
+/turf/open/transparent/openspace/icemoon,
/area/science/mixing)
"rUl" = (
/obj/structure/cable{
@@ -36338,7 +36396,7 @@
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
"sTq" = (
-/turf/open/openspace/icemoon,
+/turf/open/transparent/openspace/icemoon,
/area/engine/atmospherics_engine)
"sTz" = (
/obj/effect/turf_decal/bot_white,
@@ -37658,7 +37716,6 @@
/area/icemoon/surface/outdoors)
"tDO" = (
/obj/machinery/atmospherics/components/unary/portables_connector/visible,
-/obj/machinery/portable_atmospherics/canister/toxins,
/obj/machinery/computer/security/telescreen{
name = "Test Chamber Monitor";
network = list("test");
@@ -37778,8 +37835,8 @@
},
/obj/machinery/camera{
c_tag = "Genetics Research";
- network = list("ss13","medbay");
- dir = 8
+ dir = 8;
+ network = list("ss13","medbay")
},
/turf/open/floor/plasteel/white,
/area/medical/genetics)
@@ -37940,9 +37997,9 @@
/obj/machinery/button/door{
id = "Secure Brig Control";
name = "Brig Control Shutters";
+ pixel_x = -6;
pixel_y = -3;
- req_access_txt = "2";
- pixel_x = -6
+ req_access_txt = "2"
},
/turf/open/floor/plasteel/dark,
/area/security/warden)
@@ -39022,8 +39079,8 @@
"uuY" = (
/obj/machinery/camera{
c_tag = "Toxins Lab West";
- network = list("ss13","rd");
- dir = 4
+ dir = 4;
+ network = list("ss13","rd")
},
/obj/structure/table/reinforced,
/obj/item/assembly/prox_sensor{
@@ -39414,9 +39471,9 @@
pixel_y = 23
},
/obj/machinery/door/window/southright{
+ dir = 8;
name = "Bar Door";
- req_one_access_txt = "25;28";
- dir = 8
+ req_one_access_txt = "25;28"
},
/obj/machinery/door/firedoor/border_only{
dir = 8;
@@ -39568,8 +39625,8 @@
dir = 4
},
/obj/machinery/computer/security/telescreen/prison{
- pixel_x = 29;
- dir = 8
+ dir = 8;
+ pixel_x = 29
},
/turf/open/floor/plasteel/cult,
/area/lawoffice)
@@ -39976,8 +40033,8 @@
dir = 8
},
/obj/structure/chair{
- name = "Judge";
- dir = 4
+ dir = 4;
+ name = "Judge"
},
/turf/open/floor/wood,
/area/security/courtroom)
@@ -40691,8 +40748,8 @@
},
/obj/machinery/button/ignition{
id = "Incinerator";
- pixel_y = 35;
- pixel_x = -1
+ pixel_x = -1;
+ pixel_y = 35
},
/turf/open/floor/plasteel,
/area/engine/atmospherics_engine)
@@ -42599,8 +42656,8 @@
"wtt" = (
/obj/structure/table/wood,
/obj/item/flashlight/lamp/green{
- pixel_y = 13;
- pixel_x = -7
+ pixel_x = -7;
+ pixel_y = 13
},
/obj/item/camera/detective,
/obj/item/hand_labeler{
@@ -42608,8 +42665,8 @@
},
/obj/item/storage/briefcase,
/obj/item/storage/secure/safe{
- pixel_y = 36;
- pixel_x = 6
+ pixel_x = 6;
+ pixel_y = 36
},
/turf/open/floor/carpet,
/area/security/detectives_office)
@@ -44655,8 +44712,8 @@
areastring = "/area/engine/engineering";
dir = 8;
name = "Engineering APC";
- pixel_y = -1;
- pixel_x = -27
+ pixel_x = -27;
+ pixel_y = -1
},
/obj/machinery/firealarm{
dir = 1;
@@ -45215,14 +45272,6 @@
/area/medical/medbay/central)
"ykk" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/obj/machinery/door/firedoor/border_only{
- dir = 1;
- name = "north facing firelock"
- },
-/obj/machinery/door/airlock/research{
- name = "Toxins Lab";
- req_access_txt = "7"
- },
/obj/structure/disposalpipe/segment,
/turf/open/floor/plasteel/white,
/area/science/mixing)
@@ -81154,7 +81203,7 @@ bDW
bEl
bDE
bFK
-bJC
+rQB
prL
fiN
hmX
@@ -81411,7 +81460,7 @@ bDW
bIn
bQP
wOK
-bJC
+fjU
gzZ
gSu
ipY
@@ -82182,7 +82231,7 @@ bDW
mOv
jOB
lYy
-bJC
+fjU
ihE
fJO
eex
@@ -82439,7 +82488,7 @@ bDW
gpp
wbT
nHi
-bJC
+fjU
rDA
fjU
dvO
@@ -82696,7 +82745,7 @@ bEa
kxj
aaw
rqx
-qJV
+fjU
bKL
fJO
jKT
@@ -82953,10 +83002,10 @@ bEa
pHl
aaw
abh
-qJV
+odf
+fjU
fjU
fjU
-acb
qJV
fuG
qJV
@@ -83213,7 +83262,7 @@ cBt
tRe
gPE
syy
-gPE
+dBA
qJV
goM
gxF
@@ -86976,7 +87025,7 @@ now
mKv
sAh
sAh
-sAh
+acb
aar
uEz
uEz
@@ -87233,7 +87282,7 @@ qss
mKv
sAh
sAh
-sAh
+acb
urI
qkO
uEz
@@ -87747,7 +87796,7 @@ qss
sYv
sAh
sAh
-sAh
+acb
urI
uoV
uEz
@@ -88004,7 +88053,7 @@ qss
sYv
sAh
sAh
-sAh
+acb
urI
uoV
uEz
@@ -100079,11 +100128,11 @@ xUL
xUL
xUL
xUL
-xUL
-xUL
-xUL
rGc
jls
+rGc
+cly
+jls
odg
ucC
gUL
@@ -100335,12 +100384,12 @@ bum
bum
bum
bum
-bum
-bum
-bum
rGc
tdX
tdX
+tdX
+cly
+tdX
jPj
ucC
gUL
@@ -100592,12 +100641,12 @@ bum
bum
bum
bum
-bum
-bum
-bum
dQW
tdX
tdX
+tdX
+cly
+tdX
jls
ucC
gUL
@@ -100849,12 +100898,12 @@ bum
bum
bum
bum
-bum
-bum
-bum
rGc
tdX
tdX
+tdX
+cly
+tdX
jPj
ucC
cfs
@@ -101106,12 +101155,12 @@ bum
bum
bum
bum
-bum
-bum
-bum
dQW
tdX
tdX
+tdX
+cly
+tdX
jls
ucC
cfs
@@ -101363,11 +101412,11 @@ bum
bum
bum
bum
-bum
-bum
-bum
-xUL
+rGc
+jPj
dQW
+jPj
+rGc
flw
flw
lFN
@@ -101620,11 +101669,11 @@ bum
bum
bum
bum
-bum
-bum
-bum
-xUL
-xUL
+dQW
+cly
+cly
+cly
+jPj
dQW
jPj
bnU
@@ -101877,9 +101926,9 @@ bum
bum
bum
bum
-bum
-bum
-bum
+xUL
+xUL
+xUL
bDA
bYY
bYY
@@ -102134,9 +102183,9 @@ bum
bum
bum
bum
-bum
-bum
-bum
+xUL
+xUL
+xUL
gjW
xUL
xUL
@@ -102391,9 +102440,9 @@ bum
bum
bum
bum
-bum
-bum
-bum
+xUL
+xUL
+xUL
xUL
xUL
bum
@@ -102648,9 +102697,9 @@ bum
bum
bum
bum
-bum
-bum
-bum
+xUL
+xUL
+xUL
xUL
xUL
sTq
diff --git a/_maps/map_files/debug/multiz.dmm b/_maps/map_files/debug/multiz.dmm
index 4614829679..5a18682129 100644
--- a/_maps/map_files/debug/multiz.dmm
+++ b/_maps/map_files/debug/multiz.dmm
@@ -102,7 +102,7 @@
/turf/open/floor/plasteel,
/area/engine/gravity_generator)
"au" = (
-/turf/open/openspace,
+/turf/open/transparent/openspace,
/area/space)
"av" = (
/obj/structure/stairs{
@@ -1407,7 +1407,7 @@
},
/area/hallway/secondary/service)
"eC" = (
-/turf/open/openspace,
+/turf/open/transparent/openspace,
/area/maintenance/department/bridge)
"eD" = (
/obj/effect/turf_decal/stripes/asteroid/line{
@@ -1542,7 +1542,7 @@
/turf/open/floor/plating,
/area/space)
"iu" = (
-/turf/open/openspace,
+/turf/open/transparent/openspace,
/area/hallway/secondary/service)
"iK" = (
/turf/open/floor/plasteel{
@@ -1593,7 +1593,7 @@
},
/area/hallway/secondary/service)
"nx" = (
-/turf/open/openspace,
+/turf/open/transparent/openspace,
/area/space/nearstation)
"nz" = (
/obj/machinery/light{
@@ -1633,7 +1633,7 @@
/turf/open/floor/plating,
/area/maintenance/department/bridge)
"qo" = (
-/turf/open/openspace,
+/turf/open/transparent/openspace,
/area/engine/storage)
"qR" = (
/obj/effect/turf_decal/stripes/white/line{
@@ -1646,7 +1646,7 @@
/obj/machinery/light{
dir = 8
},
-/turf/open/openspace,
+/turf/open/transparent/openspace,
/area/engine/storage)
"sh" = (
/turf/open/floor/plasteel{
@@ -1746,7 +1746,7 @@
/area/construction)
"Bk" = (
/obj/structure/grille,
-/turf/open/openspace,
+/turf/open/transparent/openspace,
/area/space/nearstation)
"Bm" = (
/obj/machinery/light{
@@ -1876,7 +1876,7 @@
"Ob" = (
/obj/structure/lattice,
/obj/structure/grille,
-/turf/open/openspace,
+/turf/open/transparent/openspace,
/area/space/nearstation)
"Og" = (
/obj/machinery/airalarm/directional/north,
diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm
index a123ccab55..020017c3fe 100644
--- a/_maps/map_files/generic/CentCom.dmm
+++ b/_maps/map_files/generic/CentCom.dmm
@@ -13490,6 +13490,9 @@
/obj/structure/table/wood,
/obj/item/instrument/piano_synth,
/obj/item/instrument/guitar,
+/obj/structure/sign/painting{
+ pixel_x = -32
+ },
/turf/open/indestructible/hotelwood,
/area/centcom/holding)
"Fg" = (
@@ -13794,6 +13797,9 @@
/turf/open/indestructible/hotelwood,
/area/centcom/holding)
"FX" = (
+/obj/structure/sign/painting{
+ pixel_x = 32
+ },
/turf/open/floor/plasteel/stairs,
/area/centcom/holding)
"FZ" = (
@@ -14421,6 +14427,9 @@
dir = 8
},
/obj/structure/musician/piano,
+/obj/structure/sign/painting{
+ pixel_x = -32
+ },
/turf/open/indestructible/hotelwood,
/area/centcom/holding)
"Hk" = (
@@ -16225,6 +16234,12 @@
dir = 1
},
/obj/structure/table/wood,
+/obj/item/storage/crayons,
+/obj/item/storage/crayons,
+/obj/item/storage/crayons,
+/obj/structure/sign/painting{
+ pixel_x = -32
+ },
/turf/open/indestructible/hotelwood,
/area/centcom/holding)
"KU" = (
@@ -16304,6 +16319,14 @@
/obj/item/storage/box/bodybags,
/turf/open/floor/plasteel/white,
/area/centcom/holding)
+"Ll" = (
+/obj/structure/window/reinforced{
+ dir = 1
+ },
+/obj/structure/easel,
+/obj/item/canvas/twentythreeXtwentythree,
+/turf/open/indestructible/hotelwood,
+/area/centcom/holding)
"Lm" = (
/obj/machinery/shower{
dir = 4
@@ -16808,6 +16831,22 @@
},
/turf/open/floor/plasteel,
/area/centcom/supplypod/loading/two)
+"NA" = (
+/obj/structure/window/reinforced{
+ dir = 1
+ },
+/obj/structure/table/wood,
+/obj/item/canvas/twentythreeXtwentythree,
+/obj/item/canvas/twentythreeXtwentythree,
+/obj/item/canvas/twentythreeXtwentythree,
+/obj/item/canvas/twentythreeXnineteen,
+/obj/item/canvas/twentythreeXnineteen,
+/obj/item/canvas/twentythreeXnineteen,
+/obj/item/canvas/nineteenXnineteen,
+/obj/item/canvas/nineteenXnineteen,
+/obj/item/canvas/nineteenXnineteen,
+/turf/open/indestructible/hotelwood,
+/area/centcom/holding)
"NE" = (
/obj/machinery/light{
dir = 4
@@ -16924,6 +16963,12 @@
},
/turf/open/floor/plasteel,
/area/centcom/supplypod/loading/three)
+"On" = (
+/obj/structure/sign/painting{
+ pixel_x = 32
+ },
+/turf/open/indestructible/hotelwood,
+/area/centcom/holding)
"Op" = (
/obj/structure/sink{
dir = 8;
@@ -17910,6 +17955,15 @@
/obj/machinery/light,
/turf/open/floor/plasteel/freezer,
/area/centcom/holding)
+"TD" = (
+/obj/machinery/light{
+ dir = 4
+ },
+/obj/structure/sign/painting{
+ pixel_x = 32
+ },
+/turf/open/indestructible/hotelwood,
+/area/centcom/holding)
"TF" = (
/obj/effect/turf_decal/tile/red{
dir = 8
@@ -45457,8 +45511,8 @@ Nd
AE
CV
Sd
-KT
-Sd
+Ll
+CV
Sd
Sd
Sd
@@ -45714,7 +45768,7 @@ Nd
QJ
Sd
Sd
-KT
+NA
Sd
Sd
Sd
@@ -46226,8 +46280,8 @@ Fh
Fh
Wl
Sd
-MR
-Sd
+TD
+On
FX
Sd
Sd
diff --git a/_maps/multiz_debug.json b/_maps/multiz_debug.json
index 7e39981e23..e916a77d1d 100644
--- a/_maps/multiz_debug.json
+++ b/_maps/multiz_debug.json
@@ -2,5 +2,5 @@
"map_name": "MultiZ Debug",
"map_path": "map_files/debug",
"map_file": "multiz.dmm",
- "traits": [{"Up": 1}, {"Up": 1, "Down": -1}, {"Down": -1}]
+ "traits": [{"Up" : 1, "Linkage" : "Cross"}, {"Up" : 1, "Down" : -1, "Baseturf" : "/turf/open/transparent/openspace", "Linkage" : "Cross"}, {"Down" : -1, "Baseturf" : "/turf/open/transparent/openspace", "Linkage" : "Cross"}]
}
diff --git a/_maps/shuttles/emergency_discoinferno.dmm b/_maps/shuttles/emergency_discoinferno.dmm
index e142208e12..92b515f17e 100644
--- a/_maps/shuttles/emergency_discoinferno.dmm
+++ b/_maps/shuttles/emergency_discoinferno.dmm
@@ -94,7 +94,7 @@
/turf/open/floor/light/colour_cycle,
/area/shuttle/escape)
"r" = (
-/turf/open/floor/mineral/plasma,
+/turf/open/floor/mineral/plasma/disco,
/area/shuttle/escape)
"s" = (
/turf/open/floor/mineral/silver,
@@ -112,7 +112,7 @@
resistance_flags = 2
},
/obj/structure/fans/tiny,
-/turf/open/floor/mineral/plasma,
+/turf/open/floor/mineral/plasma/disco,
/area/shuttle/escape)
"v" = (
/obj/machinery/jukebox/disco/indestructible,
diff --git a/_maps/snaxi.json b/_maps/snaxi.json
index cb1917b6f6..3fc8eba15d 100644
--- a/_maps/snaxi.json
+++ b/_maps/snaxi.json
@@ -33,7 +33,7 @@
"Linkage":null,
"Gravity":true,
"Ice Ruins Underground":true,
- "Baseturf":"/turf/open/openspace/icemoon"
+ "Baseturf":"/turf/open/transparent/openspace/icemoon"
},
{
"Down":-1,
diff --git a/byond-extools.dll b/byond-extools.dll
index 4910fad01b..bd6b34c48e 100644
Binary files a/byond-extools.dll and b/byond-extools.dll differ
diff --git a/code/__DEFINES/_flags/_flags.dm b/code/__DEFINES/_flags/_flags.dm
index 0734feaa42..ffa3f1c751 100644
--- a/code/__DEFINES/_flags/_flags.dm
+++ b/code/__DEFINES/_flags/_flags.dm
@@ -98,7 +98,7 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define ZAP_MOB_DAMAGE (1<<3)
#define ZAP_MOB_STUN (1<<4)
-#define ZAP_DEFAULT_FLAGS ALL
+#define ZAP_DEFAULT_FLAGS ZAP_MOB_STUN | ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE
#define ZAP_FUSION_FLAGS ZAP_OBJ_DAMAGE | ZAP_MOB_DAMAGE | ZAP_MOB_STUN
#define ZAP_SUPERMATTER_FLAGS NONE
diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm
index b883a54209..a3e5423753 100644
--- a/code/__DEFINES/antagonists.dm
+++ b/code/__DEFINES/antagonists.dm
@@ -63,6 +63,16 @@
#define CONTRACT_UPLINK_PAGE_CONTRACTS "CONTRACTS"
#define CONTRACT_UPLINK_PAGE_HUB "HUB"
+
+///Heretics --
+#define IS_HERETIC(mob) (mob.mind?.has_antag_datum(/datum/antagonist/heretic))
+
+#define PATH_SIDE "Side"
+
+#define PATH_ASH "Ash"
+#define PATH_RUST "Rust"
+#define PATH_FLESH "Flesh"
+
//Overthrow time to update heads obj
#define OBJECTIVE_UPDATING_TIME 300
@@ -91,4 +101,4 @@
#define BLOB_REROLL_TIME 2400 // blob gets a free reroll every X time
#define BLOB_SPREAD_COST 4
#define BLOB_ATTACK_REFUND 2 //blob refunds this much if it attacks and doesn't spread
-#define BLOB_REFLECTOR_COST 15
\ No newline at end of file
+#define BLOB_REFLECTOR_COST 15
diff --git a/code/__DEFINES/atom_hud.dm b/code/__DEFINES/atom_hud.dm
index 01f14c748e..386473a3ae 100644
--- a/code/__DEFINES/atom_hud.dm
+++ b/code/__DEFINES/atom_hud.dm
@@ -60,6 +60,7 @@
#define ANTAG_HUD_BROTHER 23
#define ANTAG_HUD_BLOODSUCKER 24
#define ANTAG_HUD_FUGITIVE 25
+#define ANTAG_HUD_HERETIC 26
// Notification action types
#define NOTIFY_JUMP "jump"
diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index 6900f36a33..65994dda5a 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -15,22 +15,31 @@
//////////////////////////////////////////////////////////////////
// /datum signals
-#define COMSIG_COMPONENT_ADDED "component_added" //sent to the new datum parent when a component is added to them: (/datum/component)
-#define COMSIG_COMPONENT_REMOVING "component_removing" //sent to the datum parent before a component is removed from them because of RemoveComponent: (/datum/component)
-#define COMSIG_COMPONENT_UNREGISTER_PARENT "component_unregister_parent" //sent to the component itself when unregistered from a parent
-#define COMSIG_COMPONENT_REGISTER_PARENT "component_register_parent" //sent to the component itself when registered to a parent
-#define COMSIG_PARENT_PREQDELETED "parent_preqdeleted" //before a datum's Destroy() is called: (force), returning a nonzero value will cancel the qdel operation
-#define COMSIG_PARENT_QDELETING "parent_qdeleting" //just before a datum's Destroy() is called: (force), at this point none of the other components chose to interrupt qdel and Destroy will be called
-
-/// Trait signals
-#define COMPONENT_ADD_TRAIT (1<<0)
-#define COMPONENT_REMOVE_TRAIT (1<<1)
+/// when a component is added to a datum: (/datum/component)
+#define COMSIG_COMPONENT_ADDED "component_added"
+/// before a component is removed from a datum because of RemoveComponent: (/datum/component)
+#define COMSIG_COMPONENT_REMOVING "component_removing"
+/// before a datum's Destroy() is called: (force), returning a nonzero value will cancel the qdel operation
+#define COMSIG_PARENT_PREQDELETED "parent_preqdeleted"
+/// just before a datum's Destroy() is called: (force), at this point none of the other components chose to interrupt qdel and Destroy will be called
+#define COMSIG_PARENT_QDELETING "parent_qdeleting"
+/// generic topic handler (usr, href_list)
+#define COMSIG_TOPIC "handle_topic"
/// fires on the target datum when an element is attached to it (/datum/element)
#define COMSIG_ELEMENT_ATTACH "element_attach"
/// fires on the target datum when an element is attached to it (/datum/element)
#define COMSIG_ELEMENT_DETACH "element_detach"
+/// sent to the component itself when unregistered from a parent
+#define COMSIG_COMPONENT_UNREGISTER_PARENT "component_unregister_parent"
+/// sent to the component itself when registered to a parent
+#define COMSIG_COMPONENT_REGISTER_PARENT "component_register_parent"
+
+/// Trait signals
+#define COMPONENT_ADD_TRAIT (1<<0)
+#define COMPONENT_REMOVE_TRAIT (1<<1)
+
// /atom signals
//from base of atom/proc/Initialize(): sent any time a new atom is created
#define COMSIG_ATOM_CREATED "atom_created"
@@ -56,30 +65,54 @@
#define COMSIG_ATOM_EXIT "atom_exit" //from base of atom/Exit(): (/atom/movable/exiting, /atom/newloc)
#define COMPONENT_ATOM_BLOCK_EXIT 1
#define COMSIG_ATOM_EXITED "atom_exited" //from base of atom/Exited(): (atom/movable/exiting, atom/newloc)
-#define COMSIG_ATOM_EX_ACT "atom_ex_act" //from base of atom/ex_act(): (severity, target)
-#define COMSIG_ATOM_EMP_ACT "atom_emp_act" //from base of atom/emp_act(): (severity)
-#define COMSIG_ATOM_FIRE_ACT "atom_fire_act" //from base of atom/fire_act(): (exposed_temperature, exposed_volume)
-#define COMSIG_ATOM_BULLET_ACT "atom_bullet_act" //from base of atom/bullet_act(): (/obj/item/projectile, def_zone)
-#define COMSIG_ATOM_BLOB_ACT "atom_blob_act" //from base of atom/blob_act(): (/obj/structure/blob)
-#define COMSIG_ATOM_ACID_ACT "atom_acid_act" //from base of atom/acid_act(): (acidpwr, acid_volume)
-#define COMSIG_ATOM_EMAG_ACT "atom_emag_act" //from base of atom/emag_act(): ()
-#define COMSIG_ATOM_RAD_ACT "atom_rad_act" //from base of atom/rad_act(intensity)
-#define COMSIG_ATOM_NARSIE_ACT "atom_narsie_act" //from base of atom/narsie_act(): ()
-#define COMSIG_ATOM_RATVAR_ACT "atom_ratvar_act" //from base of atom/ratvar_act(): ()
-#define COMSIG_ATOM_RCD_ACT "atom_rcd_act" //from base of atom/rcd_act(): (/mob, /obj/item/construction/rcd, passed_mode)
-#define COMSIG_ATOM_SING_PULL "atom_sing_pull" //from base of atom/singularity_pull(): (S, current_size)
-#define COMSIG_ATOM_SET_LIGHT "atom_set_light" //from base of atom/set_light(): (l_range, l_power, l_color)
-#define COMSIG_ATOM_DIR_CHANGE "atom_dir_change" //from base of atom/setDir(): (old_dir, new_dir)
-#define COMSIG_ATOM_CONTENTS_DEL "atom_contents_del" //from base of atom/handle_atom_del(): (atom/deleted)
-#define COMSIG_ATOM_HAS_GRAVITY "atom_has_gravity" //from base of atom/has_gravity(): (turf/location, list/forced_gravities)
-#define COMSIG_ATOM_RAD_PROBE "atom_rad_probe" //from proc/get_rad_contents(): ()
- #define COMPONENT_BLOCK_RADIATION 1
-#define COMSIG_ATOM_RAD_CONTAMINATING "atom_rad_contam" //from base of datum/radiation_wave/radiate(): (strength)
- #define COMPONENT_BLOCK_CONTAMINATION 1
-#define COMSIG_ATOM_RAD_WAVE_PASSING "atom_rad_wave_pass" //from base of datum/radiation_wave/check_obstructions(): (datum/radiation_wave, width)
- #define COMPONENT_RAD_WAVE_HANDLED 1
-#define COMSIG_ATOM_CANREACH "atom_can_reach" //from internal loop in atom/movable/proc/CanReach(): (list/next)
- #define COMPONENT_BLOCK_REACH 1
+///from base of atom/ex_act(): (severity, target)
+#define COMSIG_ATOM_EX_ACT "atom_ex_act"
+///from base of atom/emp_act(): (severity)
+#define COMSIG_ATOM_EMP_ACT "atom_emp_act"
+///from base of atom/fire_act(): (exposed_temperature, exposed_volume)
+#define COMSIG_ATOM_FIRE_ACT "atom_fire_act"
+///from base of atom/bullet_act(): (/obj/projectile, def_zone)
+#define COMSIG_ATOM_BULLET_ACT "atom_bullet_act"
+///from base of atom/blob_act(): (/obj/structure/blob)
+#define COMSIG_ATOM_BLOB_ACT "atom_blob_act"
+///from base of atom/acid_act(): (acidpwr, acid_volume)
+#define COMSIG_ATOM_ACID_ACT "atom_acid_act"
+///from base of atom/emag_act(): (/mob/user)
+#define COMSIG_ATOM_EMAG_ACT "atom_emag_act"
+///from base of atom/rad_act(intensity)
+#define COMSIG_ATOM_RAD_ACT "atom_rad_act"
+///from base of atom/narsie_act(): ()
+#define COMSIG_ATOM_NARSIE_ACT "atom_narsie_act"
+///from base of atom/ratvar_act(): ()
+#define COMSIG_ATOM_RATVAR_ACT "atom_ratvar_act"
+///from base of atom/rcd_act(): (/mob, /obj/item/construction/rcd, passed_mode)
+#define COMSIG_ATOM_RCD_ACT "atom_rcd_act"
+///from base of atom/singularity_pull(): (S, current_size)
+#define COMSIG_ATOM_SING_PULL "atom_sing_pull"
+///from obj/machinery/bsa/full/proc/fire(): ()
+#define COMSIG_ATOM_BSA_BEAM "atom_bsa_beam_pass"
+ #define COMSIG_ATOM_BLOCKS_BSA_BEAM (1<<0)
+///from base of atom/set_light(): (l_range, l_power, l_color)
+#define COMSIG_ATOM_SET_LIGHT "atom_set_light"
+///from base of atom/setDir(): (old_dir, new_dir). Called before the direction changes.
+#define COMSIG_ATOM_DIR_CHANGE "atom_dir_change"
+///from base of atom/handle_atom_del(): (atom/deleted)
+#define COMSIG_ATOM_CONTENTS_DEL "atom_contents_del"
+///from base of atom/has_gravity(): (turf/location, list/forced_gravities)
+#define COMSIG_ATOM_HAS_GRAVITY "atom_has_gravity"
+///from proc/get_rad_contents(): ()
+#define COMSIG_ATOM_RAD_PROBE "atom_rad_probe"
+ #define COMPONENT_BLOCK_RADIATION (1<<0)
+///from base of datum/radiation_wave/radiate(): (strength)
+#define COMSIG_ATOM_RAD_CONTAMINATING "atom_rad_contam"
+ #define COMPONENT_BLOCK_CONTAMINATION (1<<0)
+///from base of datum/radiation_wave/check_obstructions(): (datum/radiation_wave, width)
+#define COMSIG_ATOM_RAD_WAVE_PASSING "atom_rad_wave_pass"
+ #define COMPONENT_RAD_WAVE_HANDLED (1<<0)
+///from internal loop in atom/movable/proc/CanReach(): (list/next)
+#define COMSIG_ATOM_CANREACH "atom_can_reach"
+ #define COMPONENT_BLOCK_REACH (1<<0)
+
#define COMSIG_ATOM_SCREWDRIVER_ACT "atom_screwdriver_act" //from base of atom/screwdriver_act(): (mob/living/user, obj/item/I)
#define COMSIG_ATOM_INTERCEPT_TELEPORT "intercept_teleport" //called when teleporting into a protected turf: (channel, turf/origin, turf/destination)
#define COMPONENT_BLOCK_TELEPORT 1
@@ -279,6 +312,7 @@
#define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct" //from base of obj/deconstruct(): (disassembled)
#define COMSIG_OBJ_BREAK "obj_break" //from base of /obj/obj_break(): (damage_flag)
#define COMSIG_OBJ_SETANCHORED "obj_setanchored" //called in /obj/structure/setAnchored(): (value)
+#define COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH "obj_default_unfasten_wrench" //called exclusively in plumbing, for now
#define COMSIG_OBJ_ATTACK_GENERIC "obj_attack_generic" //from base of atom/animal_attack(): (/mob/user)
#define COMPONENT_STOP_GENERIC_ATTACK 1
diff --git a/code/__DEFINES/footsteps.dm b/code/__DEFINES/footsteps.dm
index 2dd66b9833..215e287adf 100644
--- a/code/__DEFINES/footsteps.dm
+++ b/code/__DEFINES/footsteps.dm
@@ -7,6 +7,8 @@
#define FOOTSTEP_WATER "water"
#define FOOTSTEP_LAVA "lava"
#define FOOTSTEP_MEAT "meat"
+#define FOOTSTEP_RUST "rust"
+
//barefoot sounds
#define FOOTSTEP_WOOD_BAREFOOT "woodbarefoot"
#define FOOTSTEP_WOOD_CLAW "woodclaw"
@@ -91,7 +93,9 @@ GLOBAL_LIST_INIT(footstep, list(
'sound/effects/footstep/lava2.ogg',
'sound/effects/footstep/lava3.ogg'), 100, 0),
FOOTSTEP_MEAT = list(list(
- 'sound/effects/meatslap.ogg'), 100, 0)
+ 'sound/effects/meatslap.ogg'), 100, 0),
+ FOOTSTEP_RUST = list(list(
+ 'sound/effects/footstep/rustystep1.ogg'), 100, 0)
))
//bare footsteps lists
@@ -135,7 +139,9 @@ GLOBAL_LIST_INIT(barefootstep, list(
'sound/effects/footstep/lava2.ogg',
'sound/effects/footstep/lava3.ogg'), 100, 0),
FOOTSTEP_MEAT = list(list(
- 'sound/effects/meatslap.ogg'), 100, 0)
+ 'sound/effects/meatslap.ogg'), 100, 0),
+ FOOTSTEP_RUST = list(list(
+ 'sound/effects/footstep/rustystep1.ogg'), 100, 0)
))
//claw footsteps lists
@@ -179,7 +185,9 @@ GLOBAL_LIST_INIT(clawfootstep, list(
'sound/effects/footstep/lava2.ogg',
'sound/effects/footstep/lava3.ogg'), 100, 0),
FOOTSTEP_MEAT = list(list(
- 'sound/effects/meatslap.ogg'), 100, 0)
+ 'sound/effects/meatslap.ogg'), 100, 0),
+ FOOTSTEP_RUST = list(list(
+ 'sound/effects/footstep/rustystep1.ogg'), 100, 0)
))
//heavy footsteps list
@@ -197,5 +205,7 @@ GLOBAL_LIST_INIT(heavyfootstep, list(
'sound/effects/footstep/lava2.ogg',
'sound/effects/footstep/lava3.ogg'), 100, 0),
FOOTSTEP_MEAT = list(list(
- 'sound/effects/meatslap.ogg'), 100, 0)
+ 'sound/effects/meatslap.ogg'), 100, 0),
+ FOOTSTEP_RUST = list(list(
+ 'sound/effects/footstep/rustystep1.ogg'), 150, 2)
))
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index d66521d945..55be13834d 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -17,7 +17,7 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
/turf/open/chasm,
/turf/open/lava,
/turf/open/water,
- /turf/open/openspace
+ /turf/open/transparent/openspace
)))
#define isgroundlessturf(A) (is_type_in_typecache(A, GLOB.turfs_without_ground))
@@ -44,6 +44,8 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
#define isplatingturf(A) (istype(A, /turf/open/floor/plating))
+#define istransparentturf(A) (istype(A, /turf/open/transparent))
+
//Mobs
#define isliving(A) (istype(A, /mob/living))
diff --git a/code/__DEFINES/logging.dm b/code/__DEFINES/logging.dm
index 71de692410..ecb58f1291 100644
--- a/code/__DEFINES/logging.dm
+++ b/code/__DEFINES/logging.dm
@@ -19,6 +19,7 @@
#define INVESTIGATE_FERMICHEM "fermichem"
#define INVESTIGATE_RCD "rcd"
#define INVESTIGATE_CRYOGENICS "cryogenics"
+#define INVESTIGATE_GHOST "ghost"
// Logging types for log_message()
#define LOG_ATTACK (1 << 0)
diff --git a/code/__DEFINES/maths.dm b/code/__DEFINES/maths.dm
index 24726b8058..370f869c48 100644
--- a/code/__DEFINES/maths.dm
+++ b/code/__DEFINES/maths.dm
@@ -46,6 +46,8 @@
// Cosecant
#define CSC(x) (1 / sin(x))
+#define ATAN2(x, y) ( !(x) && !(y) ? 0 : (y) >= 0 ? arccos((x) / sqrt((x)*(x) + (y)*(y))) : -arccos((x) / sqrt((x)*(x) + (y)*(y))) )
+
// Greatest Common Divisor - Euclid's algorithm
/proc/Gcd(a, b)
return b ? Gcd(b, (a) % (b)) : a
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index 782095f883..9c39446a67 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -64,7 +64,6 @@
#define DEFAULT_BODYPART_ICON 'icons/mob/human_parts.dmi'
#define DEFAULT_BODYPART_ICON_ORGANIC 'icons/mob/human_parts_greyscale.dmi'
#define DEFAULT_BODYPART_ICON_ROBOTIC 'icons/mob/augmentation/augments.dmi'
-#define DEFAULT_BODYPART_ICON_CITADEL 'modular_citadel/icons/mob/mutant_bodyparts.dmi'
#define MONKEY_BODYPART "monkey"
#define ALIEN_BODYPART "alien"
@@ -332,3 +331,5 @@
/// If you examine the same atom twice in this timeframe, we call examine_more() instead of examine()
#define EXAMINE_MORE_TIME 1 SECONDS
+
+#define SILENCE_RANGED_MESSAGE (1<<0)
diff --git a/code/__DEFINES/plumbing.dm b/code/__DEFINES/plumbing.dm
new file mode 100644
index 0000000000..5ea7c46b42
--- /dev/null
+++ b/code/__DEFINES/plumbing.dm
@@ -0,0 +1,9 @@
+#define FIRST_DUCT_LAYER 1
+#define SECOND_DUCT_LAYER 2
+#define THIRD_DUCT_LAYER 4
+#define FOURTH_DUCT_LAYER 8
+#define FIFTH_DUCT_LAYER 16
+
+#define DUCT_LAYER_DEFAULT THIRD_DUCT_LAYER
+
+#define MACHINE_REAGENT_TRANSFER 10
diff --git a/code/__DEFINES/pool.dm b/code/__DEFINES/pool.dm
index 64bbd20b19..1bf39dcb1d 100644
--- a/code/__DEFINES/pool.dm
+++ b/code/__DEFINES/pool.dm
@@ -8,5 +8,5 @@
GLOBAL_LIST_INIT(blacklisted_pool_reagents, list(
/datum/reagent/toxin/plasma, /datum/reagent/oxygen, /datum/reagent/nitrous_oxide, /datum/reagent/nitrogen, //gases
/datum/reagent/fermi, //blanket fermichem ban sorry. this also covers mkultra, genital enlargers, etc etc.
- /datum/reagent/consumable/femcum, /datum/reagent/consumable/semen //NO.
+ /datum/reagent/consumable/semen //NO.
))
diff --git a/code/__DEFINES/qdel.dm b/code/__DEFINES/qdel.dm
index 4296e3c2e9..63259774fa 100644
--- a/code/__DEFINES/qdel.dm
+++ b/code/__DEFINES/qdel.dm
@@ -6,10 +6,17 @@
#define QDEL_HINT_IWILLGC 2 //functionally the same as the above. qdel should assume the object will gc on its own, and not check it.
#define QDEL_HINT_HARDDEL 3 //qdel should assume this object won't gc, and queue a hard delete using a hard reference.
#define QDEL_HINT_HARDDEL_NOW 4 //qdel should assume this object won't gc, and hard del it post haste.
-#define QDEL_HINT_FINDREFERENCE 5 //functionally identical to QDEL_HINT_QUEUE if TESTING is not enabled in _compiler_options.dm.
- //if TESTING is enabled, qdel will call this object's find_references() verb.
-#define QDEL_HINT_IFFAIL_FINDREFERENCE 6 //Above but only if gc fails.
-//defines for the gc_destroyed var
+
+#ifdef LEGACY_REFERENCE_TRACKING
+/** If LEGACY_REFERENCE_TRACKING is enabled, qdel will call this object's find_references() verb.
+ *
+ * Functionally identical to QDEL_HINT_QUEUE if GC_FAILURE_HARD_LOOKUP is not enabled in _compiler_options.dm.
+*/
+#define QDEL_HINT_FINDREFERENCE 5
+/// Behavior as QDEL_HINT_FINDREFERENCE, but only if the GC fails and a hard delete is forced.
+#define QDEL_HINT_IFFAIL_FINDREFERENCE 6
+#endif
+
#define GC_QUEUE_CHECK 1
#define GC_QUEUE_HARDDELETE 2
diff --git a/code/__DEFINES/reagents.dm b/code/__DEFINES/reagents.dm
index f4beef7ee8..44e97ef345 100644
--- a/code/__DEFINES/reagents.dm
+++ b/code/__DEFINES/reagents.dm
@@ -57,6 +57,10 @@
#define ADD_REAGENT 2 // reagent added
#define REM_REAGENT 3 // reagent removed (may still exist)
+
+#define PILL_STYLE_COUNT 22 //Update this if you add more pill icons or you die (literally, we'll toss a nuke at whever your ip turns up)
+#define RANDOM_PILL_STYLE 22 //Dont change this one though
+
#define THRESHOLD_UNHUSK 50 // health threshold for synthflesh/rezadone to unhusk someone
//reagent bitflags, used for altering how they works
diff --git a/code/__DEFINES/rockpaperscissors.dm b/code/__DEFINES/rockpaperscissors.dm
new file mode 100644
index 0000000000..77ba81938d
--- /dev/null
+++ b/code/__DEFINES/rockpaperscissors.dm
@@ -0,0 +1,7 @@
+#define ROCKPAPERSCISSORS_RANGE 3
+#define ROCKPAPERSCISSORS_TIME_LIMIT 20 SECONDS
+
+#define ROCKPAPERSCISSORS_LOSE "lose"
+#define ROCKPAPERSCISSORS_WIN "win"
+#define ROCKPAPERSCISSORS_TIE "tie"
+#define ROCKPAPERSCISSORS_NOT_DECIDED "not_decided"
\ No newline at end of file
diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm
index 7fabb74157..d7487eb54b 100644
--- a/code/__DEFINES/role_preferences.dm
+++ b/code/__DEFINES/role_preferences.dm
@@ -17,6 +17,7 @@
#define ROLE_ALIEN "xenomorph"
#define ROLE_PAI "pAI"
#define ROLE_CULTIST "cultist"
+#define ROLE_HERETIC "Heretic"
#define ROLE_BLOB "blob"
#define ROLE_NINJA "space ninja"
#define ROLE_MONKEY "monkey"
@@ -64,6 +65,7 @@ GLOBAL_LIST_INIT(special_roles, list(
ROLE_INTERNAL_AFFAIRS = /datum/game_mode/traitor/internal_affairs,
ROLE_SENTIENCE,
ROLE_GANG = /datum/game_mode/gang,
+ ROLE_HERETIC = /datum/game_mode/heretics,
ROLE_BLOODSUCKER = /datum/game_mode/bloodsucker
//ROLE_MONSTERHUNTER Disabled for now
))
diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm
index 9a3b5d55f4..bfff1dc629 100644
--- a/code/__DEFINES/status_effects.dm
+++ b/code/__DEFINES/status_effects.dm
@@ -111,6 +111,10 @@
#define STATUS_EFFECT_LIMP /datum/status_effect/limp //For when you have a busted leg (or two!) and want additional slowdown when walking on that leg
+#define STATUS_EFFECT_AMOK /datum/status_effect/amok //Makes the target automatically strike out at adjecent non-heretics.
+
+#define STATUS_EFFECT_CLOUDSTRUCK /datum/status_effect/cloudstruck //blinds and applies an overlay.
+
/// shoves inflict this to indicate the next shove while this is in effect should disarm guns
#define STATUS_EFFECT_OFF_BALANCE /datum/status_effect/off_balance
diff --git a/code/__DEFINES/storage/volumetrics.dm b/code/__DEFINES/storage/volumetrics.dm
index c3f45976ce..e6b732e083 100644
--- a/code/__DEFINES/storage/volumetrics.dm
+++ b/code/__DEFINES/storage/volumetrics.dm
@@ -24,7 +24,10 @@ GLOBAL_LIST_INIT(default_weight_class_to_volume, list(
// Let's keep all of this in one place. given what we put above anyways..
// volume amount for items
+/// volume for a data disk
#define ITEM_VOLUME_DISK 1
+/// volume for a shotgun stripper clip holding 4 shells
+#define ITEM_VOLUME_STRIPPER_CLIP (DEFAULT_VOLUME_NORMAL * 0.5)
// #define SAMPLE_VOLUME_AMOUNT 2
diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm
index 7a188281d0..81b5c5620f 100644
--- a/code/__DEFINES/subsystems.dm
+++ b/code/__DEFINES/subsystems.dm
@@ -146,11 +146,11 @@
#define SSAIR_EQUALIZE 8
#define SSAIR_ACTIVETURFS 9
+// |= on overlays is not actually guaranteed to not add same appearances but we're optimistically using it anyway.
#define COMPILE_OVERLAYS(A)\
if (TRUE) {\
var/list/ad = A.add_overlays;\
var/list/rm = A.remove_overlays;\
- var/list/po = A.priority_overlays;\
if(LAZYLEN(rm)){\
A.overlays -= rm;\
A.remove_overlays = null;\
@@ -159,11 +159,5 @@
A.overlays |= ad;\
A.add_overlays = null;\
}\
- if(LAZYLEN(po)){\
- A.overlays |= po;\
- }\
- else{\
- A.priority_overlays = null;\
- }\
A.flags_1 &= ~OVERLAY_QUEUED_1;\
}
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index e8f584cf75..674cc16980 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -104,7 +104,9 @@
#define TRAIT_RESISTCOLD "resist_cold"
#define TRAIT_RESISTHIGHPRESSURE "resist_high_pressure"
#define TRAIT_RESISTLOWPRESSURE "resist_low_pressure"
+#define TRAIT_BOMBIMMUNE "bomb_immunity"
#define TRAIT_RADIMMUNE "rad_immunity"
+#define TRAIT_GENELESS "geneless"
#define TRAIT_VIRUSIMMUNE "virus_immunity"
#define TRAIT_PIERCEIMMUNE "pierce_immunity"
#define TRAIT_NODISMEMBER "dismember_immunity"
@@ -257,6 +259,7 @@
#define CURSED_ITEM_TRAIT "cursed-item" // The item is magically cursed
#define ABSTRACT_ITEM_TRAIT "abstract-item"
#define STATUS_EFFECT_TRAIT "status-effect"
+#define CLOTHING_TRAIT "clothing"
#define ROUNDSTART_TRAIT "roundstart" //cannot be removed without admin intervention
#define GHOSTROLE_TRAIT "ghostrole"
#define APHRO_TRAIT "aphro"
@@ -311,4 +314,4 @@
#define ACTIVE_BLOCK_TRAIT "active_block"
/// This trait is added by the parry system.
#define ACTIVE_PARRY_TRAIT "active_parry"
-#define STICKY_NODROP "sticky-nodrop" //sticky nodrop sounds like a bad soundcloud rapper's name
\ No newline at end of file
+#define STICKY_NODROP "sticky-nodrop" //sticky nodrop sounds like a bad soundcloud rapper's name
diff --git a/code/__DEFINES/vv.dm b/code/__DEFINES/vv.dm
index 101330cc8b..fe46fdc710 100644
--- a/code/__DEFINES/vv.dm
+++ b/code/__DEFINES/vv.dm
@@ -75,6 +75,7 @@
#define VV_HK_MARK "mark"
#define VV_HK_ADDCOMPONENT "addcomponent"
#define VV_HK_MODIFY_TRAITS "modtraits"
+#define VV_HK_VIEW_REFERENCES "viewreferences"
// /datum/gas_mixture
#define VV_HK_SET_MOLES "set_moles"
diff --git a/code/__HELPERS/cmp.dm b/code/__HELPERS/cmp.dm
index a688d20451..4ee622961a 100644
--- a/code/__HELPERS/cmp.dm
+++ b/code/__HELPERS/cmp.dm
@@ -128,6 +128,10 @@ GLOBAL_VAR_INIT(cmp_field, "name")
else
return B.required_temp - A.required_temp //return hottest
+
+/proc/cmp_mob_realname_dsc(mob/A,mob/B)
+ return sorttext(A.real_name,B.real_name)
+
/proc/cmp_job_display_asc(datum/job/A, datum/job/B)
return A.display_order - B.display_order
@@ -135,4 +139,4 @@ GLOBAL_VAR_INIT(cmp_field, "name")
return sorttext(initial(b.name),initial(a.name))
/proc/cmp_typepaths_asc(A, B)
- return sorttext("[B]","[A]")
\ No newline at end of file
+ return sorttext("[B]","[A]")
diff --git a/code/__HELPERS/donator_groupings.dm b/code/__HELPERS/donator_groupings.dm
index bdff20553a..4305fb1ed5 100644
--- a/code/__HELPERS/donator_groupings.dm
+++ b/code/__HELPERS/donator_groupings.dm
@@ -17,9 +17,9 @@ For fast lookups, this is generated using regenerate_donator_grouping_list()
/proc/regenerate_donator_grouping_list()
GLOB.donators_by_group = list() //reinit everything
var/list/donator_list = GLOB.donators_by_group //cache
- var/list/tier_1 = TIER_1_DONATORS
- donator_list[DONATOR_GROUP_TIER_1] = tier_1.Copy() //The .Copy() is to "decouple"/make a new list, rather than letting the global list impact the config list.
- var/list/tier_2 = tier_1 + TIER_2_DONATORS //Using + on lists implies making new lists, so we don't need to manually Copy().
+ var/list/tier_3 = TIER_3_DONATORS
+ donator_list[DONATOR_GROUP_TIER_3] = tier_3.Copy() //The .Copy() is to "decouple"/make a new list, rather than letting the global list impact the config list.
+ var/list/tier_2 = tier_3 + TIER_2_DONATORS //Using + on lists implies making new lists, so we don't need to manually Copy().
donator_list[DONATOR_GROUP_TIER_2] = tier_2
- var/list/tier_3 = tier_2 + TIER_3_DONATORS
- donator_list[DONATOR_GROUP_TIER_3] = tier_3
+ var/list/tier_1 = tier_2 + TIER_1_DONATORS
+ donator_list[DONATOR_GROUP_TIER_1] = tier_1
diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm
index d66e83d651..1119ef44ed 100644
--- a/code/__HELPERS/global_lists.dm
+++ b/code/__HELPERS/global_lists.dm
@@ -37,10 +37,10 @@
//CIT CHANGES START HERE, ADDS SNOWFLAKE BODYPARTS AND MORE
//mammal bodyparts (fucking furries)
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_body_markings, GLOB.mam_body_markings_list)
- init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_tails, GLOB.mam_tails_list)
- init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_ears, GLOB.mam_ears_list)
- init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_snouts, GLOB.mam_snouts_list)
- init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_tails_animated, GLOB.mam_tails_animated_list)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/mam_tails, GLOB.mam_tails_list)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/ears/mam_ears, GLOB.mam_ears_list)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/snouts/mam_snouts, GLOB.mam_snouts_list)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/tails_animated/mam_tails_animated, GLOB.mam_tails_animated_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/taur, GLOB.taur_list)
//xeno parts (hiss?)
init_sprite_accessory_subtypes(/datum/sprite_accessory/xeno_head, GLOB.xeno_head_list)
diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm
index c4964022e5..52e26b67e7 100644
--- a/code/__HELPERS/mobs.dm
+++ b/code/__HELPERS/mobs.dm
@@ -93,16 +93,16 @@
if(!GLOB.mam_body_markings_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_body_markings, GLOB.mam_body_markings_list)
if(!GLOB.mam_tails_list.len)
- init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_tails, GLOB.mam_tails_list)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/mam_tails, GLOB.mam_tails_list)
if(!GLOB.mam_ears_list.len)
- init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_ears, GLOB.mam_ears_list)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/ears/mam_ears, GLOB.mam_ears_list)
if(!GLOB.mam_snouts_list.len)
- init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_snouts, GLOB.mam_snouts_list)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/snouts/mam_snouts, GLOB.mam_snouts_list)
//snowflake check so people's ckey features don't get randomly put on unmonkeys/spawns
var/list/snowflake_mam_tails_list = list()
for(var/mtpath in GLOB.mam_tails_list)
- var/datum/sprite_accessory/mam_tails/instance = GLOB.mam_tails_list[mtpath]
+ var/datum/sprite_accessory/tails/mam_tails/instance = GLOB.mam_tails_list[mtpath]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if(intendedspecies && S.recommended_species && !S.recommended_species.Find(intendedspecies))
@@ -120,7 +120,7 @@
snowflake_markings_list[S.name] = mmpath
var/list/snowflake_ears_list = list()
for(var/mepath in GLOB.mam_ears_list)
- var/datum/sprite_accessory/mam_ears/instance = GLOB.mam_ears_list[mepath]
+ var/datum/sprite_accessory/ears/mam_ears/instance = GLOB.mam_ears_list[mepath]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if(intendedspecies && S.recommended_species && !S.recommended_species.Find(intendedspecies))
@@ -129,7 +129,7 @@
snowflake_ears_list[S.name] = mepath
var/list/snowflake_mam_snouts_list = list()
for(var/mspath in GLOB.mam_snouts_list)
- var/datum/sprite_accessory/mam_snouts/instance = GLOB.mam_snouts_list[mspath]
+ var/datum/sprite_accessory/snouts/mam_snouts/instance = GLOB.mam_snouts_list[mspath]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if(intendedspecies && S.recommended_species && !S.recommended_species.Find(intendedspecies))
@@ -138,7 +138,7 @@
snowflake_mam_snouts_list[S.name] = mspath
var/list/snowflake_ipc_antenna_list = list()
for(var/mspath in GLOB.ipc_antennas_list)
- var/datum/sprite_accessory/mam_snouts/instance = GLOB.ipc_antennas_list[mspath]
+ var/datum/sprite_accessory/snouts/mam_snouts/instance = GLOB.ipc_antennas_list[mspath]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if(intendedspecies && S.recommended_species && !S.recommended_species.Find(intendedspecies))
diff --git a/code/_compile_options.dm b/code/_compile_options.dm
index 9a36c626ba..0e0bd4ffaa 100644
--- a/code/_compile_options.dm
+++ b/code/_compile_options.dm
@@ -11,15 +11,28 @@
#ifdef TESTING
#define DATUMVAR_DEBUGGING_MODE
-//#define GC_FAILURE_HARD_LOOKUP //makes paths that fail to GC call find_references before del'ing.
- //implies FIND_REF_NO_CHECK_TICK
+/*
+* Enables extools-powered reference tracking system, letting you see what is referencing objects that refuse to hard delete.
+*
+* * Requires TESTING to be defined to work.
+*/
+//#define REFERENCE_TRACKING
-//#define FIND_REF_NO_CHECK_TICK //Sets world.loop_checks to false and prevents find references from sleeping
+///Method of tracking references without using extools. Slower, kept to avoid over-reliance on extools.
+//#define LEGACY_REFERENCE_TRACKING
+#ifdef LEGACY_REFERENCE_TRACKING
+///Use the legacy reference on things hard deleting by default.
+//#define GC_FAILURE_HARD_LOOKUP
+#ifdef GC_FAILURE_HARD_LOOKUP
+#define FIND_REF_NO_CHECK_TICK
+#endif //ifdef GC_FAILURE_HARD_LOOKUP
+
+#endif //ifdef LEGACY_REFERENCE_TRACKING
//#define VISUALIZE_ACTIVE_TURFS //Highlights atmos active turfs in green
-#endif
+#endif //ifdef TESTING
//#define UNIT_TESTS //Enables unit tests via TEST_RUN_PARAMETER
#ifndef PRELOAD_RSC //set to:
diff --git a/code/_globalvars/game_modes.dm b/code/_globalvars/game_modes.dm
index 01a34c2ab7..960e1f8d59 100644
--- a/code/_globalvars/game_modes.dm
+++ b/code/_globalvars/game_modes.dm
@@ -9,4 +9,8 @@ GLOBAL_DATUM(start_state, /datum/station_state) // Used in round-end report
//TODO clear this one up too
-GLOBAL_DATUM(cult_narsie, /obj/singularity/narsie/large/cult)
\ No newline at end of file
+GLOBAL_DATUM(cult_narsie, /obj/singularity/narsie/large/cult)
+
+
+///We want reality_smash_tracker to exist only once and be accesable from anywhere.
+GLOBAL_DATUM_INIT(reality_smash_track, /datum/reality_smash_tracker, new)
diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm
index a25381f266..71c2b2e13b 100644
--- a/code/_globalvars/lists/flavor_misc.dm
+++ b/code/_globalvars/lists/flavor_misc.dm
@@ -40,6 +40,46 @@ GLOBAL_LIST_EMPTY(insect_fluffs_list)
GLOBAL_LIST_EMPTY(insect_markings_list)
GLOBAL_LIST_EMPTY(caps_list)
+//a way to index the right bodypart list given the type of bodypart
+GLOBAL_LIST_INIT(mutant_reference_list, list(
+ "tail_lizard" = GLOB.tails_list_lizard,
+ "waggingtail_lizard" = GLOB.animated_tails_list_lizard,
+ "tail_human" = GLOB.tails_list_human,
+ "waggingtail_human" = GLOB.animated_tails_list_human,
+ "spines" = GLOB.spines_list,
+ "waggingspines" = GLOB.animated_spines_list,
+ "snout" = GLOB.snouts_list,
+ "frills" = GLOB.frills_list,
+ "horns" = GLOB.horns_list,
+ "ears" = GLOB.ears_list,
+ "body_markings" = GLOB.body_markings_list,
+ "wings" = GLOB.wings_list,
+ "wingsopen" = GLOB.wings_open_list,
+ "deco_wings" = GLOB.deco_wings_list,
+ "legs" = GLOB.legs_list,
+ "insect_wings" = GLOB.insect_wings_list,
+ "insect_fluff" = GLOB.insect_fluffs_list,
+ "insect_markings" = GLOB.insect_markings_list,
+ "caps" = GLOB.caps_list,
+ "ipc_screen" = GLOB.ipc_screens_list,
+ "ipc_antenna" = GLOB.ipc_antennas_list,
+ "mam_tail" = GLOB.mam_tails_list,
+ "mam_waggingtail" = GLOB.mam_tails_animated_list,
+ "mam_body_markings" = GLOB.mam_body_markings_list,
+ "mam_ears" = GLOB.mam_ears_list,
+ "mam_snouts" = GLOB.mam_snouts_list,
+ "taur" = GLOB.taur_list,
+ "xenodorsal" = GLOB.xeno_dorsal_list,
+ "xenohead" = GLOB.xeno_head_list,
+ "xenotail" = GLOB.xeno_tail_list))
+
+//references wag types to regular types, wings open to wings, etc
+GLOBAL_LIST_INIT(mutant_transform_list, list("wingsopen" = "wings",
+ "waggingtail_human" = "tail_human",
+ "waggingtail_lizard" = "tail_lizard",
+ "waggingspines" = "spines",
+ "mam_waggingtail" = "mam_tail"))
+
GLOBAL_LIST_INIT(ghost_forms_with_directions_list, list("ghost")) //stores the ghost forms that support directional sprites
GLOBAL_LIST_INIT(ghost_forms_with_accessories_list, list("ghost")) //stores the ghost forms that support hair and other such things
@@ -231,4 +271,15 @@ GLOBAL_LIST_INIT(speech_verbs, list("default","says","gibbers", "states", "chitt
GLOBAL_LIST_INIT(roundstart_tongues, list("default","human tongue" = /obj/item/organ/tongue, "lizard tongue" = /obj/item/organ/tongue/lizard, "skeleton tongue" = /obj/item/organ/tongue/bone, "fly tongue" = /obj/item/organ/tongue/fly, "ipc tongue" = /obj/item/organ/tongue/robot/ipc))
+//locked parts are those that your picked species requires to have
+//unlocked parts are those that anyone can choose on customisation regardless
+//parts not in unlocked, but in all, are thus locked
+GLOBAL_LIST_INIT(all_mutant_parts, list("tail_lizard" = "Tail", "mam_tail" = "Tail", "tail_human" = "Tail", "snout" = "Snout", "frills" = "Frills", "spines" = "Spines", "body_markings" = "Body Markings", "mam_body_markings" = "Species Markings" , "mam_ears" = "Ears", "ears" = "Ears", "mam_snouts" = "Snout", "legs" = "Legs", "deco_wings" = "Decorative Wings", "insect_wings" = "Insect Wings", "insect_fluff" = "Insect Fluff", "taur" = "Tauric Body", "insect_markings" = "Insect Markings", "wings" = "Wings", "xenohead" = "Caste Head", "xenotail" = "Tail", "xenodorsal" = "Dorsal Spines", "ipc_screen" = "Screen", "ipc_antenna" = "Antenna", "meat_type" = "Meat Type", "horns" = "Horns"))
+GLOBAL_LIST_INIT(unlocked_mutant_parts, list("horns", "insect_fluff"))
+//parts in either of the above two lists that require a second option that allows them to be coloured
+GLOBAL_LIST_INIT(colored_mutant_parts, list("insect_wings" = "wings_color", "deco_wings" = "wings_color", "horns" = "horns_color"))
+//species ids that have greyscale sprites
+GLOBAL_LIST_INIT(greyscale_limb_types, list("human","moth","lizard","pod","plant","jelly","slime","golem","lum","stargazer","mush","ethereal","snail","c_golem","b_golem","mammal","xeno","ipc","insect","synthliz","avian","aquatic"))
+
+//species ids that need snowflake coloring applied
diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm
index 4de7c88bf7..fee70ee3d5 100644
--- a/code/_globalvars/lists/objects.dm
+++ b/code/_globalvars/lists/objects.dm
@@ -41,3 +41,6 @@ GLOBAL_LIST_EMPTY(ai_status_displays)
GLOBAL_LIST_EMPTY(mob_spawners) // All mob_spawn objects
GLOBAL_LIST_EMPTY(alert_consoles) // Station alert consoles, /obj/machinery/computer/station_alert
+
+//list of everyone playing rock paper scissors
+GLOBAL_LIST_EMPTY(rockpaperscissors_players)
diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm
index 8d8b8820b2..605b20a4f3 100644
--- a/code/_globalvars/traits.dm
+++ b/code/_globalvars/traits.dm
@@ -37,7 +37,9 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_RESISTCOLD" = TRAIT_RESISTCOLD,
"TRAIT_RESISTHIGHPRESSURE" = TRAIT_RESISTHIGHPRESSURE,
"TRAIT_RESISTLOWPRESSURE" = TRAIT_RESISTLOWPRESSURE,
+ "TRAIT_BOMBIMMUNE" = TRAIT_BOMBIMMUNE,
"TRAIT_RADIMMUNE" = TRAIT_RADIMMUNE,
+ "TRAIT_GENELESS" = TRAIT_GENELESS,
"TRAIT_VIRUSIMMUNE" = TRAIT_VIRUSIMMUNE,
"TRAIT_PIERCEIMMUNE" = TRAIT_PIERCEIMMUNE,
"TRAIT_NODISMEMBER" = TRAIT_NODISMEMBER,
diff --git a/code/_onclick/hud/screen_objects/storage.dm b/code/_onclick/hud/screen_objects/storage.dm
index ce7bc96c96..72b2d035a3 100644
--- a/code/_onclick/hud/screen_objects/storage.dm
+++ b/code/_onclick/hud/screen_objects/storage.dm
@@ -122,13 +122,13 @@
if(pixel_size == pixels)
return
pixel_size = pixels
- cut_overlays(TRUE)
+ cut_overlays()
//our icon size is 32 pixels.
transform = matrix((pixels - (VOLUMETRIC_STORAGE_BOX_BORDER_SIZE * 2)) / VOLUMETRIC_STORAGE_BOX_ICON_SIZE, 0, 0, 0, 1, 0)
left.pixel_x = -((pixels - VOLUMETRIC_STORAGE_BOX_ICON_SIZE) * 0.5) - VOLUMETRIC_STORAGE_BOX_BORDER_SIZE
right.pixel_x = ((pixels - VOLUMETRIC_STORAGE_BOX_ICON_SIZE) * 0.5) + VOLUMETRIC_STORAGE_BOX_BORDER_SIZE
- add_overlay(left, TRUE)
- add_overlay(right, TRUE)
+ add_overlay(left)
+ add_overlay(right)
/obj/screen/storage/volumetric_edge
layer = VOLUMETRIC_STORAGE_BOX_LAYER
diff --git a/code/_onclick/overmind.dm b/code/_onclick/overmind.dm
index 8ace273dd8..419524c871 100644
--- a/code/_onclick/overmind.dm
+++ b/code/_onclick/overmind.dm
@@ -32,4 +32,4 @@
/mob/camera/blob/AltClickOn(atom/A) //Remove a blob
var/turf/T = get_turf(A)
if(T)
- remove_blob(T)
\ No newline at end of file
+ remove_blob(T)
diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm
index 5765f291e9..2e3cb1ea46 100644
--- a/code/controllers/configuration/entries/game_options.dm
+++ b/code/controllers/configuration/entries/game_options.dm
@@ -98,6 +98,11 @@
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
@@ -529,4 +534,4 @@
config_entry_value = 6
/datum/config_entry/number/max_shuttle_size
- config_entry_value = 250
+ config_entry_value = 500
diff --git a/code/controllers/subsystem/acid.dm b/code/controllers/subsystem/acid.dm
index e3c415960b..7c9e7634ab 100644
--- a/code/controllers/subsystem/acid.dm
+++ b/code/controllers/subsystem/acid.dm
@@ -29,7 +29,7 @@ SUBSYSTEM_DEF(acid)
if(O.acid_level && O.acid_processing())
else
- O.cut_overlay(GLOB.acid_overlay, TRUE)
+ O.update_icon()
processing -= O
if (MC_TICK_CHECK)
diff --git a/code/controllers/subsystem/fluid.dm b/code/controllers/subsystem/fluid.dm
new file mode 100644
index 0000000000..c4fa13d693
--- /dev/null
+++ b/code/controllers/subsystem/fluid.dm
@@ -0,0 +1,5 @@
+PROCESSING_SUBSYSTEM_DEF(fluids)
+ name = "Fluids"
+ wait = 20
+ stat_tag = "FD" //its actually Fluid Ducts
+ flags = SS_NO_INIT | SS_TICKER
diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm
index 8a1c08bc35..b46e22c1fa 100644
--- a/code/controllers/subsystem/garbage.dm
+++ b/code/controllers/subsystem/garbage.dm
@@ -25,7 +25,7 @@ SUBSYSTEM_DEF(garbage)
//Queue
var/list/queues
- #ifdef TESTING
+ #ifdef LEGACY_REFERENCE_TRACKING
var/list/reference_find_on_fail = list()
var/list/reference_find_on_fail_types = list()
#endif
@@ -134,7 +134,7 @@ SUBSYSTEM_DEF(garbage)
++gcedlasttick
++totalgcs
pass_counts[level]++
- #ifdef TESTING
+ #ifdef LEGACY_REFERENCE_TRACKING
reference_find_on_fail -= refID //It's deleted we don't care anymore.
#endif
if (MC_TICK_CHECK)
@@ -145,7 +145,9 @@ SUBSYSTEM_DEF(garbage)
fail_counts[level]++
switch (level)
if (GC_QUEUE_CHECK)
- #ifdef TESTING
+ #ifdef REFERENCE_TRACKING
+ D.find_references()
+ #elif defined(LEGACY_REFERENCE_TRACKING)
if(reference_find_on_fail[refID])
D.find_references()
#ifdef GC_FAILURE_HARD_LOOKUP
@@ -156,7 +158,19 @@ SUBSYSTEM_DEF(garbage)
#endif
var/type = D.type
var/datum/qdel_item/I = items[type]
+ #ifdef TESTING
+ log_world("## TESTING: GC: -- \ref[D] | [type] was unable to be GC'd --")
+ for(var/c in GLOB.admins) //Using testing() here would fill the logs with ADMIN_VV garbage
+ var/client/admin = c
+ if(!check_rights_for(admin, R_ADMIN))
+ continue
+ to_chat(admin, "## TESTING: GC: -- [ADMIN_VV(D)] | [type] was unable to be GC'd --")
testing("GC: -- \ref[src] | [type] was unable to be GC'd --")
+ #endif
+ #ifdef REFERENCE_TRACKING
+ GLOB.deletion_failures += D //It should no longer be bothered by the GC, manual deletion only.
+ continue
+ #endif
I.failures++
if (GC_QUEUE_HARDDELETE)
HardDelete(D)
@@ -181,7 +195,7 @@ SUBSYSTEM_DEF(garbage)
var/gctime = world.time
var/refid = "\ref[D]"
-#ifdef TESTING
+#ifdef LEGACY_REFERENCE_TRACKING
if(reference_find_on_fail_types[D.type])
reference_find_on_fail["\ref[D]"] = TRUE
#endif
@@ -193,7 +207,7 @@ SUBSYSTEM_DEF(garbage)
queue[refid] = gctime
-#ifdef TESTING
+#ifdef LEGACY_REFERENCE_TRACKING
/datum/controller/subsystem/garbage/proc/add_type_to_findref(type)
if(!ispath(type))
return "NOT A VAILD PATH"
@@ -260,12 +274,6 @@ SUBSYSTEM_DEF(garbage)
/datum/qdel_item/New(mytype)
name = "[mytype]"
-#ifdef TESTING
-/proc/qdel_and_find_ref_if_fail(datum/D, force = FALSE)
- SSgarbage.reference_find_on_fail["\ref[D]"] = TRUE
- qdel(D, force)
-#endif
-
// Should be treated as a replacement for the 'del' keyword.
// Datums passed to this will be given a chance to clean up references to allow the GC to collect them.
/proc/qdel(datum/D, force=FALSE, ...)
@@ -319,16 +327,13 @@ SUBSYSTEM_DEF(garbage)
SSgarbage.Queue(D, GC_QUEUE_HARDDELETE)
if (QDEL_HINT_HARDDEL_NOW) //qdel should assume this object won't gc, and hard del it post haste.
SSgarbage.HardDelete(D)
- if (QDEL_HINT_FINDREFERENCE)//qdel will, if TESTING is enabled, display all references to this object, then queue the object for deletion.
+ #ifdef LEGACY_REFERENCE_TRACKING
+ if (QDEL_HINT_FINDREFERENCE) //qdel will, if LEGACY_REFERENCE_TRACKING is enabled, display all references to this object, then queue the object for deletion.
SSgarbage.Queue(D)
- #ifdef TESTING
- D.find_references()
- #endif
if (QDEL_HINT_IFFAIL_FINDREFERENCE)
SSgarbage.Queue(D)
- #ifdef TESTING
SSgarbage.reference_find_on_fail["\ref[D]"] = TRUE
- #endif
+ #endif
else
#ifdef TESTING
if(!I.no_hint)
@@ -339,119 +344,6 @@ SUBSYSTEM_DEF(garbage)
else if(D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
CRASH("[D.type] destroy proc was called multiple times, likely due to a qdel loop in the Destroy logic")
-#ifdef TESTING
-
-/datum/verb/find_refs()
- set category = "Debug"
- set name = "Find References"
- set src in world
-
- find_references(FALSE)
-
-/datum/proc/find_references(skip_alert)
- running_find_references = type
- if(usr && usr.client)
- if(usr.client.running_find_references)
- testing("CANCELLED search for references to a [usr.client.running_find_references].")
- usr.client.running_find_references = null
- running_find_references = null
- //restart the garbage collector
- SSgarbage.can_fire = 1
- SSgarbage.next_fire = world.time + world.tick_lag
- return
-
- if(!skip_alert)
- if(alert("Running this will lock everything up for about 5 minutes. Would you like to begin the search?", "Find References", "Yes", "No") == "No")
- running_find_references = null
- return
-
- //this keeps the garbage collector from failing to collect objects being searched for in here
- SSgarbage.can_fire = 0
-
- if(usr && usr.client)
- usr.client.running_find_references = type
-
- testing("Beginning search for references to a [type].")
- last_find_references = world.time
-
- DoSearchVar(GLOB) //globals
- for(var/datum/thing in world) //atoms (don't beleive it's lies)
- DoSearchVar(thing, "World -> [thing]")
-
- for (var/datum/thing) //datums
- DoSearchVar(thing, "World -> [thing]")
-
- for (var/client/thing) //clients
- DoSearchVar(thing, "World -> [thing]")
-
- testing("Completed search for references to a [type].")
- if(usr && usr.client)
- usr.client.running_find_references = null
- running_find_references = null
-
- //restart the garbage collector
- SSgarbage.can_fire = 1
- SSgarbage.next_fire = world.time + world.tick_lag
-
-/datum/verb/qdel_then_find_references()
- set category = "Debug"
- set name = "qdel() then Find References"
- set src in world
-
- qdel(src, TRUE) //Force.
- if(!running_find_references)
- find_references(TRUE)
-
-/datum/verb/qdel_then_if_fail_find_references()
- set category = "Debug"
- set name = "qdel() then Find References if GC failure"
- set src in world
-
- qdel_and_find_ref_if_fail(src, TRUE)
-
-/datum/proc/DoSearchVar(X, Xname, recursive_limit = 64)
- if(usr && usr.client && !usr.client.running_find_references)
- return
- if (!recursive_limit)
- return
-
- if(istype(X, /datum))
- var/datum/D = X
- if(D.last_find_references == last_find_references)
- return
-
- D.last_find_references = last_find_references
- var/list/L = D.vars
-
- for(var/varname in L)
- if (varname == "vars")
- continue
- var/variable = L[varname]
-
- if(variable == src)
- testing("Found [src.type] \ref[src] in [D.type]'s [varname] var. [Xname]")
-
- else if(islist(variable))
- DoSearchVar(variable, "[Xname] -> list", recursive_limit-1)
-
- else if(islist(X))
- var/normal = IS_NORMAL_LIST(X)
- for(var/I in X)
- if (I == src)
- testing("Found [src.type] \ref[src] in list [Xname].")
-
- else if (I && !isnum(I) && normal && X[I] == src)
- testing("Found [src.type] \ref[src] in list [Xname]\[[I]\]")
-
- else if (islist(I))
- DoSearchVar(I, "[Xname] -> list", recursive_limit-1)
-
-#ifndef FIND_REF_NO_CHECK_TICK
- CHECK_TICK
-#endif
-
-#endif
-
#ifdef TESTING
/proc/writeDatumCount()
var/list/datums = list()
diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm
index 97addfa131..617004646a 100644
--- a/code/controllers/subsystem/mapping.dm
+++ b/code/controllers/subsystem/mapping.dm
@@ -113,7 +113,7 @@ SUBSYSTEM_DEF(mapping)
// needs to be whitelisted for underground too so place_below ruins work
seedRuins(ice_ruins, CONFIG_GET(number/icemoon_budget), list(/area/icemoon/surface/outdoors/unexplored, /area/icemoon/underground/unexplored), ice_ruins_templates)
for (var/ice_z in ice_ruins)
- spawn_rivers(ice_z, 4, /turf/open/openspace/icemoon, /area/icemoon/surface/outdoors/unexplored/rivers)
+ spawn_rivers(ice_z, 4, /turf/open/transparent/openspace/icemoon, /area/icemoon/surface/outdoors/unexplored/rivers)
var/list/ice_ruins_underground = levels_by_trait(ZTRAIT_ICE_RUINS_UNDERGROUND)
if (ice_ruins_underground.len)
diff --git a/code/controllers/subsystem/overlays.dm b/code/controllers/subsystem/overlays.dm
index 20eb2af001..ea0f82436c 100644
--- a/code/controllers/subsystem/overlays.dm
+++ b/code/controllers/subsystem/overlays.dm
@@ -114,67 +114,47 @@ SUBSYSTEM_DEF(overlays)
#define NOT_QUEUED_ALREADY (!(flags_1 & OVERLAY_QUEUED_1))
#define QUEUE_FOR_COMPILE flags_1 |= OVERLAY_QUEUED_1; SSoverlays.queue += src;
-/atom/proc/cut_overlays(priority = FALSE)
- LAZYINITLIST(priority_overlays)
+/atom/proc/cut_overlays()
LAZYINITLIST(remove_overlays)
LAZYINITLIST(add_overlays)
remove_overlays = overlays.Copy()
add_overlays.Cut()
- if(priority)
- priority_overlays.Cut()
-
//If not already queued for work and there are overlays to remove
if(NOT_QUEUED_ALREADY && remove_overlays.len)
QUEUE_FOR_COMPILE
-/atom/proc/cut_overlay(list/overlays, priority)
+/atom/proc/cut_overlay(list/overlays)
if(!overlays)
return
overlays = build_appearance_list(overlays)
LAZYINITLIST(add_overlays) //always initialized after this point
- LAZYINITLIST(priority_overlays)
LAZYINITLIST(remove_overlays)
var/a_len = add_overlays.len
var/r_len = remove_overlays.len
- var/p_len = priority_overlays.len
remove_overlays += overlays
add_overlays -= overlays
-
- if(priority)
- var/list/cached_priority = priority_overlays
- LAZYREMOVE(cached_priority, overlays)
-
var/fa_len = add_overlays.len
var/fr_len = remove_overlays.len
- var/fp_len = priority_overlays.len
//If not already queued and there is work to be done
- if(NOT_QUEUED_ALREADY && (fa_len != a_len || fr_len != r_len || fp_len != p_len))
+ if(NOT_QUEUED_ALREADY && (fa_len != a_len || fr_len != r_len))
QUEUE_FOR_COMPILE
-/atom/proc/add_overlay(list/overlays, priority = FALSE)
+/atom/proc/add_overlay(list/overlays)
if(!overlays)
return
overlays = build_appearance_list(overlays)
LAZYINITLIST(add_overlays) //always initialized after this point
- LAZYINITLIST(priority_overlays)
var/a_len = add_overlays.len
- var/p_len = priority_overlays.len
- if(priority)
- priority_overlays += overlays //or in the image. Can we use [image] = image?
- var/fp_len = priority_overlays.len
- if(NOT_QUEUED_ALREADY && fp_len != p_len)
- QUEUE_FOR_COMPILE
- else
- add_overlays += overlays
- var/fa_len = add_overlays.len
- if(NOT_QUEUED_ALREADY && fa_len != a_len)
- QUEUE_FOR_COMPILE
+ add_overlays += overlays
+ var/fa_len = add_overlays.len
+ if(NOT_QUEUED_ALREADY && fa_len != a_len)
+ QUEUE_FOR_COMPILE
/atom/proc/copy_overlays(atom/other, cut_old) //copys our_overlays from another atom
if(!other)
diff --git a/code/controllers/subsystem/processing/instruments.dm b/code/controllers/subsystem/processing/instruments.dm
index a4e0d7703f..ee0fd1ea00 100644
--- a/code/controllers/subsystem/processing/instruments.dm
+++ b/code/controllers/subsystem/processing/instruments.dm
@@ -4,16 +4,26 @@ PROCESSING_SUBSYSTEM_DEF(instruments)
init_order = INIT_ORDER_INSTRUMENTS
flags = SS_KEEP_TIMING
priority = FIRE_PRIORITY_INSTRUMENTS
- var/static/list/datum/instrument/instrument_data = list() //id = datum
+ /// List of all instrument data, associative id = datum
+ var/static/list/datum/instrument/instrument_data = list()
+ /// List of all song datums.
var/static/list/datum/song/songs = list()
+ /// Max lines in songs
var/static/musician_maxlines = 600
+ /// Max characters per line in songs
var/static/musician_maxlinechars = 300
+ /// Deciseconds between hearchecks. Too high and instruments seem to lag when people are moving around in terms of who can hear it. Too low and the server lags from this.
var/static/musician_hearcheck_mindelay = 5
+ /// Maximum instrument channels total instruments are allowed to use. This is so you don't have instruments deadlocking all sound channels.
var/static/max_instrument_channels = MAX_INSTRUMENT_CHANNELS
+ /// Current number of channels allocated for instruments
var/static/current_instrument_channels = 0
+ /// Single cached list for synthesizer instrument ids, so you don't have to have a new list with every synthesizer.
+ var/static/list/synthesizer_instrument_ids
/datum/controller/subsystem/processing/instruments/Initialize()
initialize_instrument_data()
+ synthesizer_instrument_ids = get_allowed_instrument_ids()
return ..()
/datum/controller/subsystem/processing/instruments/proc/on_song_new(datum/song/S)
@@ -29,7 +39,10 @@ PROCESSING_SUBSYSTEM_DEF(instruments)
continue
I = new path
I.Initialize()
- instrument_data[I.id || "[I.type]"] = I
+ if(!I.id)
+ qdel(I)
+ continue
+ instrument_data[I.id] = I
CHECK_TICK
/datum/controller/subsystem/processing/instruments/proc/get_instrument(id_or_path)
diff --git a/code/datums/action.dm b/code/datums/action.dm
index 0033df09d7..fbf7487e4d 100644
--- a/code/datums/action.dm
+++ b/code/datums/action.dm
@@ -157,7 +157,7 @@
/datum/action/proc/ApplyIcon(obj/screen/movable/action_button/current_button, force = FALSE)
if(icon_icon && button_icon_state && ((current_button.button_icon_state != button_icon_state) || force))
- current_button.cut_overlays(TRUE)
+ current_button.cut_overlays()
current_button.add_overlay(mutable_appearance(icon_icon, button_icon_state))
current_button.button_icon_state = button_icon_state
diff --git a/code/datums/components/crafting/recipes/recipes_clothing.dm b/code/datums/components/crafting/recipes/recipes_clothing.dm
index 2a24c0b451..717e99e8b2 100644
--- a/code/datums/components/crafting/recipes/recipes_clothing.dm
+++ b/code/datums/components/crafting/recipes/recipes_clothing.dm
@@ -40,13 +40,23 @@
reqs = list(/obj/item/paper = 20)
category = CAT_CLOTHING
+/datum/crafting_recipe/balaclavabreath
+ name = "Breathaclava"
+ result = /obj/item/clothing/mask/balaclava/breath
+ time = 10
+ reqs = list(/obj/item/clothing/mask/balaclava = 1,
+ /obj/item/clothing/mask/breath = 1)
+ category = CAT_CLOTHING
+
+
+
/datum/crafting_recipe/armwraps
name = "Armwraps"
result = /obj/item/clothing/gloves/fingerless/pugilist
time = 60
tools = list(TOOL_WIRECUTTER)
reqs = list(/obj/item/stack/sheet/cloth = 4,
- /obj/item/stack/sheet/durathread = 2,
+ /obj/item/stack/sticky_tape = 2,
/obj/item/stack/sheet/leather = 2)
category = CAT_CLOTHING
diff --git a/code/datums/components/crafting/recipes/recipes_misc.dm b/code/datums/components/crafting/recipes/recipes_misc.dm
index 0cb0547978..f113be728d 100644
--- a/code/datums/components/crafting/recipes/recipes_misc.dm
+++ b/code/datums/components/crafting/recipes/recipes_misc.dm
@@ -2,6 +2,15 @@
//Large Objects//
/////////////////
+/datum/crafting_recipe/plunger
+ name = "Plunger"
+ result = /obj/item/plunger
+ time = 1
+ reqs = list(/obj/item/stack/sheet/plastic = 1,
+ /obj/item/stack/sheet/mineral/wood = 1)
+ category = CAT_MISC
+ subcategory = CAT_TOOL
+
/datum/crafting_recipe/showercurtain
name = "Shower Curtains"
reqs = list(/obj/item/stack/sheet/cloth = 2,
@@ -188,7 +197,7 @@
result = /obj/item/screwdriver/bronze
reqs = list(/obj/item/screwdriver = 1,
/obj/item/stack/cable_coil = 10,
- /obj/item/stack/tile/bronze = 1,
+ /obj/item/stack/sheet/bronze = 1,
/datum/reagent/water = 15)
time = 40
subcategory = CAT_TOOL
@@ -200,7 +209,7 @@
result = /obj/item/weldingtool/bronze
reqs = list(/obj/item/weldingtool = 1,
/obj/item/stack/cable_coil = 10,
- /obj/item/stack/tile/bronze = 1,
+ /obj/item/stack/sheet/bronze = 1,
/datum/reagent/water = 15)
time = 40
subcategory = CAT_TOOL
@@ -212,7 +221,7 @@
result = /obj/item/wirecutters/bronze
reqs = list(/obj/item/wirecutters = 1,
/obj/item/stack/cable_coil = 10,
- /obj/item/stack/tile/bronze = 1,
+ /obj/item/stack/sheet/bronze = 1,
/datum/reagent/water = 15)
time = 40
subcategory = CAT_TOOL
@@ -224,7 +233,7 @@
result = /obj/item/crowbar/bronze
reqs = list(/obj/item/crowbar = 1,
/obj/item/stack/cable_coil = 10,
- /obj/item/stack/tile/bronze = 1,
+ /obj/item/stack/sheet/bronze = 1,
/datum/reagent/water = 15)
time = 40
subcategory = CAT_TOOL
@@ -236,7 +245,7 @@
result = /obj/item/wrench/bronze
reqs = list(/obj/item/wrench = 1,
/obj/item/stack/cable_coil = 10,
- /obj/item/stack/tile/bronze = 1,
+ /obj/item/stack/sheet/bronze = 1,
/datum/reagent/water = 15)
time = 40
subcategory = CAT_TOOL
@@ -269,6 +278,19 @@
subcategory = CAT_TOOL
category = CAT_MISC
+/datum/crafting_recipe/heretic/codex
+ name = "Codex Cicatrix"
+ result = /obj/item/forbidden_book
+ tools = list(/obj/item/pen)
+ reqs = list(/obj/item/paper = 5,
+ /obj/item/organ/eyes = 1,
+ /obj/item/organ/heart = 1,
+ /obj/item/stack/sheet/animalhide/human = 1)
+ time = 150
+ subcategory = CAT_MISCELLANEOUS
+ category = CAT_MISC
+ always_availible = FALSE
+
////////////
//Vehicles//
////////////
@@ -324,7 +346,7 @@
result = /obj/item/toy/sword/cx
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
-
+
/datum/crafting_recipe/catgirlplushie
name = "Catgirl Plushie"
reqs = list(/obj/item/toy/plush/hairball = 3)
diff --git a/code/datums/components/embedded.dm b/code/datums/components/embedded.dm
index 51098756d3..8c4e62979b 100644
--- a/code/datums/components/embedded.dm
+++ b/code/datums/components/embedded.dm
@@ -119,7 +119,7 @@
UnregisterSignal(weapon, list(COMSIG_MOVABLE_MOVED, COMSIG_PARENT_QDELETING))
if(overlay)
var/atom/A = parent
- A.cut_overlay(overlay, TRUE)
+ UnregisterSignal(A,COMSIG_ATOM_UPDATE_OVERLAYS)
qdel(overlay)
return ..()
@@ -326,7 +326,8 @@
var/matrix/M = matrix()
M.Translate(pixelX, pixelY)
overlay.transform = M
- hit.add_overlay(overlay, TRUE)
+ RegisterSignal(hit,COMSIG_ATOM_UPDATE_OVERLAYS,.proc/apply_overlay)
+ hit.update_icon()
if(harmful)
hit.visible_message("[weapon] embeds itself in [hit]!")
@@ -339,6 +340,8 @@
else
hit.visible_message("[weapon] sticks itself to [hit]!")
+/datum/component/embedded/proc/apply_overlay(atom/source, list/overlay_list)
+ overlay_list += overlay
/datum/component/embedded/proc/examineTurf(datum/source, mob/user, list/examine_list)
if(harmful)
diff --git a/code/datums/components/plumbing/_plumbing.dm b/code/datums/components/plumbing/_plumbing.dm
new file mode 100644
index 0000000000..6592e41103
--- /dev/null
+++ b/code/datums/components/plumbing/_plumbing.dm
@@ -0,0 +1,215 @@
+/datum/component/plumbing
+ ///Index with "1" = /datum/ductnet/theductpointingnorth etc. "1" being the num2text from NORTH define
+ var/list/datum/ductnet/ducts = list()
+ ///shortcut to our parents' reagent holder
+ var/datum/reagents/reagents
+ ///TRUE if we wanna add proper pipe outless under our parent object. this is pretty good if i may so so myself
+ var/use_overlays = TRUE
+ ///We can't just cut all of the parents' overlays, so we'll track them here
+ var/list/image/ducterlays
+ ///directions in wich we act as a supplier
+ var/supply_connects
+ ///direction in wich we act as a demander
+ var/demand_connects
+ ///FALSE to pretty much just not exist in the plumbing world so we can be moved, TRUE to go plumbo mode
+ var/active = FALSE
+ ///if TRUE connects will spin with the parent object visually and codually, so you can have it work in any direction. FALSE if you want it to be static
+ var/turn_connects = TRUE
+
+/datum/component/plumbing/Initialize(start=TRUE, _turn_connects=TRUE) //turn_connects for wheter or not we spin with the object to change our pipes
+ if(parent && !istype(parent, /atom/movable))
+ return COMPONENT_INCOMPATIBLE
+ var/atom/movable/AM = parent
+ if(!AM.reagents)
+ return COMPONENT_INCOMPATIBLE
+ reagents = AM.reagents
+ turn_connects = _turn_connects
+
+ RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED,COMSIG_PARENT_PREQDELETED), .proc/disable)
+ RegisterSignal(parent, list(COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH), .proc/toggle_active)
+
+ if(start)
+ enable()
+
+ if(use_overlays)
+ create_overlays()
+
+/datum/component/plumbing/process()
+ if(!demand_connects || !reagents)
+ STOP_PROCESSING(SSfluids, src)
+ return
+ if(reagents.total_volume < reagents.maximum_volume)
+ for(var/D in GLOB.cardinals)
+ if(D & demand_connects)
+ send_request(D)
+///Can we be added to the ductnet?
+/datum/component/plumbing/proc/can_add(datum/ductnet/D, dir)
+ if(!active)
+ return
+ if(!dir || !D)
+ return FALSE
+ if(num2text(dir) in ducts)
+ return FALSE
+
+ return TRUE
+///called from in process(). only calls process_request(), but can be overwritten for children with special behaviour
+/datum/component/plumbing/proc/send_request(dir)
+ process_request(amount = MACHINE_REAGENT_TRANSFER, reagent = null, dir = dir)
+///check who can give us what we want, and how many each of them will give us
+/datum/component/plumbing/proc/process_request(amount, reagent, dir)
+ var/list/valid_suppliers = list()
+ var/datum/ductnet/net
+ if(!ducts.Find(num2text(dir)))
+ return
+ net = ducts[num2text(dir)]
+ for(var/A in net.suppliers)
+ var/datum/component/plumbing/supplier = A
+ if(supplier.can_give(amount, reagent, net))
+ valid_suppliers += supplier
+ for(var/A in valid_suppliers)
+ var/datum/component/plumbing/give = A
+ give.transfer_to(src, amount / valid_suppliers.len, reagent, net)
+///returns TRUE when they can give the specified amount and reagent. called by process request
+/datum/component/plumbing/proc/can_give(amount, reagent, datum/ductnet/net)
+ if(amount <= 0)
+ return
+
+ if(reagent) //only asked for one type of reagent
+ for(var/A in reagents.reagent_list)
+ var/datum/reagent/R = A
+ if(R.type == reagent)
+ return TRUE
+ else if(reagents.total_volume > 0) //take whatever
+ return TRUE
+///this is where the reagent is actually transferred and is thus the finish point of our process()
+/datum/component/plumbing/proc/transfer_to(datum/component/plumbing/target, amount, reagent, datum/ductnet/net)
+ if(!reagents || !target || !target.reagents)
+ return FALSE
+ if(reagent)
+ reagents.trans_id_to(target.parent, reagent, amount)
+ else
+ reagents.trans_to(target.parent, amount)
+///We create our luxurious piping overlays/underlays, to indicate where we do what. only called once if use_overlays = TRUE in Initialize()
+/datum/component/plumbing/proc/create_overlays()
+ var/atom/movable/AM = parent
+ for(var/image/I in ducterlays)
+ AM.overlays.Remove(I)
+ qdel(I)
+ ducterlays = list()
+ for(var/D in GLOB.cardinals)
+ var/color
+ var/direction
+ if(D & demand_connects)
+ color = "red" //red because red is mean and it takes
+ else if(D & supply_connects)
+ color = "blue" //blue is nice and gives
+ else
+ continue
+ var/image/I
+ if(turn_connects)
+ switch(D)
+ if(NORTH)
+ direction = "north"
+ if(SOUTH)
+ direction = "south"
+ if(EAST)
+ direction = "east"
+ if(WEST)
+ direction = "west"
+ I = image('icons/obj/plumbing/plumbers.dmi', "[direction]-[color]", layer = AM.layer - 1)
+ else
+ I = image('icons/obj/plumbing/plumbers.dmi', color, layer = AM.layer - 1) //color is not color as in the var, it's just the name
+ I.dir = D
+ AM.add_overlay(I)
+ ducterlays += I
+///we stop acting like a plumbing thing and disconnect if we are, so we can safely be moved and stuff
+/datum/component/plumbing/proc/disable()
+ if(!active)
+ return
+ STOP_PROCESSING(SSfluids, src)
+ for(var/A in ducts)
+ var/datum/ductnet/D = ducts[A]
+ D.remove_plumber(src)
+ active = FALSE
+ for(var/D in GLOB.cardinals)
+ if(D & (demand_connects | supply_connects))
+ for(var/obj/machinery/duct/duct in get_step(parent, D))
+ duct.attempt_connect()
+
+///settle wherever we are, and start behaving like a piece of plumbing
+/datum/component/plumbing/proc/enable()
+ if(active)
+ return
+ update_dir()
+ active = TRUE
+ var/atom/movable/AM = parent
+ for(var/obj/machinery/duct/D in AM.loc) //Destroy any ducts under us. Ducts also self destruct if placed under a plumbing machine. machines disable when they get moved
+ if(D.anchored) //that should cover everything
+ D.disconnect_duct()
+
+ if(demand_connects)
+ START_PROCESSING(SSfluids, src)
+
+ for(var/D in GLOB.cardinals)
+ if(D & (demand_connects | supply_connects))
+ for(var/atom/movable/A in get_step(parent, D))
+ if(istype(A, /obj/machinery/duct))
+ var/obj/machinery/duct/duct = A
+ duct.attempt_connect()
+ else
+ var/datum/component/plumbing/P = A.GetComponent(/datum/component/plumbing)
+ if(P)
+ direct_connect(P, D)
+
+/// Toggle our machinery on or off. This is called by a hook from default_unfasten_wrench with anchored as only param, so we dont have to copypaste this on every object that can move
+/datum/component/plumbing/proc/toggle_active(obj/O, new_state)
+ if(new_state)
+ enable()
+ else
+ disable()
+/** We update our connects only when we settle down by taking our current and original direction to find our new connects
+* If someone wants it to fucking spin while connected to something go actually knock yourself out
+*/
+/datum/component/plumbing/proc/update_dir()
+ if(!turn_connects)
+ return
+ var/atom/movable/AM = parent
+ var/new_demand_connects
+ var/new_supply_connects
+ var/new_dir = AM.dir
+ var/angle = 180 - dir2angle(new_dir)
+ if(new_dir == SOUTH)
+ demand_connects = initial(demand_connects)
+ supply_connects = initial(supply_connects)
+ else
+ for(var/D in GLOB.cardinals)
+ if(D & initial(demand_connects))
+ new_demand_connects += turn(D, angle)
+ if(D & initial(supply_connects))
+ new_supply_connects += turn(D, angle)
+ demand_connects = new_demand_connects
+ supply_connects = new_supply_connects
+///Give the direction of a pipe, and it'll return wich direction it originally was when it's object pointed SOUTH
+/datum/component/plumbing/proc/get_original_direction(dir)
+ var/atom/movable/AM = parent
+ return turn(dir, dir2angle(AM.dir) - 180)
+//special case in-case we want to connect directly with another machine without a duct
+/datum/component/plumbing/proc/direct_connect(datum/component/plumbing/P, dir)
+ if(!P.active)
+ return
+ var/opposite_dir = turn(dir, 180)
+ if(P.demand_connects & opposite_dir && supply_connects & dir || P.supply_connects & opposite_dir && demand_connects & dir) //make sure we arent connecting two supplies or demands
+ var/datum/ductnet/net = new()
+ net.add_plumber(src, dir)
+ net.add_plumber(P, opposite_dir)
+
+///has one pipe input that only takes, example is manual output pipe
+/datum/component/plumbing/simple_demand
+ demand_connects = NORTH
+///has one pipe output that only supplies. example is liquid pump and manual input pipe
+/datum/component/plumbing/simple_supply
+ supply_connects = NORTH
+///input and output, like a holding tank
+/datum/component/plumbing/tank
+ demand_connects = WEST
+ supply_connects = EAST
diff --git a/code/datums/components/plumbing/chemical_acclimator.dm b/code/datums/components/plumbing/chemical_acclimator.dm
new file mode 100644
index 0000000000..1cbe6ff017
--- /dev/null
+++ b/code/datums/components/plumbing/chemical_acclimator.dm
@@ -0,0 +1,21 @@
+/datum/component/plumbing/acclimator
+ demand_connects = WEST
+ supply_connects = EAST
+ var/obj/machinery/plumbing/acclimator/AC
+
+/datum/component/plumbing/acclimator/Initialize(start=TRUE, _turn_connects=TRUE)
+ . = ..()
+ if(!istype(parent, /obj/machinery/plumbing/acclimator))
+ return COMPONENT_INCOMPATIBLE
+ AC = parent
+
+/datum/component/plumbing/acclimator/can_give(amount, reagent)
+ . = ..()
+ if(. && AC.emptying)
+ return TRUE
+ return FALSE
+///We're overriding process and not send_request, because all process does is do the requests, so we might aswell cut out the middle man and save some code from running
+/datum/component/plumbing/acclimator/process()
+ if(AC.emptying)
+ return
+ . = ..()
diff --git a/code/datums/components/plumbing/filter.dm b/code/datums/components/plumbing/filter.dm
new file mode 100644
index 0000000000..76b76323c5
--- /dev/null
+++ b/code/datums/components/plumbing/filter.dm
@@ -0,0 +1,59 @@
+///The magical plumbing component used by the chemical filters. The different supply connects behave differently depending on the filters set on the chemical filter
+/datum/component/plumbing/filter
+ demand_connects = NORTH
+ supply_connects = SOUTH | EAST | WEST //SOUTH is straight, EAST is left and WEST is right. We look from the perspective of the insert
+
+/datum/component/plumbing/filter/Initialize()
+ . = ..()
+ if(!istype(parent, /obj/machinery/plumbing/filter))
+ return COMPONENT_INCOMPATIBLE
+
+/datum/component/plumbing/filter/can_give(amount, reagent, datum/ductnet/net)
+ . = ..()
+ if(.)
+ var/direction
+ for(var/A in ducts)
+ if(ducts[A] == net)
+ direction = get_original_direction(text2num(A)) //we need it relative to the direction, so filters don't change when we turn the filter
+ break
+ if(!direction)
+ return FALSE
+ if(reagent)
+ if(!can_give_in_direction(direction, reagent))
+ return FALSE
+
+/datum/component/plumbing/filter/transfer_to(datum/component/plumbing/target, amount, reagent, datum/ductnet/net)
+ if(!reagents || !target || !target.reagents)
+ return FALSE
+ var/direction
+ for(var/A in ducts)
+ if(ducts[A] == net)
+ direction = get_original_direction(text2num(A))
+ break
+ if(reagent)
+ reagents.trans_id_to(target.parent, reagent, amount)
+ else
+ for(var/A in reagents.reagent_list)
+ var/datum/reagent/R = A
+ if(!can_give_in_direction(direction, R.type))
+ continue
+ var/new_amount
+ if(R.volume < amount)
+ new_amount = amount - R.volume
+ reagents.trans_id_to(target.parent, R.type, amount)
+ amount = new_amount
+ if(amount <= 0)
+ break
+///We check if the direction and reagent are valid to give. Needed for filters since different outputs have different behaviours
+/datum/component/plumbing/filter/proc/can_give_in_direction(dir, reagent)
+ var/obj/machinery/plumbing/filter/F = parent
+ switch(dir)
+ if(SOUTH) //straight
+ if(!F.left.Find(reagent) && !F.right.Find(reagent))
+ return TRUE
+ if(WEST) //right
+ if(F.right.Find(reagent))
+ return TRUE
+ if(EAST) //left
+ if(F.left.Find(reagent))
+ return TRUE
diff --git a/code/datums/components/plumbing/reaction_chamber.dm b/code/datums/components/plumbing/reaction_chamber.dm
new file mode 100644
index 0000000000..90f4e621da
--- /dev/null
+++ b/code/datums/components/plumbing/reaction_chamber.dm
@@ -0,0 +1,38 @@
+/datum/component/plumbing/reaction_chamber
+ demand_connects = WEST
+ supply_connects = EAST
+
+/datum/component/plumbing/reaction_chamber/Initialize(start=TRUE, _turn_connects=TRUE)
+ . = ..()
+ if(!istype(parent, /obj/machinery/plumbing/reaction_chamber))
+ return COMPONENT_INCOMPATIBLE
+
+/datum/component/plumbing/reaction_chamber/can_give(amount, reagent, datum/ductnet/net)
+ . = ..()
+ var/obj/machinery/plumbing/reaction_chamber/RC = parent
+ if(!. || !RC.emptying)
+ return FALSE
+
+/datum/component/plumbing/reaction_chamber/send_request(dir)
+ var/obj/machinery/plumbing/reaction_chamber/RC = parent
+ if(RC.emptying || !LAZYLEN(RC.required_reagents))
+ return
+ for(var/RT in RC.required_reagents)
+ var/has_reagent = FALSE
+ for(var/A in reagents.reagent_list)
+ var/datum/reagent/RD = A
+ if(RT == RD.type)
+ has_reagent = TRUE
+ if(RD.volume < RC.required_reagents[RT])
+ process_request(min(RC.required_reagents[RT] - RD.volume, MACHINE_REAGENT_TRANSFER) , RT, dir)
+ return
+ if(!has_reagent)
+ process_request(min(RC.required_reagents[RT], MACHINE_REAGENT_TRANSFER), RT, dir)
+ return
+
+ RC.reagent_flags &= ~NO_REACT
+ reagents.handle_reactions()
+
+ RC.emptying = TRUE //If we move this up, it'll instantly get turned off since any reaction always sets the reagent_total to zero. Other option is make the reaction update
+ //everything for every chemical removed, wich isn't a good option either.
+ RC.on_reagent_change() //We need to check it now, because some reactions leave nothing left.
diff --git a/code/datums/components/plumbing/splitter.dm b/code/datums/components/plumbing/splitter.dm
new file mode 100644
index 0000000000..7194e8803b
--- /dev/null
+++ b/code/datums/components/plumbing/splitter.dm
@@ -0,0 +1,45 @@
+/datum/component/plumbing/splitter
+ demand_connects = NORTH
+ supply_connects = SOUTH | EAST
+
+/datum/component/plumbing/splitter/Initialize()
+ . = ..()
+ if(. && !istype(parent, /obj/machinery/plumbing/splitter))
+ return FALSE
+
+/datum/component/plumbing/splitter/can_give(amount, reagent, datum/ductnet/net)
+ . = ..()
+ if(!.)
+ return
+ . = FALSE
+ var/direction
+ for(var/A in ducts)
+ if(ducts[A] == net)
+ direction = get_original_direction(text2num(A))
+ break
+ var/obj/machinery/plumbing/splitter/S = parent
+ switch(direction)
+ if(SOUTH)
+ if(S.turn_straight && S.transfer_straight <= amount)
+ S.turn_straight = FALSE
+ return TRUE
+ if(EAST)
+ if(!S.turn_straight && S.transfer_side <= amount)
+ S.turn_straight = TRUE
+ return TRUE
+
+/datum/component/plumbing/splitter/transfer_to(datum/component/plumbing/target, amount, reagent, datum/ductnet/net)
+ var/direction
+ for(var/A in ducts)
+ if(ducts[A] == net)
+ direction = get_original_direction(text2num(A))
+ break
+ var/obj/machinery/plumbing/splitter/S = parent
+ switch(direction)
+ if(SOUTH)
+ if(amount >= S.transfer_straight)
+ amount = S.transfer_straight
+ if(EAST)
+ if(amount >= S.transfer_side)
+ amount = S.transfer_side
+ . = ..()
diff --git a/code/datums/components/shielded.dm b/code/datums/components/shielded.dm
index 2052e57f49..3cf70e80ef 100644
--- a/code/datums/components/shielded.dm
+++ b/code/datums/components/shielded.dm
@@ -14,6 +14,7 @@
var/mob/living/holder //who is currently benefiting from the shield.
var/dissipating = FALSE //Is this shield meant to dissipate over time instead of recharging.
var/del_on_overload = FALSE //will delete itself once it has no charges left.
+ var/cached_vis_overlay //text identifier of the visual overlay.
/datum/component/shielded/Initialize(current, max = 3, delay = 20 SECONDS, rate = 1, slots, state = "shield-old", broken, \
sound = 'sound/magic/charge.ogg', end_sound = 'sound/machines/ding.ogg', diss = FALSE, del_overload = FALSE)
@@ -47,9 +48,8 @@
holder = L
var/to_add = charges >= 1 ? shield_state : broken_state
if(to_add)
- var/mutable_appearance/M = mutable_appearance('icons/effects/effects.dmi', to_add)
- M.layer = (L.layer > MOB_LAYER ? L.layer : MOB_LAYER) + 0.01
- holder.add_overlay(M, TRUE)
+ var/layer = (L.layer > MOB_LAYER ? L.layer : MOB_LAYER) + 0.01
+ SSvis_overlays.add_vis_overlay(L, 'icons/effects/effects.dmi', to_add, layer, GAME_PLANE, L.dir)
/datum/component/shielded/UnregisterFromParent()
. = ..()
@@ -57,9 +57,9 @@
UnregisterSignal(parent, list(COMSIG_ITEM_RUN_BLOCK,COMSIG_ITEM_CHECK_BLOCK,COMSIG_ITEM_EQUIPPED,COMSIG_ITEM_DROPPED))
if(holder)
UnregisterSignal(holder, list(COMSIG_LIVING_RUN_BLOCK, COMSIG_LIVING_GET_BLOCKING_ITEMS))
- var/to_remove = charges >= 1 ? shield_state : broken_state
- if(to_remove)
- holder.cut_overlay(mutable_appearance('icons/effects/effects.dmi', to_remove), TRUE)
+ if(cached_vis_overlay)
+ SSvis_overlays.remove_vis_overlay(holder, cached_vis_overlay)
+ cached_vis_overlay = null
holder = null
/datum/component/shielded/process()
@@ -80,7 +80,7 @@
holder.visible_message("[holder]'s shield overloads!")
qdel(src)
return
- if(holder && (old_charges < 1 && charges >= 1) || (!del_on_overload && old_charges >= 1 && charges < 1))
+ if(holder && ((old_charges < 1 && charges >= 1) || (!del_on_overload && old_charges >= 1 && charges < 1)))
update_shield_overlay(charges < 1)
/datum/component/shielded/proc/adjust_charges(amount)
@@ -93,20 +93,19 @@
holder.visible_message("[holder]'s shield overloads!")
qdel(src)
return
- if(holder && (old_charges < 1 && charges >= 1) || (!del_on_overload && old_charges >= 1 && charges < 1))
+ if(holder && ((old_charges < 1 && charges >= 1) || (!del_on_overload && old_charges >= 1 && charges < 1)))
update_shield_overlay(charges < 1)
/datum/component/shielded/proc/update_shield_overlay(broken)
if(!holder)
return
- var/to_remove = broken ? shield_state : broken_state
var/to_add = broken ? broken_state : shield_state
- if(to_remove)
- holder.cut_overlay(mutable_appearance('icons/effects/effects.dmi', to_remove), TRUE)
+ if(cached_vis_overlay)
+ SSvis_overlays.remove_vis_overlay(holder, cached_vis_overlay)
+ cached_vis_overlay = null
if(to_add)
- var/mutable_appearance/M = mutable_appearance('icons/effects/effects.dmi', to_add)
- M.layer = (holder.layer > MOB_LAYER ? holder.layer : MOB_LAYER) + 0.01
- holder.add_overlay(M, TRUE)
+ var/layer = (holder.layer > MOB_LAYER ? holder.layer : MOB_LAYER) + 0.01
+ SSvis_overlays.add_vis_overlay(holder, 'icons/effects/effects.dmi', to_add, layer, GAME_PLANE, holder.dir)
/datum/component/shielded/proc/on_equip(obj/item/source, mob/living/equipper, slot)
if(!(accepted_slots & slotdefine2slotbit(slot)))
@@ -117,17 +116,16 @@
RegisterSignal(equipper, COMSIG_LIVING_GET_BLOCKING_ITEMS, .proc/include_shield)
var/to_add = charges >= 1 ? shield_state : broken_state
if(to_add)
- var/mutable_appearance/M = mutable_appearance('icons/effects/effects.dmi', to_add)
- M.layer = (holder.layer > MOB_LAYER ? holder.layer : MOB_LAYER) + 0.01
- equipper.add_overlay(M, TRUE)
+ var/layer = (holder.layer > MOB_LAYER ? holder.layer : MOB_LAYER) + 0.01
+ cached_vis_overlay = SSvis_overlays.add_vis_overlay(holder, 'icons/effects/effects.dmi', to_add, layer, GAME_PLANE, holder.dir)
/datum/component/shielded/proc/on_drop(obj/item/source, mob/dropper)
if(holder == dropper)
UnregisterSignal(holder, COMSIG_LIVING_GET_BLOCKING_ITEMS)
UnregisterSignal(parent, list(COMSIG_ITEM_RUN_BLOCK, COMSIG_ITEM_CHECK_BLOCK))
- var/to_remove = charges >= 1 ? shield_state : broken_state
- if(to_remove)
- holder.cut_overlay(mutable_appearance('icons/effects/effects.dmi', to_remove), TRUE)
+ if(cached_vis_overlay)
+ SSvis_overlays.remove_vis_overlay(holder, cached_vis_overlay)
+ cached_vis_overlay = null
holder = null
/datum/component/shielded/proc/include_shield(mob/source, list/items)
diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm
index 460a73bf5a..4a9c558d39 100644
--- a/code/datums/components/uplink.dm
+++ b/code/datums/components/uplink.dm
@@ -29,8 +29,8 @@ GLOBAL_LIST_EMPTY(uplinks)
var/saved_player_population = 0
var/list/filters = list()
-
-/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20, datum/ui_state/_checkstate, datum/traitor_class/traitor_class)
+
+/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20, datum/traitor_class/traitor_class)
if(!isitem(parent))
return COMPONENT_INCOMPATIBLE
@@ -144,6 +144,8 @@ GLOBAL_LIST_EMPTY(uplinks)
return COMPONENT_NO_INTERACT
/datum/component/uplink/ui_state(mob/user)
+ if(istype(parent, /obj/item/implant/uplink))
+ return GLOB.not_incapacitated_state
return GLOB.inventory_state
/datum/component/uplink/ui_interact(mob/user, datum/tgui/ui)
diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm
index 348f9e6778..a91549ab4c 100644
--- a/code/datums/datumvars.dm
+++ b/code/datums/datumvars.dm
@@ -31,6 +31,9 @@
VV_DROPDOWN_OPTION(VV_HK_EXPOSE, "Show VV To Player")
VV_DROPDOWN_OPTION(VV_HK_ADDCOMPONENT, "Add Component/Element")
VV_DROPDOWN_OPTION(VV_HK_MODIFY_TRAITS, "Modify Traits")
+ #ifdef REFERENCE_TRACKING
+ VV_DROPDOWN_OPTION(VV_HK_VIEW_REFERENCES, "View References")
+ #endif
//This proc is only called if everything topic-wise is verified. The only verifications that should happen here is things like permission checks!
//href_list is a reference, modifying it in these procs WILL change the rest of the proc in topic.dm of admin/view_variables!
diff --git a/code/datums/diseases/advance/symptoms/species.dm b/code/datums/diseases/advance/symptoms/species.dm
index 49a3cf8d07..2d5255842b 100644
--- a/code/datums/diseases/advance/symptoms/species.dm
+++ b/code/datums/diseases/advance/symptoms/species.dm
@@ -31,4 +31,3 @@
/datum/symptom/inorganic_adaptation/OnRemove(datum/disease/advance/A)
A.infectable_biotypes &= ~MOB_MINERAL
-
diff --git a/code/datums/dna.dm b/code/datums/dna.dm
index de5c1ece91..9486029fdd 100644
--- a/code/datums/dna.dm
+++ b/code/datums/dna.dm
@@ -137,10 +137,10 @@
L[DNA_COLOR_TWO_BLOCK] = sanitize_hexcolor(features["mcolor2"], 6)
L[DNA_COLOR_THREE_BLOCK] = sanitize_hexcolor(features["mcolor3"], 6)
if(!GLOB.mam_tails_list.len)
- init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_tails, GLOB.mam_tails_list)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/mam_tails, GLOB.mam_tails_list)
L[DNA_MUTANTTAIL_BLOCK] = construct_block(GLOB.mam_tails_list.Find(features["mam_tail"]), GLOB.mam_tails_list.len)
if(!GLOB.mam_ears_list.len)
- init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_ears, GLOB.mam_ears_list)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/ears/mam_ears, GLOB.mam_ears_list)
L[DNA_MUTANTEAR_BLOCK] = construct_block(GLOB.mam_ears_list.Find(features["mam_ears"]), GLOB.mam_ears_list.len)
if(!GLOB.mam_body_markings_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_body_markings, GLOB.mam_body_markings_list)
diff --git a/code/datums/ductnet.dm b/code/datums/ductnet.dm
new file mode 100644
index 0000000000..14a74a67c4
--- /dev/null
+++ b/code/datums/ductnet.dm
@@ -0,0 +1,65 @@
+///We handle the unity part of plumbing. We track who is connected to who.
+/datum/ductnet
+ var/list/suppliers = list()
+ var/list/demanders = list()
+ var/list/obj/machinery/duct/ducts = list()
+
+ var/capacity
+///Add a duct to our network
+/datum/ductnet/proc/add_duct(obj/machinery/duct/D)
+ if(!D || (D in ducts))
+ return
+ ducts += D
+ D.duct = src
+///Remove a duct from our network and commit suicide, because this is probably easier than to check who that duct was connected to and what part of us was lost
+/datum/ductnet/proc/remove_duct(obj/machinery/duct/ducting)
+ destroy_network(FALSE)
+ for(var/obj/machinery/duct/D in ducting.neighbours)
+ addtimer(CALLBACK(D, /obj/machinery/duct/proc/reconnect), 0) //all needs to happen after the original duct that was destroyed finishes destroying itself
+ addtimer(CALLBACK(D, /obj/machinery/duct/proc/generate_connects), 0)
+ qdel(src)
+///add a plumbing object to either demanders or suppliers
+/datum/ductnet/proc/add_plumber(datum/component/plumbing/P, dir)
+ if(!P.can_add(src, dir))
+ return FALSE
+ P.ducts[num2text(dir)] = src
+ if(dir & P.supply_connects)
+ suppliers += P
+ else if(dir & P.demand_connects)
+ demanders += P
+ return TRUE
+///remove a plumber. we dont delete ourselves because ductnets dont persist through plumbing objects
+/datum/ductnet/proc/remove_plumber(datum/component/plumbing/P)
+ suppliers.Remove(P) //we're probably only in one of these, but Remove() is inherently sane so this is fine
+ demanders.Remove(P)
+
+ for(var/dir in P.ducts)
+ if(P.ducts[dir] == src)
+ P.ducts -= dir
+ if(!ducts.len) //there were no ducts, so it was a direct connection. we destroy ourselves since a ductnet with only one plumber and no ducts is worthless
+ destroy_network()
+///we combine ductnets. this occurs when someone connects to seperate sets of fluid ducts
+/datum/ductnet/proc/assimilate(datum/ductnet/D)
+ ducts.Add(D.ducts)
+ suppliers.Add(D.suppliers)
+ demanders.Add(D.demanders)
+ for(var/A in D.suppliers + D.demanders)
+ var/datum/component/plumbing/P = A
+ for(var/s in P.ducts)
+ if(P.ducts[s] != D)
+ continue
+ P.ducts[s] = src //all your ducts are belong to us
+ for(var/A in D.ducts)
+ var/obj/machinery/duct/M = A
+ M.duct = src //forget your old master
+
+ destroy_network()
+///destroy the network and tell all our ducts and plumbers we are gone
+/datum/ductnet/proc/destroy_network(delete=TRUE)
+ for(var/A in suppliers + demanders)
+ remove_plumber(A)
+ for(var/A in ducts)
+ var/obj/machinery/duct/D = A
+ D.duct = null
+ if(delete) //I don't want code to run with qdeleted objects because that can never be good, so keep this in-case the ductnet has some business left to attend to before commiting suicide
+ qdel(src)
diff --git a/code/datums/elements/bsa_blocker.dm b/code/datums/elements/bsa_blocker.dm
new file mode 100644
index 0000000000..61140ad0ed
--- /dev/null
+++ b/code/datums/elements/bsa_blocker.dm
@@ -0,0 +1,10 @@
+//blocks bluespace artillery beams that try to fly through
+//look not all elements need to be fancy
+/datum/element/bsa_blocker/Attach(datum/target)
+ if(!isatom(target))
+ return ELEMENT_INCOMPATIBLE
+ RegisterSignal(target, COMSIG_ATOM_BSA_BEAM, .proc/block_bsa)
+ return ..()
+
+/datum/element/bsa_blocker/proc/block_bsa()
+ return COMSIG_ATOM_BLOCKS_BSA_BEAM
diff --git a/code/datums/elements/decal.dm b/code/datums/elements/decal.dm
index 4bd482915a..50519b08e7 100644
--- a/code/datums/elements/decal.dm
+++ b/code/datums/elements/decal.dm
@@ -33,39 +33,34 @@
if(description)
RegisterSignal(A, COMSIG_PARENT_EXAMINE, .proc/examine)
- apply(A, TRUE)
-
num_decals_per_atom[A]++
+ apply(A)
/datum/element/decal/Detach(datum/target)
var/atom/A = target
- remove(A, A.dir)
- UnregisterSignal(A, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_PARENT_EXAMINE))
- LAZYREMOVE(num_decals_per_atom, A)
+ num_decals_per_atom[A]--
+ apply(A, TRUE)
+ if(!num_decals_per_atom[A])
+ UnregisterSignal(A, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_PARENT_EXAMINE, COMSIG_ATOM_UPDATE_OVERLAYS))
+ LAZYREMOVE(num_decals_per_atom, A)
return ..()
-/datum/element/decal/proc/remove(atom/target, old_dir)
- pic.dir = first_dir == NORTH ? target.dir : turn(first_dir, dir2angle(old_dir))
- for(var/i in 1 to num_decals_per_atom[target])
- target.cut_overlay(pic, TRUE)
+/datum/element/decal/proc/apply(atom/target, removing = FALSE)
+ if(num_decals_per_atom[target] == 1 && !removing)
+ RegisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/apply_overlay, TRUE)
+ target.update_icon()
if(isitem(target))
addtimer(CALLBACK(target, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE)
-/datum/element/decal/proc/apply(atom/target, init = FALSE)
- pic.dir = first_dir == NORTH ? target.dir : turn(first_dir, dir2angle(target.dir))
- if(init)
- target.add_overlay(pic, TRUE)
- else
- for(var/i in 1 to num_decals_per_atom[target])
- target.add_overlay(pic, TRUE)
- if(isitem(target))
- addtimer(CALLBACK(target, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE)
+/datum/element/decal/proc/apply_overlay(atom/source, list/overlay_list)
+ pic.dir = first_dir == NORTH ? source.dir : turn(first_dir, dir2angle(source.dir))
+ for(var/i in 1 to num_decals_per_atom[source])
+ overlay_list += pic
-/datum/element/decal/proc/rotate_react(datum/source, old_dir, new_dir)
+/datum/element/decal/proc/rotate_react(atom/source, old_dir, new_dir)
if(old_dir == new_dir)
return
- remove(source, old_dir)
- apply(source)
+ source.update_icon()
/datum/element/decal/proc/clean_react(datum/source, strength)
if(strength >= cleanable)
diff --git a/code/datums/hud.dm b/code/datums/hud.dm
index c1811fb9b3..1c23d5f2a0 100644
--- a/code/datums/hud.dm
+++ b/code/datums/hud.dm
@@ -28,7 +28,8 @@ GLOBAL_LIST_INIT(huds, list(
ANTAG_HUD_CLOCKWORK = new/datum/atom_hud/antag(),
ANTAG_HUD_BROTHER = new/datum/atom_hud/antag/hidden(),
ANTAG_HUD_BLOODSUCKER = new/datum/atom_hud/antag/bloodsucker(),
- ANTAG_HUD_FUGITIVE = new/datum/atom_hud/antag()
+ ANTAG_HUD_FUGITIVE = new/datum/atom_hud/antag(),
+ ANTAG_HUD_HERETIC = new/datum/atom_hud/antag/hidden()
))
/datum/atom_hud
diff --git a/code/datums/materials/basemats.dm b/code/datums/materials/basemats.dm
index 721af65449..1469965b57 100644
--- a/code/datums/materials/basemats.dm
+++ b/code/datums/materials/basemats.dm
@@ -287,7 +287,7 @@ Unless you know what you're doing, only use the first three numbers. They're in
desc = "Clock Cult? Never heard of it."
color = "#92661A"
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
- sheet_type = /obj/item/stack/tile/bronze
+ sheet_type = /obj/item/stack/sheet/bronze
value_per_unit = 0.025
armor_modifiers = list("melee" = 1, "bullet" = 1, "laser" = 1, "energy" = 1, "bomb" = 1, "bio" = 1, "rad" = 1.5, "fire" = 1.5, "acid" = 1.5)
beauty_modifier = 0.2
diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm
index 787d6375a7..38b004a657 100644
--- a/code/datums/mood_events/generic_negative_events.dm
+++ b/code/datums/mood_events/generic_negative_events.dm
@@ -162,6 +162,11 @@
mood_change = -8
timeout = 3 MINUTES
+/datum/mood_event/gates_of_mansus
+ description = "LIVING IN A PERFORMANCE IS WORSE THAN DEATH\n"
+ mood_change = -25
+ timeout = 4 MINUTES
+
//These are unused so far but I want to remember them to use them later
/datum/mood_event/cloned_corpse
diff --git a/code/datums/mood_events/generic_positive_events.dm b/code/datums/mood_events/generic_positive_events.dm
index 8f98917ed3..b73756c2b1 100644
--- a/code/datums/mood_events/generic_positive_events.dm
+++ b/code/datums/mood_events/generic_positive_events.dm
@@ -70,6 +70,11 @@
mood_change = 40 //maybe being a cultist isnt that bad after all
hidden = TRUE
+/datum/mood_event/heretics
+ description = "THE HIGHER I RISE, THE MORE I SEE.\n"
+ mood_change = 12 //maybe being a cultist isnt that bad after all
+ hidden = TRUE
+
/datum/mood_event/family_heirloom
description = "My family heirloom is safe with me.\n"
mood_change = 1
diff --git a/code/datums/mutations/antenna.dm b/code/datums/mutations/antenna.dm
index 978802fd80..ad08b8ebdc 100644
--- a/code/datums/mutations/antenna.dm
+++ b/code/datums/mutations/antenna.dm
@@ -90,6 +90,8 @@
to_chat(user, "You catch some drifting memories of their past conversations...")
for(var/spoken_memory in recent_speech)
to_chat(user, "[recent_speech[spoken_memory]]")
+ if(usr in GLOB.rockpaperscissors_players)
+ to_chat(user, "They're planning on playing [GLOB.rockpaperscissors_players[usr][1]]")
if(iscarbon(M))
var/mob/living/carbon/human/H = M
to_chat(user, "You find that their intent is to [H.a_intent]...")
diff --git a/code/datums/ruins/space.dm b/code/datums/ruins/space.dm
index 5d86290f8f..64b8692ccd 100644
--- a/code/datums/ruins/space.dm
+++ b/code/datums/ruins/space.dm
@@ -325,6 +325,12 @@
name = "Abductor Replication Lab"
description = "Some scientists tried and almost succeeded to recreate abductor tools. Somewhat slower and a bit less modern than their originals, these tools are the best you can get if you aren't an alien."
+/datum/map_template/ruin/space/spacediner
+ id = "spacediner"
+ suffix = "spacediner.dmm"
+ name = "Space Diner"
+ description = "Come, traveler of the bluespace planes. Sit, enjoy a drink and take one of the fair maidens for a night. The exit is the way you came in, via that teleporter thingy, but do remember to stay safe."
+
//Space ruins for the station z
/datum/map_template/ruin/spacenearstation
prefix = "_maps/RandomRuins/SpaceRuinsStation/"
diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm
index 6e59d4fa2c..9cd47403d1 100644
--- a/code/datums/status_effects/debuffs.dm
+++ b/code/datums/status_effects/debuffs.dm
@@ -403,6 +403,197 @@
owner.underlays -= marked_underlay //if this is being called, we should have an owner at this point.
..()
+/datum/status_effect/eldritch
+ duration = 15 SECONDS
+ status_type = STATUS_EFFECT_REPLACE
+ alert_type = null
+ on_remove_on_mob_delete = TRUE
+ ///underlay used to indicate that someone is marked
+ var/mutable_appearance/marked_underlay
+ ///path for the underlay
+ var/effect_sprite = ""
+
+/datum/status_effect/eldritch/on_creation(mob/living/new_owner, ...)
+ marked_underlay = mutable_appearance('icons/effects/effects.dmi', effect_sprite,BELOW_MOB_LAYER)
+ return ..()
+
+/datum/status_effect/eldritch/on_apply()
+ . = ..()
+ if(owner.mob_size >= MOB_SIZE_HUMAN)
+ RegisterSignal(owner,COMSIG_ATOM_UPDATE_OVERLAYS,.proc/update_owner_underlay)
+ owner.update_icon()
+ return TRUE
+ return FALSE
+
+/datum/status_effect/eldritch/on_remove()
+ UnregisterSignal(owner,COMSIG_ATOM_UPDATE_OVERLAYS)
+ owner.update_icon()
+ return ..()
+
+/datum/status_effect/eldritch/proc/update_owner_underlay(atom/source, list/overlays)
+ overlays += marked_underlay
+
+/datum/status_effect/eldritch/Destroy()
+ QDEL_NULL(marked_underlay)
+ return ..()
+
+/**
+ * What happens when this mark gets popped
+ *
+ * Adds actual functionality to each mark
+ */
+/datum/status_effect/eldritch/proc/on_effect()
+ playsound(owner, 'sound/magic/repulse.ogg', 75, TRUE)
+ qdel(src) //what happens when this is procced.
+
+//Each mark has diffrent effects when it is destroyed that combine with the mansus grasp effect.
+/datum/status_effect/eldritch/flesh
+ id = "flesh_mark"
+ effect_sprite = "emark1"
+
+/datum/status_effect/eldritch/flesh/on_effect()
+
+ if(ishuman(owner))
+ var/mob/living/carbon/human/H = owner
+ var/obj/item/bodypart/bodypart = pick(H.bodyparts)
+ var/datum/wound/slash/severe/crit_wound = new
+ crit_wound.apply_wound(bodypart)
+ return ..()
+
+/datum/status_effect/eldritch/ash
+ id = "ash_mark"
+ effect_sprite = "emark2"
+ ///Dictates how much damage and stamina loss this mark will cause.
+ var/repetitions = 1
+
+/datum/status_effect/eldritch/ash/on_creation(mob/living/new_owner, _repetition = 5)
+ . = ..()
+ repetitions = min(1,_repetition)
+
+/datum/status_effect/eldritch/ash/on_effect()
+ if(iscarbon(owner))
+ var/mob/living/carbon/carbon_owner = owner
+ carbon_owner.adjustStaminaLoss(10 * repetitions)
+ carbon_owner.adjustFireLoss(5 * repetitions)
+ for(var/mob/living/carbon/victim in range(1,carbon_owner))
+ if(IS_HERETIC(victim) || victim == carbon_owner)
+ continue
+ victim.apply_status_effect(type,repetitions-1)
+ break
+ return ..()
+
+/datum/status_effect/eldritch/rust
+ id = "rust_mark"
+ effect_sprite = "emark3"
+
+/datum/status_effect/eldritch/rust/on_effect()
+ if(!iscarbon(owner))
+ return
+ var/mob/living/carbon/carbon_owner = owner
+ for(var/obj/item/I in carbon_owner.get_all_gear()) //Affects roughly 75% of items
+ if(!QDELETED(I) && prob(75)) //Just in case
+ I.take_damage(100)
+ return ..()
+
+/datum/status_effect/corrosion_curse
+ id = "corrosion_curse"
+ status_type = STATUS_EFFECT_REPLACE
+ alert_type = null
+ tick_interval = 1 SECONDS
+
+/datum/status_effect/corrosion_curse/on_creation(mob/living/new_owner, ...)
+ . = ..()
+ to_chat(owner, "Your feel your body starting to break apart...")
+
+/datum/status_effect/corrosion_curse/tick()
+ . = ..()
+ if(!ishuman(owner))
+ return
+ var/mob/living/carbon/human/H = owner
+ var/chance = rand(0,100)
+ switch(chance)
+ if(0 to 19)
+ H.vomit()
+ if(20 to 29)
+ H.Dizzy(10)
+ if(30 to 39)
+ H.adjustOrganLoss(ORGAN_SLOT_LIVER,5)
+ if(40 to 49)
+ H.adjustOrganLoss(ORGAN_SLOT_HEART,5)
+ if(50 to 59)
+ H.adjustOrganLoss(ORGAN_SLOT_STOMACH,5)
+ if(60 to 69)
+ H.adjustOrganLoss(ORGAN_SLOT_EYES,10)
+ if(70 to 79)
+ H.adjustOrganLoss(ORGAN_SLOT_EARS,10)
+ if(80 to 89)
+ H.adjustOrganLoss(ORGAN_SLOT_LUNGS,10)
+ if(90 to 99)
+ H.adjustOrganLoss(ORGAN_SLOT_TONGUE,10)
+ if(100)
+ H.adjustOrganLoss(ORGAN_SLOT_BRAIN,20)
+
+/datum/status_effect/amok
+ id = "amok"
+ status_type = STATUS_EFFECT_REPLACE
+ alert_type = null
+ duration = 10 SECONDS
+ tick_interval = 1 SECONDS
+
+/datum/status_effect/amok/on_apply(mob/living/afflicted)
+ . = ..()
+ to_chat(owner, "Your feel filled with a rage that is not your own!")
+
+/datum/status_effect/amok/tick()
+ . = ..()
+ var/prev_intent = owner.a_intent
+ owner.a_intent = INTENT_HARM
+
+ var/list/mob/living/targets = list()
+ for(var/mob/living/potential_target in oview(owner, 1))
+ if(IS_HERETIC(potential_target) || potential_target.mind?.has_antag_datum(/datum/antagonist/heretic_monster))
+ continue
+ targets += potential_target
+ if(LAZYLEN(targets))
+ owner.log_message(" attacked someone due to the amok debuff.", LOG_ATTACK) //the following attack will log itself
+ owner.ClickOn(pick(targets))
+ owner.a_intent = prev_intent
+
+/datum/status_effect/cloudstruck
+ id = "cloudstruck"
+ status_type = STATUS_EFFECT_REPLACE
+ duration = 3 SECONDS
+ on_remove_on_mob_delete = TRUE
+ ///This overlay is applied to the owner for the duration of the effect.
+ var/mutable_appearance/mob_overlay
+
+/datum/status_effect/cloudstruck/on_creation(mob/living/new_owner, set_duration)
+ if(isnum(set_duration))
+ duration = set_duration
+ . = ..()
+
+/datum/status_effect/cloudstruck/on_apply()
+ . = ..()
+ mob_overlay = mutable_appearance('icons/effects/eldritch.dmi', "cloud_swirl", ABOVE_MOB_LAYER)
+ owner.overlays += mob_overlay
+ owner.update_icon()
+ ADD_TRAIT(owner, TRAIT_BLIND, "cloudstruck")
+ return TRUE
+
+/datum/status_effect/cloudstruck/on_remove()
+ . = ..()
+ if(QDELETED(owner))
+ return
+ REMOVE_TRAIT(owner, TRAIT_BLIND, "cloudstruck")
+ if(owner)
+ owner.overlays -= mob_overlay
+ owner.update_icon()
+
+/datum/status_effect/cloudstruck/Destroy()
+ . = ..()
+ QDEL_NULL(mob_overlay)
+
+
/datum/status_effect/stacking/saw_bleed
id = "saw_bleed"
tick_interval = 6
diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm
index 6cef7ac50f..179adf46bd 100644
--- a/code/datums/wires/airlock.dm
+++ b/code/datums/wires/airlock.dm
@@ -53,8 +53,6 @@
/datum/wires/airlock/interactable(mob/user)
var/obj/machinery/door/airlock/A = holder
- if(!A.hasSiliconAccessInArea(user) && A.isElectrified() && A.shock(user, 100))
- return FALSE
if(A.panel_open)
return TRUE
@@ -73,6 +71,8 @@
/datum/wires/airlock/on_pulse(wire)
set waitfor = FALSE
var/obj/machinery/door/airlock/A = holder
+ if(!A.hasSiliconAccessInArea(usr) && A.isElectrified() && A.shock(usr, 100))
+ return FALSE
switch(wire)
if(WIRE_POWER1, WIRE_POWER2) // Pulse to loose power.
A.loseMainPower()
@@ -127,6 +127,8 @@
/datum/wires/airlock/on_cut(wire, mend)
var/obj/machinery/door/airlock/A = holder
+ if(!A.hasSiliconAccessInArea(usr) && A.isElectrified() && A.shock(usr, 100))
+ return FALSE
switch(wire)
if(WIRE_POWER1, WIRE_POWER2) // Cut to loose power, repair all to gain power.
if(mend && !is_cut(WIRE_POWER1) && !is_cut(WIRE_POWER2))
@@ -174,4 +176,4 @@
A.update_icon()
if(WIRE_ZAP1, WIRE_ZAP2) // Ouch.
if(isliving(usr))
- A.shock(usr, 50)
\ No newline at end of file
+ A.shock(usr, 50)
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index dfa9776489..8a66394ecc 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -26,7 +26,6 @@
var/list/atom_colours //used to store the different colors on an atom
//its inherent color, the colored paint applied on it, special color effect etc...
- var/list/priority_overlays //overlays that should remain on top and not normally removed when using cut_overlay functions, like c4.
var/list/remove_overlays // a very temporary list of overlays to remove
var/list/add_overlays // a very temporary list of overlays to add
@@ -145,7 +144,6 @@
qdel(reagents)
LAZYCLEARLIST(overlays)
- LAZYCLEARLIST(priority_overlays)
for(var/i in targeted_by)
var/mob/M = i
@@ -1121,3 +1119,11 @@
max_grav = max(G.setting,max_grav)
return max_grav
return SSmapping.level_trait(T.z, ZTRAIT_GRAVITY)
+
+/**
+ * Causes effects when the atom gets hit by a rust effect from heretics
+ *
+ * Override this if you want custom behaviour in whatever gets hit by the rust
+ */
+/atom/proc/rust_heretic_act()
+ return
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 0238529195..0a6c2b9eca 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -646,3 +646,10 @@
animate(I, alpha = 175, pixel_x = to_x, pixel_y = to_y, time = 3, transform = M, easing = CUBIC_EASING)
sleep(1)
animate(I, alpha = 0, transform = matrix(), time = 1)
+
+/atom/movable/proc/set_anchored(anchorvalue) //literally only for plumbing ran
+ SHOULD_CALL_PARENT(TRUE)
+ if(anchored == anchorvalue)
+ return
+ . = anchored
+ anchored = anchorvalue
diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm
index 406e142a25..be8dee5bf8 100644
--- a/code/game/gamemodes/clock_cult/clock_cult.dm
+++ b/code/game/gamemodes/clock_cult/clock_cult.dm
@@ -224,8 +224,7 @@ Credit where due:
qdel(S)
if(S && !QDELETED(S))
to_chat(L, "[slot] is a clockwork slab, a multipurpose tool used to construct machines and invoke ancient words of power. If this is your first time \
- as a servant, you can find a concise tutorial in the Recollection category of its interface.")
- to_chat(L, "If you want more information, you can read the wiki page to learn more.")
+ as a servant, you can read the wiki page to learn more.")
return TRUE
return FALSE
diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm
index da33da5f43..63574c6475 100644
--- a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm
+++ b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm
@@ -191,6 +191,24 @@
SSticker.mode_result = "loss - rev heads killed"
SSticker.news_report = REVS_LOSE
+//////////////////////////////////////////////
+// //
+// HERETIC SMUGGLER //
+// //
+//////////////////////////////////////////////
+
+/datum/dynamic_ruleset/latejoin/heretic_smuggler
+ name = "Heretic Smuggler"
+ antag_datum = /datum/antagonist/heretic
+ antag_flag = ROLE_HERETIC
+ protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
+ restricted_roles = list("AI","Cyborg")
+ required_candidates = 1
+ weight = 4
+ cost = 10
+ requirements = list(40,30,20,10,10,10,10,10,10,10)
+ repeatable = TRUE
+
//////////////////////////////////////////////
// //
// BLOODSUCKERS //
diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
index edaadeae1c..766ddcefc7 100644
--- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
+++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
@@ -143,6 +143,46 @@
changeling.add_antag_datum(new_antag)
return TRUE
+//////////////////////////////////////////////
+// //
+// ELDRITCH CULT //
+// //
+//////////////////////////////////////////////
+
+/datum/dynamic_ruleset/roundstart/heretics
+ name = "Heretics"
+ antag_flag = ROLE_HERETIC
+ antag_datum = /datum/antagonist/heretic
+ protected_roles = list("Prisoner","Security Officer", "Warden", "Detective", "Head of Security", "Captain")
+ restricted_roles = list("AI", "Cyborg")
+ required_candidates = 1
+ weight = 3
+ cost = 20
+ scaling_cost = 15
+ requirements = list(50,45,45,40,35,20,20,15,10,10)
+ antag_cap = list(1,1,1,1,2,2,2,2,3,3)
+
+
+/datum/dynamic_ruleset/roundstart/heretics/pre_execute()
+ . = ..()
+ var/num_ecult = antag_cap[indice_pop] * (scaled_times + 1)
+
+ for (var/i = 1 to num_ecult)
+ var/mob/picked_candidate = pick_n_take(candidates)
+ assigned += picked_candidate.mind
+ picked_candidate.mind.restricted_roles = restricted_roles
+ picked_candidate.mind.special_role = ROLE_HERETIC
+ return TRUE
+
+/datum/dynamic_ruleset/roundstart/heretics/execute()
+
+ for(var/c in assigned)
+ var/datum/mind/cultie = c
+ var/datum/antagonist/heretic/new_antag = new antag_datum()
+ cultie.add_antag_datum(new_antag)
+
+ return TRUE
+
//////////////////////////////////////////////
// //
// WIZARDS //
diff --git a/code/game/gamemodes/dynamic/dynamic_storytellers.dm b/code/game/gamemodes/dynamic/dynamic_storytellers.dm
index 561b38fde1..148de9568a 100644
--- a/code/game/gamemodes/dynamic/dynamic_storytellers.dm
+++ b/code/game/gamemodes/dynamic/dynamic_storytellers.dm
@@ -50,10 +50,6 @@ Property weights are:
for(var/r in SSevents.running)
var/datum/round_event/R = r
threat += R.threat()
- for(var/mob/living/simple_animal/hostile/H in GLOB.mob_living_list)
- var/turf/T = get_turf(H)
- if(H.stat != DEAD && is_station_level(T.z) && !("Station" in H.faction))
- threat += H.threat()
for(var/obj/item/phylactery/P in GLOB.poi_list)
threat += 25 // can't be giving them too much of a break
for (var/mob/M in mode.current_players[CURRENT_LIVING_PLAYERS])
@@ -91,6 +87,8 @@ Property weights are:
mean += 2.5
if(CHAOS_MAX)
mean += 5
+ else
+ voters += 0.5
if(voters)
GLOB.dynamic_curve_centre += (mean/voters)
if(flags & USE_PREV_ROUND_WEIGHTS)
@@ -128,7 +126,8 @@ Property weights are:
for(var/property in property_weights)
if(property in rule.property_weights) // just treat it as 0 if it's not in there
property_weight += rule.property_weights[property] * property_weights[property]
- drafted_rules[rule] = (rule.get_weight() * property_weight)*rule.weight_mult
+ if(property_weight > 0)
+ drafted_rules[rule] = rule.get_weight() * property_weight * rule.weight_mult
return drafted_rules
/datum/dynamic_storyteller/proc/midround_draft()
@@ -140,25 +139,26 @@ Property weights are:
if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)))
continue
rule.trim_candidates()
- var/threat_weight = 1
- if(!(rule.flags & MINOR_RULESET)) // makes the traitor rulesets always possible anyway
- var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat))
- /* Basically, the closer the cost is to the current threat-level-away-from-threat, the more likely it is to
- pick this particular ruleset.
- Let's use a toy example: there's 60 threat level and 10 threat spent.
- We want to pick a ruleset that's close to that, so we run the below equation, on two rulesets.
- Ruleset 1 has 30 cost, ruleset 2 has 5 cost.
- When we do the math, ruleset 1's threat_weight is 0.538, and ruleset 2's is 0.238, meaning ruleset 1
- is 2.26 times as likely to be picked, all other things considered.
- Of course, we don't want it to GUARANTEE the closest, that's no fun, so it's just a weight.
- */
- threat_weight = abs(1-abs(1-LOGISTIC_FUNCTION(2,0.05,cost_difference,0)))
if (rule.ready())
var/property_weight = 0
for(var/property in property_weights)
- if(property in rule.property_weights)
+ if(property in rule.property_weights) // just treat it as 0 if it's not in there
property_weight += rule.property_weights[property] * property_weights[property]
- drafted_rules[rule] = round(((rule.get_weight() * property_weight)*rule.weight_mult*threat_weight)*1000,1)
+ if(property_weight > 0)
+ var/threat_weight = 1
+ if(!(rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)) // makes the traitor rulesets always possible anyway
+ var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat))
+ /* Basically, the closer the cost is to the current threat-level-away-from-threat, the more likely it is to
+ pick this particular ruleset.
+ Let's use a toy example: there's 60 threat level and 10 threat spent.
+ We want to pick a ruleset that's close to that, so we run the below equation, on two rulesets.
+ Ruleset 1 has 30 cost, ruleset 2 has 5 cost.
+ When we do the math, ruleset 1's threat_weight is 0.538, and ruleset 2's is 0.238, meaning ruleset 1
+ is 2.26 times as likely to be picked, all other things considered.
+ Of course, we don't want it to GUARANTEE the closest, that's no fun, so it's just a weight.
+ */
+ threat_weight = abs(1-abs(1-LOGISTIC_FUNCTION(2,0.05,cost_difference,0)))
+ drafted_rules[rule] = rule.get_weight() * property_weight * rule.weight_mult * threat_weight
return drafted_rules
/datum/dynamic_storyteller/proc/latejoin_draft(mob/living/carbon/human/newPlayer)
@@ -175,28 +175,29 @@ Property weights are:
rule.candidates = list(newPlayer)
rule.trim_candidates()
- var/threat_weight = 1
- if(!(rule.flags & MINOR_RULESET))
- var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat))
- threat_weight = 1-abs(1-(LOGISTIC_FUNCTION(2,0.05,cost_difference,0)))
if (rule.ready())
var/property_weight = 0
for(var/property in property_weights)
if(property in rule.property_weights)
property_weight += rule.property_weights[property] * property_weights[property]
- drafted_rules[rule] = round(((rule.get_weight() * property_weight)*rule.weight_mult*threat_weight)*1000,1)
+ if(property_weight > 0)
+ var/threat_weight = 1
+ if(!(rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET))
+ var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat))
+ threat_weight = 1-abs(1-(LOGISTIC_FUNCTION(2,0.05,cost_difference,0)))
+ drafted_rules[rule] = rule.get_weight() * property_weight * rule.weight_mult * threat_weight
return drafted_rules
/datum/dynamic_storyteller/proc/event_draft()
var/list/drafted_rules = list()
for(var/datum/dynamic_ruleset/event/rule in mode.events)
- if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && (mode.threat_level - mode.threat) >= rule.cost)
- if(rule.ready())
- var/property_weight = 0
- for(var/property in property_weights)
- if(property in rule.property_weights)
- property_weight += rule.property_weights[property] * property_weights[property]
- drafted_rules[rule] = (rule.get_weight() + property_weight)*rule.weight_mult
+ if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && (mode.threat_level + 20 - mode.threat) >= rule.cost && rule.ready())
+ var/property_weight = 0
+ for(var/property in property_weights)
+ if(property in rule.property_weights)
+ property_weight += rule.property_weights[property] * property_weights[property]
+ if(property_weight > 0)
+ drafted_rules[rule] = rule.get_weight() + property_weight * rule.weight_mult
return drafted_rules
@@ -313,9 +314,8 @@ Property weights are:
/datum/dynamic_storyteller/random/event_draft()
var/list/drafted_rules = list()
for(var/datum/dynamic_ruleset/event/rule in mode.events)
- if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
- if(rule.ready())
- drafted_rules[rule] = 1
+ if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && rule.ready())
+ drafted_rules[rule] = 1
return drafted_rules
/datum/dynamic_storyteller/story
@@ -330,7 +330,7 @@ Property weights are:
/datum/dynamic_storyteller/story/calculate_threat()
var/current_time = (world.time / SSautotransfer.targettime)*180
- mode.threat_level = round(mode.initial_threat_level*(sin(current_time)+0.25),0.1)
+ mode.threat_level = round((mode.initial_threat_level*(sin(current_time)/2)+0.75),0.1)
return ..()
/datum/dynamic_storyteller/classic
diff --git a/code/game/gamemodes/eldritch_cult/eldritch_cult.dm b/code/game/gamemodes/eldritch_cult/eldritch_cult.dm
new file mode 100644
index 0000000000..20a129a5a3
--- /dev/null
+++ b/code/game/gamemodes/eldritch_cult/eldritch_cult.dm
@@ -0,0 +1,67 @@
+/datum/game_mode/heretics
+ name = "heresy"
+ config_tag = "heresy"
+ antag_flag = ROLE_HERETIC
+ false_report_weight = 5
+ restricted_jobs = list("AI", "Cyborg")
+ protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") //citadel change - adds HoP, CE, CMO, and RD to heretic role blacklist
+ required_players = 15
+ required_enemies = 1
+ recommended_enemies = 4
+ reroll_friendly = 1
+ enemy_minimum_age = 0
+ round_ends_with_antag_death = 0
+
+ announce_span = "danger"
+ announce_text = "Heretics have been spotted on the station!\n\
+ Heretics: Accomplish your objectives.\n\
+ Crew: Do not let the madman succeed!"
+
+ var/ecult_possible = 4 //hard limit on culties if scaling is turned off
+ var/num_ecult = 1
+ var/list/culties = list()
+
+/datum/game_mode/heretics/pre_setup()
+
+ if(CONFIG_GET(flag/protect_roles_from_antagonist))
+ restricted_jobs += protected_jobs
+
+ if(CONFIG_GET(flag/protect_assistant_from_antagonist))
+ restricted_jobs += "Assistant"
+
+
+ var/esc = CONFIG_GET(number/ecult_scaling_coeff)
+ if(esc)
+ num_ecult = min(max(1, min(round(num_players() / (esc * 2)) + 2, round(num_players() / esc))),4)
+ else
+ num_ecult = max(1, min(num_players(), ecult_possible))
+
+ for(var/i in 1 to num_ecult)
+ if(!antag_candidates.len)
+ break
+ var/datum/mind/cultie = antag_pick(antag_candidates)
+ antag_candidates -= cultie
+ cultie.special_role = ROLE_HERETIC
+ cultie.restricted_roles = restricted_jobs
+ culties += cultie
+
+ var/enough_heretics = culties.len > 0
+
+ if(!enough_heretics)
+ setup_error = "Not enough heretic candidates"
+ return FALSE
+ else
+ for(var/antag in culties)
+ return TRUE
+
+/datum/game_mode/heretics/post_setup()
+ for(var/c in culties)
+ var/datum/mind/cultie = c
+ log_game("[key_name(cultie)] has been selected as a heretic!")
+ var/datum/antagonist/heretic/new_antag = new()
+ cultie.add_antag_datum(new_antag)
+ return ..()
+
+/datum/game_mode/heretics/generate_report()
+ return "Cybersun Industries has announced that they have successfully raided a high-security library. The library contained a very dangerous book that was \
+ shown to posses anomalous properties. We suspect that the book has been copied over, Stay vigilant!"
diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm
index 50c08a5dcd..2b7411d03f 100644
--- a/code/game/machinery/_machinery.dm
+++ b/code/game/machinery/_machinery.dm
@@ -117,6 +117,7 @@ Class Procs:
var/new_occupant_dir = SOUTH //The direction the occupant will be set to look at when entering the machine.
var/speed_process = FALSE // Process as fast as possible?
var/obj/item/circuitboard/circuit // Circuit to be created and inserted when the machinery is created
+ var/wire_compatible = FALSE
// For storing and overriding ui id and dimensions
var/tgui_id // ID of TGUI interface
var/ui_style // ID of custom TGUI style (optional)
@@ -433,6 +434,7 @@ Class Procs:
to_chat(user, "You [anchored ? "un" : ""]secure [src].")
setAnchored(!anchored)
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
+ SEND_SIGNAL(src, COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH, anchored)
return SUCCESSFUL_UNFASTEN
return FAILED_UNFASTEN
return CANT_UNFASTEN
@@ -547,3 +549,6 @@ Class Procs:
. = . % 9
AM.pixel_x = -8 + ((.%3)*8)
AM.pixel_y = -8 + (round( . / 3)*8)
+
+/obj/machinery/rust_heretic_act()
+ take_damage(500, BRUTE, "melee", 1)
diff --git a/code/game/machinery/doors/airlock_types.dm b/code/game/machinery/doors/airlock_types.dm
index 530a287134..b34e97d374 100644
--- a/code/game/machinery/doors/airlock_types.dm
+++ b/code/game/machinery/doors/airlock_types.dm
@@ -310,6 +310,17 @@
opacity = 0
glass = TRUE
+/obj/machinery/door/airlock/bronze
+ name = "bronze airlock"
+ icon = 'icons/obj/doors/airlocks/clockwork/pinion_airlock.dmi'
+ overlays_file = 'icons/obj/doors/airlocks/clockwork/overlays.dmi'
+ assemblytype = /obj/structure/door_assembly/door_assembly_bronze
+
+/obj/machinery/door/airlock/bronze/seethru
+ assemblytype = /obj/structure/door_assembly/door_assembly_bronze/seethru
+ opacity = 0
+ glass = TRUE
+
//////////////////////////////////
/*
Station2 Airlocks
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 5b691607db..f16a5f9292 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -153,6 +153,9 @@
/obj/mecha/get_cell()
return cell
+/obj/mecha/rust_heretic_act()
+ take_damage(500, BRUTE)
+
/obj/mecha/Destroy()
go_out()
var/mob/living/silicon/ai/AI
diff --git a/code/game/objects/effects/effect_system/effects_sparks.dm b/code/game/objects/effects/effect_system/effects_sparks.dm
index 19b0dc76dd..a388d3bc67 100644
--- a/code/game/objects/effects/effect_system/effects_sparks.dm
+++ b/code/game/objects/effects/effect_system/effects_sparks.dm
@@ -63,3 +63,23 @@
/datum/effect_system/lightning_spread
effect_type = /obj/effect/particle_effect/sparks/electricity
+
+//fake sparks, not subtyped because we don't want light/heat, nor checks inside an often used proc for a rare subcase for saving like 10 lines of code
+/obj/effect/particle_effect/fake_sparks
+ name = "lightning"
+ icon_state = "electricity"
+
+/obj/effect/particle_effect/fake_sparks/Initialize()
+ . = ..()
+ flick(icon_state, src) // replay the animation
+ playsound(src, "sparks", 100, TRUE)
+ QDEL_IN(src, 20)
+
+/datum/effect_system/fake_spark_spread
+ effect_type = /obj/effect/particle_effect/fake_sparks
+
+/proc/do_fake_sparks(n, c, source)
+ var/datum/effect_system/fake_spark_spread/sparks = new
+ sparks.set_up(n, c, source)
+ sparks.autocleanup = TRUE
+ sparks.start()
diff --git a/code/game/objects/effects/spawners/bundle.dm b/code/game/objects/effects/spawners/bundle.dm
index 3f2701c03f..b75df644eb 100644
--- a/code/game/objects/effects/spawners/bundle.dm
+++ b/code/game/objects/effects/spawners/bundle.dm
@@ -168,3 +168,26 @@
items = list(
/obj/item/clothing/mask/gas/sexymime,
/obj/item/clothing/under/rank/civilian/mime/sexy)
+
+/obj/effect/spawner/bundle/crate/Initialize(mapload)
+ if(items && items.len)
+ var/turf/T = get_turf(src)
+ var/obj/structure/closet/LC = locate(/obj/structure/closet) in T
+ if(LC)
+ for(var/path in items)
+ new path(LC)
+ return INITIALIZE_HINT_QDEL
+
+/obj/effect/spawner/bundle/crate/mosin
+ name = "Mosin-Nagant spawner"
+ items = list(
+ /obj/item/gun/ballistic/shotgun/boltaction,
+ /obj/item/ammo_box/a762
+ )
+
+/obj/effect/spawner/bundle/crate/surplusrifle
+ name = "surplus rifle spawner"
+ items = list(
+ /obj/item/gun/ballistic/automatic/surplus,
+ /obj/item/ammo_box/magazine/m10mm/rifle
+ )
diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
index 396f463136..8d5458333c 100644
--- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm
+++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
@@ -139,6 +139,23 @@
/obj/effect/temp_visual/dir_setting/curse/hand
icon_state = "cursehand"
+/obj/effect/temp_visual/bsa_splash
+ name = "\improper Bluespace energy wave"
+ desc = "A massive, rippling wave of bluepace energy, all rapidly exhausting itself the moment it leaves the concentrated beam of light."
+ icon = 'icons/effects/beam_splash.dmi'
+ icon_state = "beam_splash_l"
+ layer = ABOVE_ALL_MOB_LAYER
+ pixel_y = -16
+ duration = 50
+
+/obj/effect/temp_visual/bsa_splash/Initialize(mapload, dir)
+ . = ..()
+ switch(dir)
+ if(WEST)
+ icon_state = "beam_splash_w"
+ if(EAST)
+ icon_state = "beam_splash_e"
+
/obj/effect/temp_visual/wizard
name = "water"
icon = 'icons/mob/mob.dmi'
diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm
index 2fbb45173b..c89e318714 100644
--- a/code/game/objects/items/RCD.dm
+++ b/code/game/objects/items/RCD.dm
@@ -135,6 +135,14 @@ RLD
flick("[icon_state]_empty", src) //somewhat hacky thing to make RCDs with ammo counters actually have a blinking yellow light
return .
+
+/obj/item/construction/proc/check_menu(mob/living/user)
+ if(!istype(user))
+ return FALSE
+ if(user.incapacitated() || !user.Adjacent(src))
+ return FALSE
+ return TRUE
+
/obj/item/construction/proc/range_check(atom/A, mob/user)
if(!(A in range(custom_range, get_turf(user))))
to_chat(user, "The \'Out of Range\' light on [src] blinks red.")
@@ -276,13 +284,6 @@ RLD
//Not scaling these down to button size because they look horrible then, instead just bumping up radius.
return MA
-/obj/item/construction/rcd/proc/check_menu(mob/living/user)
- if(!istype(user))
- return FALSE
- if(user.incapacitated() || !user.Adjacent(src))
- return FALSE
- return TRUE
-
/obj/item/construction/rcd/proc/change_computer_dir(mob/user)
if(!user)
return
@@ -856,6 +857,82 @@ RLD
desc = "It contains the design for firelock, air alarm, fire alarm, apc circuits and crap power cells."
upgrade = RCD_UPGRADE_SIMPLE_CIRCUITS
+/obj/item/construction/plumbing
+ name = "Plumbing Constructor"
+ desc = "An expertly modified RCD outfitted to construct plumbing machinery. Reload with compressed matter cartridges."
+ icon = 'icons/obj/tools.dmi'
+ icon_state = "arcd"
+ item_state = "oldrcd"
+ has_ammobar = FALSE
+ matter = 200
+ max_matter = 200
+
+ ///type of the plumbing machine
+ var/blueprint = null
+ ///index, used in the attack self to get the type. stored here since it doesnt change
+ var/list/choices = list()
+ ///index, used in the attack self to get the type. stored here since it doesnt change
+ var/list/name_to_type = list()
+ ///
+ var/list/machinery_data = list("cost" = list(), "delay" = list())
+
+/obj/item/construction/plumbing/attack_self(mob/user)
+ ..()
+ if(!choices.len)
+ for(var/A in subtypesof(/obj/machinery/plumbing))
+ var/obj/machinery/plumbing/M = A
+ if(initial(M.rcd_constructable))
+ choices += list(initial(M.name) = image(icon = initial(M.icon), icon_state = initial(M.icon_state)))
+ name_to_type[initial(M.name)] = M
+ machinery_data["cost"][A] = initial(M.rcd_cost)
+ machinery_data["delay"][A] = initial(M.rcd_delay)
+
+ var/choice = show_radial_menu(user, src, choices, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE, tooltips = TRUE)
+ if(!check_menu(user))
+ return
+
+ blueprint = name_to_type[choice]
+ playsound(src, 'sound/effects/pop.ogg', 50, FALSE)
+ to_chat(user, "You change [name]s blueprint to '[choice]'.")
+
+///pretty much rcd_create, but named differently to make myself feel less bad for copypasting from a sibling-type
+/obj/item/construction/plumbing/proc/create_machine(atom/A, mob/user)
+ if(!machinery_data || !isopenturf(A))
+ return FALSE
+
+ if(checkResource(machinery_data["cost"][blueprint], user) && blueprint)
+ if(do_after(user, machinery_data["delay"][blueprint], target = A))
+ if(checkResource(machinery_data["cost"][blueprint], user) && canPlace(A))
+ useResource(machinery_data["cost"][blueprint], user)
+ activate()
+ playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE)
+ new blueprint (A, FALSE, FALSE)
+ return TRUE
+
+/obj/item/construction/plumbing/proc/canPlace(turf/T)
+ if(!isopenturf(T))
+ return FALSE
+ . = TRUE
+ for(var/obj/O in T.contents)
+ if(O.density) //let's not built ontop of dense stuff, like big machines and other obstacles, it kills my immershion
+ return FALSE
+
+/obj/item/construction/plumbing/afterattack(atom/A, mob/user)
+ . = ..()
+ if(!range_check(A, user))
+ return
+ if(istype(A, /obj/machinery/plumbing))
+ var/obj/machinery/plumbing/P = A
+ if(P.anchored)
+ to_chat(user, "The [P.name] needs to be unanchored!")
+ return
+ if(do_after(user, 20, target = P))
+ P.deconstruct() //Let's not substract matter
+ playsound(get_turf(src), 'sound/machines/click.ogg', 50, TRUE) //this is just such a great sound effect
+ else
+ create_machine(A, user)
+
+
#undef GLOW_MODE
#undef LIGHT_MODE
#undef REMOVE_MODE
diff --git a/code/game/objects/items/RPD.dm b/code/game/objects/items/RPD.dm
index b3d5ed431a..70e4441c66 100644
--- a/code/game/objects/items/RPD.dm
+++ b/code/game/objects/items/RPD.dm
@@ -6,6 +6,7 @@ RPD
#define ATMOS_CATEGORY 0
#define DISPOSALS_CATEGORY 1
#define TRANSIT_CATEGORY 2
+#define PLUMBING_CATEGORY 3
#define BUILD_MODE (1<<0)
#define WRENCH_MODE (1<<1)
@@ -75,6 +76,13 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
)
))
+GLOBAL_LIST_INIT(fluid_duct_recipes, list(
+ "Fluid Ducts" = list(
+ new /datum/pipe_info/plumbing("Duct", /obj/machinery/duct, PIPE_ONEDIR),
+ new /datum/pipe_info/plumbing/multilayer("Duct Layer-Manifold",/obj/machinery/duct/multilayered, PIPE_STRAIGHT)
+ )
+))
+
/datum/pipe_info
var/name
var/icon_state
@@ -175,6 +183,15 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
if(dt == PIPE_UNARY_FLIPPABLE)
icon_state = "[icon_state]_preview"
+/datum/pipe_info/plumbing/New(label, obj/path, dt=PIPE_UNARY)
+ name = label
+ id = path
+ icon_state = initial(path.icon_state)
+ dirtype = dt
+
+/datum/pipe_info/plumbing/multilayer //exists as identifier so we can see the difference between multi_layer and just ducts properly later on
+
+
/obj/item/pipe_dispenser
name = "Rapid Piping Device (RPD)"
desc = "A device used to rapidly pipe things."
@@ -200,15 +217,19 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
var/atmos_build_speed = 5 //deciseconds (500ms)
var/disposal_build_speed = 5
var/transit_build_speed = 5
+ var/plumbing_build_speed = 5
var/destroy_speed = 5
var/paint_speed = 5
var/category = ATMOS_CATEGORY
var/piping_layer = PIPING_LAYER_DEFAULT
+ var/ducting_layer = DUCT_LAYER_DEFAULT
var/datum/pipe_info/recipe
var/static/datum/pipe_info/first_atmos
var/static/datum/pipe_info/first_disposal
var/static/datum/pipe_info/first_transit
var/mode = BUILD_MODE | DESTROY_MODE | WRENCH_MODE
+ var/static/datum/pipe_info/first_plumbing
+ var/locked = FALSE //wheter we can change categories. Useful for the plumber
/obj/item/pipe_dispenser/New()
. = ..()
@@ -253,12 +274,15 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
var/list/data = list(
"category" = category,
"piping_layer" = piping_layer,
- // "ducting_layer" = ducting_layer, //uhh is this for chem thing?
+
+ "ducting_layer" = ducting_layer,
+
"preview_rows" = recipe.get_preview(p_dir),
"categories" = list(),
"selected_color" = paint_color,
"paint_colors" = GLOB.pipe_paint_colors,
- "mode" = mode
+ "mode" = mode,
+ "locked" = locked
)
var/list/recipes
@@ -269,6 +293,8 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
recipes = GLOB.disposal_pipe_recipes
if(TRANSIT_CATEGORY)
recipes = GLOB.transit_tube_recipes
+ if(PLUMBING_CATEGORY)
+ recipes = GLOB.fluid_duct_recipes
for(var/c in recipes)
var/list/cat = recipes[c]
var/list/r = list()
@@ -297,6 +323,8 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
recipe = first_atmos
if(TRANSIT_CATEGORY)
recipe = first_transit
+ if(PLUMBING_CATEGORY)
+ recipe = first_plumbing
p_dir = NORTH
playeffect = FALSE
if("piping_layer")
@@ -468,16 +496,56 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
if(mode & WRENCH_MODE)
tube.wrench_act(user, src)
return
-
+ if(PLUMBING_CATEGORY) //Plumbing.
+ if(!can_make_pipe)
+ return ..()
+ A = get_turf(A)
+ if(isclosedturf(A))
+ to_chat(user, "[src]'s error light flickers; there's something in the way!")
+ return
+ to_chat(user, "You start building a fluid duct...")
+ playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
+ if(do_after(user, plumbing_build_speed, target = A))
+ var/obj/machinery/duct/D
+ if(recipe.type == /datum/pipe_info/plumbing/multilayer)
+ var/temp_connects = NORTH + SOUTH
+ if(queued_p_dir == EAST)
+ temp_connects = EAST + WEST
+ D = new queued_p_type (A, TRUE, GLOB.pipe_paint_colors[paint_color], ducting_layer, temp_connects)
+ else
+ D = new queued_p_type (A, TRUE, GLOB.pipe_paint_colors[paint_color], ducting_layer)
+ D.add_fingerprint(usr)
+ if(mode & WRENCH_MODE)
+ D.wrench_act(user, src)
else
return ..()
/obj/item/pipe_dispenser/proc/activate()
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
+/* unneeded, you can craft ducts from plastic
+/obj/item/pipe_dispenser/plumbing
+ name = "Plumberinator"
+ desc = "A crude device to rapidly plumb things."
+ icon_state = "plumberer"
+ category = PLUMBING_CATEGORY
+ locked = TRUE
+
+/obj/item/pipe_dispenser/plumbing/Initialize()
+ . = ..()
+ spark_system = new
+ spark_system.set_up(5, 0, src)
+ spark_system.attach(src)
+ if(!first_plumbing)
+ first_plumbing = GLOB.fluid_duct_recipes[GLOB.fluid_duct_recipes[1]][1]
+
+ recipe = first_plumbing
+
+*/
#undef ATMOS_CATEGORY
#undef DISPOSALS_CATEGORY
#undef TRANSIT_CATEGORY
+#undef PLUMBING_CATEGORY
#undef BUILD_MODE
#undef DESTROY_MODE
diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm
index 56eb25f953..37d19783b5 100644
--- a/code/game/objects/items/circuitboards/machine_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm
@@ -48,6 +48,13 @@
/obj/item/stack/cable_coil = 5,
/obj/item/stack/sheet/glass = 1)
+/obj/item/circuitboard/machine/medipen_refiller
+ name = "Medipen Refiller (Machine Board)"
+ icon_state = "medical"
+ build_path = /obj/machinery/medipen_refiller
+ req_components = list(
+ /obj/item/stock_parts/matter_bin = 1)
+
/obj/item/circuitboard/machine/clonepod
name = "Clone Pod (Machine Board)"
build_path = /obj/machinery/clonepod
@@ -512,6 +519,10 @@
/obj/item/stack/sheet/glass = 1)
needs_anchored = FALSE
+/obj/item/circuitboard/machine/hydroponics/automagic
+ name = "Automatic Hydroponics Tray (Machine Board)"
+ build_path = /obj/machinery/hydroponics/constructable/automagic
+
/obj/item/circuitboard/machine/seed_extractor
name = "Seed Extractor (Machine Board)"
build_path = /obj/machinery/seed_extractor
diff --git a/code/game/objects/items/dualsaber.dm b/code/game/objects/items/dualsaber.dm
index e5e97d2b2b..cf5c3d4fc5 100644
--- a/code/game/objects/items/dualsaber.dm
+++ b/code/game/objects/items/dualsaber.dm
@@ -51,6 +51,10 @@
// no attacking while blocking
block_lock_attacking = TRUE
block_projectile_mitigation = 75
+ // more efficient vs projectiles
+ block_stamina_efficiency_override = list(
+ TEXT_ATTACK_TYPE_PROJECTILE = 4
+ )
parry_time_windup = 0
parry_time_active = 8
@@ -65,14 +69,20 @@
parry_imperfect_falloff_percent = 10
parry_efficiency_to_counterattack = 100
parry_efficiency_considered_successful = 25 // VERY generous
- parry_efficiency_perfect = 90
parry_failed_stagger_duration = 3 SECONDS
parry_failed_clickcd_duration = CLICK_CD_MELEE
- // more efficient vs projectiles
- block_stamina_efficiency_override = list(
- TEXT_ATTACK_TYPE_PROJECTILE = 4
- )
+/obj/item/dualsaber/active_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, override_direction)
+ if((attack_type & ATTACK_TYPE_PROJECTILE) && is_energy_reflectable_projectile(object))
+ block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_RETURN_TO_SENDER
+ return BLOCK_SUCCESS | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT
+ return ..()
+
+/obj/item/dualsaber/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
+ . = ..()
+ if(parry_efficiency >= 90) // perfect parry
+ block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_RETURN_TO_SENDER
+ . |= BLOCK_SHOULD_REDIRECT
/obj/item/dualsaber/Initialize()
. = ..()
diff --git a/code/game/objects/items/granters.dm b/code/game/objects/items/granters.dm
index 609cc3b719..979fa7e958 100644
--- a/code/game/objects/items/granters.dm
+++ b/code/game/objects/items/granters.dm
@@ -253,7 +253,7 @@
user.set_nutrition(NUTRITION_LEVEL_STARVING + 50)
/obj/item/book/granter/spell/blind
- spell = /obj/effect/proc_holder/spell/targeted/trigger/blind
+ spell = /obj/effect/proc_holder/spell/pointed/trigger/blind
spellname = "blind"
icon_state ="bookblind"
desc = "This book looks blurry, no matter how you look at it."
@@ -265,7 +265,7 @@
user.blind_eyes(10)
/obj/item/book/granter/spell/mindswap
- spell = /obj/effect/proc_holder/spell/targeted/mind_transfer
+ spell = /obj/effect/proc_holder/spell/pointed/mind_transfer
spellname = "mindswap"
icon_state ="bookmindswap"
desc = "This book's cover is pristine, though its pages look ragged and torn."
@@ -289,7 +289,7 @@
if(stored_swap == user)
to_chat(user,"You stare at the book some more, but there doesn't seem to be anything else to learn...")
return
- var/obj/effect/proc_holder/spell/targeted/mind_transfer/swapper = new
+ var/obj/effect/proc_holder/spell/pointed/mind_transfer/swapper = new
if(swapper.cast(list(stored_swap), user, TRUE, TRUE))
to_chat(user,"You're suddenly somewhere else... and someone else?!")
to_chat(stored_swap,"Suddenly you're staring at [src] again... where are you, who are you?!")
@@ -324,7 +324,7 @@
user.DefaultCombatKnockdown(40)
/obj/item/book/granter/spell/barnyard
- spell = /obj/effect/proc_holder/spell/targeted/barnyardcurse
+ spell = /obj/effect/proc_holder/spell/pointed/barnyardcurse
spellname = "barnyard"
icon_state ="bookhorses"
desc = "This book is more horse than your mind has room for."
diff --git a/code/game/objects/items/grenades/plastic.dm b/code/game/objects/items/grenades/plastic.dm
index a2b0e3edd4..014487332c 100644
--- a/code/game/objects/items/grenades/plastic.dm
+++ b/code/game/objects/items/grenades/plastic.dm
@@ -60,7 +60,8 @@
if(target)
if(!QDELETED(target))
location = get_turf(target)
- target.cut_overlay(plastic_overlay, TRUE)
+ target.cut_overlay(plastic_overlay)
+ UnregisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/add_plastic_overlay)
if(!ismob(target) || full_damage_on_mobs)
target.ex_act(EXPLODE_HEAVY, target)
else
@@ -126,13 +127,17 @@
I.embedding["embed_chance"] = 0
I.updateEmbedding()
- target.add_overlay(plastic_overlay, TRUE)
+ RegisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/add_plastic_overlay)
+ target.update_icon()
if(!nadeassembly)
to_chat(user, "You plant the bomb. Timer counting down from [det_time].")
addtimer(CALLBACK(src, .proc/prime), det_time*10)
else
qdel(src) //How?
+/obj/item/grenade/plastic/proc/add_plastic_overlay(atom/source, list/overlay_list)
+ overlay_list += plastic_overlay
+
/obj/item/grenade/plastic/proc/shout_syndicate_crap(mob/M)
if(!M)
return
diff --git a/code/game/objects/items/implants/implant_uplink.dm b/code/game/objects/items/implants/implant_uplink.dm
index 9895c1e34c..0cac8f838a 100644
--- a/code/game/objects/items/implants/implant_uplink.dm
+++ b/code/game/objects/items/implants/implant_uplink.dm
@@ -9,7 +9,7 @@
/obj/item/implant/uplink/Initialize(mapload, _owner)
. = ..()
- AddComponent(/datum/component/uplink, _owner, TRUE, FALSE, null, starting_tc, GLOB.not_incapacitated_state)
+ AddComponent(/datum/component/uplink, _owner, TRUE, FALSE, null, starting_tc)
/obj/item/implanter/uplink
name = "implanter (uplink)"
diff --git a/code/game/objects/items/miscellaneous.dm b/code/game/objects/items/miscellaneous.dm
index a7f7e3152c..6f1aec287b 100644
--- a/code/game/objects/items/miscellaneous.dm
+++ b/code/game/objects/items/miscellaneous.dm
@@ -47,8 +47,11 @@
spawn_option(stored_options[choice],M)
qdel(src)
-/obj/item/choice_beacon/proc/spawn_option(obj/choice,mob/living/M)
- var/obj/new_item = new choice()
+/obj/item/choice_beacon/proc/create_choice_atom(atom/choice, mob/owner)
+ return new choice()
+
+/obj/item/choice_beacon/proc/spawn_option(atom/choice,mob/living/M)
+ var/obj/new_item = create_choice_atom(choice, M)
var/obj/structure/closet/supplypod/bluespacepod/pod = new()
pod.explosionSize = list(0,0,0,0)
new_item.forceMove(pod)
@@ -152,10 +155,50 @@
augment_list[initial(A.name)] = A
return augment_list
-/obj/item/choice_beacon/augments/spawn_option(obj/choice,mob/living/M)
+/obj/item/choice_beacon/augments/spawn_option(atom/choice,mob/living/M)
new choice(get_turf(M))
to_chat(M, "You hear something crackle from the beacon for a moment before a voice speaks. \"Please stand by for a message from S.E.L.F. Message as follows: Item request received. Your package has been transported, use the autosurgeon supplied to apply the upgrade. Message ends.\"")
+/obj/item/choice_beacon/pet //donator beacon that summons a small friendly animal
+ name = "pet beacon"
+ desc = "Straight from the outerspace pet shop to your feet."
+ var/static/list/pets = list("Crab" = /mob/living/simple_animal/crab,
+ "Cat" = /mob/living/simple_animal/pet/cat,
+ "Space cat" = /mob/living/simple_animal/pet/cat/space,
+ "Kitten" = /mob/living/simple_animal/pet/cat/kitten,
+ "Dog" = /mob/living/simple_animal/pet/dog,
+ "Corgi" = /mob/living/simple_animal/pet/dog/corgi,
+ "Pug" = /mob/living/simple_animal/pet/dog/pug,
+ "Exotic Corgi" = /mob/living/simple_animal/pet/dog/corgi/exoticcorgi,
+ "Fox" = /mob/living/simple_animal/pet/fox,
+ "Red Panda" = /mob/living/simple_animal/pet/redpanda,
+ "Possum" = /mob/living/simple_animal/opossum)
+ var/pet_name
+
+/obj/item/choice_beacon/pet/generate_display_names()
+ return pets
+
+/obj/item/choice_beacon/pet/create_choice_atom(atom/choice, mob/owner)
+ var/mob/living/simple_animal/new_choice = new choice()
+ new_choice.butcher_results = null //please don't eat your pet, chef
+ var/obj/item/pet_carrier/donator/carrier = new() //a donator pet carrier is just a carrier that can't be shoved in an autolathe for metal
+ carrier.add_occupant(new_choice)
+ new_choice.mob_size = MOB_SIZE_TINY //yeah we're not letting you use this roundstart pet to hurt people / knock them down
+ new_choice.pass_flags = PASSTABLE | PASSMOB //your pet is not a bullet/person shield
+ new_choice.density = FALSE
+ new_choice.blood_volume = 0 //your pet cannot be used to drain blood from for a bloodsucker
+ new_choice.desc = "A pet [initial(choice.name)], owned by [owner]!"
+ new_choice.can_have_ai = FALSE //no it cant be sentient damnit
+ if(pet_name)
+ new_choice.name = pet_name
+ new_choice.unique_name = TRUE
+ return carrier
+
+/obj/item/choice_beacon/pet/spawn_option(atom/choice,mob/living/M)
+ pet_name = input(M, "What would you like to name the pet? (leave blank for default name)", "Pet Name")
+ ..()
+
+//choice boxes (they just open in your hand instead of making a pod)
/obj/item/choice_beacon/box
name = "choice box (default)"
desc = "Think really hard about what you want, and then rip it open!"
@@ -163,21 +206,17 @@
icon_state = "deliverypackage3"
item_state = "deliverypackage3"
-/obj/item/choice_beacon/box/spawn_option(obj/choice,mob/living/M)
- to_chat(M, "The box opens, revealing the [choice]!")
+/obj/item/choice_beacon/box/spawn_option(atom/choice,mob/living/M)
+ var/choice_text = choice
+ if(ispath(choice_text))
+ choice_text = initial(choice.name)
+ to_chat(M, "The box opens, revealing the [choice_text]!")
playsound(src.loc, 'sound/items/poster_ripped.ogg', 50, 1)
M.temporarilyRemoveItemFromInventory(src, TRUE)
M.put_in_hands(new choice)
qdel(src)
-/obj/item/choice_beacon/box/plushie
- name = "choice box (plushie)"
- desc = "Using the power of quantum entanglement, this box contains every plush, until the moment it is opened!"
- icon = 'icons/obj/plushes.dmi'
- icon_state = "box"
- item_state = "box"
-
-/obj/item/choice_beacon/box/spawn_option(choice,mob/living/M)
+/obj/item/choice_beacon/box/plushie/spawn_option(choice,mob/living/M)
if(ispath(choice, /obj/item/toy/plush))
..() //regular plush, spawn it naturally
else
@@ -188,6 +227,31 @@
M.put_in_hands(new choice)
qdel(src)
+/obj/item/choice_beacon/box/carpet //donator carpet beacon
+ name = "choice box (carpet)"
+ desc = "Contains 50 of a selected carpet inside!"
+ var/static/list/carpet_list = list(/obj/item/stack/tile/carpet/black/fifty = "Black Carpet",
+ "Black & Red Carpet" = /obj/item/stack/tile/carpet/blackred/fifty,
+ "Monochrome Carpet" = /obj/item/stack/tile/carpet/monochrome/fifty,
+ "Blue Carpet" = /obj/item/stack/tile/carpet/blue/fifty,
+ "Cyan Carpet" = /obj/item/stack/tile/carpet/cyan/fifty,
+ "Green Carpet" = /obj/item/stack/tile/carpet/green/fifty,
+ "Orange Carpet" = /obj/item/stack/tile/carpet/orange/fifty,
+ "Purple Carpet" = /obj/item/stack/tile/carpet/purple/fifty,
+ "Red Carpet" = /obj/item/stack/tile/carpet/red/fifty,
+ "Royal Black Carpet" = /obj/item/stack/tile/carpet/royalblack/fifty,
+ "Royal Blue Carpet" = /obj/item/stack/tile/carpet/royalblue/fifty)
+
+/obj/item/choice_beacon/box/carpet/generate_display_names()
+ return carpet_list
+
+/obj/item/choice_beacon/box/plushie
+ name = "choice box (plushie)"
+ desc = "Using the power of quantum entanglement, this box contains every plush, until the moment it is opened!"
+ icon = 'icons/obj/plushes.dmi'
+ icon_state = "box"
+ item_state = "box"
+
/obj/item/choice_beacon/box/plushie/generate_display_names()
var/list/plushie_list = list()
//plushie set 1: just subtypes of /obj/item/toy/plush
diff --git a/code/game/objects/items/pet_carrier.dm b/code/game/objects/items/pet_carrier.dm
index c6b5a7e224..ef2fb44d3d 100644
--- a/code/game/objects/items/pet_carrier.dm
+++ b/code/game/objects/items/pet_carrier.dm
@@ -29,6 +29,9 @@
var/has_lock_sprites = TRUE //whether to load the lock overlays or not
var/allows_hostiles = FALSE //does the pet carrier allow hostile entities to be held within it?
+/obj/item/pet_carrier/donator
+ custom_materials = null //you cant just use the loadout item to get free metal!
+
/obj/item/pet_carrier/Destroy()
if(occupants.len)
for(var/V in occupants)
@@ -240,7 +243,31 @@
custom_materials = list(/datum/material/glass = 1000, /datum/material/bluespace = 600)
escape_time = 200 //equal to the time of a bluespace bodybag
alternate_escape_time = 100
+
+ ///gas supply for simplemobs so they don't die
var/datum/gas_mixture/occupant_gas_supply
+ ///level until the reagent gets INGEST ed instead of TOUCH
+ var/sipping_level = 150
+ ///prob50 level of sipping
+ var/sipping_probably = 99
+ ///chem transfer rate / second
+ var/transfer_rate = 5
+
+/obj/item/pet_carrier/bluespace/Initialize()
+ . = ..()
+ create_reagents(300, OPENCONTAINER, DEFAULT_REAGENTS_VALUE) //equivalent of bsbeakers
+
+/obj/item/pet_carrier/bluespace/Destroy()
+ STOP_PROCESSING(SSobj, src)
+ return ..()
+
+/obj/item/pet_carrier/bluespace/attack_self(mob/living/user)
+ ..()
+ if(reagents)
+ if(open)
+ reagents.reagents_holder_flags = OPENCONTAINER
+ else
+ reagents.reagents_holder_flags = NONE
/obj/item/pet_carrier/bluespace/update_icon_state()
if(open)
@@ -248,11 +275,28 @@
else
icon_state = "bluespace_jar"
-/obj/item/pet_carrier/bluespace/throw_impact()
+/obj/item/pet_carrier/bluespace/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
. = ..()
//delete the item upon impact, releasing the creature inside (this is handled by its deletion)
if(occupants.len)
loc.visible_message("The bluespace jar smashes, releasing [occupants[1]]!")
+
+ if(reagents?.total_volume && ismob(hit_atom) && hit_atom.reagents)
+ reagents.total_volume *= rand(5,10) * 0.1 //Not all of it makes contact with the target
+ var/mob/M = hit_atom
+ var/R = reagents.log_list()
+ hit_atom.visible_message("[M] has been splashed with something!", \
+ "[M] has been splashed with something!")
+ var/turf/TT = get_turf(hit_atom)
+ var/throwerstring
+ if(thrownby)
+ log_combat(thrownby, M, "splashed", R)
+ var/turf/AT = get_turf(thrownby)
+ throwerstring = " THROWN BY [key_name(thrownby)] at [AT] (AREACOORD(AT)]"
+ log_reagent("SPLASH: [src] mob throw_impact() onto [key_name(hit_atom)] at [TT] ([AREACOORD(TT)])[throwerstring] - [R]")
+ reagents.reaction(hit_atom, TOUCH)
+ reagents.clear_reagents()
+
playsound(src, "shatter", 70, 1)
qdel(src)
@@ -260,21 +304,24 @@
. = ..()
if(!occupant_gas_supply)
occupant_gas_supply = new
+
if(isanimal(occupant))
var/mob/living/simple_animal/animal = occupant
occupant_gas_supply[/datum/gas/oxygen] = 0.0064 //make sure it has some gas in so it isn't depressurized
occupant_gas_supply.set_temperature(animal.minbodytemp) //simple animals only care about temperature/pressure when their turf isnt a location
- else
- if(ishuman(occupant)) //humans require resistance to cold/heat and living in no air while inside, and lose this when outside
- ADD_TRAIT(occupant, TRAIT_RESISTCOLD, "bluespace_container_cold_resist")
- ADD_TRAIT(occupant, TRAIT_RESISTHEAT, "bluespace_container_heat_resist")
- ADD_TRAIT(occupant, TRAIT_NOBREATH, "bluespace_container_no_breath")
- ADD_TRAIT(occupant, TRAIT_RESISTHIGHPRESSURE, "bluespace_container_resist_high_pressure")
- ADD_TRAIT(occupant, TRAIT_RESISTLOWPRESSURE, "bluespace_container_resist_low_pressure")
+
+ if(ishuman(occupant)) //humans require resistance to cold/heat and living in no air while inside, and lose this when outside
+ START_PROCESSING(SSobj, src)
+ ADD_TRAIT(occupant, TRAIT_RESISTCOLD, "bluespace_container_cold_resist")
+ ADD_TRAIT(occupant, TRAIT_RESISTHEAT, "bluespace_container_heat_resist")
+ ADD_TRAIT(occupant, TRAIT_NOBREATH, "bluespace_container_no_breath")
+ ADD_TRAIT(occupant, TRAIT_RESISTHIGHPRESSURE, "bluespace_container_resist_high_pressure")
+ ADD_TRAIT(occupant, TRAIT_RESISTLOWPRESSURE, "bluespace_container_resist_low_pressure")
/obj/item/pet_carrier/bluespace/remove_occupant(mob/living/occupant)
. = ..()
if(ishuman(occupant))
+ STOP_PROCESSING(SSobj, src)
REMOVE_TRAIT(occupant, TRAIT_RESISTCOLD, "bluespace_container_cold_resist")
REMOVE_TRAIT(occupant, TRAIT_RESISTHEAT, "bluespace_container_heat_resist")
REMOVE_TRAIT(occupant, TRAIT_NOBREATH, "bluespace_container_no_breath")
@@ -287,6 +334,18 @@
occupant_gas_supply = new
return occupant_gas_supply
+/obj/item/pet_carrier/bluespace/process()
+ if(!reagents)
+ return
+ for(var/mob/living/L in occupants)
+ if(!ishuman(L))
+ continue
+ if((reagents.total_volume >= sipping_level) || ((reagents.total_volume >= sipping_probably) && prob(50))) //sipp
+ reagents.reaction(L, INGEST) //consume
+ reagents.trans_to(L, transfer_rate)
+ else
+ reagents.reaction(L, TOUCH, show_message = FALSE)
+
/obj/item/pet_carrier/bluespace/load_occupant(mob/living/user, mob/living/target)
if(..())
name = "[initial(name)] ([target])"
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index 9ea8c9c689..7ba2196184 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -128,6 +128,7 @@
absorption_capacity = 5
splint_factor = 0.35
custom_price = PRICE_REALLY_CHEAP
+ grind_results = list(/datum/reagent/cellulose = 2)
// gauze is only relevant for wounds, which are handled in the wounds themselves
/obj/item/stack/medical/gauze/try_heal(mob/living/M, mob/user, silent)
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 5f6341ea21..645051b7c2 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -412,6 +412,7 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \
force = 0
throwforce = 0
merge_type = /obj/item/stack/sheet/cloth
+ grind_results = list(/datum/reagent/cellulose = 2)
/obj/item/stack/sheet/cloth/get_main_recipes()
. = ..()
@@ -672,6 +673,10 @@ GLOBAL_LIST_INIT(brass_recipes, list ( \
GLOBAL_LIST_INIT(bronze_recipes, list ( \
new/datum/stack_recipe("wall gear", /obj/structure/girder/bronze, 2, time = 20, one_per_turf = TRUE, on_floor = TRUE), \
null,
+ new/datum/stack_recipe("directional bronze window", /obj/structure/window/bronze/unanchored, time = 0, on_floor = TRUE, window_checks = TRUE), \
+ new/datum/stack_recipe("fulltile bronze window", /obj/structure/window/bronze/fulltile/unanchored, 2, time = 0, on_floor = TRUE, window_checks = TRUE), \
+ new/datum/stack_recipe("pinion airlock assembly", /obj/structure/door_assembly/door_assembly_bronze, 4, time = 50, one_per_turf = TRUE, on_floor = TRUE), \
+ new/datum/stack_recipe("bronze pinion airlock assembly", /obj/structure/door_assembly/door_assembly_bronze/seethru, 4, time = 50, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("bronze hat", /obj/item/clothing/head/bronze), \
new/datum/stack_recipe("bronze suit", /obj/item/clothing/suit/bronze), \
new/datum/stack_recipe("bronze boots", /obj/item/clothing/shoes/bronze), \
@@ -679,9 +684,10 @@ GLOBAL_LIST_INIT(bronze_recipes, list ( \
new/datum/stack_recipe("bronze chair", /obj/structure/chair/bronze, 1, time = 0, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("bronze bar stool", /obj/structure/chair/stool/bar/bronze, 1, time = 0, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("bronze stool", /obj/structure/chair/stool/bronze, 1, time = 0, one_per_turf = TRUE, on_floor = TRUE), \
+ new /datum/stack_recipe("bronze floor tiles", /obj/item/stack/tile/bronze, 1, 4, 20), \
))
-/obj/item/stack/tile/bronze
+/obj/item/stack/sheet/bronze
name = "brass"
desc = "On closer inspection, what appears to be wholly-unsuitable-for-building brass is actually more structurally stable bronze."
singular_name = "bronze sheet"
@@ -690,27 +696,21 @@ GLOBAL_LIST_INIT(bronze_recipes, list ( \
icon = 'icons/obj/stack_objects.dmi'
custom_materials = list(/datum/material/bronze = MINERAL_MATERIAL_AMOUNT)
resistance_flags = FIRE_PROOF | ACID_PROOF
- throwforce = 10
- max_amount = 50
- throw_speed = 1
- throw_range = 3
- turf_type = /turf/open/floor/bronze
- novariants = FALSE
grind_results = list(/datum/reagent/iron = 5, /datum/reagent/copper = 3) //we have no "tin" reagent so this is the closest thing
- merge_type = /obj/item/stack/tile/bronze
+ merge_type = /obj/item/stack/sheet/bronze
tableVariant = /obj/structure/table/bronze
material_type = /datum/material/bronze
-/obj/item/stack/tile/bronze/attack_self(mob/living/user)
+/obj/item/stack/sheet/bronze/attack_self(mob/living/user)
if(is_servant_of_ratvar(user)) //still lets them build with it, just gives a message
to_chat(user, "Wha... what is this cheap imitation crap? This isn't brass at all!")
..()
-/obj/item/stack/tile/bronze/get_main_recipes()
+/obj/item/stack/sheet/bronze/get_main_recipes()
. = ..()
. += GLOB.bronze_recipes
-/obj/item/stack/tile/bronze/thirty
+/obj/item/stack/sheet/bronze/thirty
amount = 30
/*
@@ -774,6 +774,7 @@ GLOBAL_LIST_INIT(plastic_recipes, list(
new /datum/stack_recipe("water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/empty), \
new /datum/stack_recipe("large water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/large/empty,3), \
new /datum/stack_recipe("shower curtain", /obj/structure/curtain, 10, time = 10, one_per_turf = 1, on_floor = 1), \
+ new /datum/stack_recipe("duct", /obj/item/stack/ducts,1), \
new /datum/stack_recipe("laser pointer case", /obj/item/glasswork/glass_base/laserpointer_shell, 30), \
new /datum/stack_recipe("wet floor sign", /obj/item/caution, 2)))
@@ -842,6 +843,7 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra
merge_type = /obj/item/stack/sheet/cotton
var/pull_effort = 30
var/loom_result = /obj/item/stack/sheet/cloth
+ grind_results = list(/datum/reagent/cellulose = 5)
/obj/item/stack/sheet/cotton/ten
amount = 10
@@ -857,6 +859,7 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra
merge_type = /obj/item/stack/sheet/cotton/durathread
pull_effort = 70
loom_result = /obj/item/stack/sheet/durathread
+ grind_results = list(/datum/reagent/cellulose = 10)
/obj/item/stack/sheet/meat
name = "meat sheets"
diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm
index 13fca1e8fe..0d85e897d2 100644
--- a/code/game/objects/items/stacks/tiles/tile_types.dm
+++ b/code/game/objects/items/stacks/tiles/tile_types.dm
@@ -513,3 +513,12 @@
icon_state = "material_tile"
turf_type = /turf/open/floor/material
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
+
+/obj/item/stack/tile/bronze
+ name = "bronze tile"
+ singular_name = "bronze floor tile"
+ desc = "A tile made out of bronze. Looks like clockwork."
+ icon_state = "material_tile"
+ color = "#92661A"
+ turf_type = /turf/open/floor/bronze
+ custom_materials = list(/datum/material/bronze = 250)
diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm
index 3c554aa58e..0001494fdd 100755
--- a/code/game/objects/items/storage/belt.dm
+++ b/code/game/objects/items/storage/belt.dm
@@ -478,7 +478,7 @@
/obj/item/assembly/signaler,
/obj/item/lightreplacer,
/obj/item/rcd_ammo,
- /obj/item/construction/rcd,
+ /obj/item/construction,
/obj/item/pipe_dispenser,
/obj/item/stack/rods,
/obj/item/stack/tile/plasteel,
@@ -492,7 +492,7 @@
icon_state = "grenadebeltnew"
item_state = "security"
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
-
+
/obj/item/storage/belt/grenade/ComponentInitialize()
. = ..()
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm
index 7532aacbfa..28850e79a2 100644
--- a/code/game/objects/items/storage/book.dm
+++ b/code/game/objects/items/storage/book.dm
@@ -47,41 +47,58 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible",
user.visible_message("[user] is offering [user.p_them()]self to [deity_name]! It looks like [user.p_theyre()] trying to commit suicide!")
return (BRUTELOSS)
-/obj/item/storage/book/bible/attack_self(mob/living/carbon/human/H)
- if(!istype(H))
+/obj/item/storage/book/bible/attack_self(mob/living/carbon/human/user)
+ if(!istype(user))
return
- // If H is the Chaplain, we can set the icon_state of the bible (but only once!)
- if(!GLOB.bible_icon_state && H.job == "Chaplain")
- var/dat = "
Pick Bible StylePick a bible style
"
- for(var/i in 1 to GLOB.biblestates.len)
- var/icon/bibleicon = icon('icons/obj/storage.dmi', GLOB.biblestates[i])
- var/nicename = GLOB.biblenames[i]
- H << browse_rsc(bibleicon, nicename)
- dat += {" | [nicename] |
"}
- dat += "
"
- H << browse(dat, "window=editicon;can_close=0;can_minimize=0;size=250x650")
+ if(GLOB.bible_icon_state) // if there is already a bible icon return FALSE
+ return FALSE
+ if(user.job != "Chaplain") // if the user is not the chaplain, return FALSE
+ return FALSE
-/obj/item/storage/book/bible/Topic(href, href_list)
- if(!usr.canUseTopic(src))
- return
- if(href_list["seticon"] && GLOB && !GLOB.bible_icon_state)
- var/iconi = text2num(href_list["seticon"])
- var/biblename = GLOB.biblenames[iconi]
- var/obj/item/storage/book/bible/B = locate(href_list["src"])
- B.icon_state = GLOB.biblestates[iconi]
- B.item_state = GLOB.bibleitemstates[iconi]
+ var/list/skins = list()
+ for(var/i in 1 to GLOB.biblestates.len)
+ var/image/bible_image = image(icon = 'icons/obj/storage.dmi', icon_state = GLOB.biblestates[i])
+ skins += list("[GLOB.biblenames[i]]" = bible_image)
- if(B.icon_state == "honk1" || B.icon_state == "honk2")
- var/mob/living/carbon/human/H = usr
- H.dna.add_mutation(CLOWNMUT)
- H.dna.add_mutation(SMILE)
- H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(H), SLOT_WEAR_MASK)
+ var/choice = show_radial_menu(user, src, skins, custom_check = CALLBACK(src, .proc/check_menu, user), radius = 40, require_near = TRUE)
+ if(!choice)
+ return FALSE
+ var/bible_index = GLOB.biblenames.Find(choice)
+ if(!bible_index)
+ return FALSE
+ icon_state = GLOB.biblestates[bible_index]
+ item_state = GLOB.bibleitemstates[bible_index]
- GLOB.bible_icon_state = B.icon_state
- GLOB.bible_item_state = B.item_state
+ if(icon_state == "honk1" || icon_state == "honk2")
+ var/mob/living/carbon/human/H = usr
+ H.dna.add_mutation(CLOWNMUT)
+ H.dna.add_mutation(SMILE)
+ H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(H), SLOT_WEAR_MASK)
- SSblackbox.record_feedback("text", "religion_book", 1, "[biblename]")
- usr << browse(null, "window=editicon")
+ GLOB.bible_icon_state = icon_state
+ GLOB.bibleitemstates = item_state
+ SSblackbox.record_feedback("text", "religion_book", 1, "[choice]")
+
+/**
+ * Checks if we are allowed to interact with the radial
+ *
+ * Arguements: user The mob interacting with the menu
+ */
+
+/obj/item/storage/book/bible/proc/check_menu(mob/living/carbon/human/user)
+ if(GLOB.bible_icon_state)
+ return FALSE
+ if(!istype(user))
+ return FALSE
+ if(!user.is_holding(src))
+ return FALSE
+ if(!user.can_read(src))
+ return FALSE
+ if(user.incapacitated())
+ return FALSE
+ if(user.job != "Chaplain")
+ return FALSE
+ return TRUE
/obj/item/storage/book/bible/proc/bless(mob/living/carbon/human/H, mob/living/user)
for(var/X in H.bodyparts)
diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm
index ed0ee8ad07..73246276c2 100644
--- a/code/game/objects/items/storage/toolbox.dm
+++ b/code/game/objects/items/storage/toolbox.dm
@@ -245,19 +245,20 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
new /obj/item/stack/cable_coil/white(src)
/obj/item/storage/toolbox/ammo
- name = "ammo box"
- desc = "It contains a few clips."
+ name = "ammunition case (7.62mm stripper clips)"
+ desc = "It contains a few 7.62 stripper clips."
icon_state = "ammobox"
item_state = "ammobox"
+ var/ammotype = /obj/item/ammo_box/a762 // make sure this is a typepath thanks
/obj/item/storage/toolbox/ammo/PopulateContents()
- new /obj/item/ammo_box/a762(src)
- new /obj/item/ammo_box/a762(src)
- new /obj/item/ammo_box/a762(src)
- new /obj/item/ammo_box/a762(src)
- new /obj/item/ammo_box/a762(src)
- new /obj/item/ammo_box/a762(src)
- new /obj/item/ammo_box/a762(src)
+ for (var/i = 0, i < 7, i++)
+ new ammotype(src)
+
+/obj/item/storage/toolbox/ammo/surplus
+ name = "ammunition case (10mm rifle magazines)"
+ desc = "It contains a few 10mm rifle magazines."
+ ammotype = /obj/item/ammo_box/magazine/m10mm/rifle
/obj/item/storage/toolbox/infiltrator
name = "insidious case"
@@ -280,6 +281,7 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
/obj/item/clothing/suit/armor/vest/infiltrator,
/obj/item/clothing/under/syndicate/bloodred,
/obj/item/clothing/gloves/color/latex/nitrile/infiltrator,
+ /obj/item/clothing/gloves/tackler/combat/insulated/infiltrator,
/obj/item/clothing/mask/infiltrator,
/obj/item/clothing/shoes/combat/sneakboots,
/obj/item/gun/ballistic/automatic/pistol,
@@ -291,7 +293,7 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
new /obj/item/clothing/head/helmet/infiltrator(src)
new /obj/item/clothing/suit/armor/vest/infiltrator(src)
new /obj/item/clothing/under/syndicate/bloodred(src)
- new /obj/item/clothing/gloves/color/latex/nitrile/infiltrator(src)
+ new /obj/item/clothing/gloves/tackler/combat/insulated/infiltrator(src)
new /obj/item/clothing/mask/infiltrator(src)
new /obj/item/clothing/shoes/combat/sneakboots(src)
diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm
index e7dc636cf3..f462050789 100644
--- a/code/game/objects/items/weaponry.dm
+++ b/code/game/objects/items/weaponry.dm
@@ -252,6 +252,10 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/obj/item/katana/timestop
name = "temporal katana"
desc = "Delicately balanced, this finely-crafted blade hums with barely-restrained potential."
+ icon_state = "temporalkatana"
+ item_state = "temporalkatana"
+ lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
block_chance = 0 // oops
force = 27.5 // oops
item_flags = ITEM_CAN_PARRY
@@ -263,6 +267,21 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
flynn.emote("smirk")
new /obj/effect/timestop/magic(get_turf(owner), 1, 50, list(owner)) // null roddies counter
+/obj/item/katana/timestop/suicide_act(mob/living/user) // stolen from hierophant staff
+ new /obj/effect/timestop/magic(get_turf(user), 1, 50, list(user)) // free usage for dying
+ user.visible_message("[user] poses menacingly with the [src]! It looks like [user.p_theyre()] trying to teleport behind someone!")
+ user.say("Heh.. Nothing personnel, kid..", forced = "temporal katana suicide")
+ sleep(20)
+ if(!user)
+ return
+ user.visible_message("[user] vanishes into a cloud of falling dust and burning embers, likely off to style on some poor sod in the distance!")
+ playsound(user,'sound/magic/blink.ogg', 75, TRUE)
+ for(var/obj/item/I in user)
+ if(I != src)
+ user.dropItemToGround(I)
+ user.dropItemToGround(src) //Drop us last, so it goes on top of their stuff
+ qdel(user)
+
/obj/item/melee/bokken // parrying stick
name = "bokken"
desc = "A space-Japanese training sword made of wood and shaped like a katana."
@@ -297,7 +316,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
parry_time_perfect = 1.5
parry_time_perfect_leeway = 1
parry_imperfect_falloff_percent = 7.5
- parry_efficiency_to_counterattack = 100
+ parry_efficiency_to_counterattack = 120
parry_efficiency_considered_successful = 65 // VERY generous
parry_efficiency_perfect = 120
parry_efficiency_perfect_override = list(
@@ -306,13 +325,13 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
parry_failed_stagger_duration = 3 SECONDS
parry_data = list(
PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 2.5, // 7*2.5 = 17.5, 8*2.5 = 20, 9*2.5 = 22.5, 10*2.5 = 25
- )
+ )
/datum/block_parry_data/bokken/quick_parry // emphasizing REALLY SHORT PARRIES
parry_stamina_cost = 6 // still more costly than most parries, but less than a full bokken parry
parry_time_active = 5 // REALLY small parry window
parry_time_perfect = 2.5 // however...
- parry_time_perfect_leeway = 2.5 // the entire time, the parry is perfect
+ parry_time_perfect_leeway = 2 // the entire time, the parry is perfect
parry_failed_stagger_duration = 1 SECONDS
parry_failed_clickcd_duration = 1 SECONDS // more forgiving punishments for missed parries
// still, don't fucking miss your parries or you're down stamina and staggered to shit
diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm
index 14017ffb2d..f5003e035b 100644
--- a/code/game/objects/obj_defense.dm
+++ b/code/game/objects/obj_defense.dm
@@ -186,7 +186,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
if(!acid_level)
SSacid.processing[src] = src
- add_overlay(GLOB.acid_overlay, TRUE)
+ 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)
@@ -224,7 +224,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
if(!(resistance_flags & ON_FIRE) && (resistance_flags & FLAMMABLE))
resistance_flags |= ON_FIRE
SSfire_burning.processing[src] = src
- add_overlay(GLOB.fire_overlay, TRUE)
+ update_icon()
return 1
//called when the obj is destroyed by fire
@@ -236,7 +236,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
/obj/proc/extinguish()
if(resistance_flags & ON_FIRE)
resistance_flags &= ~ON_FIRE
- cut_overlay(GLOB.fire_overlay, TRUE)
+ update_icon()
SSfire_burning.processing -= src
/obj/zap_act(power, zap_flags, shocked_targets)
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index 79dd13b0ae..99b302e9ce 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -317,6 +317,13 @@
icon_state = unique_reskin[choice]
to_chat(M, "[src] is now skinned as '[choice]'.")
+/obj/update_overlays()
+ . = ..()
+ if(acid_level)
+ . += GLOB.acid_overlay
+ if(resistance_flags & ON_FIRE)
+ . += GLOB.fire_overlay
+
//Called when the object is constructed by an autolathe
//Has a reference to the autolathe so you can do !!FUN!! things with hacked lathes
/obj/proc/autolathe_crafted(obj/machinery/autolathe/A)
@@ -329,3 +336,6 @@
. = ..()
if(. && ricochet_damage_mod)
take_damage(P.damage * ricochet_damage_mod, P.damage_type, P.flag, 0, turn(P.dir, 180), P.armour_penetration) // pass along ricochet_damage_mod damage to the structure for the ricochet
+
+/obj/proc/plunger_act(obj/item/plunger/P, mob/living/user, reinforced)
+ return
diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm
index b758317fe2..52036427c8 100644
--- a/code/game/objects/structures.dm
+++ b/code/game/objects/structures.dm
@@ -112,3 +112,6 @@
if(0 to 25)
if(!broken)
return "It's falling apart!"
+
+/obj/structure/rust_heretic_act()
+ take_damage(500, BRUTE, "melee", 1)
diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm
index 1316f45530..39bef1a9c0 100644
--- a/code/game/objects/structures/beds_chairs/chair.dm
+++ b/code/game/objects/structures/beds_chairs/chair.dm
@@ -487,7 +487,7 @@
desc = "A bronze bar stool with red silk for a pillow."
icon_state = "barbrass"
item_chair = /obj/item/chair/stool/bar/bronze
- buildstacktype = /obj/item/stack/tile/bronze
+ buildstacktype = /obj/item/stack/sheet/bronze
buildstackamount = 1
/obj/structure/chair/stool/brass
@@ -503,7 +503,7 @@
desc = "A bronze stool with a silk top for comfort."
icon_state = "stoolbrass"
item_chair = /obj/item/chair/stool/bronze
- buildstacktype = /obj/item/stack/tile/bronze
+ buildstacktype = /obj/item/stack/sheet/bronze
buildstackamount = 1
/obj/item/chair/stool/brass
@@ -603,7 +603,7 @@
desc = "A spinny chair made of bronze. It has little cogs for wheels!"
anchored = FALSE
icon_state = "brass_chair"
- buildstacktype = /obj/item/stack/tile/bronze
+ buildstacktype = /obj/item/stack/sheet/bronze
buildstackamount = 1
item_chair = null
diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm
index 45cac650b8..c36fba96cb 100644
--- a/code/game/objects/structures/bedsheet_bin.dm
+++ b/code/game/objects/structures/bedsheet_bin.dm
@@ -243,10 +243,24 @@ LINEN BINS
/obj/item/bedsheet/random/Initialize()
..()
- var/type = pick(typesof(/obj/item/bedsheet) - /obj/item/bedsheet/random)
+ var/type = pick(typesof(/obj/item/bedsheet) - list(/obj/item/bedsheet/random, /obj/item/bedsheet/chameleon))
new type(loc)
return INITIALIZE_HINT_QDEL
+/obj/item/bedsheet/chameleon //donator chameleon bedsheet
+ name = "chameleon bedsheet"
+ desc = "Bedsheet technology has truly gone too far."
+ var/datum/action/item_action/chameleon/change/chameleon_action
+
+/obj/item/bedsheet/chameleon/New()
+ ..()
+ chameleon_action = new(src)
+ chameleon_action.chameleon_type = /obj/item/bedsheet
+ chameleon_action.chameleon_name = "Bedsheet"
+ chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/bedsheet/chameleon, /obj/item/bedsheet/random), only_root_path = TRUE)
+ chameleon_action.initialize_disguises()
+
+//bedsheet bin
/obj/structure/bedsheetbin
name = "linen bin"
desc = "It looks rather cosy."
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 043232e9e3..5c5b2bb132 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -111,6 +111,9 @@
var/mob/living/L = user
if(HAS_TRAIT(L, TRAIT_SKITTISH))
. += "Ctrl-Shift-click [src] to jump inside."
+ if(isobserver(user))
+ . += "It contains: [english_list(contents)]."
+ investigate_log("had its contents examined by [user] as a ghost.", INVESTIGATE_GHOST)
/obj/structure/closet/CanPass(atom/movable/mover, turf/target)
if(wall_mounted)
diff --git a/code/game/objects/structures/door_assembly_types.dm b/code/game/objects/structures/door_assembly_types.dm
index fe9c4e7bbc..5fb454b5bc 100644
--- a/code/game/objects/structures/door_assembly_types.dm
+++ b/code/game/objects/structures/door_assembly_types.dm
@@ -240,3 +240,14 @@
airlock_type = /obj/machinery/door/airlock/wood
mineral = "wood"
glass_type = /obj/machinery/door/airlock/wood/glass
+
+/obj/structure/door_assembly/door_assembly_bronze
+ name = "bronze airlock assembly"
+ icon = 'icons/obj/doors/airlocks/clockwork/pinion_airlock.dmi'
+ base_name = "bronze airlock"
+ airlock_type = /obj/machinery/door/airlock/bronze
+ noglass = TRUE
+ material_type = /obj/item/stack/tile/bronze
+
+/obj/structure/door_assembly/door_assembly_bronze/seethru
+ airlock_type = /obj/machinery/door/airlock/bronze/seethru
diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm
index ff62b9cc48..87cfbb56e0 100644
--- a/code/game/objects/structures/girders.dm
+++ b/code/game/objects/structures/girders.dm
@@ -442,19 +442,19 @@
to_chat(user, "You start slicing apart [src]...")
if(W.use_tool(src, user, 40, volume=50))
to_chat(user, "You slice apart [src].")
- var/obj/item/stack/tile/bronze/B = new(drop_location(), 2)
+ var/obj/item/stack/sheet/bronze/B = new(drop_location(), 2)
transfer_fingerprints_to(B)
qdel(src)
else if(istype(W, /obj/item/pickaxe/drill/jackhammer))
to_chat(user, "Your jackhammer smashes through the girder!")
- var/obj/item/stack/tile/bronze/B = new(drop_location(), 2)
+ var/obj/item/stack/sheet/bronze/B = new(drop_location(), 2)
transfer_fingerprints_to(B)
W.play_tool_sound(src)
qdel(src)
- else if(istype(W, /obj/item/stack/tile/bronze))
- var/obj/item/stack/tile/bronze/B = W
+ else if(istype(W, /obj/item/stack/sheet/bronze))
+ var/obj/item/stack/sheet/bronze/B = W
if(B.get_amount() < 2)
to_chat(user, "You need at least two bronze sheets to build a bronze wall!")
return 0
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index 36e4f825da..7853b9619c 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -86,6 +86,10 @@
/obj/structure/grille/attack_animal(mob/user)
. = ..()
+ if(!user.CheckActionCooldown(CLICK_CD_MELEE))
+ return
+ user.DelayNextAction(flush = TRUE)
+ user.do_attack_animation(src)
if(!shock(user, 70) && !QDELETED(src)) //Last hit still shocks but shouldn't deal damage to the grille)
take_damage(rand(5,10), BRUTE, "melee", 1)
@@ -114,12 +118,12 @@
/obj/structure/grille/attack_alien(mob/living/user)
if(!user.CheckActionCooldown(CLICK_CD_MELEE))
return
+ user.DelayNextAction(flush = TRUE)
user.do_attack_animation(src)
user.visible_message("[user] mangles [src].", null, null, COMBAT_MESSAGE_RANGE)
if(!shock(user, 70))
take_damage(20, BRUTE, "melee", 1)
-
/obj/structure/grille/CanPass(atom/movable/mover, turf/target)
if(istype(mover) && (mover.pass_flags & PASSGRILLE))
return TRUE
diff --git a/code/game/objects/structures/lavaland/geyser.dm b/code/game/objects/structures/lavaland/geyser.dm
index 4f6256e9c4..263b47aab2 100644
--- a/code/game/objects/structures/lavaland/geyser.dm
+++ b/code/game/objects/structures/lavaland/geyser.dm
@@ -9,7 +9,7 @@
var/erupting_state = null //set to null to get it greyscaled from "[icon_state]_soup". Not very usable with the whole random thing, but more types can be added if you change the spawn prob
var/activated = FALSE //whether we are active and generating chems
- var/reagent_id = /datum/reagent/fuel/oil
+ var/reagent_id = /datum/reagent/oil
var/potency = 2 //how much reagents we add every process (2 seconds)
var/max_volume = 500
var/start_volume = 50
@@ -77,10 +77,10 @@
/obj/item/plunger/reinforced
name = "reinforced plunger"
- desc = "It's an M. 7 Reinforced Plunger© for heavy duty plunging."
+ desc = "It's an M. 7 Reinforced Plunger� for heavy duty plunging."
icon_state = "reinforced_plunger"
reinforced = TRUE
plunge_mod = 0.8
- custom_premium_price = 1200
+ custom_premium_price = 600
diff --git a/code/game/objects/structures/stairs.dm b/code/game/objects/structures/stairs.dm
index d1a2a6f9f6..1358b2e296 100644
--- a/code/game/objects/structures/stairs.dm
+++ b/code/game/objects/structures/stairs.dm
@@ -3,7 +3,7 @@
#define STAIR_TERMINATOR_YES 2
// dir determines the direction of travel to go upwards (due to lack of sprites, currently only 1 and 2 make sense)
-// stairs require /turf/open/openspace as the tile above them to work
+// stairs require /turf/open/transparent/openspace as the tile above them to work
// multiple stair objects can be chained together; the Z level transition will happen on the final stair object in the chain
/obj/structure/stairs
@@ -12,7 +12,7 @@
icon_state = "stairs"
anchored = TRUE
- var/force_open_above = FALSE // replaces the turf above this stair obj with /turf/open/openspace
+ var/force_open_above = FALSE // replaces the turf above this stair obj with /turf/open/transparent/openspace
var/terminator_mode = STAIR_TERMINATOR_AUTOMATIC
var/turf/listeningTo
@@ -95,20 +95,20 @@
/obj/structure/stairs/proc/build_signal_listener()
if(listeningTo)
UnregisterSignal(listeningTo, COMSIG_TURF_MULTIZ_NEW)
- var/turf/open/openspace/T = get_step_multiz(get_turf(src), UP)
+ var/turf/open/transparent/openspace/T = get_step_multiz(get_turf(src), UP)
RegisterSignal(T, COMSIG_TURF_MULTIZ_NEW, .proc/on_multiz_new)
listeningTo = T
/obj/structure/stairs/proc/force_open_above()
- var/turf/open/openspace/T = get_step_multiz(get_turf(src), UP)
+ var/turf/open/transparent/openspace/T = get_step_multiz(get_turf(src), UP)
if(T && !istype(T))
- T.ChangeTurf(/turf/open/openspace, flags = CHANGETURF_INHERIT_AIR)
+ T.ChangeTurf(/turf/open/transparent/openspace, flags = CHANGETURF_INHERIT_AIR)
/obj/structure/stairs/proc/on_multiz_new(turf/source, dir)
if(dir == UP)
- var/turf/open/openspace/T = get_step_multiz(get_turf(src), UP)
+ var/turf/open/transparent/openspace/T = get_step_multiz(get_turf(src), UP)
if(T && !istype(T))
- T.ChangeTurf(/turf/open/openspace, flags = CHANGETURF_INHERIT_AIR)
+ T.ChangeTurf(/turf/open/transparent/openspace, flags = CHANGETURF_INHERIT_AIR)
/obj/structure/stairs/intercept_zImpact(atom/movable/AM, levels = 1)
. = ..()
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index a553e63b0f..9f91d2c5e0 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -597,7 +597,7 @@
icon = 'icons/obj/smooth_structures/brass_table.dmi'
icon_state = "brass_table"
resistance_flags = FIRE_PROOF | ACID_PROOF
- buildstack = /obj/item/stack/tile/bronze
+ buildstack = /obj/item/stack/sheet/bronze
canSmoothWith = list(/obj/structure/table/reinforced/brass, /obj/structure/table/bronze)
/obj/structure/table/bronze/tablelimbsmash(mob/living/user, mob/living/pushed_mob)
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 3373278c0c..74f006296f 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -875,3 +875,26 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
return
..()
update_icon()
+
+/obj/structure/window/bronze
+ name = "brass window"
+ desc = "A paper-thin pane of translucent yet reinforced brass. Nevermind, this is just weak bronze!"
+ icon = 'icons/obj/smooth_structures/clockwork_window.dmi'
+ icon_state = "clockwork_window_single"
+ glass_type = /obj/item/stack/tile/bronze
+
+/obj/structure/window/bronze/unanchored
+ anchored = FALSE
+
+/obj/structure/window/bronze/fulltile
+ icon_state = "clockwork_window"
+ canSmoothWith = null
+ smooth = SMOOTH_TRUE
+ fulltile = TRUE
+ flags_1 = PREVENT_CLICK_UNDER_1
+ dir = FULLTILE_WINDOW_DIR
+ max_integrity = 50
+ glass_amount = 2
+
+/obj/structure/window/bronze/fulltile/unanchored
+ anchored = FALSE
diff --git a/code/game/sound.dm b/code/game/sound.dm
index 577b058178..0feb01c223 100644
--- a/code/game/sound.dm
+++ b/code/game/sound.dm
@@ -226,5 +226,9 @@
soundin = pick('sound/effects/clangsmall1.ogg', 'sound/effects/clangsmall2.ogg')
if("slosh")
soundin = pick('sound/effects/slosh1.ogg', 'sound/effects/slosh2.ogg')
+ if("smcalm")
+ soundin = pick('sound/machines/sm/accent/normal/1.ogg', 'sound/machines/sm/accent/normal/2.ogg', 'sound/machines/sm/accent/normal/3.ogg', 'sound/machines/sm/accent/normal/4.ogg', 'sound/machines/sm/accent/normal/5.ogg', 'sound/machines/sm/accent/normal/6.ogg', 'sound/machines/sm/accent/normal/7.ogg', 'sound/machines/sm/accent/normal/8.ogg', 'sound/machines/sm/accent/normal/9.ogg', 'sound/machines/sm/accent/normal/10.ogg', 'sound/machines/sm/accent/normal/11.ogg', 'sound/machines/sm/accent/normal/12.ogg', 'sound/machines/sm/accent/normal/13.ogg', 'sound/machines/sm/accent/normal/14.ogg', 'sound/machines/sm/accent/normal/15.ogg', 'sound/machines/sm/accent/normal/16.ogg', 'sound/machines/sm/accent/normal/17.ogg', 'sound/machines/sm/accent/normal/18.ogg', 'sound/machines/sm/accent/normal/19.ogg', 'sound/machines/sm/accent/normal/20.ogg', 'sound/machines/sm/accent/normal/21.ogg', 'sound/machines/sm/accent/normal/22.ogg', 'sound/machines/sm/accent/normal/23.ogg', 'sound/machines/sm/accent/normal/24.ogg', 'sound/machines/sm/accent/normal/25.ogg', 'sound/machines/sm/accent/normal/26.ogg', 'sound/machines/sm/accent/normal/27.ogg', 'sound/machines/sm/accent/normal/28.ogg', 'sound/machines/sm/accent/normal/29.ogg', 'sound/machines/sm/accent/normal/30.ogg', 'sound/machines/sm/accent/normal/31.ogg', 'sound/machines/sm/accent/normal/32.ogg', 'sound/machines/sm/accent/normal/33.ogg')
+ if("smdelam")
+ soundin = pick('sound/machines/sm/accent/delam/1.ogg', 'sound/machines/sm/accent/normal/2.ogg', 'sound/machines/sm/accent/normal/3.ogg', 'sound/machines/sm/accent/normal/4.ogg', 'sound/machines/sm/accent/normal/5.ogg', 'sound/machines/sm/accent/normal/6.ogg', 'sound/machines/sm/accent/normal/7.ogg', 'sound/machines/sm/accent/normal/8.ogg', 'sound/machines/sm/accent/normal/9.ogg', 'sound/machines/sm/accent/normal/10.ogg', 'sound/machines/sm/accent/normal/11.ogg', 'sound/machines/sm/accent/normal/12.ogg', 'sound/machines/sm/accent/normal/13.ogg', 'sound/machines/sm/accent/normal/14.ogg', 'sound/machines/sm/accent/normal/15.ogg', 'sound/machines/sm/accent/normal/16.ogg', 'sound/machines/sm/accent/normal/17.ogg', 'sound/machines/sm/accent/normal/18.ogg', 'sound/machines/sm/accent/normal/19.ogg', 'sound/machines/sm/accent/normal/20.ogg', 'sound/machines/sm/accent/normal/21.ogg', 'sound/machines/sm/accent/normal/22.ogg', 'sound/machines/sm/accent/normal/23.ogg', 'sound/machines/sm/accent/normal/24.ogg', 'sound/machines/sm/accent/normal/25.ogg', 'sound/machines/sm/accent/normal/26.ogg', 'sound/machines/sm/accent/normal/27.ogg', 'sound/machines/sm/accent/normal/28.ogg', 'sound/machines/sm/accent/normal/29.ogg', 'sound/machines/sm/accent/normal/30.ogg', 'sound/machines/sm/accent/normal/31.ogg', 'sound/machines/sm/accent/normal/32.ogg', 'sound/machines/sm/accent/normal/33.ogg')
//END OF CIT CHANGES
return soundin
diff --git a/code/game/turfs/closed.dm b/code/game/turfs/closed.dm
index b78826b23b..be0c444541 100644
--- a/code/game/turfs/closed.dm
+++ b/code/game/turfs/closed.dm
@@ -29,6 +29,9 @@
icon = 'icons/turf/walls.dmi'
explosion_block = 50
+/turf/closed/indestructible/rust_heretic_act()
+ return
+
/turf/closed/indestructible/TerraformTurf(path, new_baseturf, flags, defer_change = FALSE, ignore_air = FALSE)
return
@@ -198,13 +201,13 @@
/turf/closed/indestructible/rock/glacierrock
name = "unaturally hard ice wall"
- desc = "Ice, hardened over thousands of years, you're not breaking through this."
+ desc = "Ice, hardened over thousands of years, you're not breaking through this."
icon = 'icons/turf/walls.dmi'
icon_state = "snow_rock"
/turf/closed/indestructible/rock/glacierrock/blue
name = "blue ice wall"
- desc = "The incredible compressive forces that formed this sturdy ice wall gave it a blue color."
+ desc = "The incredible compressive forces that formed this sturdy ice wall gave it a blue color."
icon = 'icons/turf/walls.dmi'
icon_state = "ice"
canSmoothWith = list(/turf/closed/indestructible/rock/glacierrock/blue)
diff --git a/code/game/turfs/openspace/openspace.dm b/code/game/turfs/openspace/openspace.dm
index 90fab29611..ea539ce5b5 100644
--- a/code/game/turfs/openspace/openspace.dm
+++ b/code/game/turfs/openspace/openspace.dm
@@ -11,66 +11,47 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
layer = SPLASHSCREEN_LAYER
-/turf/open/openspace
+/turf/open/transparent/openspace
name = "open space"
desc = "Watch your step!"
icon_state = "transparent"
- baseturfs = /turf/open/openspace
+ baseturfs = /turf/open/transparent/openspace
CanAtmosPassVertical = ATMOS_PASS_YES
//mouse_opacity = MOUSE_OPACITY_TRANSPARENT
var/can_cover_up = TRUE
var/can_build_on = TRUE
-/turf/open/openspace/debug/update_multiz()
+/turf/open/transparent/openspace/airless
+ initial_gas_mix = AIRLESS_ATMOS
+
+/turf/open/transparent/openspace/debug/update_multiz()
..()
return TRUE
-/turf/open/openspace/Initialize() // handle plane and layer here so that they don't cover other obs/turfs in Dream Maker
+///No bottom level for openspace.
+/turf/open/transparent/openspace/show_bottom_level()
+ return FALSE
+
+/turf/open/transparent/openspace/Initialize() // handle plane and layer here so that they don't cover other obs/turfs in Dream Maker
. = ..()
- plane = OPENSPACE_PLANE
- layer = OPENSPACE_LAYER
+
vis_contents += GLOB.openspace_backdrop_one_for_all //Special grey square for projecting backdrop darkness filter on it.
- return INITIALIZE_HINT_LATELOAD
-/turf/open/openspace/LateInitialize()
- update_multiz(TRUE, TRUE)
+/turf/open/transparent/openspace/can_have_cabling()
+ if(locate(/obj/structure/lattice/catwalk, src))
+ return TRUE
+ return FALSE
-/turf/open/openspace/Destroy()
- vis_contents.len = 0
- return ..()
-
-/turf/open/openspace/update_multiz(prune_on_fail = FALSE, init = FALSE)
- . = ..()
- var/turf/T = below()
- if(!T)
- vis_contents.len = 0
- if(prune_on_fail)
- ChangeTurf(/turf/open/floor/plating)
- return FALSE
- if(init)
- vis_contents += T
+/turf/open/transparent/openspace/zAirIn()
return TRUE
-/turf/open/openspace/multiz_turf_del(turf/T, dir)
- if(dir != DOWN)
- return
- update_multiz()
-
-/turf/open/openspace/multiz_turf_new(turf/T, dir)
- if(dir != DOWN)
- return
- update_multiz()
-
-/turf/open/openspace/zAirIn()
+/turf/open/transparent/openspace/zAirOut()
return TRUE
-/turf/open/openspace/zAirOut()
+/turf/open/transparent/openspace/zPassIn(atom/movable/A, direction, turf/source)
return TRUE
-/turf/open/openspace/zPassIn(atom/movable/A, direction, turf/source)
- return TRUE
-
-/turf/open/openspace/zPassOut(atom/movable/A, direction, turf/destination)
+/turf/open/transparent/openspace/zPassOut(atom/movable/A, direction, turf/destination)
if(A.anchored)
return FALSE
for(var/obj/O in contents)
@@ -78,13 +59,13 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
return FALSE
return TRUE
-/turf/open/openspace/proc/CanCoverUp()
+/turf/open/transparent/openspace/proc/CanCoverUp()
return can_cover_up
-/turf/open/openspace/proc/CanBuildHere()
+/turf/open/transparent/openspace/proc/CanBuildHere()
return can_build_on
-/turf/open/openspace/attackby(obj/item/C, mob/user, params)
+/turf/open/transparent/openspace/attackby(obj/item/C, mob/user, params)
..()
if(!CanBuildHere())
return
@@ -98,14 +79,14 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
if(L)
if(R.use(1))
to_chat(user, "You construct a catwalk.")
- playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
+ playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE)
new/obj/structure/lattice/catwalk(src)
else
to_chat(user, "You need two rods to build a catwalk!")
return
if(R.use(1))
to_chat(user, "You construct a lattice.")
- playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
+ playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE)
ReplaceWithLattice()
else
to_chat(user, "You need one rod to build a lattice.")
@@ -118,7 +99,7 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
var/obj/item/stack/tile/plasteel/S = C
if(S.use(1))
qdel(L)
- playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
+ playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE)
to_chat(user, "You build a floor.")
PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
else
@@ -126,7 +107,7 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
else
to_chat(user, "The plating is going to need some support! Place metal rods first.")
-/turf/open/openspace/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
+/turf/open/transparent/openspace/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
if(!CanBuildHere())
return FALSE
@@ -139,7 +120,7 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
return list("mode" = RCD_FLOORWALL, "delay" = 0, "cost" = 3)
return FALSE
-/turf/open/openspace/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode)
+/turf/open/transparent/openspace/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode)
switch(passed_mode)
if(RCD_FLOORWALL)
to_chat(user, "You build a floor.")
@@ -147,12 +128,12 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
return TRUE
return FALSE
-/turf/open/openspace/icemoon
+/turf/open/transparent/openspace/icemoon
name = "ice chasm"
- baseturfs = /turf/open/openspace/icemoon
- can_cover_up = FALSE
- can_build_on = FALSE
+ baseturfs = /turf/open/transparent/openspace/icemoon
+ can_cover_up = TRUE
+ can_build_on = TRUE
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
-/turf/open/openspace/icemoon/can_zFall(atom/movable/A, levels = 1, turf/target)
+/turf/open/transparent/openspace/icemoon/can_zFall(atom/movable/A, levels = 1, turf/target)
return TRUE
diff --git a/code/game/turfs/openspace/transparent.dm b/code/game/turfs/openspace/transparent.dm
new file mode 100644
index 0000000000..8efc60a15b
--- /dev/null
+++ b/code/game/turfs/openspace/transparent.dm
@@ -0,0 +1,95 @@
+/turf/open/transparent
+ baseturfs = /turf/open/transparent/openspace
+ intact = FALSE //this means wires go on top
+
+/turf/open/transparent/Initialize() // handle plane and layer here so that they don't cover other obs/turfs in Dream Maker
+ . = ..()
+ plane = OPENSPACE_PLANE
+ layer = OPENSPACE_LAYER
+
+ return INITIALIZE_HINT_LATELOAD
+
+/turf/open/transparent/LateInitialize()
+ update_multiz(TRUE, TRUE)
+
+/turf/open/transparent/Destroy()
+ vis_contents.len = 0
+ return ..()
+
+/turf/open/transparent/update_multiz(prune_on_fail = FALSE, init = FALSE)
+ . = ..()
+ var/turf/T = below()
+ if(!T)
+ vis_contents.len = 0
+ if(!show_bottom_level() && prune_on_fail) //If we cant show whats below, and we prune on fail, change the turf to plating as a fallback
+ ChangeTurf(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
+ return FALSE
+ if(init)
+ vis_contents += T
+ return TRUE
+
+/turf/open/transparent/multiz_turf_del(turf/T, dir)
+ if(dir != DOWN)
+ return
+ update_multiz()
+
+/turf/open/transparent/multiz_turf_new(turf/T, dir)
+ if(dir != DOWN)
+ return
+ update_multiz()
+
+///Called when there is no real turf below this turf
+/turf/open/transparent/proc/show_bottom_level()
+ var/turf/path = SSmapping.level_trait(z, ZTRAIT_BASETURF) || /turf/open/space
+ if(!ispath(path))
+ path = text2path(path)
+ if(!ispath(path))
+ warning("Z-level [z] has invalid baseturf '[SSmapping.level_trait(z, ZTRAIT_BASETURF)]'")
+ path = /turf/open/space
+ var/mutable_appearance/underlay_appearance = mutable_appearance(initial(path.icon), initial(path.icon_state), layer = TURF_LAYER, plane = PLANE_SPACE)
+ underlays += underlay_appearance
+ return TRUE
+
+
+/turf/open/transparent/glass
+ name = "Glass floor"
+ desc = "Dont jump on it, or do, I'm not your mom."
+ icon = 'icons/turf/floors/glass.dmi'
+ icon_state = "floor_glass"
+ smooth = SMOOTH_MORE
+ var/floor_tile = /obj/item/stack/sheet/glass
+ canSmoothWith = list(/turf/open/transparent/glass, /turf/open/transparent/glass/reinforced)
+ footstep = FOOTSTEP_PLATING
+ barefootstep = FOOTSTEP_HARD_BAREFOOT
+ clawfootstep = FOOTSTEP_HARD_CLAW
+ heavyfootstep = FOOTSTEP_GENERIC_HEAVY
+
+/turf/open/transparent/glass/Initialize()
+ icon_state = "" //Prevent the normal icon from appearing behind the smooth overlays
+ return ..()
+
+/turf/open/transparent/glass/wrench_act(mob/living/user, obj/item/I)
+ to_chat(user, "You begin removing glass...")
+ if(I.use_tool(src, user, 30, volume=80))
+ if(!istype(src, /turf/open/transparent/glass))
+ return TRUE
+ if(floor_tile)
+ new floor_tile(src, 2)
+ ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
+ return TRUE
+
+/turf/open/transparent/glass/reinforced
+ name = "Reinforced glass floor"
+ desc = "Do jump on it, it can take it."
+ icon = 'icons/turf/floors/reinf_glass.dmi'
+ floor_tile = /obj/item/stack/sheet/rglass
+
+/turf/open/transparent/glass/reinforced/wrench_act(mob/living/user, obj/item/I)
+ to_chat(user, "You begin removing reinforced glass...")
+ if(I.use_tool(src, user, 30, volume=80))
+ if(!istype(src, /turf/open/transparent/glass/reinforced))
+ return TRUE
+ if(floor_tile)
+ new floor_tile(src, 2)
+ ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
+ return TRUE
diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm
index 946401ba18..5024a4bada 100644
--- a/code/game/turfs/simulated/floor/fancy_floor.dm
+++ b/code/game/turfs/simulated/floor/fancy_floor.dm
@@ -63,6 +63,11 @@
to_chat(user, "You forcefully pry off the planks, destroying them in the process.")
return make_plating()
+/turf/open/floor/wood/rust_heretic_act()
+ if(prob(70))
+ new /obj/effect/temp_visual/glowing_rune(src)
+ ChangeTurf(/turf/open/floor/plating/rust)
+
/turf/open/floor/wood/cold
temperature = 255.37
diff --git a/code/game/turfs/simulated/floor/mineral_floor.dm b/code/game/turfs/simulated/floor/mineral_floor.dm
index 8e0230a2b0..fe6ed2da9b 100644
--- a/code/game/turfs/simulated/floor/mineral_floor.dm
+++ b/code/game/turfs/simulated/floor/mineral_floor.dm
@@ -58,6 +58,12 @@
if(exposed_temperature > 300)
PlasmaBurn(exposed_temperature)
+// Plasma floor that can't be removed, for disco
+
+/turf/open/floor/mineral/plasma/disco
+ name = "disco floor"
+/turf/open/floor/mineral/plasma/disco/crowbar_act(mob/living/user, obj/item/I)
+ return
//GOLD
diff --git a/code/game/turfs/simulated/floor/misc_floor.dm b/code/game/turfs/simulated/floor/misc_floor.dm
index f6e70f8ef5..c70332eacb 100644
--- a/code/game/turfs/simulated/floor/misc_floor.dm
+++ b/code/game/turfs/simulated/floor/misc_floor.dm
@@ -259,7 +259,7 @@
desc = "Some heavy bronze tiles."
icon = 'icons/obj/clockwork_objects.dmi'
icon_state = "clockwork_floor"
- floor_tile = /obj/item/stack/tile/bronze
+ floor_tile = /obj/item/stack/sheet/bronze
/turf/open/floor/padded
name = "padded floor"
@@ -267,3 +267,15 @@
icon = 'icons/turf/floors.dmi'
icon_state = "floor_padded"
floor_tile = /obj/item/stack/tile/padded
+
+/turf/open/floor/plating/rust
+ name = "rusted plating"
+ desc = "Corrupted steel."
+ icon_state = "plating_rust"
+ footstep = FOOTSTEP_RUST
+ barefootstep = FOOTSTEP_RUST
+ clawfootstep = FOOTSTEP_RUST
+ heavyfootstep = FOOTSTEP_RUST
+
+/turf/open/floor/plating/rust/rust_heretic_act()
+ return
diff --git a/code/game/turfs/simulated/floor/plasteel_floor.dm b/code/game/turfs/simulated/floor/plasteel_floor.dm
index af48160ef1..614c63a14c 100644
--- a/code/game/turfs/simulated/floor/plasteel_floor.dm
+++ b/code/game/turfs/simulated/floor/plasteel_floor.dm
@@ -8,6 +8,11 @@
. = ..()
. += "There's a small crack on the edge of it."
+/turf/open/floor/plasteel/rust_heretic_act()
+ if(prob(70))
+ new /obj/effect/temp_visual/glowing_rune(src)
+ ChangeTurf(/turf/open/floor/plating/rust)
+
/turf/open/floor/plasteel/update_icon()
if(!..())
return 0
diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm
index ac80bddd00..35ee06a584 100644
--- a/code/game/turfs/simulated/floor/plating.dm
+++ b/code/game/turfs/simulated/floor/plating.dm
@@ -66,6 +66,40 @@
R.use(2)
to_chat(user, "You reinforce the floor.")
return
+ if(istype(C, /obj/item/stack/sheet/glass))
+ if(broken || burnt)
+ to_chat(user, "Repair the plating first!")
+ return
+ var/obj/item/stack/sheet/glass/G = C
+ if (G.get_amount() < 2)
+ to_chat(user, "You need two glass sheets to make a glass floor!")
+ return
+ else
+ to_chat(user, "You begin adding glass to the floor...")
+ if(do_after(user, 5, target = src))
+ if (G.get_amount() >= 2 && !istype(src, /turf/open/transparent/glass))
+ PlaceOnTop(/turf/open/transparent/glass, flags = CHANGETURF_INHERIT_AIR)
+ playsound(src, 'sound/items/deconstruct.ogg', 80, 1)
+ G.use(2)
+ to_chat(user, "You add glass to the floor.")
+ return
+ if(istype(C, /obj/item/stack/sheet/rglass))
+ if(broken || burnt)
+ to_chat(user, "Repair the plating first!")
+ return
+ var/obj/item/stack/sheet/rglass/RG = C
+ if (RG.get_amount() < 2)
+ to_chat(user, "You need two reinforced glass sheets to make a reinforced glass floor!")
+ return
+ else
+ to_chat(user, "You begin adding reinforced glass to the floor...")
+ if(do_after(user, 10, target = src))
+ if (RG.get_amount() >= 2 && !istype(src, /turf/open/transparent/glass/reinforced))
+ PlaceOnTop(/turf/open/transparent/glass/reinforced, flags = CHANGETURF_INHERIT_AIR)
+ playsound(src, 'sound/items/deconstruct.ogg', 80, 1)
+ RG.use(2)
+ to_chat(user, "You add reinforced glass to the floor.")
+ return
else if(istype(C, /obj/item/stack/tile))
if(!broken && !burnt)
for(var/obj/O in src)
@@ -98,6 +132,11 @@
return TRUE
+/turf/open/floor/plating/rust_heretic_act()
+ if(prob(70))
+ new /obj/effect/temp_visual/glowing_rune(src)
+ ChangeTurf(/turf/open/floor/plating/rust)
+
/turf/open/floor/plating/make_plating()
return
diff --git a/code/game/turfs/simulated/floor/plating/asteroid.dm b/code/game/turfs/simulated/floor/plating/asteroid.dm
index 1fbeee7523..6e7dbaf904 100644
--- a/code/game/turfs/simulated/floor/plating/asteroid.dm
+++ b/code/game/turfs/simulated/floor/plating/asteroid.dm
@@ -149,6 +149,8 @@
var/list/megafauna_spawn_list
/// Flora that can spawn in the tunnel, weighted list
var/list/flora_spawn_list
+ //terrain to spawn weighted list
+ var/list/terrain_spawn_list
/// Turf type to choose when spawning in tunnel at 1% chance, weighted list
var/list/choose_turf_type
/// if the tunnel should keep being created
@@ -230,7 +232,8 @@
megafauna_spawn_list = list(/mob/living/simple_animal/hostile/megafauna/dragon = 4, /mob/living/simple_animal/hostile/megafauna/colossus = 2, /mob/living/simple_animal/hostile/megafauna/bubblegum = SPAWN_BUBBLEGUM)
if (!flora_spawn_list)
flora_spawn_list = list(/obj/structure/flora/ash/leaf_shroom = 2 , /obj/structure/flora/ash/cap_shroom = 2 , /obj/structure/flora/ash/stem_shroom = 2 , /obj/structure/flora/ash/cacti = 1, /obj/structure/flora/ash/tall_shroom = 2)
-
+ if(!terrain_spawn_list)
+ terrain_spawn_list = list(/obj/structure/geyser/random = 1)
. = ..()
if(!has_data)
produce_tunnel_from_data()
@@ -334,8 +337,19 @@
spawned_flora = SpawnFlora(T)
if(!spawned_flora) // no rocks beneath mob spawners / mobs.
SpawnMonster(T)
+ SpawnTerrain(T)
T.ChangeTurf(turf_type, null, CHANGETURF_IGNORE_AIR)
+/turf/open/floor/plating/asteroid/airless/cave/proc/SpawnTerrain(turf/T)
+ if(prob(1))
+ if(istype(loc, /area/mine/explored) || istype(loc, /area/lavaland/surface/outdoors/explored))
+ return
+ var/randumb = pickweight(terrain_spawn_list)
+ for(var/obj/structure/geyser/F in range(7, T))
+ if(istype(F, randumb))
+ return
+ new randumb(T)
+
/// Spawns a random mob or megafauna in the tunnel
/turf/open/floor/plating/asteroid/airless/cave/proc/SpawnMonster(turf/T)
if(!isarea(loc))
diff --git a/code/game/turfs/simulated/wall/misc_walls.dm b/code/game/turfs/simulated/wall/misc_walls.dm
index d445be91cb..e4d991a082 100644
--- a/code/game/turfs/simulated/wall/misc_walls.dm
+++ b/code/game/turfs/simulated/wall/misc_walls.dm
@@ -188,17 +188,25 @@
icon = 'icons/turf/walls/rusty_wall.dmi'
hardness = 45
+/turf/closed/wall/rust/rust_heretic_act()
+ ScrapeAway()
+
/turf/closed/wall/r_wall/rust
name = "rusted reinforced wall"
desc = "A huge chunk of rusted reinforced metal."
icon = 'icons/turf/walls/rusty_reinforced_wall.dmi'
hardness = 15
+/turf/closed/wall/r_wall/rust/rust_heretic_act()
+ if(prob(50))
+ return
+ ScrapeAway()
+
/turf/closed/wall/mineral/bronze
name = "clockwork wall"
desc = "A huge chunk of bronze, decorated like gears and cogs."
icon = 'icons/turf/walls/clockwork_wall.dmi'
icon_state = "clockwork_wall"
- sheet_type = /obj/item/stack/tile/bronze
+ sheet_type = /obj/item/stack/sheet/bronze
sheet_amount = 2
girder_type = /obj/structure/girder/bronze
diff --git a/code/game/turfs/simulated/wall/reinf_walls.dm b/code/game/turfs/simulated/wall/reinf_walls.dm
index 6b41f41763..5e60f65ccc 100644
--- a/code/game/turfs/simulated/wall/reinf_walls.dm
+++ b/code/game/turfs/simulated/wall/reinf_walls.dm
@@ -235,6 +235,13 @@
if(the_rcd.canRturf)
return ..()
+/turf/closed/wall/r_wall/rust_heretic_act()
+ if(prob(50))
+ return
+ if(prob(70))
+ new /obj/effect/temp_visual/glowing_rune(src)
+ ChangeTurf(/turf/closed/wall/r_wall/rust)
+
/turf/closed/wall/r_wall/syndicate
name = "hull"
desc = "The armored hull of an ominous looking ship."
diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm
index b020ab87c9..9ff4f668a4 100644
--- a/code/game/turfs/simulated/walls.dm
+++ b/code/game/turfs/simulated/walls.dm
@@ -325,4 +325,9 @@
add_overlay(dent_decals)
+/turf/closed/wall/rust_heretic_act()
+ if(prob(70))
+ new /obj/effect/temp_visual/glowing_rune(src)
+ ChangeTurf(/turf/closed/wall/rust)
+
#undef MAX_DENT_DECALS
diff --git a/code/game/world.dm b/code/game/world.dm
index 55333fb3e6..a342200b3d 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -12,6 +12,9 @@ GLOBAL_LIST(topic_status_cache)
if (fexists(EXTOOLS))
call(EXTOOLS, "maptick_initialize")()
enable_debugger()
+#ifdef REFERENCE_TRACKING
+ enable_reference_tracking()
+#endif
world.Profile(PROFILE_START)
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 718f9d4246..e9abb7db87 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -171,7 +171,11 @@ GLOBAL_LIST_INIT(admin_verbs_debug, world.AVerbsDebug())
/client/proc/cmd_display_overlay_log,
/client/proc/reload_configuration,
/datum/admins/proc/create_or_modify_area,
- /client/proc/generate_wikichem_list //DO NOT PRESS UNLESS YOU WANT SUPERLAG
+#ifdef REFERENCE_TRACKING
+ /datum/admins/proc/view_refs,
+ /datum/admins/proc/view_del_failures,
+#endif
+ /client/proc/generate_wikichem_list, //DO NOT PRESS UNLESS YOU WANT SUPERLAG
)
GLOBAL_PROTECT(admin_verbs_debug)
GLOBAL_LIST_INIT(admin_verbs_possess, list(/proc/possess, /proc/release))
diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm
index b93c8dabf1..edf95dc47e 100644
--- a/code/modules/admin/verbs/adminhelp.dm
+++ b/code/modules/admin/verbs/adminhelp.dm
@@ -254,6 +254,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
//message from the initiator without a target, all admins will see this
//won't bug irc
/datum/admin_help/proc/MessageNoRecipient(msg)
+ msg = sanitize(copytext_char(msg, 1, MAX_MESSAGE_LEN))
var/ref_src = "[REF(src)]"
//Message to be sent to all admins
var/admin_msg = "Ticket [TicketHref("#[id]", ref_src)]: [LinkedReplyName(ref_src)] [FullMonty(ref_src)]: [keywords_lookup(msg)]"
diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm
index 68b9a8e341..b7f05740a3 100644
--- a/code/modules/admin/verbs/adminpm.dm
+++ b/code/modules/admin/verbs/adminpm.dm
@@ -55,7 +55,7 @@
if(AH)
message_admins("[key_name_admin(src)] has started replying to [key_name(C, 0, 0)]'s admin help.")
- var/msg = stripped_multiline_input(src,"Message:", "Private message to [key_name(C, 0, 0)]")
+ var/msg = input(src,"Message:", "Private message to [C.holder?.fakekey ? "an Administrator" : key_name(C, 0, 0)].") as message|null
if (!msg)
message_admins("[key_name_admin(src)] has cancelled their reply to [key_name(C, 0, 0)]'s admin help.")
return
@@ -90,7 +90,7 @@
if(!ircreplyamount) //to prevent people from spamming irc/discord
return
if(!msg)
- msg = stripped_multiline_input(src,"Message:", "Private message to Administrator")
+ msg = input(src,"Message:", "Private message to Administrator") as message|null
if(!msg)
return
@@ -112,7 +112,7 @@
//get message text, limit it's length.and clean/escape html
if(!msg)
- msg = stripped_multiline_input(src,"Message:", "Private message to [key_name(recipient, 0, 0)]")
+ msg = input(src,"Message:", "Private message to [recipient.holder?.fakekey ? "an Administrator" : key_name(recipient, 0, 0)].") as message|null
msg = trim(msg)
if(!msg)
return
@@ -133,7 +133,7 @@
//clean the message if it's not sent by a high-rank admin
if(!check_rights(R_SERVER|R_DEBUG,0)||irc)//no sending html to the poor bots
- msg = trim(sanitize(msg), MAX_MESSAGE_LEN)
+ msg = sanitize(copytext_char(msg, 1, MAX_MESSAGE_LEN))
if(!msg)
return
@@ -188,10 +188,10 @@
//AdminPM popup for ApocStation and anybody else who wants to use it. Set it with POPUP_ADMIN_PM in config.txt ~Carn
if(CONFIG_GET(flag/popup_admin_pm))
- spawn() //so we don't hold the caller proc up
+ spawn() //so we don't hold the caller proc up. Please functionalize this
var/sender = src
var/sendername = key
- var/reply = stripped_multiline_input(recipient, msg,"Admin PM from-[sendername]", "") //show message and await a reply
+ var/reply = input(recipient, msg,"Admin PM from-[sendername]", "") as message|null //show message and await a reply
if(recipient && reply)
if(sender)
recipient.cmd_admin_pm(sender,reply) //sender is still about, let's reply to them
diff --git a/code/modules/admin/view_variables/reference_tracking.dm b/code/modules/admin/view_variables/reference_tracking.dm
new file mode 100644
index 0000000000..70aac2f107
--- /dev/null
+++ b/code/modules/admin/view_variables/reference_tracking.dm
@@ -0,0 +1,225 @@
+#ifdef REFERENCE_TRACKING
+
+GLOBAL_LIST_EMPTY(deletion_failures)
+
+/world/proc/enable_reference_tracking()
+ if (fexists(EXTOOLS))
+ call(EXTOOLS, "ref_tracking_initialize")()
+
+/proc/get_back_references(datum/D)
+ CRASH("/proc/get_back_references not hooked by extools, reference tracking will not function!")
+
+/proc/get_forward_references(datum/D)
+ CRASH("/proc/get_forward_references not hooked by extools, reference tracking will not function!")
+
+/proc/clear_references(datum/D)
+ return
+
+/datum/admins/proc/view_refs(atom/D in world) //it actually supports datums as well but byond no likey
+ set category = "Debug"
+ set name = "View References"
+
+ if(!check_rights(R_DEBUG) || !D)
+ return
+
+ var/list/backrefs = get_back_references(D)
+ if(isnull(backrefs))
+ var/datum/browser/popup = new(usr, "ref_view", "Error
")
+ popup.set_content("Reference tracking not enabled")
+ popup.open(FALSE)
+ return
+
+ var/list/frontrefs = get_forward_references(D)
+ var/list/dat = list()
+ dat += "References of \ref[D] - [D]
\[Refresh\]
"
+ dat += "Back references - these things hold references to this object.
"
+ dat += ""
+ dat += "| Ref | Type | Variable Name | Follow | "
+ for(var/ref in backrefs)
+ var/datum/backreference = ref
+ if(isnull(backreference))
+ dat += "
|---|
| GC'd Reference |
"
+ if(istype(backreference))
+ dat += "| [REF(backreference)] | [backreference.type] | [backrefs[backreference]] | \[Follow\] |
"
+ else if(islist(backreference))
+ dat += "| [REF(backreference)] | list | [backrefs[backreference]] | \[Follow\] |
"
+ else
+ dat += "| Weird reference type. Add more debugging checks. |
"
+ dat += "
"
+ dat += "Forward references - this object is referencing those things.
"
+ dat += ""
+ dat += "| Variable name | Ref | Type | Follow | "
+ for(var/ref in frontrefs)
+ var/datum/backreference = frontrefs[ref]
+ dat += "
|---|
| [ref] | [REF(backreference)] | [backreference.type] | \[Follow\] |
"
+ dat += "
"
+ dat = dat.Join()
+
+ var/datum/browser/popup = new(usr, "ref_view", "References of \ref[D]
")
+ popup.set_content(dat)
+ popup.open(FALSE)
+
+
+/datum/admins/proc/view_del_failures()
+ set category = "Debug"
+ set name = "View Deletion Failures"
+
+ if(!check_rights(R_DEBUG))
+ return
+
+ var/list/dat = list("")
+ for(var/t in GLOB.deletion_failures)
+ if(isnull(t))
+ dat += "| GC'd Reference | Clear Nulls |
"
+ continue
+ var/datum/thing = t
+ dat += "| \ref[thing] | [thing.type][thing.gc_destroyed ? " (destroyed)" : ""] [ADMIN_VV(thing)] |
"
+ dat += "
"
+ dat = dat.Join()
+
+ var/datum/browser/popup = new(usr, "del_failures", "Deletion Failures
")
+ popup.set_content(dat)
+ popup.open(FALSE)
+
+
+/datum/proc/find_references()
+ testing("Beginning search for references to a [type].")
+ var/list/backrefs = get_back_references(src)
+ for(var/ref in backrefs)
+ if(isnull(ref))
+ log_world("## TESTING: Datum reference found, but gone now.")
+ continue
+ if(islist(ref))
+ log_world("## TESTING: Found [type] \ref[src] in list.")
+ continue
+ var/datum/datum_ref = ref
+ if(!istype(datum_ref))
+ log_world("## TESTING: Found [type] \ref[src] in unknown type reference: [datum_ref].")
+ return
+ log_world("## TESTING: Found [type] \ref[src] in [datum_ref.type][datum_ref.gc_destroyed ? " (destroyed)" : ""]")
+ message_admins("Found [type] \ref[src] [ADMIN_VV(src)] in [datum_ref.type][datum_ref.gc_destroyed ? " (destroyed)" : ""] [ADMIN_VV(datum_ref)]")
+ testing("Completed search for references to a [type].")
+
+#endif
+
+#ifdef LEGACY_REFERENCE_TRACKING
+
+/datum/verb/legacy_find_refs()
+ set category = "Debug"
+ set name = "Find References"
+ set src in world
+
+ find_references(FALSE)
+
+
+/datum/proc/find_references_legacy(skip_alert)
+ running_find_references = type
+ if(usr?.client)
+ if(usr.client.running_find_references)
+ testing("CANCELLED search for references to a [usr.client.running_find_references].")
+ usr.client.running_find_references = null
+ running_find_references = null
+ //restart the garbage collector
+ SSgarbage.can_fire = TRUE
+ SSgarbage.next_fire = world.time + world.tick_lag
+ return
+
+ if(!skip_alert && alert("Running this will lock everything up for about 5 minutes. Would you like to begin the search?", "Find References", "Yes", "No") != "Yes")
+ running_find_references = null
+ return
+
+ //this keeps the garbage collector from failing to collect objects being searched for in here
+ SSgarbage.can_fire = FALSE
+
+ if(usr?.client)
+ usr.client.running_find_references = type
+
+ testing("Beginning search for references to a [type].")
+ last_find_references = world.time
+
+ DoSearchVar(GLOB) //globals
+ for(var/datum/thing in world) //atoms (don't beleive its lies)
+ DoSearchVar(thing, "World -> [thing]")
+
+ for(var/datum/thing) //datums
+ DoSearchVar(thing, "World -> [thing]")
+
+ for(var/client/thing) //clients
+ DoSearchVar(thing, "World -> [thing]")
+
+ testing("Completed search for references to a [type].")
+ if(usr?.client)
+ usr.client.running_find_references = null
+ running_find_references = null
+
+ //restart the garbage collector
+ SSgarbage.can_fire = TRUE
+ SSgarbage.next_fire = world.time + world.tick_lag
+
+
+/datum/verb/qdel_then_find_references()
+ set category = "Debug"
+ set name = "qdel() then Find References"
+ set src in world
+
+ qdel(src, TRUE) //force a qdel
+ if(!running_find_references)
+ find_references(TRUE)
+
+
+/datum/verb/qdel_then_if_fail_find_references()
+ set category = "Debug"
+ set name = "qdel() then Find References if GC failure"
+ set src in world
+
+ qdel_and_find_ref_if_fail(src, TRUE)
+
+
+/datum/proc/DoSearchVar(potential_container, container_name, recursive_limit = 64)
+ if(usr?.client && !usr.client.running_find_references)
+ return
+
+ if(!recursive_limit)
+ return
+
+ if(istype(potential_container, /datum))
+ var/datum/datum_container = potential_container
+ if(datum_container.last_find_references == last_find_references)
+ return
+
+ datum_container.last_find_references = last_find_references
+ var/list/vars_list = datum_container.vars
+
+ for(var/varname in vars_list)
+ if (varname == "vars")
+ continue
+ var/variable = vars_list[varname]
+
+ if(variable == src)
+ testing("Found [type] \ref[src] in [datum_container.type]'s [varname] var. [container_name]")
+
+ else if(islist(variable))
+ DoSearchVar(variable, "[container_name] -> list", recursive_limit - 1)
+
+ else if(islist(potential_container))
+ var/normal = IS_NORMAL_LIST(potential_container)
+ for(var/element_in_list in potential_container)
+ if(element_in_list == src)
+ testing("Found [type] \ref[src] in list [container_name].")
+
+ else if(element_in_list && !isnum(element_in_list) && normal && potential_container[element_in_list] == src)
+ testing("Found [type] \ref[src] in list [container_name]\[[element_in_list]\]")
+
+ else if(islist(element_in_list))
+ DoSearchVar(element_in_list, "[container_name] -> list", recursive_limit - 1)
+
+ #ifndef FIND_REF_NO_CHECK_TICK
+ CHECK_TICK
+ #endif
+
+
+/proc/qdel_and_find_ref_if_fail(datum/thing_to_del, force = FALSE)
+ SSgarbage.reference_find_on_fail[REF(thing_to_del)] = TRUE
+ qdel(thing_to_del, force)
+
+#endif
diff --git a/code/modules/admin/view_variables/topic_basic.dm b/code/modules/admin/view_variables/topic_basic.dm
index d6e4c2b944..9ee7103562 100644
--- a/code/modules/admin/view_variables/topic_basic.dm
+++ b/code/modules/admin/view_variables/topic_basic.dm
@@ -45,6 +45,16 @@
usr.client.admin_delete(target)
if (isturf(src)) // show the turf that took its place
usr.client.debug_variables(src)
+ return
+ #ifdef REFERENCE_TRACKING
+ if(href_list[VV_HK_VIEW_REFERENCES])
+ var/datum/D = locate(href_list[VV_HK_TARGET])
+ if(!D)
+ to_chat(usr, "Unable to locate item.")
+ return
+ usr.client.holder.view_refs(target)
+ return
+ #endif
if(href_list[VV_HK_MARK])
usr.client.mark_datum(target)
if(href_list[VV_HK_ADDCOMPONENT])
diff --git a/code/modules/admin/view_variables/view_variables.dm b/code/modules/admin/view_variables/view_variables.dm
index abe445589f..a4dff725f7 100644
--- a/code/modules/admin/view_variables/view_variables.dm
+++ b/code/modules/admin/view_variables/view_variables.dm
@@ -61,6 +61,7 @@
"Set len" = VV_HREF_TARGETREF_INTERNAL(refid, VV_HK_LIST_SET_LENGTH),
"Shuffle" = VV_HREF_TARGETREF_INTERNAL(refid, VV_HK_LIST_SHUFFLE),
"Show VV To Player" = VV_HREF_TARGETREF_INTERNAL(refid, VV_HK_EXPOSE),
+ "View References" = VV_HREF_TARGETREF_INTERNAL(refid, VV_HK_VIEW_REFERENCES),
"---"
)
for(var/i in 1 to length(dropdownoptions))
diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm
index 8bff37ab03..14f7b34309 100644
--- a/code/modules/antagonists/_common/antag_datum.dm
+++ b/code/modules/antagonists/_common/antag_datum.dm
@@ -14,6 +14,8 @@ GLOBAL_LIST_EMPTY(antagonists)
var/list/objectives = list()
var/antag_memory = ""//These will be removed with antag datum
var/antag_moodlet //typepath of moodlet that the mob will gain with their status
+ var/antag_hud_type
+ var/antag_hud_name
/// If above 0, this is the multiplier for the speed at which we hijack the shuttle. Do not directly read, use hijack_speed().
var/hijack_speed = 0
@@ -77,6 +79,17 @@ GLOBAL_LIST_EMPTY(antagonists)
hud.leave_hud(mob_override)
set_antag_hud(mob_override, null)
+// Handles adding and removing the clumsy mutation from clown antags. Gets called in apply/remove_innate_effects
+/datum/antagonist/proc/handle_clown_mutation(mob/living/mob_override, message, removing = TRUE)
+ var/mob/living/carbon/human/H = mob_override
+ if(H && istype(H) && owner.assigned_role == "Clown")
+ if(removing) // They're a clown becoming an antag, remove clumsy
+ H.dna.remove_mutation(CLOWNMUT)
+ if(!silent && message)
+ to_chat(H, "[message]")
+ else
+ H.dna.add_mutation(CLOWNMUT) // We're removing their antag status, add back clumsy
+
//Assign default team and creates one for one of a kind team antagonists
/datum/antagonist/proc/create_team(datum/team/team)
return
@@ -268,7 +281,6 @@ GLOBAL_LIST_EMPTY(antagonists)
. = CONFIG_GET(keyed_list/antag_threat)[lowertext(name)]
if(. == null)
return threat
- return threat
//This one is created by admin tools for custom objectives
/datum/antagonist/custom
diff --git a/code/modules/antagonists/blob/blob.dm b/code/modules/antagonists/blob/blob.dm
index 9a82bb546b..c449bd3012 100644
--- a/code/modules/antagonists/blob/blob.dm
+++ b/code/modules/antagonists/blob/blob.dm
@@ -4,11 +4,17 @@
antagpanel_category = "Blob"
show_to_ghosts = TRUE
job_rank = ROLE_BLOB
- threat = 20
+ threat = 50
var/datum/action/innate/blobpop/pop_action
var/starting_points_human_blob = 60
var/point_rate_human_blob = 2
+/datum/antagonist/blob/threat()
+ . = ..()
+ if(isovermind(owner.current))
+ var/mob/camera/blob/overmind = owner.current
+ . *= (overmind.blobs_legit.len / overmind.max_count)
+
/datum/antagonist/blob/roundend_report()
var/basic_report = ..()
//Display max blobpoints for blebs that lost
diff --git a/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm b/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm
index ba2363ecc0..f9763b92fd 100644
--- a/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm
+++ b/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm
@@ -75,7 +75,6 @@
desc = "A floating, fragile spore."
icon_state = "blobpod"
icon_living = "blobpod"
- threat = 0.2
health = 30
maxHealth = 30
verb_say = "psychically pulses"
diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_life.dm b/code/modules/antagonists/bloodsucker/bloodsucker_life.dm
index a81f702a75..4117fc2b36 100644
--- a/code/modules/antagonists/bloodsucker/bloodsucker_life.dm
+++ b/code/modules/antagonists/bloodsucker/bloodsucker_life.dm
@@ -28,7 +28,6 @@
if(istype(owner.current.loc, /obj/structure/closet/crate/coffin))
Torpor_Begin()
// Wait before next pass
- FreeAllVassals() // Free my Vassals! (if I haven't yet)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -308,6 +307,7 @@
+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// HUMAN FOOD
diff --git a/code/modules/antagonists/bloodsucker/powers/fortitude.dm b/code/modules/antagonists/bloodsucker/powers/fortitude.dm
index 76f3cc77a4..740ec81782 100644
--- a/code/modules/antagonists/bloodsucker/powers/fortitude.dm
+++ b/code/modules/antagonists/bloodsucker/powers/fortitude.dm
@@ -23,6 +23,7 @@
ADD_TRAIT(user, TRAIT_PIERCEIMMUNE, "fortitude")
ADD_TRAIT(user, TRAIT_NODISMEMBER, "fortitude")
ADD_TRAIT(user, TRAIT_STUNIMMUNE, "fortitude")
+ ADD_TRAIT(user, TRAIT_NORUNNING, "fortitude")
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
fortitude_resist = max(0.3, 0.7 - level_current * 0.1)
@@ -53,6 +54,7 @@
REMOVE_TRAIT(user, TRAIT_PIERCEIMMUNE, "fortitude")
REMOVE_TRAIT(user, TRAIT_NODISMEMBER, "fortitude")
REMOVE_TRAIT(user, TRAIT_STUNIMMUNE, "fortitude")
+ REMOVE_TRAIT(user, TRAIT_NORUNNING, "fortitude")
if(!ishuman(owner))
return
var/mob/living/carbon/human/H = owner
diff --git a/code/modules/antagonists/clockcult/clock_mobs.dm b/code/modules/antagonists/clockcult/clock_mobs.dm
index 87466d65f2..2f00fd4e4a 100644
--- a/code/modules/antagonists/clockcult/clock_mobs.dm
+++ b/code/modules/antagonists/clockcult/clock_mobs.dm
@@ -6,7 +6,6 @@
unique_name = 1
minbodytemp = 0
unsuitable_atmos_damage = 0
- threat = 1
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) //Robotic
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
healable = FALSE
diff --git a/code/modules/antagonists/clockcult/clock_mobs/clockwork_marauder.dm b/code/modules/antagonists/clockcult/clock_mobs/clockwork_marauder.dm
index 79b919b1e9..76c9db7231 100644
--- a/code/modules/antagonists/clockcult/clock_mobs/clockwork_marauder.dm
+++ b/code/modules/antagonists/clockcult/clock_mobs/clockwork_marauder.dm
@@ -9,7 +9,6 @@
desc = "The stalwart apparition of a soldier, blazing with crimson flames. It's armed with a gladius and shield."
icon_state = "clockwork_marauder"
mob_biotypes = MOB_HUMANOID
- threat = 3
health = 120
maxHealth = 120
force_threshold = 8
diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm
index 00c4d73428..b7c94d56df 100644
--- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm
+++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm
@@ -97,7 +97,7 @@
desc = "Charges your slab with divine energy, allowing you to overwhelm a target with Ratvar's light."
invocations = list("Divinity, show them your light!")
whispered = TRUE
- channel_time = 15 // I think making kindle channel a third of the time less is a good make up for the fact that it silences people for such a little amount of time.
+ channel_time = 25 //2.5 seconds should be a okay compromise between being able to use it when needed, and not being able to just pause in combat for a second and hardstunning your enemy
power_cost = 125
usage_tip = "The light can be used from up to two tiles away. Damage taken will GREATLY REDUCE the stun's duration."
tier = SCRIPTURE_DRIVER
@@ -137,6 +137,30 @@
quickbind_desc = "Applies handcuffs to a struck target."
+//Belligerent: Channeled for up to fifteen times over thirty seconds. Forces non-servants that can hear the chant to walk, doing minor damage. Nar-Sian cultists are burned.
+/datum/clockwork_scripture/channeled/belligerent
+ descname = "Channeled, Area Slowdown"
+ name = "Belligerent"
+ desc = "Forces all nearby non-servants to walk rather than run, doing minor damage. Chanted every two seconds for up to thirty seconds."
+ chant_invocations = list("Punish their blindness!", "Take time, make slow!", "Kneel before The Justiciar!", "Halt their charges!", "Cease the tides!")
+ chant_amount = 15
+ chant_interval = 20
+ channel_time = 20
+ power_cost = 300
+ usage_tip = "Useful for crowd control in a populated area and disrupting mass movement."
+ tier = SCRIPTURE_DRIVER
+ primary_component = BELLIGERENT_EYE
+ sort_priority = 7
+ quickbind = TRUE
+ quickbind_desc = "Forces nearby non-Servants to walk, doing minor damage with each chant.
Maximum 15 chants."
+
+/datum/clockwork_scripture/channeled/belligerent/chant_effects(chant_number)
+ for(var/mob/living/carbon/C in hearers(7, invoker))
+ C.apply_status_effect(STATUS_EFFECT_BELLIGERENT)
+ new /obj/effect/temp_visual/ratvar/belligerent(get_turf(invoker))
+ return TRUE
+
+
//Vanguard: Provides twenty seconds of greatly increased stamina regeneration and stun immunity. At the end of the twenty seconds, 25% of all stuns absorbed aswell as 50% of healed stamloss are applied to the invoker.
/datum/clockwork_scripture/vanguard
descname = "Self Stun Immunity"
@@ -149,7 +173,7 @@
usage_tip = "You cannot reactivate Vanguard while still shielded by it."
tier = SCRIPTURE_DRIVER
primary_component = VANGUARD_COGWHEEL
- sort_priority = 7
+ sort_priority = 8
quickbind = TRUE
quickbind_desc = "Allows you to temporarily have quickly regenerating stamina and absorb stuns. Part of the stuns absorbed and staminaloss healed will affect you when disabled."
@@ -181,7 +205,7 @@
usage_tip = "The Compromise is very fast to invoke, and will remove holy water from the target Servant."
tier = SCRIPTURE_DRIVER
primary_component = VANGUARD_COGWHEEL
- sort_priority = 8
+ sort_priority = 9
quickbind = TRUE
quickbind_desc = "Allows you to convert a Servant's brute, burn, and oxygen damage to half toxin damage.
Click your slab to disable."
slab_overlay = "compromise"
@@ -255,7 +279,7 @@
tier = SCRIPTURE_DRIVER
space_allowed = TRUE
primary_component = GEIS_CAPACITOR
- sort_priority = 10
+ sort_priority = 11
important = TRUE
quickbind = TRUE
quickbind_desc = "Creates a new Clockwork Slab."
@@ -276,7 +300,7 @@
tier = SCRIPTURE_DRIVER
space_allowed = TRUE
primary_component = GEIS_CAPACITOR
- sort_priority = 11
+ sort_priority = 12
quickbind = TRUE
quickbind_desc = "Creates a pair of Wraith Spectacles, which grant true sight but cause gradual vision loss."
@@ -295,7 +319,7 @@
usage_tip = "This gateway is strictly one-way and will only allow things through the invoker's portal."
tier = SCRIPTURE_DRIVER
primary_component = GEIS_CAPACITOR
- sort_priority = 9
+ sort_priority = 10
quickbind = TRUE
quickbind_desc = "Allows you to create a one-way Spatial Gateway to a living Servant or Clockwork Obelisk."
diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm
index 8819544928..eaec652f68 100644
--- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm
+++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm
@@ -459,26 +459,3 @@
invoker.light_range = 0
invoker.update_light()
return ..()
-
-//Belligerent: Channeled for up to fifteen times over thirty seconds. Forces non-servants that can hear the chant to walk, doing minor damage. Nar-Sian cultists are burned.
-/datum/clockwork_scripture/channeled/belligerent
- descname = "Channeled, Area Slowdown"
- name = "Belligerent"
- desc = "Forces all nearby non-servants to walk rather than run, doing minor damage. Chanted every two seconds for up to thirty seconds."
- chant_invocations = list("Punish their blindness!", "Take time, make slow!", "Kneel before The Justiciar!", "Halt their charges!", "Cease the tides!")
- chant_amount = 15
- chant_interval = 20
- channel_time = 20
- power_cost = 300
- usage_tip = "Useful for crowd control in a populated area and disrupting mass movement."
- tier = SCRIPTURE_DRIVER
- primary_component = BELLIGERENT_EYE
- sort_priority = 1
- quickbind = TRUE
- quickbind_desc = "Forces nearby non-Servants to walk, doing minor damage with each chant.
Maximum 15 chants."
-
-/datum/clockwork_scripture/channeled/belligerent/chant_effects(chant_number)
- for(var/mob/living/carbon/C in hearers(7, invoker))
- C.apply_status_effect(STATUS_EFFECT_BELLIGERENT)
- new /obj/effect/temp_visual/ratvar/belligerent(get_turf(invoker))
- return TRUE
diff --git a/code/modules/antagonists/eldritch_cult/eldritch_antag.dm b/code/modules/antagonists/eldritch_cult/eldritch_antag.dm
new file mode 100644
index 0000000000..367710b110
--- /dev/null
+++ b/code/modules/antagonists/eldritch_cult/eldritch_antag.dm
@@ -0,0 +1,229 @@
+/datum/antagonist/heretic
+ name = "Heretic"
+ roundend_category = "Heretics"
+ antagpanel_category = "Heretic"
+ antag_moodlet = /datum/mood_event/heretics
+ job_rank = ROLE_HERETIC
+ antag_hud_type = ANTAG_HUD_HERETIC
+ antag_hud_name = "heretic"
+ var/give_equipment = TRUE
+ var/list/researched_knowledge = list()
+ var/total_sacrifices = 0
+ var/ascended = FALSE
+
+/datum/antagonist/heretic/admin_add(datum/mind/new_owner,mob/admin)
+ give_equipment = TRUE
+ new_owner.add_antag_datum(src)
+ message_admins("[key_name_admin(admin)] has heresized [key_name_admin(new_owner)].")
+ log_admin("[key_name(admin)] has heresized [key_name(new_owner)].")
+
+/datum/antagonist/heretic/greet()
+ owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ecult_op.ogg', 100, FALSE, pressure_affected = FALSE)//subject to change
+ to_chat(owner, "You are the Heretic!
\
+ The old ones gave you these tasks to fulfill:")
+ owner.announce_objectives()
+ to_chat(owner, "The book whispers, the forbidden knowledge walks once again!
\
+ Your book allows you to research abilities, but be careful, you cannot undo what has been done.
\
+ You gain charges by either collecting influences or sacrificing people tracked by the living heart
\
+ You can find a basic guide at : https://tgstation13.org/wiki/Heresy_101 ")
+
+/datum/antagonist/heretic/on_gain()
+ var/mob/living/current = owner.current
+ if(ishuman(current))
+ forge_primary_objectives()
+ gain_knowledge(/datum/eldritch_knowledge/spell/basic)
+ gain_knowledge(/datum/eldritch_knowledge/living_heart)
+ gain_knowledge(/datum/eldritch_knowledge/codex_cicatrix)
+ gain_knowledge(/datum/eldritch_knowledge/eldritch_blade)
+ current.log_message("has been converted to the cult of the forgotten ones!", LOG_ATTACK, color="#960000")
+ GLOB.reality_smash_track.AddMind(owner)
+ START_PROCESSING(SSprocessing,src)
+ if(give_equipment)
+ equip_cultist()
+ owner.teach_crafting_recipe(/datum/crafting_recipe/heretic/codex)
+ return ..()
+
+/datum/antagonist/heretic/on_removal()
+
+ for(var/X in researched_knowledge)
+ var/datum/eldritch_knowledge/EK = researched_knowledge[X]
+ EK.on_lose(owner.current)
+
+ if(!silent)
+ to_chat(owner.current, "Your mind begins to flare as the otherwordly knowledge escapes your grasp!")
+ owner.current.log_message("has renounced the cult of the old ones!", LOG_ATTACK, color="#960000")
+ GLOB.reality_smash_track.RemoveMind(owner)
+ STOP_PROCESSING(SSprocessing,src)
+
+ return ..()
+
+
+/datum/antagonist/heretic/proc/equip_cultist()
+ var/mob/living/carbon/H = owner.current
+ if(!istype(H))
+ return
+ . += ecult_give_item(/obj/item/forbidden_book, H)
+ . += ecult_give_item(/obj/item/living_heart, H)
+
+/datum/antagonist/heretic/proc/ecult_give_item(obj/item/item_path, mob/living/carbon/human/H)
+ var/list/slots = list(
+ "backpack" = SLOT_IN_BACKPACK,
+ "left pocket" = SLOT_L_STORE,
+ "right pocket" = SLOT_R_STORE
+ )
+
+ var/T = new item_path(H)
+ var/item_name = initial(item_path.name)
+ var/where = H.equip_in_one_of_slots(T, slots)
+ if(!where)
+ to_chat(H, "Unfortunately, you weren't able to get a [item_name]. This is very bad and you should adminhelp immediately (press F1).")
+ return FALSE
+ else
+ to_chat(H, "You have a [item_name] in your [where].")
+ if(where == "backpack")
+ SEND_SIGNAL(H.back, COMSIG_TRY_STORAGE_SHOW, H)
+ return TRUE
+
+/datum/antagonist/heretic/process()
+
+ for(var/X in researched_knowledge)
+ var/datum/eldritch_knowledge/EK = researched_knowledge[X]
+ EK.on_life(owner.current)
+
+/datum/antagonist/heretic/proc/forge_primary_objectives()
+ var/list/assasination = list()
+ var/list/protection = list()
+ for(var/i in 1 to 2)
+ var/pck = pick("assasinate","protect")
+ switch(pck)
+ if("assasinate")
+ var/datum/objective/assassinate/A = new
+ A.owner = owner
+ var/list/owners = A.get_owners()
+ A.find_target(owners,protection)
+ assasination += A.target
+ objectives += A
+ if("protect")
+ var/datum/objective/protect/P = new
+ P.owner = owner
+ var/list/owners = P.get_owners()
+ P.find_target(owners,assasination)
+ protection += P.target
+ objectives += P
+
+
+ var/datum/objective/sacrifice_ecult/SE = new
+ SE.owner = owner
+ SE.update_explanation_text()
+ objectives += SE
+
+ var/datum/objective/escape/escape_objective = new
+ escape_objective.owner = owner
+ objectives += escape_objective
+
+/datum/antagonist/heretic/apply_innate_effects(mob/living/mob_override)
+ . = ..()
+ var/mob/living/current = owner.current
+ if(mob_override)
+ current = mob_override
+ add_antag_hud(antag_hud_type, antag_hud_name, current)
+ handle_clown_mutation(current, mob_override ? null : "Knowledge described in the book allowed you to overcome your clownish nature, allowing you to use complex items effectively.")
+ current.faction |= "heretics"
+
+/datum/antagonist/heretic/remove_innate_effects(mob/living/mob_override)
+ . = ..()
+ var/mob/living/current = owner.current
+ if(mob_override)
+ current = mob_override
+ remove_antag_hud(antag_hud_type, current)
+ handle_clown_mutation(current, removing = FALSE)
+ current.faction -= "heretics"
+
+/datum/antagonist/heretic/get_admin_commands()
+ . = ..()
+ .["Equip"] = CALLBACK(src,.proc/equip_cultist)
+
+/datum/antagonist/heretic/roundend_report()
+ var/list/parts = list()
+
+ var/cultiewin = TRUE
+
+ parts += printplayer(owner)
+ parts += "Sacrifices Made: [total_sacrifices]"
+
+ if(length(objectives))
+ var/count = 1
+ for(var/o in objectives)
+ var/datum/objective/objective = o
+ if(objective.check_completion())
+ parts += "Objective #[count]: [objective.explanation_text] Success!"
+ else
+ parts += "Objective #[count]: [objective.explanation_text] Fail."
+ cultiewin = FALSE
+ count++
+ if(ascended)
+ parts += "HERETIC HAS ASCENDED!"
+ else
+ if(cultiewin)
+ parts += "The heretic was successful!"
+ else
+ parts += "The heretic has failed."
+
+ parts += "Knowledge Researched: "
+
+ var/list/knowledge_message = list()
+ var/list/knowledge = get_all_knowledge()
+ for(var/X in knowledge)
+ var/datum/eldritch_knowledge/EK = knowledge[X]
+ knowledge_message += "[EK.name]"
+ parts += knowledge_message.Join(", ")
+
+ return parts.Join("
")
+////////////////
+// Knowledge //
+////////////////
+
+/datum/antagonist/heretic/proc/gain_knowledge(datum/eldritch_knowledge/EK)
+ if(get_knowledge(EK))
+ return FALSE
+ var/datum/eldritch_knowledge/initialized_knowledge = new EK
+ researched_knowledge[initialized_knowledge.type] = initialized_knowledge
+ initialized_knowledge.on_gain(owner.current)
+ return TRUE
+
+/datum/antagonist/heretic/proc/get_researchable_knowledge()
+ var/list/researchable_knowledge = list()
+ var/list/banned_knowledge = list()
+ for(var/X in researched_knowledge)
+ var/datum/eldritch_knowledge/EK = researched_knowledge[X]
+ researchable_knowledge |= EK.next_knowledge
+ banned_knowledge |= EK.banned_knowledge
+ banned_knowledge |= EK.type
+ researchable_knowledge -= banned_knowledge
+ return researchable_knowledge
+
+/datum/antagonist/heretic/proc/get_knowledge(wanted)
+ return researched_knowledge[wanted]
+
+/datum/antagonist/heretic/proc/get_all_knowledge()
+ return researched_knowledge
+
+////////////////
+// Objectives //
+////////////////
+
+/datum/objective/sacrifice_ecult
+ name = "sacrifice"
+
+/datum/objective/sacrifice_ecult/update_explanation_text()
+ . = ..()
+ target_amount = rand(2,4)
+ explanation_text = "Sacrifice at least [target_amount] people."
+
+/datum/objective/sacrifice_ecult/check_completion()
+ if(!owner)
+ return FALSE
+ var/datum/antagonist/heretic/cultie = owner.has_antag_datum(/datum/antagonist/heretic)
+ if(!cultie)
+ return FALSE
+ return cultie.total_sacrifices >= target_amount
diff --git a/code/modules/antagonists/eldritch_cult/eldritch_book.dm b/code/modules/antagonists/eldritch_cult/eldritch_book.dm
new file mode 100644
index 0000000000..839150d37d
--- /dev/null
+++ b/code/modules/antagonists/eldritch_cult/eldritch_book.dm
@@ -0,0 +1,145 @@
+/obj/item/forbidden_book
+ name = "Codex Cicatrix"
+ desc = "Book describing the secrets of the veil."
+ icon = 'icons/obj/eldritch.dmi'
+ icon_state = "book"
+ item_state = "book"
+ w_class = WEIGHT_CLASS_SMALL
+ ///Last person that touched this
+ var/mob/living/last_user
+ ///how many charges do we have?
+ var/charge = 0
+ ///Where we cannot create the rune?
+ var/static/list/blacklisted_turfs = typecacheof(list(/turf/closed,/turf/open/space,/turf/open/lava))
+
+/obj/item/forbidden_book/Destroy()
+ last_user = null
+ . = ..()
+
+
+/obj/item/forbidden_book/examine(mob/user)
+ . = ..()
+ if(!IS_HERETIC(user))
+ return
+ . += "The Tome holds [charge] charges."
+ . += "Use it on the floor to create a transmutation rune, used to perform rituals."
+ . += "Hit an influence in the black part with it to gain a charge."
+ . += "Hit a transmutation rune to destroy it."
+
+/obj/item/forbidden_book/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
+ . = ..()
+ if(!proximity_flag || !IS_HERETIC(user))
+ return
+ if(istype(target,/obj/effect/eldritch))
+ remove_rune(target,user)
+ if(istype(target,/obj/effect/reality_smash))
+ get_power_from_influence(target,user)
+ if(istype(target,/turf/open))
+ draw_rune(target,user)
+
+///Gives you a charge and destroys a corresponding influence
+/obj/item/forbidden_book/proc/get_power_from_influence(atom/target, mob/user)
+ var/obj/effect/reality_smash/RS = target
+ to_chat(target, "You start drawing power from influence...")
+ if(do_after(user,10 SECONDS,TRUE,RS))
+ qdel(RS)
+ charge += 1
+
+///Draws a rune on a selected turf
+/obj/item/forbidden_book/proc/draw_rune(atom/target,mob/user)
+
+ for(var/turf/T in range(1,target))
+ if(is_type_in_typecache(T, blacklisted_turfs))
+ to_chat(target, "The terrain doesn't support runes!")
+ return
+ var/A = get_turf(target)
+ to_chat(user, "You start drawing a rune...")
+
+ if(do_after(user,30 SECONDS,FALSE, user))
+
+ new /obj/effect/eldritch/big(A)
+
+///Removes runes from the selected turf
+/obj/item/forbidden_book/proc/remove_rune(atom/target,mob/user)
+
+ to_chat(user, "You start removing a rune...")
+ if(do_after(user,2 SECONDS,FALSE, user))
+ qdel(target)
+
+/obj/item/forbidden_book/ui_interact(mob/user, datum/tgui/ui = null)
+ if(!IS_HERETIC(user))
+ return FALSE
+ last_user = user
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ icon_state = "book_open"
+ flick("book_opening", src)
+ ui = new(user, src, "ForbiddenLore", name)
+ ui.open()
+
+/obj/item/forbidden_book/ui_data(mob/user)
+ var/datum/antagonist/heretic/cultie = user.mind.has_antag_datum(/datum/antagonist/heretic)
+ var/list/to_know = list()
+ for(var/Y in cultie.get_researchable_knowledge())
+ to_know += new Y
+ var/list/known = cultie.get_all_knowledge()
+ var/list/data = list()
+ var/list/lore = list()
+
+ data["charges"] = charge
+
+ for(var/X in to_know)
+ lore = list()
+ var/datum/eldritch_knowledge/EK = X
+ lore["type"] = EK.type
+ lore["name"] = EK.name
+ lore["cost"] = EK.cost
+ lore["disabled"] = EK.cost <= charge ? FALSE : TRUE
+ lore["path"] = EK.route
+ lore["state"] = "Research"
+ lore["flavour"] = EK.gain_text
+ lore["desc"] = EK.desc
+ data["to_know"] += list(lore)
+
+ for(var/X in known)
+ lore = list()
+ var/datum/eldritch_knowledge/EK = known[X]
+ lore["name"] = EK.name
+ lore["cost"] = EK.cost
+ lore["disabled"] = TRUE
+ lore["path"] = EK.route
+ lore["state"] = "Researched"
+ lore["flavour"] = EK.gain_text
+ lore["desc"] = EK.desc
+ data["to_know"] += list(lore)
+
+ if(!length(data["to_know"]))
+ data["to_know"] = null
+
+ return data
+
+/obj/item/forbidden_book/ui_act(action, params)
+ . = ..()
+ if(.)
+ return
+ switch(action)
+ if("research")
+ var/datum/antagonist/heretic/cultie = last_user.mind.has_antag_datum(/datum/antagonist/heretic)
+ var/ekname = params["name"]
+ for(var/X in cultie.get_researchable_knowledge())
+ var/datum/eldritch_knowledge/EK = X
+ if(initial(EK.name) != ekname)
+ continue
+ if(cultie.gain_knowledge(EK))
+ charge -= text2num(params["cost"])
+ return TRUE
+
+ update_icon() // Not applicable to all objects.
+
+/obj/item/forbidden_book/ui_close(mob/user)
+ flick("book_closing",src)
+ icon_state = initial(icon_state)
+ return ..()
+
+/obj/item/forbidden_book/debug
+ charge = 100
diff --git a/code/modules/antagonists/eldritch_cult/eldritch_effects.dm b/code/modules/antagonists/eldritch_cult/eldritch_effects.dm
new file mode 100644
index 0000000000..899e588bda
--- /dev/null
+++ b/code/modules/antagonists/eldritch_cult/eldritch_effects.dm
@@ -0,0 +1,289 @@
+/obj/effect/eldritch
+ name = "Generic rune"
+ desc = "Weird combination of shapes and symbols etched into the floor itself. The indentation is filled with thick black tar-like fluid."
+ anchored = TRUE
+ icon_state = ""
+ resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
+ layer = SIGIL_LAYER
+ ///Used mainly for summoning ritual to prevent spamming the rune to create millions of monsters.
+ var/is_in_use = FALSE
+
+/obj/effect/eldritch/attack_hand(mob/living/user)
+ . = ..()
+ if(.)
+ return
+ try_activate(user)
+
+/obj/effect/eldritch/proc/try_activate(mob/living/user)
+ if(!IS_HERETIC(user))
+ return
+ if(!is_in_use)
+ INVOKE_ASYNC(src, .proc/activate , user)
+
+/obj/effect/eldritch/attacked_by(obj/item/I, mob/living/user)
+ . = ..()
+ if(istype(I,/obj/item/nullrod))
+ qdel(src)
+
+/obj/effect/eldritch/proc/activate(mob/living/user)
+ is_in_use = TRUE
+ // Have fun trying to read this proc.
+ var/datum/antagonist/heretic/cultie = user.mind.has_antag_datum(/datum/antagonist/heretic)
+ var/list/knowledge = cultie.get_all_knowledge()
+ var/list/atoms_in_range = list()
+
+ for(var/A in range(1, src))
+ var/atom/atom_in_range = A
+ if(istype(atom_in_range,/area))
+ continue
+ if(istype(atom_in_range,/turf)) // we dont want turfs
+ continue
+ if(istype(atom_in_range,/mob/living))
+ var/mob/living/living_in_range = atom_in_range
+ if(living_in_range.stat != DEAD || living_in_range == user) // we only accept corpses, no living beings allowed.
+ continue
+ atoms_in_range += atom_in_range
+ for(var/X in knowledge)
+ var/datum/eldritch_knowledge/current_eldritch_knowledge = knowledge[X]
+
+ //has to be done so that we can freely edit the local_required_atoms without fucking up the eldritch knowledge
+ var/list/local_required_atoms = list()
+
+ if(!current_eldritch_knowledge.required_atoms || current_eldritch_knowledge.required_atoms.len == 0)
+ continue
+
+ local_required_atoms += current_eldritch_knowledge.required_atoms
+
+ var/list/selected_atoms = list()
+
+ if(!current_eldritch_knowledge.recipe_snowflake_check(atoms_in_range,drop_location(),selected_atoms))
+ continue
+
+ for(var/LR in local_required_atoms)
+ var/list/local_required_atom_list = LR
+
+ for(var/LAIR in atoms_in_range)
+ var/atom/local_atom_in_range = LAIR
+ if(is_type_in_list(local_atom_in_range,local_required_atom_list))
+ selected_atoms |= local_atom_in_range
+ local_required_atoms -= list(local_required_atom_list)
+
+ if(length(local_required_atoms) > 0)
+ continue
+
+ flick("[icon_state]_active",src)
+ playsound(user, 'sound/magic/castsummon.ogg', 75, TRUE)
+ //we are doing this since some on_finished_recipe subtract the atoms from selected_atoms making them invisible permanently.
+ var/list/atoms_to_disappear = selected_atoms.Copy()
+ for(var/to_disappear in atoms_to_disappear)
+ var/atom/atom_to_disappear = to_disappear
+ //temporary so we dont have to deal with the bs of someone picking those up when they may be deleted
+ atom_to_disappear.invisibility = INVISIBILITY_ABSTRACT
+ if(current_eldritch_knowledge.on_finished_recipe(user,selected_atoms,loc))
+ current_eldritch_knowledge.cleanup_atoms(selected_atoms)
+ is_in_use = FALSE
+
+ for(var/to_appear in atoms_to_disappear)
+ var/atom/atom_to_appear = to_appear
+ //we need to reappear the item just in case the ritual didnt consume everything... or something.
+ atom_to_appear.invisibility = initial(atom_to_appear.invisibility)
+
+ return
+ is_in_use = FALSE
+ to_chat(user,"Your ritual failed! You used either wrong components or are missing something important!")
+
+/obj/effect/eldritch/big
+ name = "transmutation circle"
+ icon = 'icons/effects/96x96.dmi'
+ icon_state = "eldritch_rune1"
+ pixel_x = -32 //So the big ol' 96x96 sprite shows up right
+ pixel_y = -32
+
+/**
+ * #Reality smash tracker
+ *
+ * Stupid fucking list holder, DONT create new ones, it will break the game, this is automnatically created whenever eldritch cultists are created.
+ *
+ * Tracks relevant data, generates relevant data, useful tool
+ */
+/datum/reality_smash_tracker
+ ///list of tracked reality smashes
+ var/list/smashes = list()
+ ///List of mobs with ability to see the smashes
+ var/list/targets = list()
+
+/datum/reality_smash_tracker/Destroy(force, ...)
+ if(GLOB.reality_smash_track == src)
+ stack_trace("/datum/reality_smash_tracker was deleted. Heretics may no longer access any influences. Fix it or call coder support")
+ QDEL_LIST(smashes)
+ targets.Cut()
+ return ..()
+
+/**
+ * Automatically fixes the target and smash network
+ *
+ * Fixes any bugs that are caused by late Generate() or exchanging clients
+ */
+/datum/reality_smash_tracker/proc/ReworkNetwork()
+ listclearnulls(smashes)
+ for(var/mind in targets)
+ if(isnull(mind))
+ stack_trace("A null somehow landed in a list of minds")
+ continue
+ for(var/X in smashes)
+ var/obj/effect/reality_smash/reality_smash = X
+ reality_smash.AddMind(mind)
+
+/**
+ * Generates a set amount of reality smashes based on the N value
+ *
+ * Automatically creates more reality smashes
+ */
+/datum/reality_smash_tracker/proc/_Generate()
+ var/targ_len = length(targets)
+ var/smash_len = length(smashes)
+ var/number = targ_len * 6 - smash_len
+
+ for(var/i in 0 to number)
+
+ var/turf/chosen_location = get_safe_random_station_turf()
+ //we also dont want them close to each other, at least 1 tile of seperation
+ var/obj/effect/reality_smash/what_if_i_have_one = locate() in range(1, chosen_location)
+ var/obj/effect/broken_illusion/what_if_i_had_one_but_got_used = locate() in range(1, chosen_location)
+ if(what_if_i_have_one || what_if_i_had_one_but_got_used) //we dont want to spawn
+ continue
+ var/obj/effect/reality_smash/RS = new/obj/effect/reality_smash(chosen_location)
+ smashes += RS
+ ReworkNetwork()
+
+
+/**
+ * Adds a mind to the list of people that can see the reality smashes
+ *
+ * Use this whenever you want to add someone to the list
+ */
+/datum/reality_smash_tracker/proc/AddMind(var/datum/mind/M)
+ RegisterSignal(M.current,COMSIG_MOB_CLIENT_LOGIN,.proc/ReworkNetwork)
+ targets |= M
+ _Generate()
+ for(var/X in smashes)
+ var/obj/effect/reality_smash/reality_smash = X
+ reality_smash.AddMind(M)
+
+
+/**
+ * Removes a mind from the list of people that can see the reality smashes
+ *
+ * Use this whenever you want to remove someone from the list
+ */
+/datum/reality_smash_tracker/proc/RemoveMind(var/datum/mind/M)
+ UnregisterSignal(M.current,COMSIG_MOB_CLIENT_LOGIN)
+ targets -= M
+ for(var/obj/effect/reality_smash/RS in smashes)
+ RS.RemoveMind(M)
+
+/obj/effect/broken_illusion
+ name = "pierced reality"
+ icon = 'icons/effects/eldritch.dmi'
+ icon_state = "pierced_illusion"
+ anchored = TRUE
+ resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
+
+/obj/effect/broken_illusion/attack_hand(mob/living/user)
+ if(!ishuman(user))
+ return ..()
+ var/mob/living/carbon/human/human_user = user
+ if(IS_HERETIC(human_user))
+ to_chat(human_user,"You know better than to tempt forces out of your control.")
+ else
+ var/obj/item/bodypart/arm = human_user.get_active_hand()
+ if(prob(25))
+ to_chat(human_user,"An otherwordly presence tears your arm apart into atoms as you try to touch the hole in the very fabric of reality!")
+ arm.dismember()
+ qdel(arm)
+ else
+ to_chat(human_user,"You pull your hand away from the hole as eldritch energy flails out, trying to latch onto existence itself!")
+
+/obj/effect/broken_illusion/attack_tk(mob/user)
+ if(!ishuman(user))
+ return
+ var/mob/living/carbon/human/human_user = user
+ if(IS_HERETIC(human_user))
+ to_chat(human_user,"You know better than to tempt forces out of your control.")
+ else
+ //a very elaborate way to suicide
+ to_chat(human_user,"Eldritch energy lashes out, piercing your fragile mind, tearing it to pieces!")
+ human_user.ghostize()
+ var/obj/item/bodypart/head/head = locate() in human_user.bodyparts
+ if(head)
+ head.dismember()
+ qdel(head)
+ else
+ human_user.gib()
+
+ var/datum/effect_system/reagents_explosion/explosion = new()
+ explosion.set_up(1, get_turf(human_user), 1, 0)
+ explosion.start()
+
+/obj/effect/broken_illusion/examine(mob/user)
+ if(!IS_HERETIC(user) && ishuman(user))
+ var/mob/living/carbon/human/human_user = user
+ to_chat(human_user,"Your brain hurts when you look at this!")
+ human_user.adjustOrganLoss(ORGAN_SLOT_BRAIN,30)
+ . = ..()
+
+/obj/effect/reality_smash
+ name = "/improper reality smash"
+ icon = 'icons/effects/eldritch.dmi'
+ anchored = TRUE
+ resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
+ ///We cannot use icon_state since this is invisible, functions the same way but with custom behaviour.
+ var/image_state = "reality_smash"
+ ///Who can see us?
+ var/list/minds = list()
+ ///Tracked image
+ var/image/img
+
+/obj/effect/reality_smash/Initialize()
+ . = ..()
+ img = image(icon, src, image_state, OBJ_LAYER)
+ generate_name()
+
+/obj/effect/reality_smash/Destroy()
+ on_destroy()
+ return ..()
+
+///Custom effect that happens on destruction
+/obj/effect/reality_smash/proc/on_destroy()
+ for(var/cm in minds)
+ var/datum/mind/cultie = cm
+ if(cultie.current?.client)
+ cultie.current.client.images -= img
+ //clear the list
+ minds -= cultie
+ GLOB.reality_smash_track.smashes -= src
+ img = null
+ new /obj/effect/broken_illusion(drop_location())
+
+///Makes the mind able to see this effect
+/obj/effect/reality_smash/proc/AddMind(var/datum/mind/cultie)
+ minds |= cultie
+ if(cultie.current.client)
+ cultie.current.client.images |= img
+
+
+
+///Makes the mind not able to see this effect
+/obj/effect/reality_smash/proc/RemoveMind(var/datum/mind/cultie)
+ minds -= cultie
+ if(cultie.current.client)
+ cultie.current.client.images -= img
+
+
+
+///Generates random name
+/obj/effect/reality_smash/proc/generate_name()
+ var/static/list/prefix = list("Omniscient","Thundering","Enlightening","Intrusive","Rejectful","Atomized","Subtle","Rising","Lowering","Fleeting","Towering","Blissful","Arrogant","Threatening","Peaceful","Aggressive")
+ var/static/list/postfix = list("Flaw","Presence","Crack","Heat","Cold","Memory","Reminder","Breeze","Grasp","Sight","Whisper","Flow","Touch","Veil","Thought","Imperfection","Blemish","Blush")
+
+ name = pick(prefix) + " " + pick(postfix)
diff --git a/code/modules/antagonists/eldritch_cult/eldritch_items.dm b/code/modules/antagonists/eldritch_cult/eldritch_items.dm
new file mode 100644
index 0000000000..4dab6d789d
--- /dev/null
+++ b/code/modules/antagonists/eldritch_cult/eldritch_items.dm
@@ -0,0 +1,142 @@
+/obj/item/living_heart
+ name = "living heart"
+ desc = "Link to the worlds beyond."
+ icon = 'icons/obj/eldritch.dmi'
+ icon_state = "living_heart"
+ w_class = WEIGHT_CLASS_SMALL
+ ///Target
+ var/mob/living/carbon/human/target
+
+/obj/item/living_heart/attack_self(mob/user)
+ . = ..()
+ if(!IS_HERETIC(user))
+ return
+ if(!target)
+ to_chat(user,"No target could be found. Put the living heart on the rune and use the rune to recieve a target.")
+ return
+ var/dist = get_dist(user.loc,target.loc)
+ var/dir = get_dir(user.loc,target.loc)
+
+ switch(dist)
+ if(0 to 15)
+ to_chat(user,"[target.real_name] is near you. They are to the [dir2text(dir)] of you!")
+ if(16 to 31)
+ to_chat(user,"[target.real_name] is somewhere in your vicinty. They are to the [dir2text(dir)] of you!")
+ if(32 to 127)
+ to_chat(user,"[target.real_name] is far away from you. They are to the [dir2text(dir)] of you!")
+ else
+ to_chat(user,"[target.real_name] is beyond our reach.")
+
+ if(target.stat == DEAD)
+ to_chat(user,"[target.real_name] is dead. Bring them onto a transmutation rune!")
+
+/obj/item/melee/sickly_blade
+ name = "eldritch blade"
+ desc = "A sickly green crescent blade, decorated with an ornamental eye. You feel like you're being watched..."
+ icon = 'icons/obj/eldritch.dmi'
+ icon_state = "eldritch_blade"
+ item_state = "eldritch_blade"
+ lefthand_file = 'icons/mob/inhands/64x64_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/64x64_righthand.dmi'
+ inhand_x_dimension = 64
+ inhand_y_dimension = 64
+ flags_1 = CONDUCT_1
+ sharpness = SHARP_EDGED
+ w_class = WEIGHT_CLASS_NORMAL
+ force = 17
+ throwforce = 10
+ hitsound = 'sound/weapons/bladeslice.ogg'
+ attack_verb = list("attacked", "slashed", "stabbed", "sliced", "tore", "lacerated", "ripped", "diced", "rended")
+
+/obj/item/melee/sickly_blade/attack(mob/living/M, mob/living/user)
+ if(!IS_HERETIC(user))
+ to_chat(user,"You feel a pulse of some alien intellect lash out at your mind!")
+ var/mob/living/carbon/human/human_user = user
+ human_user.AdjustParalyzed(5 SECONDS)
+ return FALSE
+ return ..()
+
+/obj/item/melee/sickly_blade/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
+ . = ..()
+ var/datum/antagonist/heretic/cultie = user.mind.has_antag_datum(/datum/antagonist/heretic)
+ if(!cultie || !proximity_flag)
+ return
+ var/list/knowledge = cultie.get_all_knowledge()
+ for(var/X in knowledge)
+ var/datum/eldritch_knowledge/eldritch_knowledge_datum = knowledge[X]
+ eldritch_knowledge_datum.on_eldritch_blade(target,user,proximity_flag,click_parameters)
+
+/obj/item/melee/sickly_blade/rust
+ name = "rusted blade"
+ desc = "This crescent blade is decrepit, wasting to dust. Yet still it bites, catching flesh with jagged, rotten teeth."
+ icon_state = "rust_blade"
+ item_state = "rust_blade"
+ embedding = list("pain_mult" = 4, "embed_chance" = 75, "fall_chance" = 10, "ignore_throwspeed_threshold" = TRUE)
+ throwforce = 17
+
+/obj/item/melee/sickly_blade/ash
+ name = "ashen blade"
+ desc = "Molten and unwrought, a hunk of metal warped to cinders and slag. Unmade, it aspires to be more than it is, and shears soot-filled wounds with a blunt edge."
+ icon_state = "ash_blade"
+ item_state = "ash_blade"
+ force = 20
+
+/obj/item/melee/sickly_blade/flesh
+ name = "flesh blade"
+ desc = "A crescent blade born from a fleshwarped creature. Keenly aware, it seeks to spread to others the excruciations it has endured from dead origins."
+ icon_state = "flesh_blade"
+ item_state = "flesh_blade"
+ wound_bonus = 5
+ bare_wound_bonus = 15
+
+/obj/item/clothing/neck/eldritch_amulet
+ name = "warm eldritch medallion"
+ desc = "A strange medallion. Peering through the crystalline surface, the world around you melts away. You see your own beating heart, and the pulse of a thousand others."
+ icon = 'icons/obj/eldritch.dmi'
+ icon_state = "eye_medalion"
+ w_class = WEIGHT_CLASS_SMALL
+ ///What trait do we want to add upon equipiing
+ var/trait = TRAIT_THERMAL_VISION
+
+/obj/item/clothing/neck/eldritch_amulet/equipped(mob/user, slot)
+ . = ..()
+ if(ishuman(user) && user.mind && slot == SLOT_NECK && IS_HERETIC(user))
+ ADD_TRAIT(user, trait, CLOTHING_TRAIT)
+ user.update_sight()
+
+/obj/item/clothing/neck/eldritch_amulet/dropped(mob/user)
+ . = ..()
+ REMOVE_TRAIT(user, trait, CLOTHING_TRAIT)
+ user.update_sight()
+
+/obj/item/clothing/neck/eldritch_amulet/piercing
+ name = "piercing eldritch medallion"
+ desc = "A strange medallion. Peering through the crystalline surface, the light refracts into new and terrifying spectrums of color. You see yourself, reflected off cascading mirrors, warped into improbable shapes."
+ trait = TRAIT_XRAY_VISION
+
+/obj/item/clothing/head/hooded/cult_hoodie/eldritch
+ name = "ominous hood"
+ icon_state = "eldritch"
+ desc = "A torn, dust-caked hood. Strange eyes line the inside."
+ flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
+ flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
+ flash_protect = 2
+
+/obj/item/clothing/suit/hooded/cultrobes/eldritch
+ name = "ominous armor"
+ desc = "A ragged, dusty set of robes. Strange eyes line the inside."
+ icon_state = "eldritch_armor"
+ item_state = "eldritch_armor"
+ flags_inv = HIDESHOES|HIDEJUMPSUIT
+ body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS
+ allowed = list(/obj/item/melee/sickly_blade, /obj/item/forbidden_book)
+ hoodtype = /obj/item/clothing/head/hooded/cult_hoodie/eldritch
+ // slightly better than normal cult robes
+ armor = list("melee" = 50, "bullet" = 50, "laser" = 50,"energy" = 50, "bomb" = 35, "bio" = 20, "rad" = 0, "fire" = 20, "acid" = 20)
+
+/obj/item/reagent_containers/glass/beaker/eldritch
+ name = "flask of eldritch essence"
+ desc = "Toxic to the close minded. Healing to those with knowledge of the beyond."
+ icon = 'icons/obj/eldritch.dmi'
+ icon_state = "eldrich_flask"
+ list_reagents = list(/datum/reagent/eldritch = 50)
diff --git a/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm b/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm
new file mode 100644
index 0000000000..065844bedf
--- /dev/null
+++ b/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm
@@ -0,0 +1,303 @@
+
+/**
+ * #Eldritch Knwoledge
+ *
+ * Datum that makes eldritch cultist interesting.
+ *
+ * Eldritch knowledge aren't instantiated anywhere roundstart, and are initalized and destroyed as the round goes on.
+ */
+/datum/eldritch_knowledge
+ ///Name of the knowledge
+ var/name = "Basic knowledge"
+ ///Description of the knowledge
+ var/desc = "Basic knowledge of forbidden arts."
+ ///What shows up
+ var/gain_text = ""
+ ///Cost of knowledge in souls
+ var/cost = 0
+ ///Next knowledge in the research tree
+ var/list/next_knowledge = list()
+ ///What knowledge is incompatible with this. This will simply make it impossible to research knowledges that are in banned_knowledge once this gets researched.
+ var/list/banned_knowledge = list()
+ ///Used with rituals, how many items this needs
+ var/list/required_atoms = list()
+ ///What do we get out of this
+ var/list/result_atoms = list()
+ ///What path is this on defaults to "Side"
+ var/route = PATH_SIDE
+
+/datum/eldritch_knowledge/New()
+ . = ..()
+ var/list/temp_list
+ for(var/X in required_atoms)
+ var/atom/A = X
+ temp_list += list(typesof(A))
+ required_atoms = temp_list
+
+/**
+ * What happens when this is assigned to an antag datum
+ *
+ * This proc is called whenever a new eldritch knowledge is added to an antag datum
+ */
+/datum/eldritch_knowledge/proc/on_gain(mob/user)
+ to_chat(user, "[gain_text]")
+ return
+/**
+ * What happens when you loose this
+ *
+ * This proc is called whenever antagonist looses his antag datum, put cleanup code in here
+ */
+/datum/eldritch_knowledge/proc/on_lose(mob/user)
+ return
+/**
+ * What happens every tick
+ *
+ * This proc is called on SSprocess in eldritch cultist antag datum. SSprocess happens roughly every second
+ */
+/datum/eldritch_knowledge/proc/on_life(mob/user)
+ return
+
+/**
+ * Special check for recipes
+ *
+ * If you are adding a more complex summoning or something that requires a special check that parses through all the atoms in an area override this.
+ */
+/datum/eldritch_knowledge/proc/recipe_snowflake_check(list/atoms,loc)
+ return TRUE
+
+/**
+ * What happens once the recipe is succesfully finished
+ *
+ * By default this proc creates atoms from result_atoms list. Override this is you want something else to happen.
+ */
+/datum/eldritch_knowledge/proc/on_finished_recipe(mob/living/user,list/atoms,loc)
+ if(result_atoms.len == 0)
+ return FALSE
+
+ for(var/A in result_atoms)
+ new A(loc)
+
+ return TRUE
+
+/**
+ * Used atom cleanup
+ *
+ * Overide this proc if you dont want ALL ATOMS to be destroyed. useful in many situations.
+ */
+/datum/eldritch_knowledge/proc/cleanup_atoms(list/atoms)
+ for(var/X in atoms)
+ var/atom/A = X
+ if(!isliving(A))
+ atoms -= A
+ qdel(A)
+ return
+
+/**
+ * Mansus grasp act
+ *
+ * Gives addtional effects to mansus grasp spell
+ */
+/datum/eldritch_knowledge/proc/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters)
+ return FALSE
+
+
+/**
+ * Sickly blade act
+ *
+ * Gives addtional effects to sickly blade weapon
+ */
+/datum/eldritch_knowledge/proc/on_eldritch_blade(target,user,proximity_flag,click_parameters)
+ return
+
+//////////////
+///Subtypes///
+//////////////
+
+/datum/eldritch_knowledge/spell
+ var/obj/effect/proc_holder/spell/spell_to_add
+
+/datum/eldritch_knowledge/spell/on_gain(mob/user)
+ var/obj/effect/proc_holder/S = new spell_to_add
+ user.mind.AddSpell(S)
+ return ..()
+
+/datum/eldritch_knowledge/spell/on_lose(mob/user)
+ user.mind.RemoveSpell(spell_to_add)
+ return ..()
+
+/datum/eldritch_knowledge/curse
+ var/timer = 5 MINUTES
+ var/list/fingerprints = list()
+
+/datum/eldritch_knowledge/curse/recipe_snowflake_check(list/atoms, loc)
+ fingerprints = list()
+ for(var/X in atoms)
+ var/atom/A = X
+ fingerprints |= A.fingerprints
+ listclearnulls(fingerprints)
+ if(fingerprints.len == 0)
+ return FALSE
+ return TRUE
+
+/datum/eldritch_knowledge/curse/on_finished_recipe(mob/living/user,list/atoms,loc)
+
+ var/list/compiled_list = list()
+
+ for(var/H in GLOB.human_list)
+ var/mob/living/carbon/human/human_to_check = H
+ if(fingerprints[md5(human_to_check.dna.uni_identity)])
+ compiled_list |= human_to_check.real_name
+ compiled_list[human_to_check.real_name] = human_to_check
+
+ if(compiled_list.len == 0)
+ to_chat(user, "The items don't posses required fingerprints.")
+ return FALSE
+
+ var/chosen_mob = input("Select the person you wish to curse","Your target") as null|anything in sortList(compiled_list, /proc/cmp_mob_realname_dsc)
+ if(!chosen_mob)
+ return FALSE
+ curse(compiled_list[chosen_mob])
+ addtimer(CALLBACK(src, .proc/uncurse, compiled_list[chosen_mob]),timer)
+ return TRUE
+
+/datum/eldritch_knowledge/curse/proc/curse(mob/living/chosen_mob)
+ return
+
+/datum/eldritch_knowledge/curse/proc/uncurse(mob/living/chosen_mob)
+ return
+
+/datum/eldritch_knowledge/summon
+ //Mob to summon
+ var/mob/living/mob_to_summon
+
+
+/datum/eldritch_knowledge/summon/on_finished_recipe(mob/living/user,list/atoms,loc)
+ //we need to spawn the mob first so that we can use it in pollCandidatesForMob, we will move it from nullspace down the code
+ var/mob/living/summoned = new mob_to_summon(loc)
+ message_admins("[summoned.name] is being summoned by [user.real_name] in [loc]")
+ var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [summoned.name]", ROLE_HERETIC, null, FALSE, 100, summoned)
+ if(!LAZYLEN(candidates))
+ to_chat(user,"No ghost could be found...")
+ qdel(summoned)
+ return FALSE
+ var/mob/dead/observer/C = pick(candidates)
+ log_game("[key_name_admin(C)] has taken control of ([key_name_admin(summoned)]), their master is [user.real_name]")
+ summoned.ghostize(FALSE)
+ summoned.key = C.key
+ summoned.mind.add_antag_datum(/datum/antagonist/heretic_monster)
+ var/datum/antagonist/heretic_monster/heretic_monster = summoned.mind.has_antag_datum(/datum/antagonist/heretic_monster)
+ var/datum/antagonist/heretic/master = user.mind.has_antag_datum(/datum/antagonist/heretic)
+ heretic_monster.set_owner(master)
+ return TRUE
+
+//Ascension knowledge
+/datum/eldritch_knowledge/final
+ var/finished = FALSE
+
+/datum/eldritch_knowledge/final/recipe_snowflake_check(list/atoms, loc,selected_atoms)
+ if(finished)
+ return FALSE
+ var/counter = 0
+ for(var/mob/living/carbon/human/H in atoms)
+ selected_atoms |= H
+ counter++
+ if(counter == 3)
+ return TRUE
+ return FALSE
+
+/datum/eldritch_knowledge/final/on_finished_recipe( mob/living/user, list/atoms, loc)
+ finished = TRUE
+ return TRUE
+
+/datum/eldritch_knowledge/final/cleanup_atoms(list/atoms)
+ . = ..()
+ for(var/mob/living/carbon/human/H in atoms)
+ atoms -= H
+ H.gib()
+
+
+///////////////
+///Base lore///
+///////////////
+
+/datum/eldritch_knowledge/spell/basic
+ name = "Break of Dawn"
+ desc = "Starts your journey in the mansus. Allows you to select a target using a living heart on a transmutation rune."
+ gain_text = "Gates of Mansus open up to your mind."
+ next_knowledge = list(/datum/eldritch_knowledge/base_rust,/datum/eldritch_knowledge/base_ash,/datum/eldritch_knowledge/base_flesh)
+ cost = 0
+ spell_to_add = /obj/effect/proc_holder/spell/targeted/touch/mansus_grasp
+ required_atoms = list(/obj/item/living_heart)
+ route = "Start"
+
+/datum/eldritch_knowledge/spell/basic/recipe_snowflake_check(list/atoms, loc)
+ . = ..()
+ for(var/obj/item/living_heart/LH in atoms)
+ if(!LH.target)
+ return TRUE
+ if(LH.target in atoms)
+ return TRUE
+ return FALSE
+
+/datum/eldritch_knowledge/spell/basic/on_finished_recipe(mob/living/user, list/atoms, loc)
+ . = TRUE
+ var/mob/living/carbon/carbon_user = user
+ for(var/obj/item/living_heart/LH in atoms)
+
+ if(LH.target && LH.target.stat == DEAD)
+ to_chat(carbon_user,"Your patrons accepts your offer...")
+ var/mob/living/carbon/human/H = LH.target
+ H.become_husk()
+ LH.target = null
+ var/datum/antagonist/heretic/EC = carbon_user.mind.has_antag_datum(/datum/antagonist/heretic)
+
+ EC.total_sacrifices++
+ for(var/X in carbon_user.get_all_gear())
+ if(!istype(X,/obj/item/forbidden_book))
+ continue
+ var/obj/item/forbidden_book/FB = X
+ FB.charge++
+ FB.charge++
+ break
+
+ if(!LH.target)
+ var/datum/objective/A = new
+ A.owner = user.mind
+ var/datum/mind/targeted = A.find_target()//easy way, i dont feel like copy pasting that entire block of code
+ LH.target = targeted.current
+ qdel(A)
+ if(LH.target)
+ to_chat(user,"Your new target has been selected, go and sacrifice [LH.target.real_name]!")
+
+ else
+ to_chat(user,"target could not be found for living heart.")
+
+/datum/eldritch_knowledge/spell/basic/cleanup_atoms(list/atoms)
+ return
+
+/datum/eldritch_knowledge/living_heart
+ name = "Living Heart"
+ desc = "Allows you to create additional living hearts, using a heart, a pool of blood and a poppy. Living hearts when used on a transmutation rune will grant you a person to hunt and sacrifice on the rune. Every sacrifice gives you an additional charge in the book."
+ gain_text = "Disconnected, yet it still beats."
+ cost = 0
+ required_atoms = list(/obj/item/organ/heart,/obj/effect/decal/cleanable/blood,/obj/item/reagent_containers/food/snacks/grown/poppy)
+ result_atoms = list(/obj/item/living_heart)
+ route = "Start"
+
+/datum/eldritch_knowledge/codex_cicatrix
+ name = "Codex Cicatrix"
+ desc = "Allows you to create a spare Codex Cicatrix if you have lost one, using a bible, human skin, a pen and a pair of eyes."
+ gain_text = "Their hands are at your throat, yet you see them not."
+ cost = 0
+ required_atoms = list(/obj/item/organ/eyes,/obj/item/stack/sheet/animalhide/human,/obj/item/storage/book/bible,/obj/item/pen)
+ result_atoms = list(/obj/item/forbidden_book)
+ route = "Start"
+
+/datum/eldritch_knowledge/eldritch_blade
+ name = "Eldritch Blade"
+ desc = "Allows you to create a sickly, eldritch blade by transmuting a glass shard and a metal rod atop a transmutation rune."
+ gain_text = "The first step starts with sacrifice."
+ cost = 0
+ required_atoms = list(/obj/item/shard,/obj/item/stack/rods)
+ result_atoms = list(/obj/item/melee/sickly_blade)
+ route = "Start"
diff --git a/code/modules/antagonists/eldritch_cult/eldritch_magic.dm b/code/modules/antagonists/eldritch_cult/eldritch_magic.dm
new file mode 100644
index 0000000000..d84a997e28
--- /dev/null
+++ b/code/modules/antagonists/eldritch_cult/eldritch_magic.dm
@@ -0,0 +1,668 @@
+/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash
+ name = "Ashen Passage"
+ desc = "Low range spell allowing you to pass through a few walls."
+ school = "transmutation"
+ invocation = "DULK'ES PRE'ZIMAS"
+ invocation_type = "whisper"
+ charge_max = 150
+ range = -1
+ action_icon = 'icons/mob/actions/actions_ecult.dmi'
+ action_icon_state = "ash_shift"
+ action_background_icon_state = "bg_ecult"
+ jaunt_in_time = 13
+ jaunt_duration = 10
+ jaunt_in_type = /obj/effect/temp_visual/dir_setting/ash_shift
+ jaunt_out_type = /obj/effect/temp_visual/dir_setting/ash_shift/out
+
+/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash/long
+ jaunt_duration = 50
+
+/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash/play_sound()
+ return
+
+/obj/effect/temp_visual/dir_setting/ash_shift
+ name = "ash_shift"
+ icon = 'icons/mob/mob.dmi'
+ icon_state = "ash_shift2"
+ duration = 13
+
+/obj/effect/temp_visual/dir_setting/ash_shift/out
+ icon_state = "ash_shift"
+
+/obj/effect/proc_holder/spell/targeted/touch/mansus_grasp
+ name = "Mansus Grasp"
+ desc = "Touch spell that allows you to channel the power of the Old Gods through you."
+ hand_path = /obj/item/melee/touch_attack/mansus_fist
+ school = "evocation"
+ charge_max = 150
+ clothes_req = FALSE
+ action_icon = 'icons/mob/actions/actions_ecult.dmi'
+ action_icon_state = "mansus_grasp"
+ action_background_icon_state = "bg_ecult"
+
+/obj/item/melee/touch_attack/mansus_fist
+ name = "Mansus Grasp"
+ desc = "A sinister looking aura that distorts the flow of reality around it. Causes knockdown, major stamina damage aswell as some Brute. It gains additional beneficial effects with certain knowledges you can research."
+ icon_state = "disintegrate"
+ item_state = "disintegrate"
+ catchphrase = "T'IESA SIE'KTI VISATA"
+
+/obj/item/melee/touch_attack/mansus_fist/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
+
+ if(!proximity_flag || target == user)
+ return
+ playsound(user, 'sound/items/welder.ogg', 75, TRUE)
+ if(ishuman(target))
+ var/mob/living/carbon/human/tar = target
+ if(tar.anti_magic_check())
+ tar.visible_message("Spell bounces off of [target]!","The spell bounces off of you!")
+ return ..()
+ var/datum/mind/M = user.mind
+ var/datum/antagonist/heretic/cultie = M.has_antag_datum(/datum/antagonist/heretic)
+
+ var/use_charge = FALSE
+ if(iscarbon(target))
+ use_charge = TRUE
+ var/mob/living/carbon/C = target
+ C.adjustBruteLoss(15)
+ C.DefaultCombatKnockdown(50, override_stamdmg = 0)
+ C.adjustStaminaLoss(60)
+ var/list/knowledge = cultie.get_all_knowledge()
+
+ for(var/X in knowledge)
+ var/datum/eldritch_knowledge/EK = knowledge[X]
+ if(EK.on_mansus_grasp(target, user, proximity_flag, click_parameters))
+ use_charge = TRUE
+ if(use_charge)
+ return ..()
+
+/obj/effect/proc_holder/spell/aoe_turf/rust_conversion
+ name = "Aggressive Spread"
+ desc = "Spreads rust onto nearby turfs."
+ school = "transmutation"
+ charge_max = 300 //twice as long as mansus grasp
+ clothes_req = FALSE
+ invocation = "PLI'STI MINO DOMI'KA"
+ invocation_type = "whisper"
+ range = 3
+ action_icon = 'icons/mob/actions/actions_ecult.dmi'
+ action_icon_state = "corrode"
+ action_background_icon_state = "bg_ecult"
+
+/obj/effect/proc_holder/spell/aoe_turf/rust_conversion/cast(list/targets, mob/user = usr)
+ playsound(user, 'sound/items/welder.ogg', 75, TRUE)
+ for(var/turf/T in targets)
+ ///What we want is the 3 tiles around the user and the tile under him to be rusted, so min(dist,1)-1 causes us to get 0 for these tiles, rest of the tiles are based on chance
+ var/chance = 100 - (max(get_dist(T,user),1)-1)*100/(range+1)
+ if(!prob(chance))
+ continue
+ T.rust_heretic_act()
+
+/obj/effect/proc_holder/spell/aoe_turf/rust_conversion/small
+ name = "Rust Conversion"
+ desc = "Spreads rust onto nearby turfs."
+ range = 2
+
+/obj/effect/proc_holder/spell/targeted/touch/blood_siphon
+ name = "Blood Siphon"
+ desc = "Touch spell that heals you while damaging the enemy, has a chance to transfer wounds between you and your enemy."
+ hand_path = /obj/item/melee/touch_attack/blood_siphon
+ school = "evocation"
+ charge_max = 150
+ clothes_req = FALSE
+ invocation_type = "none"
+ action_icon = 'icons/mob/actions/actions_ecult.dmi'
+ action_icon_state = "blood_siphon"
+ action_background_icon_state = "bg_ecult"
+
+/obj/item/melee/touch_attack/blood_siphon
+ name = "Blood Siphon"
+ desc = "A sinister looking aura that distorts the flow of reality around it."
+ icon_state = "disintegrate"
+ item_state = "disintegrate"
+ catchphrase = "SUN'AI'KINI'MAS"
+
+/obj/item/melee/touch_attack/blood_siphon/afterattack(atom/target, mob/user, proximity_flag, proximity)
+ if(!proximity_flag)
+ return
+ playsound(user, 'sound/effects/curseattack.ogg', 75, TRUE)
+ if(ishuman(target))
+ var/mob/living/carbon/human/tar = target
+ if(tar.anti_magic_check())
+ tar.visible_message("Spell bounces off of [target]!","The spell bounces off of you!")
+ return ..()
+ var/mob/living/carbon/C2 = user
+ if(isliving(target))
+ var/mob/living/L = target
+ L.adjustBruteLoss(20)
+ C2.adjustBruteLoss(-20)
+ if(iscarbon(target))
+ var/mob/living/carbon/C1 = target
+ for(var/obj/item/bodypart/bodypart in C2.bodyparts)
+ for(var/i in bodypart.wounds)
+ var/datum/wound/iter_wound = i
+ if(prob(50))
+ continue
+ var/obj/item/bodypart/target_bodypart = locate(bodypart.type) in C1.bodyparts
+ if(!target_bodypart)
+ continue
+ iter_wound.remove_wound()
+ iter_wound.apply_wound(target_bodypart)
+
+ C1.blood_volume -= 20
+ if(C2.blood_volume < BLOOD_VOLUME_MAXIMUM) //we dont want to explode after all
+ C2.blood_volume += 20
+ return ..()
+
+/obj/effect/proc_holder/spell/aimed/rust_wave
+ name = "Patron's Reach"
+ desc = "Channels energy into your gauntlet - firing it results in a wave of rust being created in it's wake."
+ projectile_type = /obj/item/projectile/magic/spell/rust_wave
+ charge_max = 350
+ clothes_req = FALSE
+ action_icon = 'icons/mob/actions/actions_ecult.dmi'
+ base_icon_state = "rust_wave"
+ action_icon_state = "rust_wave"
+ action_background_icon_state = "bg_ecult"
+ sound = 'sound/effects/curse5.ogg'
+ active_msg = "You extend your hand out, preparing to send out a wave of rust."
+ deactive_msg = "You extinguish that energy, for now..."
+ invocation = "RUD'ZI VAR'ZTAS"
+ invocation_type = "whisper"
+
+/obj/item/projectile/magic/spell/rust_wave
+ name = "rust bolt"
+ icon_state = "eldritch_projectile"
+ alpha = 180
+ damage = 30
+ damage_type = TOX
+ nodamage = 0
+ hitsound = 'sound/effects/curseattack.ogg'
+ range = 15
+
+/obj/item/projectile/magic/spell/rust_wave/Moved(atom/OldLoc, Dir)
+ . = ..()
+ playsound(src, 'sound/items/welder.ogg', 75, TRUE)
+ var/list/turflist = list()
+ var/turf/T1
+ turflist += get_turf(src)
+ T1 = get_step(src,turn(dir,90))
+ turflist += T1
+ turflist += get_step(T1,turn(dir,90))
+ T1 = get_step(src,turn(dir,-90))
+ turflist += T1
+ turflist += get_step(T1,turn(dir,-90))
+ for(var/X in turflist)
+ if(!X || prob(25))
+ continue
+ var/turf/T = X
+ T.rust_heretic_act()
+
+/obj/effect/proc_holder/spell/aimed/rust_wave/short
+ name = "Small Patron's Reach"
+ projectile_type = /obj/item/projectile/magic/spell/rust_wave/short
+
+/obj/item/projectile/magic/spell/rust_wave/short
+ range = 7
+
+/obj/effect/proc_holder/spell/pointed/cleave
+ name = "Cleave"
+ desc = "Causes severe bleeding on a target and people around them"
+ school = "transmutation"
+ charge_max = 350
+ clothes_req = FALSE
+ invocation = "PLES'TI VI'RIBUS"
+ invocation_type = "whisper"
+ range = 9
+ action_icon = 'icons/mob/actions/actions_ecult.dmi'
+ action_icon_state = "cleave"
+ action_background_icon_state = "bg_ecult"
+
+/obj/effect/proc_holder/spell/pointed/cleave/cast(list/targets, mob/user)
+ if(!targets.len)
+ to_chat(user, "No target found in range!")
+ return FALSE
+ if(!can_target(targets[1], user))
+ return FALSE
+
+ for(var/mob/living/carbon/human/C in range(1,targets[1]))
+ targets |= C
+
+
+ for(var/X in targets)
+ var/mob/living/carbon/human/target = X
+ if(target == user)
+ continue
+ if(target.anti_magic_check())
+ to_chat(user, "The spell had no effect!")
+ target.visible_message("[target]'s veins flash with fire, but their magic protection repulses the blaze!", \
+ "Your veins flash with fire, but your magic protection repels the blaze!")
+ continue
+
+ target.visible_message("[target]'s veins are shredded from within as an unholy blaze erupts from their blood!", \
+ "Your veins burst from within and unholy flame erupts from your blood!")
+ var/obj/item/bodypart/bodypart = pick(target.bodyparts)
+ var/datum/wound/slash/critical/crit_wound = new
+ crit_wound.apply_wound(bodypart)
+ target.adjustFireLoss(20)
+ new /obj/effect/temp_visual/cleave(target.drop_location())
+
+/obj/effect/proc_holder/spell/pointed/cleave/can_target(atom/target, mob/user, silent)
+ . = ..()
+ if(!.)
+ return FALSE
+ if(!istype(target,/mob/living/carbon/human))
+ if(!silent)
+ to_chat(user, "You are unable to cleave [target]!")
+ return FALSE
+ return TRUE
+
+/obj/effect/proc_holder/spell/pointed/cleave/long
+ charge_max = 650
+
+/obj/effect/proc_holder/spell/pointed/touch/mad_touch
+ name = "Touch of Madness"
+ desc = "Touch spell that drains your enemies sanity."
+ school = "transmutation"
+ charge_max = 150
+ clothes_req = FALSE
+ invocation_type = "none"
+ range = 2
+ action_icon = 'icons/mob/actions/actions_ecult.dmi'
+ action_icon_state = "mad_touch"
+ action_background_icon_state = "bg_ecult"
+
+/obj/effect/proc_holder/spell/pointed/touch/mad_touch/can_target(atom/target, mob/user, silent)
+ . = ..()
+ if(!.)
+ return FALSE
+ if(!istype(target,/mob/living/carbon/human))
+ if(!silent)
+ to_chat(user, "You are unable to touch [target]!")
+ return FALSE
+ return TRUE
+
+/obj/effect/proc_holder/spell/pointed/touch/mad_touch/cast(list/targets, mob/user)
+ . = ..()
+ for(var/mob/living/carbon/target in targets)
+ if(ishuman(targets))
+ var/mob/living/carbon/human/tar = target
+ if(tar.anti_magic_check())
+ tar.visible_message("Spell bounces off of [target]!","The spell bounces off of you!")
+ return
+ if(target.mind && !target.mind.has_antag_datum(/datum/antagonist/heretic))
+ to_chat(user,"[target.name] has been cursed!")
+ SEND_SIGNAL(target, COMSIG_ADD_MOOD_EVENT, "gates_of_mansus", /datum/mood_event/gates_of_mansus)
+
+/obj/effect/proc_holder/spell/pointed/ash_final
+ name = "Nightwatcher's Rite"
+ desc = "Powerful spell that releases 5 streams of fire away from you."
+ school = "transmutation"
+ invocation = "IGNIS'INTI"
+ invocation_type = "whisper"
+ charge_max = 300
+ range = 15
+ clothes_req = FALSE
+ action_icon = 'icons/mob/actions/actions_ecult.dmi'
+ action_icon_state = "flames"
+ action_background_icon_state = "bg_ecult"
+
+/obj/effect/proc_holder/spell/pointed/ash_final/cast(list/targets, mob/user)
+ for(var/X in targets)
+ var/T
+ T = line_target(-25, range, X, user)
+ INVOKE_ASYNC(src, .proc/fire_line, user,T)
+ T = line_target(10, range, X, user)
+ INVOKE_ASYNC(src, .proc/fire_line, user,T)
+ T = line_target(0, range, X, user)
+ INVOKE_ASYNC(src, .proc/fire_line, user,T)
+ T = line_target(-10, range, X, user)
+ INVOKE_ASYNC(src, .proc/fire_line, user,T)
+ T = line_target(25, range, X, user)
+ INVOKE_ASYNC(src, .proc/fire_line, user,T)
+ return ..()
+
+/obj/effect/proc_holder/spell/pointed/ash_final/proc/line_target(offset, range, atom/at , atom/user)
+ if(!at)
+ return
+ var/angle = ATAN2(at.x - user.x, at.y - user.y) + offset
+ var/turf/T = get_turf(user)
+ for(var/i in 1 to range)
+ var/turf/check = locate(user.x + cos(angle) * i, user.y + sin(angle) * i, user.z)
+ if(!check)
+ break
+ T = check
+ return (getline(user, T) - get_turf(user))
+
+/obj/effect/proc_holder/spell/pointed/ash_final/proc/fire_line(atom/source, list/turfs)
+ var/list/hit_list = list()
+ for(var/turf/T in turfs)
+ if(istype(T, /turf/closed))
+ break
+
+ for(var/mob/living/L in T.contents)
+ if(L.anti_magic_check())
+ L.visible_message("Spell bounces off of [L]!","The spell bounces off of you!")
+ continue
+ if(L in hit_list || L == source)
+ continue
+ hit_list += L
+ L.adjustFireLoss(20)
+ to_chat(L, "You're hit by [source]'s fire breath!")
+
+ new /obj/effect/hotspot(T)
+ T.hotspot_expose(700,50,1)
+ // deals damage to mechs
+ for(var/obj/mecha/M in T.contents)
+ if(M in hit_list)
+ continue
+ hit_list += M
+ M.take_damage(45, BURN, "melee", 1)
+ sleep(1.5)
+
+/obj/effect/proc_holder/spell/targeted/shapeshift/eldritch
+ invocation_type = "none"
+ clothes_req = FALSE
+ action_background_icon_state = "bg_ecult"
+ sound = 'sound/magic/enter_blood.ogg'
+ possible_shapes = list(/mob/living/simple_animal/mouse,\
+ /mob/living/simple_animal/pet/dog/corgi,\
+ /mob/living/simple_animal/hostile/carp,\
+ /mob/living/simple_animal/bot/secbot, \
+ /mob/living/simple_animal/pet/fox,\
+ /mob/living/simple_animal/pet/cat )
+
+/obj/effect/proc_holder/spell/targeted/emplosion/eldritch
+ name = "Energetic Pulse"
+ invocation_type = "none"
+ clothes_req = FALSE
+ action_background_icon_state = "bg_ecult"
+ range = -1
+ include_user = TRUE
+ charge_max = 300
+ emp_heavy = 6
+ emp_light = 10
+ sound = 'sound/effects/lingscreech.ogg'
+
+/obj/effect/proc_holder/spell/aoe_turf/fire_cascade
+ name = "Fire Cascade"
+ desc = "creates hot turfs around you."
+ school = "transmutation"
+ charge_max = 300 //twice as long as mansus grasp
+ clothes_req = FALSE
+ invocation = "IGNIS'SAVARIN"
+ invocation_type = "whisper"
+ range = 4
+ action_icon = 'icons/mob/actions/actions_ecult.dmi'
+ action_icon_state = "fire_ring"
+ action_background_icon_state = "bg_ecult"
+
+/obj/effect/proc_holder/spell/aoe_turf/fire_cascade/cast(list/targets, mob/user = usr)
+ INVOKE_ASYNC(src, .proc/fire_cascade, user,range)
+
+/obj/effect/proc_holder/spell/aoe_turf/fire_cascade/proc/fire_cascade(atom/centre,max_range)
+ playsound(get_turf(centre), 'sound/items/welder.ogg', 75, TRUE)
+ var/_range = 1
+ for(var/i = 0, i <= max_range,i++)
+ for(var/turf/T in spiral_range_turfs(_range,centre))
+ new /obj/effect/hotspot(T)
+ T.hotspot_expose(700,50,1)
+ for(var/mob/living/livies in T.contents - centre)
+ livies.adjustFireLoss(10)
+ _range++
+ sleep(3)
+
+/obj/effect/proc_holder/spell/aoe_turf/fire_cascade/big
+ range = 6
+
+/obj/effect/proc_holder/spell/targeted/telepathy/eldritch
+ invocation = ""
+ invocation_type = "whisper"
+ clothes_req = FALSE
+ action_background_icon_state = "bg_ecult"
+
+/obj/effect/proc_holder/spell/targeted/fire_sworn
+ name = "Oath of Fire"
+ desc = "For a minute you will passively create a ring of fire around you."
+ invocation = "IGNIS'AISTRA'LISTRE"
+ invocation_type = "whisper"
+ clothes_req = FALSE
+ action_background_icon_state = "bg_ecult"
+ range = -1
+ include_user = TRUE
+ charge_max = 700
+ action_icon = 'icons/mob/actions/actions_ecult.dmi'
+ action_icon_state = "fire_ring"
+ ///how long it lasts
+ var/duration = 1 MINUTES
+ ///who casted it right now
+ var/mob/current_user
+ ///Determines if you get the fire ring effect
+ var/has_fire_ring = FALSE
+
+/obj/effect/proc_holder/spell/targeted/fire_sworn/cast(list/targets, mob/user)
+ . = ..()
+ current_user = user
+ has_fire_ring = TRUE
+ addtimer(CALLBACK(src, .proc/remove, user), duration, TIMER_OVERRIDE|TIMER_UNIQUE)
+
+/obj/effect/proc_holder/spell/targeted/fire_sworn/proc/remove()
+ has_fire_ring = FALSE
+
+/obj/effect/proc_holder/spell/targeted/fire_sworn/process()
+ . = ..()
+ if(!has_fire_ring)
+ return
+ for(var/turf/T in range(1,current_user))
+ new /obj/effect/hotspot(T)
+ T.hotspot_expose(700,50,1)
+ for(var/mob/living/livies in T.contents - current_user)
+ livies.adjustFireLoss(5)
+
+
+/obj/effect/proc_holder/spell/targeted/worm_contract
+ name = "Force Contract"
+ desc = "Forces all the worm parts to collapse onto a single turf"
+ invocation_type = "none"
+ clothes_req = FALSE
+ action_background_icon_state = "bg_ecult"
+ range = -1
+ include_user = TRUE
+ charge_max = 300
+ action_icon = 'icons/mob/actions/actions_ecult.dmi'
+ action_icon_state = "worm_contract"
+
+/obj/effect/proc_holder/spell/targeted/worm_contract/cast(list/targets, mob/user)
+ . = ..()
+ if(!istype(user,/mob/living/simple_animal/hostile/eldritch/armsy))
+ to_chat(user, "You try to contract your muscles but nothing happens...")
+ var/mob/living/simple_animal/hostile/eldritch/armsy/armsy = user
+ armsy.contract_next_chain_into_single_tile()
+
+/obj/effect/temp_visual/cleave
+ icon = 'icons/effects/eldritch.dmi'
+ icon_state = "cleave"
+ duration = 6
+
+/obj/effect/temp_visual/eldritch_smoke
+ icon = 'icons/effects/eldritch.dmi'
+ icon_state = "smoke"
+ duration = 10
+
+/obj/effect/proc_holder/spell/targeted/fiery_rebirth
+ name = "Nightwatcher's Rebirth"
+ desc = "Drains nearby alive people that are engulfed in flames. It heals 10 of each damage type per person. If a person is in critical condition it finishes them off."
+ invocation = "PETHRO'MINO'IGNI"
+ invocation_type = "whisper"
+ clothes_req = FALSE
+ action_background_icon_state = "bg_ecult"
+ range = -1
+ include_user = TRUE
+ charge_max = 600
+ action_icon = 'icons/mob/actions/actions_ecult.dmi'
+ action_icon_state = "smoke"
+
+/obj/effect/proc_holder/spell/targeted/fiery_rebirth/cast(list/targets, mob/user)
+ if(!ishuman(user))
+ return
+ var/mob/living/carbon/human/human_user = user
+ for(var/mob/living/carbon/target in view(7,user))
+ if(target.stat == DEAD || !target.on_fire)
+ continue
+ //This is essentially a death mark, use this to finish your opponent quicker.
+ if(target.InCritical())
+ target.death()
+ target.adjustFireLoss(20)
+ new /obj/effect/temp_visual/eldritch_smoke(target.drop_location())
+ human_user.ExtinguishMob()
+ human_user.adjustBruteLoss(-10, FALSE)
+ human_user.adjustFireLoss(-10, FALSE)
+ human_user.adjustStaminaLoss(-10, FALSE)
+ human_user.adjustToxLoss(-10, FALSE)
+ human_user.adjustOxyLoss(-10)
+
+/obj/effect/proc_holder/spell/pointed/manse_link
+ name = "Mansus Link"
+ desc = "Piercing through reality, connecting minds. This spell allows you to add people to a mansus net, allowing them to communicate with eachother"
+ school = "transmutation"
+ charge_max = 300
+ clothes_req = FALSE
+ invocation = "SUSEI' METO MIN'TIS"
+ invocation_type = "whisper"
+ range = 10
+ action_icon = 'icons/mob/actions/actions_ecult.dmi'
+ action_icon_state = "mansus_link"
+ action_background_icon_state = "bg_ecult"
+
+/obj/effect/proc_holder/spell/pointed/manse_link/can_target(atom/target, mob/user, silent)
+ if(!isliving(target))
+ return FALSE
+ return TRUE
+
+/obj/effect/proc_holder/spell/pointed/manse_link/cast(list/targets, mob/user)
+ var/mob/living/simple_animal/hostile/eldritch/raw_prophet/originator = user
+
+ var/mob/living/target = targets[1]
+
+ to_chat(originator, "You begin linking [target]'s mind to yours...")
+ to_chat(target, "You feel your mind being pulled... connected... intertwined with the very fabric of reality...")
+ if(!do_after(originator, 6 SECONDS, target))
+ return
+ if(!originator.link_mob(target))
+ to_chat(originator, "You can't seem to link [target]'s mind...")
+ to_chat(target, "The foreign presence leaves your mind.")
+ return
+ to_chat(originator, "You connect [target]'s mind to your mansus link!")
+
+
+/datum/action/innate/mansus_speech
+ name = "Mansus Link"
+ desc = "Send a psychic message to everyone connected to your mansus link."
+ button_icon_state = "link_speech"
+ icon_icon = 'icons/mob/actions/actions_slime.dmi'
+ background_icon_state = "bg_ecult"
+ var/mob/living/simple_animal/hostile/eldritch/raw_prophet/originator
+
+/datum/action/innate/mansus_speech/New(_originator)
+ . = ..()
+ originator = _originator
+
+/datum/action/innate/mansus_speech/Activate()
+ var/mob/living/living_owner = owner
+ if(!originator?.linked_mobs[living_owner])
+ CRASH("Uh oh the mansus link got somehow activated without it being linked to a raw prophet or the mob not being in a list of mobs that should be able to do it.")
+
+ var/message = sanitize(input("Message:", "Telepathy from the Manse") as text|null)
+
+ if(QDELETED(living_owner))
+ return
+
+ if(!originator?.linked_mobs[living_owner])
+ to_chat(living_owner, "The link seems to have been severed...")
+ Remove(living_owner)
+ return
+ if(message)
+ var/msg = "\[Mansus Link\] [living_owner]: [message]"
+ log_directed_talk(living_owner, originator, msg, LOG_SAY, "Mansus Link")
+ to_chat(originator.linked_mobs, msg)
+
+ for(var/dead_mob in GLOB.dead_mob_list)
+ var/link = FOLLOW_LINK(dead_mob, living_owner)
+ to_chat(dead_mob, "[link] [msg]")
+
+/obj/effect/proc_holder/spell/pointed/trigger/blind/eldritch
+ range = 10
+ invocation = "AK'LIS"
+ action_background_icon_state = "bg_ecult"
+
+/obj/effect/temp_visual/dir_setting/entropic
+ icon = 'icons/effects/160x160.dmi'
+ icon_state = "entropic_plume"
+ duration = 3 SECONDS
+
+/obj/effect/temp_visual/dir_setting/entropic/setDir(dir)
+ . = ..()
+ switch(dir)
+ if(NORTH)
+ pixel_x = -64
+ if(SOUTH)
+ pixel_x = -64
+ pixel_y = -128
+ if(EAST)
+ pixel_y = -64
+ if(WEST)
+ pixel_y = -64
+ pixel_x = -128
+
+/obj/effect/temp_visual/glowing_rune
+ icon = 'icons/effects/eldritch.dmi'
+ icon_state = "small_rune_1"
+ duration = 1 MINUTES
+ layer = LOW_SIGIL_LAYER
+
+/obj/effect/temp_visual/glowing_rune/Initialize()
+ . = ..()
+ pixel_y = rand(-6,6)
+ pixel_x = rand(-6,6)
+ icon_state = "small_rune_[rand(12)]"
+ update_icon()
+
+/obj/effect/proc_holder/spell/cone/staggered/entropic_plume
+ name = "Entropic Plume"
+ desc = "Spews forth a disorienting plume that causes enemies to strike each other, briefly blinds them(increasing with range) and poisons them(decreasing with range). Also spreads rust in the path of the plume."
+ school = "illusion"
+ invocation = "RU'KAS NU'DYTI"
+ invocation_type = "whisper"
+ clothes_req = FALSE
+ action_background_icon_state = "bg_ecult"
+ action_icon = 'icons/mob/actions/actions_ecult.dmi'
+ action_icon_state = "entropic_plume"
+ charge_max = 300
+ cone_levels = 5
+ respect_density = TRUE
+
+/obj/effect/proc_holder/spell/cone/staggered/entropic_plume/cast(list/targets,mob/user = usr)
+ . = ..()
+ new /obj/effect/temp_visual/dir_setting/entropic(get_step(user,user.dir), user.dir)
+
+/obj/effect/proc_holder/spell/cone/staggered/entropic_plume/do_turf_cone_effect(turf/target_turf, level)
+ . = ..()
+ target_turf.rust_heretic_act()
+
+/obj/effect/proc_holder/spell/cone/staggered/entropic_plume/do_mob_cone_effect(mob/living/victim, level)
+ . = ..()
+ if(victim.anti_magic_check() || IS_HERETIC(victim) || victim.mind?.has_antag_datum(/datum/antagonist/heretic_monster))
+ return
+ victim.apply_status_effect(STATUS_EFFECT_AMOK)
+ victim.apply_status_effect(STATUS_EFFECT_CLOUDSTRUCK, (level*10))
+ if(iscarbon(victim))
+ var/mob/living/carbon/carbon_victim = victim
+ carbon_victim.reagents.add_reagent(/datum/reagent/eldritch, min(1, 6-level))
+
+/obj/effect/proc_holder/spell/cone/staggered/entropic_plume/calculate_cone_shape(current_level)
+ if(current_level == cone_levels)
+ return 5
+ else if(current_level == cone_levels-1)
+ return 3
+ else
+ return 2
diff --git a/code/modules/antagonists/eldritch_cult/eldritch_monster_antag.dm b/code/modules/antagonists/eldritch_cult/eldritch_monster_antag.dm
new file mode 100644
index 0000000000..529128fc0a
--- /dev/null
+++ b/code/modules/antagonists/eldritch_cult/eldritch_monster_antag.dm
@@ -0,0 +1,43 @@
+///Tracking reasons
+/datum/antagonist/heretic_monster
+ name = "Eldritch Horror"
+ roundend_category = "Heretics"
+ antagpanel_category = "Heretic Beast"
+ antag_moodlet = /datum/mood_event/heretics
+ job_rank = ROLE_HERETIC
+ antag_hud_type = ANTAG_HUD_HERETIC
+ antag_hud_name = "heretic_beast"
+ var/datum/antagonist/master
+
+/datum/antagonist/heretic_monster/admin_add(datum/mind/new_owner,mob/admin)
+ new_owner.add_antag_datum(src)
+ message_admins("[key_name_admin(admin)] has heresized [key_name_admin(new_owner)].")
+ log_admin("[key_name(admin)] has heresized [key_name(new_owner)].")
+
+/datum/antagonist/heretic_monster/greet()
+ owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ecult_op.ogg', 100, FALSE, pressure_affected = FALSE)//subject to change
+ to_chat(owner, "You became an Eldritch Horror!")
+
+/datum/antagonist/heretic_monster/on_removal()
+ if(owner)
+ to_chat(owner, "Your master is no longer [master.owner.current.real_name]")
+ owner = null
+ return ..()
+
+/datum/antagonist/heretic_monster/proc/set_owner(datum/antagonist/_master)
+ master = _master
+ var/datum/objective/master_obj = new
+ master_obj.owner = src
+ master_obj.explanation_text = "Assist your master in any way you can!"
+ objectives += master_obj
+ owner.announce_objectives()
+ to_chat(owner, "Your master is [master.owner.current.real_name]")
+ return
+
+/datum/antagonist/heretic_monster/apply_innate_effects(mob/living/mob_override)
+ . = ..()
+ add_antag_hud(antag_hud_type, antag_hud_name, owner.current)
+
+/datum/antagonist/heretic_monster/remove_innate_effects(mob/living/mob_override)
+ . = ..()
+ remove_antag_hud(antag_hud_type, owner.current)
diff --git a/code/modules/antagonists/eldritch_cult/knowledge/ash_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/ash_lore.dm
new file mode 100644
index 0000000000..8efd9837a9
--- /dev/null
+++ b/code/modules/antagonists/eldritch_cult/knowledge/ash_lore.dm
@@ -0,0 +1,183 @@
+/datum/eldritch_knowledge/base_ash
+ name = "Nightwatcher's Secret"
+ desc = "Inducts you into the Path of Ash. Allows you to transmute a match with an eldritch blade into an ashen blade."
+ gain_text = "The City guard knows their watch. If you ask them at night they may tell you about the ashy lantern."
+ banned_knowledge = list(/datum/eldritch_knowledge/base_rust,/datum/eldritch_knowledge/base_flesh,/datum/eldritch_knowledge/final/rust_final,/datum/eldritch_knowledge/final/flesh_final)
+ next_knowledge = list(/datum/eldritch_knowledge/ashen_grasp)
+ required_atoms = list(/obj/item/melee/sickly_blade,/obj/item/match)
+ result_atoms = list(/obj/item/melee/sickly_blade/ash)
+ cost = 1
+ route = PATH_ASH
+
+/datum/eldritch_knowledge/spell/ashen_shift
+ name = "Ashen Shift"
+ gain_text = "Ash is all the same, how can one man master it all?"
+ desc = "A short range jaunt that will enable you to escape from danger."
+ cost = 1
+ spell_to_add = /obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash
+ next_knowledge = list(/datum/eldritch_knowledge/ash_mark,/datum/eldritch_knowledge/essence,/datum/eldritch_knowledge/ashen_eyes)
+ route = PATH_ASH
+
+/datum/eldritch_knowledge/ashen_grasp
+ name = "Grasp of Ash"
+ gain_text = "Gates have opened, minds have flooded, yet I remain."
+ desc = "Empowers your mansus grasp to knock enemies down and throw them away."
+ cost = 1
+ next_knowledge = list(/datum/eldritch_knowledge/spell/ashen_shift)
+ route = PATH_ASH
+
+/datum/eldritch_knowledge/ashen_grasp/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters)
+ . = ..()
+ if(!iscarbon(target))
+ return
+
+ var/mob/living/carbon/C = target
+ var/datum/status_effect/eldritch/E = C.has_status_effect(/datum/status_effect/eldritch/rust) || C.has_status_effect(/datum/status_effect/eldritch/ash) || C.has_status_effect(/datum/status_effect/eldritch/flesh)
+ if(E)
+ . = TRUE
+ E.on_effect()
+ for(var/X in user.mind.spell_list)
+ if(!istype(X,/obj/effect/proc_holder/spell/targeted/touch/mansus_grasp))
+ continue
+ var/obj/effect/proc_holder/spell/targeted/touch/mansus_grasp/MG = X
+ MG.charge_counter = min(round(MG.charge_counter + MG.charge_max * 0.75),MG.charge_max) // refunds 75% of charge.
+ var/atom/throw_target = get_edge_target_turf(C, user.dir)
+ if(!C.anchored)
+ . = TRUE
+ C.throw_at(throw_target, rand(4,8), 14, user)
+ return
+
+/datum/eldritch_knowledge/ashen_eyes
+ name = "Ashen Eyes"
+ gain_text = "Piercing eyes may guide me through the mundane."
+ desc = "Allows you to craft thermal vision amulet by transmutating eyes with a glass shard."
+ cost = 1
+ next_knowledge = list(/datum/eldritch_knowledge/spell/ashen_shift,/datum/eldritch_knowledge/flesh_ghoul)
+ required_atoms = list(/obj/item/organ/eyes,/obj/item/shard)
+ result_atoms = list(/obj/item/clothing/neck/eldritch_amulet)
+
+/datum/eldritch_knowledge/ash_mark
+ name = "Mark of Ash"
+ gain_text = "Spread the famine."
+ desc = "Your sickly blade now applies ash mark on hit. Use your mansus grasp to proc the mark. Mark of Ash causes stamina damage, and fire loss, and spreads to a nearby carbon. Damage decreases with how many times the mark has spread."
+ cost = 2
+ next_knowledge = list(/datum/eldritch_knowledge/curse/blindness)
+ banned_knowledge = list(/datum/eldritch_knowledge/rust_mark,/datum/eldritch_knowledge/flesh_mark)
+ route = PATH_ASH
+
+/datum/eldritch_knowledge/ash_mark/on_eldritch_blade(target,user,proximity_flag,click_parameters)
+ . = ..()
+ if(isliving(target))
+ var/mob/living/living_target = target
+ living_target.apply_status_effect(/datum/status_effect/eldritch/ash,5)
+
+/datum/eldritch_knowledge/curse/blindness
+ name = "Curse of Blindness"
+ gain_text = "The blind man walks through the world, unnoticed by the masses."
+ desc = "Curse someone with 2 minutes of complete blindness by sacrificing a pair of eyes, a screwdriver and a pool of blood, with an object that the victim has touched with their bare hands."
+ cost = 1
+ required_atoms = list(/obj/item/organ/eyes,/obj/item/screwdriver,/obj/effect/decal/cleanable/blood)
+ next_knowledge = list(/datum/eldritch_knowledge/curse/corrosion,/datum/eldritch_knowledge/ash_blade_upgrade,/datum/eldritch_knowledge/curse/paralysis)
+ timer = 2 MINUTES
+ route = PATH_ASH
+
+/datum/eldritch_knowledge/curse/blindness/curse(mob/living/chosen_mob)
+ . = ..()
+ chosen_mob.become_blind(MAGIC_TRAIT)
+
+/datum/eldritch_knowledge/curse/blindness/uncurse(mob/living/chosen_mob)
+ . = ..()
+ chosen_mob.cure_blind(MAGIC_TRAIT)
+
+/datum/eldritch_knowledge/spell/flame_birth
+ name = "Fiery Rebirth"
+ gain_text = "Nightwatcher was a man of principles, and yet he arose from the chaos he vowed to protect from."
+ desc = "Drains nearby alive people that are engulfed in flames. It heals 10 of each damage type per person. If a person is in critical condition it finishes them off."
+ cost = 1
+ spell_to_add = /obj/effect/proc_holder/spell/targeted/fiery_rebirth
+ next_knowledge = list(/datum/eldritch_knowledge/spell/cleave,/datum/eldritch_knowledge/summon/ashy,/datum/eldritch_knowledge/final/ash_final)
+ route = PATH_ASH
+
+/datum/eldritch_knowledge/ash_blade_upgrade
+ name = "Blazing Steel"
+ gain_text = "May the sun burn the heretics."
+ desc = "Your blade of choice will now add firestacks."
+ cost = 2
+ next_knowledge = list(/datum/eldritch_knowledge/spell/flame_birth)
+ banned_knowledge = list(/datum/eldritch_knowledge/rust_blade_upgrade,/datum/eldritch_knowledge/flesh_blade_upgrade)
+ route = PATH_ASH
+
+/datum/eldritch_knowledge/ash_blade_upgrade/on_eldritch_blade(target,user,proximity_flag,click_parameters)
+ . = ..()
+ if(iscarbon(target))
+ var/mob/living/carbon/C = target
+ C.adjust_fire_stacks(1)
+ C.IgniteMob()
+
+/datum/eldritch_knowledge/curse/corrosion
+ name = "Curse of Corrosion"
+ gain_text = "Cursed land, cursed man, cursed mind."
+ desc = "Curse someone for 2 minutes of vomiting and major organ damage. Using a wirecutter, a spill of blood, a heart, left arm and a right arm, and an item that the victim touched with their bare hands."
+ cost = 1
+ required_atoms = list(/obj/item/wirecutters,/obj/effect/decal/cleanable/blood,/obj/item/organ/heart,/obj/item/bodypart/l_arm,/obj/item/bodypart/r_arm)
+ next_knowledge = list(/datum/eldritch_knowledge/curse/blindness,/datum/eldritch_knowledge/spell/area_conversion)
+ timer = 2 MINUTES
+
+/datum/eldritch_knowledge/curse/corrosion/curse(mob/living/chosen_mob)
+ . = ..()
+ chosen_mob.apply_status_effect(/datum/status_effect/corrosion_curse)
+
+/datum/eldritch_knowledge/curse/corrosion/uncurse(mob/living/chosen_mob)
+ . = ..()
+ chosen_mob.remove_status_effect(/datum/status_effect/corrosion_curse)
+
+/datum/eldritch_knowledge/curse/paralysis
+ name = "Curse of Paralysis"
+ gain_text = "Corrupt their flesh, make them bleed."
+ desc = "Curse someone for 5 minutes of inability to walk. Using a knife, pool of blood, left leg, right leg, a hatchet and an item that the victim touched with their bare hands. "
+ cost = 1
+ required_atoms = list(/obj/item/kitchen/knife,/obj/effect/decal/cleanable/blood,/obj/item/bodypart/l_leg,/obj/item/bodypart/r_leg,/obj/item/hatchet)
+ next_knowledge = list(/datum/eldritch_knowledge/curse/blindness,/datum/eldritch_knowledge/summon/raw_prophet)
+ timer = 5 MINUTES
+
+/datum/eldritch_knowledge/curse/paralysis/curse(mob/living/chosen_mob)
+ . = ..()
+ ADD_TRAIT(chosen_mob,TRAIT_PARALYSIS_L_LEG,MAGIC_TRAIT)
+ ADD_TRAIT(chosen_mob,TRAIT_PARALYSIS_R_LEG,MAGIC_TRAIT)
+ chosen_mob.update_mobility()
+
+/datum/eldritch_knowledge/curse/paralysis/uncurse(mob/living/chosen_mob)
+ . = ..()
+ REMOVE_TRAIT(chosen_mob,TRAIT_PARALYSIS_L_LEG,MAGIC_TRAIT)
+ REMOVE_TRAIT(chosen_mob,TRAIT_PARALYSIS_R_LEG,MAGIC_TRAIT)
+ chosen_mob.update_mobility()
+
+/datum/eldritch_knowledge/spell/cleave
+ name = "Blood Cleave"
+ gain_text = "At first I was unfamiliar with these instruments of war, but the priest told me how to use them."
+ desc = "Grants a spell that will inflict wounds and bleeding upon the target, as well as in a short radius around them."
+ cost = 1
+ spell_to_add = /obj/effect/proc_holder/spell/pointed/cleave
+ next_knowledge = list(/datum/eldritch_knowledge/spell/entropic_plume,/datum/eldritch_knowledge/spell/flame_birth)
+
+/datum/eldritch_knowledge/final/ash_final
+ name = "Ashlord's Rite"
+ gain_text = "The forgotten lords have spoken! The Lord of Ash has come! Fear the flame!"
+ desc = "Bring three corpses onto a transmutation rune, after ascending you will become immune to fire, space, temperature and other environmental hazards. You will develop resistance to all other damages. You will be granted two spells, one which can bring forth a cascade of massive fire, and another which will surround your body in precious flames for a minute."
+ required_atoms = list(/mob/living/carbon/human)
+ cost = 5
+ route = PATH_ASH
+ var/list/trait_list = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_RADIMMUNE,TRAIT_GENELESS,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_BOMBIMMUNE)
+
+/datum/eldritch_knowledge/final/ash_final/on_finished_recipe(mob/living/user, list/atoms, loc)
+ priority_announce("$^@*$^@(#&$(@^$^@# Fear the blaze, for Ashbringer [user.real_name] has come! $^@*$^@(#&$(@^$^@#","#$^@*$^@(#&$(@^$^@#", 'sound/announcer/classic/spanomalies.ogg')
+ user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/fire_cascade/big)
+ user.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/fire_sworn)
+ var/mob/living/carbon/human/H = user
+ H.physiology.brute_mod *= 0.5
+ H.physiology.burn_mod *= 0.5
+ var/datum/antagonist/heretic/ascension = H.mind.has_antag_datum(/datum/antagonist/heretic)
+ ascension.ascended = TRUE
+ for(var/X in trait_list)
+ ADD_TRAIT(user,X,MAGIC_TRAIT)
+ return ..()
diff --git a/code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm
new file mode 100644
index 0000000000..9684e1fa0c
--- /dev/null
+++ b/code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm
@@ -0,0 +1,252 @@
+/datum/eldritch_knowledge/base_flesh
+ name = "Principle of Hunger"
+ desc = "Inducts you into the Path of Flesh. Allows you to transmute a pool of blood with your eldritch blade into a Blade of Flesh."
+ gain_text = "Hundred's of us starved, but I.. I found the strength in my greed."
+ banned_knowledge = list(/datum/eldritch_knowledge/base_ash,/datum/eldritch_knowledge/base_rust,/datum/eldritch_knowledge/final/ash_final,/datum/eldritch_knowledge/final/rust_final)
+ next_knowledge = list(/datum/eldritch_knowledge/flesh_grasp)
+ required_atoms = list(/obj/item/melee/sickly_blade,/obj/effect/decal/cleanable/blood)
+ result_atoms = list(/obj/item/melee/sickly_blade/flesh)
+ cost = 1
+ route = PATH_FLESH
+
+/datum/eldritch_knowledge/flesh_ghoul
+ name = "Imperfect Ritual"
+ desc = "Allows you to resurrect the dead as voiceless dead by sacrificing them on the transmutation rune with a poppy. Voiceless dead are mute and have 50 HP. You can only have 2 at a time."
+ gain_text = "I found notes... notes of a ritual, scraps, unfinished, and yet... I still did it."
+ cost = 1
+ required_atoms = list(/mob/living/carbon/human,/obj/item/reagent_containers/food/snacks/grown/poppy)
+ next_knowledge = list(/datum/eldritch_knowledge/flesh_mark,/datum/eldritch_knowledge/armor,/datum/eldritch_knowledge/ashen_eyes)
+ route = PATH_FLESH
+ var/max_amt = 2
+ var/current_amt = 0
+ var/list/ghouls = list()
+
+/datum/eldritch_knowledge/flesh_ghoul/on_finished_recipe(mob/living/user,list/atoms,loc)
+ var/mob/living/carbon/human/humie = locate() in atoms
+ if(QDELETED(humie) || humie.stat != DEAD)
+ return
+
+ if(length(ghouls) >= max_amt)
+ return
+
+ if(HAS_TRAIT(humie,TRAIT_HUSK))
+ return
+
+ humie.grab_ghost()
+
+ if(!humie.mind || !humie.client)
+ var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [humie.real_name], a voiceless dead.", ROLE_HERETIC, null, ROLE_HERETIC, 50,humie)
+ if(!LAZYLEN(candidates))
+ return
+ var/mob/dead/observer/C = pick(candidates)
+ message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(humie)]) to replace an AFK player.")
+ humie.ghostize(0)
+ humie.key = C.key
+
+ ADD_TRAIT(humie,TRAIT_MUTE,MAGIC_TRAIT)
+ log_game("[key_name_admin(humie)] has become a voiceless dead, their master is [user.real_name]")
+ humie.revive(full_heal = TRUE, admin_revive = TRUE)
+ humie.setMaxHealth(75)
+ humie.health = 75 // Voiceless dead are much tougher than ghouls
+ humie.become_husk()
+ humie.faction |= "heretics"
+
+ var/datum/antagonist/heretic_monster/heretic_monster = humie.mind.add_antag_datum(/datum/antagonist/heretic_monster)
+ var/datum/antagonist/heretic/master = user.mind.has_antag_datum(/datum/antagonist/heretic)
+ heretic_monster.set_owner(master)
+ atoms -= humie
+ RegisterSignal(humie,COMSIG_MOB_DEATH,.proc/remove_ghoul)
+ ghouls += humie
+
+/datum/eldritch_knowledge/flesh_ghoul/proc/remove_ghoul(datum/source)
+ var/mob/living/carbon/human/humie = source
+ ghouls -= humie
+ humie.mind.remove_antag_datum(/datum/antagonist/heretic_monster)
+ UnregisterSignal(source,COMSIG_MOB_DEATH)
+
+/datum/eldritch_knowledge/flesh_grasp
+ name = "Grasp of Flesh"
+ gain_text = "'My newfound desire, it drove me to do great things,' The Priest said."
+ desc = "Empowers your Mansus Grasp to be able to create a single ghoul out of a dead player. You cannot raise the same person twice. Ghouls have only 50 HP and look like husks."
+ cost = 1
+ next_knowledge = list(/datum/eldritch_knowledge/flesh_ghoul)
+ var/ghoul_amt = 6
+ var/list/spooky_scaries
+ route = PATH_FLESH
+
+/datum/eldritch_knowledge/flesh_grasp/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters)
+ . = ..()
+ if(!ishuman(target) || target == user)
+ return
+ var/mob/living/carbon/human/human_target = target
+ var/datum/status_effect/eldritch/eldritch_effect = human_target.has_status_effect(/datum/status_effect/eldritch/rust) || human_target.has_status_effect(/datum/status_effect/eldritch/ash) || human_target.has_status_effect(/datum/status_effect/eldritch/flesh)
+ if(eldritch_effect)
+ . = TRUE
+ eldritch_effect.on_effect()
+ if(iscarbon(target))
+ var/mob/living/carbon/carbon_target = target
+ var/obj/item/bodypart/bodypart = pick(carbon_target.bodyparts)
+ var/datum/wound/slash/severe/crit_wound = new
+ crit_wound.apply_wound(bodypart)
+
+ if(QDELETED(human_target) || human_target.stat != DEAD)
+ return
+
+ human_target.grab_ghost()
+
+ if(!human_target.mind || !human_target.client)
+ to_chat(user, "There is no soul connected to this body...")
+ return
+
+ if(HAS_TRAIT(human_target, TRAIT_HUSK))
+ to_chat(user, "You cannot revive a dead ghoul!")
+ return
+
+ if(LAZYLEN(spooky_scaries) >= ghoul_amt)
+ to_chat(user, "Your patron cannot support more ghouls on this plane!")
+ return
+
+ LAZYADD(spooky_scaries, human_target)
+ log_game("[key_name_admin(human_target)] has become a ghoul, their master is [user.real_name]")
+ //we change it to true only after we know they passed all the checks
+ . = TRUE
+ RegisterSignal(human_target,COMSIG_MOB_DEATH,.proc/remove_ghoul)
+ human_target.revive(full_heal = TRUE, admin_revive = TRUE)
+ human_target.setMaxHealth(40)
+ human_target.health = 40
+ human_target.become_husk()
+ human_target.faction |= "heretics"
+ var/datum/antagonist/heretic_monster/heretic_monster = human_target.mind.add_antag_datum(/datum/antagonist/heretic_monster)
+ var/datum/antagonist/heretic/master = user.mind.has_antag_datum(/datum/antagonist/heretic)
+ heretic_monster.set_owner(master)
+ return
+
+
+/datum/eldritch_knowledge/flesh_grasp/proc/remove_ghoul(datum/source)
+ var/mob/living/carbon/human/humie = source
+ spooky_scaries -= humie
+ humie.mind.remove_antag_datum(/datum/antagonist/heretic_monster)
+ UnregisterSignal(source, COMSIG_MOB_DEATH)
+
+/datum/eldritch_knowledge/flesh_mark
+ name = "Mark of Flesh"
+ gain_text = "I saw them, the marked ones. The screams... the silence."
+ desc = "Your sickly blade now applies a mark of flesh to those cut by it. Once marked, using your Mansus Grasp upon them will cause additional bleeding from the target."
+ cost = 2
+ next_knowledge = list(/datum/eldritch_knowledge/summon/raw_prophet)
+ banned_knowledge = list(/datum/eldritch_knowledge/rust_mark,/datum/eldritch_knowledge/ash_mark)
+ route = PATH_FLESH
+
+/datum/eldritch_knowledge/flesh_mark/on_eldritch_blade(target,user,proximity_flag,click_parameters)
+ . = ..()
+ if(isliving(target))
+ var/mob/living/living_target = target
+ living_target.apply_status_effect(/datum/status_effect/eldritch/flesh)
+
+/datum/eldritch_knowledge/flesh_blade_upgrade
+ name = "Bleeding Steel"
+ gain_text = "It rained blood, that's when I understood the gravekeeper's advice."
+ desc = "Your blade will now cause additional bleeding to those hit by it."
+ cost = 2
+ next_knowledge = list(/datum/eldritch_knowledge/summon/stalker)
+ banned_knowledge = list(/datum/eldritch_knowledge/ash_blade_upgrade,/datum/eldritch_knowledge/rust_blade_upgrade)
+ route = PATH_FLESH
+
+/datum/eldritch_knowledge/flesh_blade_upgrade/on_eldritch_blade(target,user,proximity_flag,click_parameters)
+ . = ..()
+ if(iscarbon(target))
+ var/mob/living/carbon/carbon_target = target
+ var/obj/item/bodypart/bodypart = pick(carbon_target.bodyparts)
+ var/datum/wound/slash/severe/crit_wound = new
+ crit_wound.apply_wound(bodypart)
+
+/datum/eldritch_knowledge/summon/raw_prophet
+ name = "Raw Ritual"
+ gain_text = "The uncanny man walks alone in the valley, I was able to call his aid."
+ desc = "You can now summon a Raw Prophet using eyes, a left arm, right arm and a pool of blood using a transmutation circle. Raw prophets have increased seeing range, and can see through walls. They can jaunt long distances, though they are fragile."
+ cost = 1
+ required_atoms = list(/obj/item/organ/eyes,/obj/item/bodypart/l_arm,/obj/item/bodypart/r_arm,/obj/effect/decal/cleanable/blood)
+ mob_to_summon = /mob/living/simple_animal/hostile/eldritch/raw_prophet
+ next_knowledge = list(/datum/eldritch_knowledge/flesh_blade_upgrade,/datum/eldritch_knowledge/spell/blood_siphon,/datum/eldritch_knowledge/curse/paralysis)
+ route = PATH_FLESH
+
+/datum/eldritch_knowledge/summon/stalker
+ name = "Lonely Ritual"
+ gain_text = "I was able to combine my greed and desires to summon an eldritch beast I have not seen before."
+ desc = "You can now summon a Stalker using a knife, a flower, a pen and a piece of paper using a transmutation circle. Stalkers possess the ability to shapeshift into various forms while assuming the vigor and powers of that form."
+ cost = 1
+ required_atoms = list(/obj/item/kitchen/knife,/obj/item/reagent_containers/food/snacks/grown/poppy,/obj/item/pen,/obj/item/paper)
+ mob_to_summon = /mob/living/simple_animal/hostile/eldritch/stalker
+ next_knowledge = list(/datum/eldritch_knowledge/summon/ashy,/datum/eldritch_knowledge/summon/rusty,/datum/eldritch_knowledge/final/flesh_final)
+ route = PATH_FLESH
+
+/datum/eldritch_knowledge/summon/ashy
+ name = "Ashen Ritual"
+ gain_text = "I combined principle of hunger with desire of destruction. The eyeful lords have noticed me."
+ desc = "You can now summon an Ashen One by transmuting a pile of ash, a head and a book using a transmutation circle. They possess the ability to jaunt short distances and create a cascade of flames."
+ cost = 1
+ required_atoms = list(/obj/effect/decal/cleanable/ash,/obj/item/bodypart/head,/obj/item/book)
+ mob_to_summon = /mob/living/simple_animal/hostile/eldritch/ash_spirit
+ next_knowledge = list(/datum/eldritch_knowledge/summon/stalker,/datum/eldritch_knowledge/spell/flame_birth)
+
+/datum/eldritch_knowledge/summon/rusty
+ name = "Rusted Ritual"
+ gain_text = "I combined principle of hunger with desire of corruption. The rusted hills call my name."
+ desc = "You can now summon a Rust Walker transmuting a vomit pool, a head, and a book using a transmutation circle. Rust Walkers possess the ability to spread rust and can fire bolts of rust to further corrode the area."
+ cost = 1
+ required_atoms = list(/obj/effect/decal/cleanable/vomit,/obj/item/bodypart/head,/obj/item/book)
+ mob_to_summon = /mob/living/simple_animal/hostile/eldritch/rust_spirit
+ next_knowledge = list(/datum/eldritch_knowledge/summon/stalker,/datum/eldritch_knowledge/spell/entropic_plume)
+
+/datum/eldritch_knowledge/spell/blood_siphon
+ name = "Blood Siphon"
+ gain_text = "Our blood is all the same after all, the owl told me."
+ desc = "You are granted a spell that drains some of the targets health, and returns it to you. It also has a chance to transfer any wounds you possess onto the target."
+ cost = 1
+ spell_to_add = /obj/effect/proc_holder/spell/targeted/touch/blood_siphon
+ next_knowledge = list(/datum/eldritch_knowledge/summon/raw_prophet,/datum/eldritch_knowledge/spell/area_conversion)
+
+/datum/eldritch_knowledge/final/flesh_final
+ name = "Priest's Final Hymn"
+ gain_text = "Man of this world. Hear me! For the time of the lord of arms has come!"
+ desc = "Bring three corpses to a transmutation rune to either ascend as The Lord of the Night or summon a single Terror of the Night, however you cannot ascend more than once."
+ required_atoms = list(/mob/living/carbon/human)
+ cost = 5
+ route = PATH_FLESH
+
+/datum/eldritch_knowledge/final/flesh_final/on_finished_recipe(mob/living/user, list/atoms, loc)
+ var/alert_ = alert(user,"Do you want to ascend as the lord of the night or just summon a terror of the night?","...","Yes","No")
+ user.SetImmobilized(10 HOURS) // no way someone will stand 10 hours in a spot, just so he can move while the alert is still showing.
+ switch(alert_)
+ if("No")
+ var/mob/living/summoned = new /mob/living/simple_animal/hostile/eldritch/armsy(loc)
+ message_admins("[summoned.name] is being summoned by [user.real_name] in [loc]")
+ var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [summoned.real_name]", ROLE_HERETIC, null, ROLE_HERETIC, 100,summoned)
+ user.SetImmobilized(0)
+ if(LAZYLEN(candidates) == 0)
+ to_chat(user,"No ghost could be found...")
+ qdel(summoned)
+ return FALSE
+ var/mob/dead/observer/ghost_candidate = pick(candidates)
+ priority_announce("$^@*$^@(#&$(@^$^@# Fear the dark, for vassal of arms has ascended! Terror of the night has come! $^@*$^@(#&$(@^$^@#","#$^@*$^@(#&$(@^$^@#", 'sound/announcer/classic/spanomalies.ogg')
+ log_game("[key_name_admin(ghost_candidate)] has taken control of ([key_name_admin(summoned)]).")
+ summoned.ghostize(FALSE)
+ summoned.key = ghost_candidate.key
+ summoned.mind.add_antag_datum(/datum/antagonist/heretic_monster)
+ var/datum/antagonist/heretic_monster/monster = summoned.mind.has_antag_datum(/datum/antagonist/heretic_monster)
+ var/datum/antagonist/heretic/master = user.mind.has_antag_datum(/datum/antagonist/heretic)
+ monster.set_owner(master)
+ master.ascended = TRUE
+ if("Yes")
+ var/mob/living/summoned = new /mob/living/simple_animal/hostile/eldritch/armsy/prime(loc,TRUE,10)
+ summoned.ghostize(0)
+ user.SetImmobilized(0)
+ priority_announce("$^@*$^@(#&$(@^$^@# Fear the dark, for king of arms has ascended! Lord of the night has come! $^@*$^@(#&$(@^$^@#","#$^@*$^@(#&$(@^$^@#", 'sound/announcer/classic/spanomalies.ogg')
+ log_game("[user.real_name] ascended as [summoned.real_name]")
+ var/mob/living/carbon/carbon_user = user
+ var/datum/antagonist/heretic/ascension = carbon_user.mind.has_antag_datum(/datum/antagonist/heretic)
+ ascension.ascended = TRUE
+ carbon_user.mind.transfer_to(summoned, TRUE)
+ carbon_user.gib()
+
+ return ..()
diff --git a/code/modules/antagonists/eldritch_cult/knowledge/rust_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/rust_lore.dm
new file mode 100644
index 0000000000..74b3753b69
--- /dev/null
+++ b/code/modules/antagonists/eldritch_cult/knowledge/rust_lore.dm
@@ -0,0 +1,209 @@
+/datum/eldritch_knowledge/base_rust
+ name = "Blacksmith's Tale"
+ desc = "Inducts you into the Path of Rust. Allows you to transmute an eldritch blade with any trash item into a Blade of Rust."
+ gain_text = "'Let me tell you a story,' The Blacksmith said as he gazed into his rusty blade."
+ banned_knowledge = list(/datum/eldritch_knowledge/base_ash,/datum/eldritch_knowledge/base_flesh,/datum/eldritch_knowledge/final/ash_final,/datum/eldritch_knowledge/final/flesh_final)
+ next_knowledge = list(/datum/eldritch_knowledge/rust_fist)
+ required_atoms = list(/obj/item/melee/sickly_blade,/obj/item/trash)
+ result_atoms = list(/obj/item/melee/sickly_blade/rust)
+ cost = 1
+ route = PATH_RUST
+
+/datum/eldritch_knowledge/rust_fist
+ name = "Grasp of Rust"
+ desc = "Empowers your Mansus Grasp to deal 500 damage to non-living matter and rust any structure it touches. Destroys already rusted structures."
+ gain_text = "Rust grows on the ceiling of the mansus."
+ cost = 1
+ next_knowledge = list(/datum/eldritch_knowledge/rust_regen)
+ var/rust_force = 500
+ var/static/list/blacklisted_turfs = typecacheof(list(/turf/closed,/turf/open/space,/turf/open/lava,/turf/open/chasm,/turf/open/floor/plating/rust))
+ route = PATH_RUST
+
+/datum/eldritch_knowledge/rust_fist/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters)
+ . = ..()
+ if(ishuman(target))
+ var/mob/living/carbon/human/H = target
+ var/datum/status_effect/eldritch/E = H.has_status_effect(/datum/status_effect/eldritch/rust) || H.has_status_effect(/datum/status_effect/eldritch/ash) || H.has_status_effect(/datum/status_effect/eldritch/flesh)
+ if(E)
+ E.on_effect()
+ H.adjustOrganLoss(pick(ORGAN_SLOT_BRAIN,ORGAN_SLOT_EARS,ORGAN_SLOT_EYES,ORGAN_SLOT_LIVER,ORGAN_SLOT_LUNGS,ORGAN_SLOT_STOMACH,ORGAN_SLOT_HEART),25)
+ target.rust_heretic_act()
+ target.emp_act(EMP_HEAVY)
+ return TRUE
+
+/datum/eldritch_knowledge/spell/area_conversion
+ name = "Aggressive Spread"
+ desc = "Spreads rust to nearby turfs. Destroys already rusted walls."
+ gain_text = "All wise men know not to touch the bound king."
+ cost = 1
+ spell_to_add = /obj/effect/proc_holder/spell/aoe_turf/rust_conversion
+ next_knowledge = list(/datum/eldritch_knowledge/rust_blade_upgrade,/datum/eldritch_knowledge/curse/corrosion,/datum/eldritch_knowledge/spell/blood_siphon,/datum/eldritch_knowledge/spell/rust_wave)
+ route = PATH_RUST
+
+/datum/eldritch_knowledge/spell/rust_wave
+ name = "Patron's Reach"
+ desc = "You can now send a bolt of rust that corrupts the immediate area, and poisons the first target hit."
+ gain_text = "Messengers of hope fear the rustbringer."
+ cost = 1
+ spell_to_add = /obj/effect/proc_holder/spell/aimed/rust_wave
+ route = PATH_RUST
+
+/datum/eldritch_knowledge/rust_regen
+ name = "Leeching Walk"
+ desc = "Passively heals you when you are on rusted tiles."
+ gain_text = "'The strength was unparalleled, unnatural.' The Blacksmith was smiling."
+ cost = 1
+ next_knowledge = list(/datum/eldritch_knowledge/rust_mark,/datum/eldritch_knowledge/armor,/datum/eldritch_knowledge/essence)
+ route = PATH_RUST
+
+/datum/eldritch_knowledge/rust_regen/on_life(mob/user)
+ . = ..()
+ var/turf/user_loc_turf = get_turf(user)
+ if(!istype(user_loc_turf, /turf/open/floor/plating/rust) || !isliving(user))
+ return
+ var/mob/living/living_user = user
+ living_user.adjustBruteLoss(-3, FALSE)
+ living_user.adjustFireLoss(-3, FALSE)
+ living_user.adjustToxLoss(-3, FALSE)
+ living_user.adjustOxyLoss(-1, FALSE)
+ living_user.adjustStaminaLoss(-6)
+
+/datum/eldritch_knowledge/rust_mark
+ name = "Mark of Rust"
+ desc = "Your eldritch blade now applies a rust mark. Rust marks have a chance to deal between 0 to 200 damage to 75% of enemies items. To activate the mark use your Mansus Grasp on it."
+ gain_text = "Lords of the depths help those in dire need at a cost."
+ cost = 2
+ next_knowledge = list(/datum/eldritch_knowledge/spell/area_conversion)
+ banned_knowledge = list(/datum/eldritch_knowledge/ash_mark,/datum/eldritch_knowledge/flesh_mark)
+ route = PATH_RUST
+
+/datum/eldritch_knowledge/rust_mark/on_eldritch_blade(target,user,proximity_flag,click_parameters)
+ . = ..()
+ if(isliving(target))
+ var/mob/living/living_target = target
+ living_target.apply_status_effect(/datum/status_effect/eldritch/rust)
+
+/datum/eldritch_knowledge/rust_blade_upgrade
+ name = "Toxic Steel"
+ gain_text = "Let the blade guide you through the flesh."
+ desc = "Your blade of choice will now add toxin to enemies bloodstream."
+ cost = 2
+ next_knowledge = list(/datum/eldritch_knowledge/spell/entropic_plume)
+ banned_knowledge = list(/datum/eldritch_knowledge/ash_blade_upgrade,/datum/eldritch_knowledge/flesh_blade_upgrade)
+ route = PATH_RUST
+
+/datum/eldritch_knowledge/rust_blade_upgrade/on_eldritch_blade(target,user,proximity_flag,click_parameters)
+ . = ..()
+ if(iscarbon(target))
+ var/mob/living/carbon/carbon_target = target
+ carbon_target.reagents.add_reagent(/datum/reagent/eldritch, 5)
+
+/datum/eldritch_knowledge/spell/entropic_plume
+ name = "Entropic Plume"
+ desc = "You can now send a befuddling plume that blinds, poisons and makes enemies strike each other, while also converting the immediate area into rust."
+ gain_text = "Messengers of hope fear the rustbringer."
+ cost = 1
+ spell_to_add = /obj/effect/proc_holder/spell/cone/staggered/entropic_plume
+ next_knowledge = list(/datum/eldritch_knowledge/final/rust_final,/datum/eldritch_knowledge/spell/cleave,/datum/eldritch_knowledge/summon/rusty)
+ route = PATH_RUST
+
+/datum/eldritch_knowledge/armor
+ name = "Armorer's Ritual"
+ desc = "You can now create eldritch armor using a built table and a gas mask on top of a transmutation rune."
+ gain_text = "For I am the heir to the throne of doom."
+ cost = 1
+ next_knowledge = list(/datum/eldritch_knowledge/rust_regen,/datum/eldritch_knowledge/flesh_ghoul)
+ required_atoms = list(/obj/structure/table,/obj/item/clothing/mask/gas)
+ result_atoms = list(/obj/item/clothing/suit/hooded/cultrobes/eldritch)
+
+/datum/eldritch_knowledge/essence
+ name = "Priest's Ritual"
+ desc = "You can now transmute a tank of water into a bottle of eldritch fluid."
+ gain_text = "This is an old recipe, i got it from an owl."
+ cost = 1
+ next_knowledge = list(/datum/eldritch_knowledge/rust_regen,/datum/eldritch_knowledge/spell/ashen_shift)
+ required_atoms = list(/obj/structure/reagent_dispensers/watertank)
+ result_atoms = list(/obj/item/reagent_containers/glass/beaker/eldritch)
+
+/datum/eldritch_knowledge/final/rust_final
+ name = "Rustbringer's Oath"
+ desc = "Bring three corpses onto a transmutation rune. After you finish the ritual, rust will now automatically spread from the rune. Your healing on rust is also tripled, while you become more resilient overall."
+ gain_text = "Champion of rust. Corruptor of steel. Fear the dark for Rustbringer has come!"
+ cost = 5
+ required_atoms = list(/mob/living/carbon/human)
+ route = PATH_RUST
+
+/datum/eldritch_knowledge/final/rust_final/on_finished_recipe(mob/living/user, list/atoms, loc)
+ var/mob/living/carbon/human/H = user
+ H.physiology.brute_mod *= 0.5
+ H.physiology.burn_mod *= 0.5
+ priority_announce("$^@*$^@(#&$(@^$^@# Fear the decay, for Rustbringer [user.real_name] has come! $^@*$^@(#&$(@^$^@#","#$^@*$^@(#&$(@^$^@#", 'sound/announcer/classic/spanomalies.ogg')
+ new /datum/rust_spread(loc)
+ var/datum/antagonist/heretic/ascension = H.mind.has_antag_datum(/datum/antagonist/heretic)
+ ascension.ascended = TRUE
+ return ..()
+
+
+/datum/eldritch_knowledge/final/rust_final/on_life(mob/user)
+ . = ..()
+ if(!finished)
+ return
+ var/mob/living/carbon/human/human_user = user
+ human_user.adjustBruteLoss(-6, FALSE)
+ human_user.adjustFireLoss(-6, FALSE)
+ human_user.adjustToxLoss(-6, FALSE)
+ human_user.adjustOxyLoss(-6, FALSE)
+ human_user.adjustStaminaLoss(-20)
+
+
+/**
+ * #Rust spread datum
+ *
+ * Simple datum that automatically spreads rust around it
+ *
+ * Simple implementation of automatically growing entity
+ */
+/datum/rust_spread
+ var/list/edge_turfs = list()
+ var/list/turfs = list()
+ var/static/list/blacklisted_turfs = typecacheof(list(/turf/open/indestructible,/turf/closed/indestructible,/turf/open/space,/turf/open/lava,/turf/open/chasm))
+ var/spread_per_tick = 6
+
+
+/datum/rust_spread/New(loc)
+ . = ..()
+ var/turf/turf_loc = get_turf(loc)
+ turf_loc.rust_heretic_act()
+ turfs += turf_loc
+ START_PROCESSING(SSprocessing,src)
+
+
+/datum/rust_spread/Destroy(force, ...)
+ STOP_PROCESSING(SSprocessing,src)
+ return ..()
+
+/datum/rust_spread/process()
+ compile_turfs()
+ var/turf/T
+ for(var/i in 0 to spread_per_tick)
+ T = pick(edge_turfs)
+ T.rust_heretic_act()
+ turfs += get_turf(T)
+
+/**
+ * Compile turfs
+ *
+ * Recreates all edge_turfs as well as normal turfs.
+ */
+/datum/rust_spread/proc/compile_turfs()
+ edge_turfs = list()
+ for(var/X in turfs)
+ if(!istype(X,/turf/closed/wall/rust) && !istype(X,/turf/closed/wall/r_wall/rust) && !istype(X,/turf/open/floor/plating/rust))
+ turfs -=X
+ continue
+ for(var/turf/T in range(1,X))
+ if(T in turfs)
+ continue
+ if(is_type_in_typecache(T,blacklisted_turfs))
+ continue
+ edge_turfs += T
diff --git a/code/modules/antagonists/slaughter/slaughter.dm b/code/modules/antagonists/slaughter/slaughter.dm
index 3ae9cfcfb0..d1db363b04 100644
--- a/code/modules/antagonists/slaughter/slaughter.dm
+++ b/code/modules/antagonists/slaughter/slaughter.dm
@@ -16,6 +16,7 @@
icon_state = "daemon"
icon_living = "daemon"
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
+ mob_size = MOB_SIZE_LARGE
speed = 1
a_intent = INTENT_HARM
stop_automated_movement = 1
diff --git a/code/modules/antagonists/swarmer/swarmer.dm b/code/modules/antagonists/swarmer/swarmer.dm
index b7503f4b22..305c4fadb7 100644
--- a/code/modules/antagonists/swarmer/swarmer.dm
+++ b/code/modules/antagonists/swarmer/swarmer.dm
@@ -70,7 +70,6 @@
icon_living = "swarmer"
icon_dead = "swarmer_unactivated"
icon_gib = null
- threat = 0.5
wander = 0
harm_intent_damage = 5
minbodytemp = 0
diff --git a/code/modules/antagonists/wizard/equipment/spellbook.dm b/code/modules/antagonists/wizard/equipment/spellbook.dm
index d4d117f8ee..1e98b2f753 100644
--- a/code/modules/antagonists/wizard/equipment/spellbook.dm
+++ b/code/modules/antagonists/wizard/equipment/spellbook.dm
@@ -161,12 +161,12 @@
/datum/spellbook_entry/blind
name = "Blind"
- spell_type = /obj/effect/proc_holder/spell/targeted/trigger/blind
+ spell_type = /obj/effect/proc_holder/spell/pointed/trigger/blind
cost = 1
/datum/spellbook_entry/mindswap
name = "Mindswap"
- spell_type = /obj/effect/proc_holder/spell/targeted/mind_transfer
+ spell_type = /obj/effect/proc_holder/spell/pointed/mind_transfer
category = "Mobility"
/datum/spellbook_entry/forcewall
@@ -246,7 +246,7 @@
/datum/spellbook_entry/barnyard
name = "Barnyard Curse"
- spell_type = /obj/effect/proc_holder/spell/targeted/barnyardcurse
+ spell_type = /obj/effect/proc_holder/spell/pointed/barnyardcurse
/datum/spellbook_entry/charge
name = "Charge"
diff --git a/code/modules/antagonists/wizard/wizard.dm b/code/modules/antagonists/wizard/wizard.dm
index 7263793f7f..42954c3542 100644
--- a/code/modules/antagonists/wizard/wizard.dm
+++ b/code/modules/antagonists/wizard/wizard.dm
@@ -177,7 +177,7 @@
to_chat(owner, "Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned livesaving survival spells. You are able to cast charge and forcewall.")
if(APPRENTICE_ROBELESS)
owner.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/knock(null))
- owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/mind_transfer(null))
+ owner.AddSpell(new /obj/effect/proc_holder/spell/pointed/mind_transfer(null))
to_chat(owner, "Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned stealthy, robeless spells. You are able to cast knock and mindswap.")
if(APPRENTICE_MARTIAL)
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/touch/nuclear_fist(null))
diff --git a/code/modules/antagonists/xeno/xeno.dm b/code/modules/antagonists/xeno/xeno.dm
index 2cc8e34b99..f10506a0d9 100644
--- a/code/modules/antagonists/xeno/xeno.dm
+++ b/code/modules/antagonists/xeno/xeno.dm
@@ -16,6 +16,18 @@
var/datum/team/xeno/xeno_team
threat = 3
+/datum/antagonist/xeno/threat()
+ . = 1
+ if(isalienhunter(owner))
+ . = 2
+ else if(isaliensentinel(owner))
+ . = 4
+ else if(isalienroyal(owner))
+ if(isalienqueen(owner))
+ . = 8
+ else
+ . = 6
+
/datum/antagonist/xeno/create_team(datum/team/xeno/new_team)
if(!new_team)
for(var/datum/antagonist/xeno/X in GLOB.antagonists)
diff --git a/code/modules/arousal/organs/womb.dm b/code/modules/arousal/organs/womb.dm
index 386f407a26..e89d4329aa 100644
--- a/code/modules/arousal/organs/womb.dm
+++ b/code/modules/arousal/organs/womb.dm
@@ -6,5 +6,5 @@
zone = BODY_ZONE_PRECISE_GROIN
slot = ORGAN_SLOT_WOMB
genital_flags = GENITAL_INTERNAL|GENITAL_FUID_PRODUCTION
- fluid_id = /datum/reagent/consumable/femcum
+ fluid_id = /datum/reagent/consumable/semen/femcum
linked_organ_slot = ORGAN_SLOT_VAGINA
diff --git a/code/modules/arousal/toys/dildos.dm b/code/modules/arousal/toys/dildos.dm
index 5cb6d47118..3f6fa9bb45 100644
--- a/code/modules/arousal/toys/dildos.dm
+++ b/code/modules/arousal/toys/dildos.dm
@@ -122,6 +122,7 @@ obj/item/dildo/flared/huge
name = "literal horse cock"
desc = "THIS THING IS HUGE!"
dildo_size = 4
+ force = 10
obj/item/dildo/custom
name = "customizable dildo"
diff --git a/code/modules/asset_cache/asset_list_items.dm b/code/modules/asset_cache/asset_list_items.dm
index a8b4c93764..18e3281e4b 100644
--- a/code/modules/asset_cache/asset_list_items.dm
+++ b/code/modules/asset_cache/asset_list_items.dm
@@ -264,7 +264,7 @@
name = "pipes"
/datum/asset/spritesheet/pipes/register()
- for (var/each in list('icons/obj/atmospherics/pipes/pipe_item.dmi', 'icons/obj/atmospherics/pipes/disposal.dmi'))
+ for (var/each in list('icons/obj/atmospherics/pipes/pipe_item.dmi', 'icons/obj/atmospherics/pipes/disposal.dmi', 'icons/obj/atmospherics/pipes/transit_tube.dmi', 'icons/obj/plumbing/fluid_ducts.dmi'))
InsertAll("", each, GLOB.alldirs)
..()
@@ -388,9 +388,11 @@
Insert("polycrystal", 'icons/obj/telescience.dmi', "polycrystal")
..()
+
/datum/asset/spritesheet/mafia
name = "mafia"
/datum/asset/spritesheet/mafia/register()
InsertAll("", 'icons/obj/mafia.dmi')
..()
+
diff --git a/code/modules/cargo/exports/gear.dm b/code/modules/cargo/exports/gear.dm
index 646e1c6e47..678948128f 100644
--- a/code/modules/cargo/exports/gear.dm
+++ b/code/modules/cargo/exports/gear.dm
@@ -310,7 +310,7 @@
/datum/export/gear/combatgloves
cost = 80
unit_name = "combat gloves"
- export_types = list(/obj/item/clothing/gloves/tackler/combat, /obj/item/clothing/gloves/tackler/dolphin, /obj/item/clothing/gloves/fingerless/pugilist/rapid, /obj/item/clothing/gloves/krav_maga)
+ export_types = list(/obj/item/clothing/gloves/tackler/combat, /obj/item/clothing/gloves/tackler/dolphin, /obj/item/clothing/gloves/krav_maga)
include_subtypes = TRUE
/datum/export/gear/bonegloves
diff --git a/code/modules/cargo/exports/organs_robotics.dm b/code/modules/cargo/exports/organs_robotics.dm
index 7f54e675ca..b65cf28949 100644
--- a/code/modules/cargo/exports/organs_robotics.dm
+++ b/code/modules/cargo/exports/organs_robotics.dm
@@ -2,11 +2,11 @@
/datum/export/robotics
include_subtypes = FALSE
- k_elasticity = 1/50
+ k_elasticity = 1/200
/datum/export/implant
include_subtypes = FALSE
- k_elasticity = 1/50
+ k_elasticity = 1/200
/datum/export/organs
include_subtypes = TRUE
@@ -34,8 +34,8 @@
export_types = list(/obj/item/organ/cyberimp/brain/anti_stun)
/datum/export/implant/breathtube
- cost = 150
- k_elasticity = 300/20 //Large before depleating
+ cost = 175
+ k_elasticity = 1/350 //Large before depleating
unit_name = "breath implant"
export_types = list(/obj/item/organ/cyberimp/mouth/breathing_tube)
@@ -71,35 +71,35 @@
export_types = list(/obj/item/organ/cyberimp/arm/gun/laser, /obj/item/organ/cyberimp/arm/gun/taser, /obj/item/organ/cyberimp/arm/esword, /obj/item/organ/cyberimp/arm/medibeam, /obj/item/organ/cyberimp/arm/combat, /obj/item/organ/cyberimp/arm/flash, /obj/item/organ/cyberimp/arm/baton)
include_subtypes = TRUE
-/datum/export/orgains/heart
+/datum/export/organs/heart
cost = 250
unit_name = "heart"
export_types = list(/obj/item/organ/heart)
exclude_types = list(/obj/item/organ/heart/cursed, /obj/item/organ/heart/cybernetic)
-/datum/export/orgains/tongue
+/datum/export/organs/tongue
cost = 75
unit_name = "tongue"
export_types = list(/obj/item/organ/tongue)
-/datum/export/orgains/eyes
+/datum/export/organs/eyes
cost = 50 //So many things take your eyes out anyways
unit_name = "eyes"
export_types = list(/obj/item/organ/eyes)
exclude_types = list(/obj/item/organ/eyes/robotic)
-/datum/export/orgains/stomach
+/datum/export/organs/stomach
cost = 50 //can be replaced
unit_name = "stomach"
export_types = list(/obj/item/organ/stomach)
-/datum/export/orgains/lungs
+/datum/export/organs/lungs
cost = 150
unit_name = "lungs"
export_types = list(/obj/item/organ/lungs)
exclude_types = list(/obj/item/organ/lungs/cybernetic, /obj/item/organ/lungs/cybernetic/upgraded)
-/datum/export/orgains/liver
+/datum/export/organs/liver
cost = 175
unit_name = "liver"
export_types = list(/obj/item/organ/liver)
@@ -116,33 +116,33 @@
unit_name = "upgraded cybernetic organ"
export_types = list(/obj/item/organ/lungs/cybernetic/upgraded, /obj/item/organ/liver/cybernetic/upgraded)
-/datum/export/organs/tail //Shhh
+/datum/export/organs/tail // yeah have fun pulling this off someone without catching a bwoink
cost = 500
- unit_name = "error shipment failer"
+ unit_name = "organic tail"
export_types = list(/obj/item/organ/tail)
-/datum/export/orgains/vocal_cords
+/datum/export/organs/vocal_cords
cost = 500
unit_name = "vocal cords"
export_types = list(/obj/item/organ/vocal_cords) //These are gotten via different races
-/datum/export/robotics/lims
- cost = 30
- unit_name = "robotic lim replacement"
+/datum/export/robotics/limbs
+ cost = 60
+ unit_name = "robotic limb replacement"
export_types = list(/obj/item/bodypart/l_arm/robot, /obj/item/bodypart/r_arm/robot, /obj/item/bodypart/l_leg/robot, /obj/item/bodypart/r_leg/robot, /obj/item/bodypart/chest/robot, /obj/item/bodypart/head/robot)
/datum/export/robotics/surpluse
- cost = 40
- unit_name = "robotic lim replacement"
+ cost = 50
+ unit_name = "robotic limb replacement"
export_types = list(/obj/item/bodypart/l_arm/robot/surplus, /obj/item/bodypart/r_arm/robot/surplus, /obj/item/bodypart/l_leg/robot/surplus, /obj/item/bodypart/r_leg/robot/surplus)
/datum/export/robotics/surplus_upgraded
- cost = 50
- unit_name = "upgraded robotic lim replacement"
+ cost = 80
+ unit_name = "upgraded robotic limb replacement"
export_types = list(/obj/item/bodypart/l_arm/robot/surplus_upgraded, /obj/item/bodypart/r_arm/robot/surplus_upgraded, /obj/item/bodypart/l_leg/robot/surplus_upgraded, /obj/item/bodypart/r_leg/robot/surplus_upgraded)
/datum/export/robotics/surgery_gear_basic
- cost = 10
+ cost = 50
unit_name = "surgery tool"
export_types = list(/obj/item/retractor, /obj/item/hemostat, /obj/item/cautery, /obj/item/surgicaldrill, /obj/item/scalpel, /obj/item/circular_saw, /obj/item/bonesetter, /obj/item/surgical_drapes)
diff --git a/code/modules/cargo/exports/parts.dm b/code/modules/cargo/exports/parts.dm
index da3c0cf31d..3e52780d44 100644
--- a/code/modules/cargo/exports/parts.dm
+++ b/code/modules/cargo/exports/parts.dm
@@ -102,6 +102,7 @@
export_types = list(/obj/item/stock_parts/cell/high/slime/hypercharged)
//Glass working stuff
+// i'd just like to say how i despise the previous coder's fetish for their funny glasswork
/datum/export/glasswork_dish
cost = 300
diff --git a/code/modules/cargo/exports/sheets.dm b/code/modules/cargo/exports/sheets.dm
index a562210164..b0676fbde2 100644
--- a/code/modules/cargo/exports/sheets.dm
+++ b/code/modules/cargo/exports/sheets.dm
@@ -138,11 +138,11 @@
message = "of bones"
export_types = list(/obj/item/stack/sheet/bone)
-/datum/export/stack/bronze
+/datum/export/stack/sheet/bronze
unit_name = "tiles"
cost = 5
message = "of brozne"
- export_types = list(/obj/item/stack/tile/bronze)
+ export_types = list(/obj/item/stack/sheet/bronze)
/datum/export/stack/brass
unit_name = "tiles"
diff --git a/code/modules/cargo/exports/weapons.dm b/code/modules/cargo/exports/weapons.dm
index 983348a358..dc2703c146 100644
--- a/code/modules/cargo/exports/weapons.dm
+++ b/code/modules/cargo/exports/weapons.dm
@@ -5,7 +5,7 @@
/datum/export/weapon/makeshift_shield
cost = 30
- unit_name = "unknown shield"
+ unit_name = "nonstandard shield"
export_types = list(/obj/item/shield/riot, /obj/item/shield/riot/roman, /obj/item/shield/riot/buckler, /obj/item/shield/makeshift)
/datum/export/weapon/riot_shield
@@ -37,7 +37,7 @@
/datum/export/weapon/taser
cost = 200
- unit_name = "advanced taser"
+ unit_name = "hybrid taser"
export_types = list(/obj/item/gun/energy/e_gun/advtaser)
/datum/export/weapon/laser
@@ -104,12 +104,12 @@
/datum/export/weapon/aeg
cost = 200 //Endless power
- unit_name = "advance engery gun"
+ unit_name = "advanced energy gun"
export_types = list(/obj/item/gun/energy/e_gun/nuclear)
/datum/export/weapon/deconer
cost = 600
- unit_name = "deconer"
+ unit_name = "decloner"
export_types = list(/obj/item/gun/energy/decloner)
/datum/export/weapon/ntsniper
@@ -123,9 +123,8 @@
export_types = list(/obj/item/gun/syringe/rapidsyringe)
/datum/export/weapon/temp_gun
- cost = 175 //Its just smaller
+ cost = 175
unit_name = "small temperature gun"
- k_elasticity = 1/30 //Its just a smaller temperature gun, easy to mass make
export_types = list(/obj/item/gun/energy/temperature)
/datum/export/weapon/flowergun
@@ -139,8 +138,7 @@
export_types = list(/obj/item/gun/energy/xray)
/datum/export/weapon/ioncarbine
- cost = 200
- k_elasticity = 1/30 //Its just a smaller temperature gun, easy to mass make
+ cost = 200
unit_name = "ion carbine"
export_types = list(/obj/item/gun/energy/ionrifle/carbine)
@@ -194,7 +192,7 @@
export_types = list(/obj/item/firing_pin/test_range)
/datum/export/weapon/techslug
- cost = 25
+ cost = 30
k_elasticity = 0
unit_name = "advanced shotgun shell"
export_types = list(/obj/item/ammo_casing/shotgun/dragonsbreath, /obj/item/ammo_casing/shotgun/meteorslug, /obj/item/ammo_casing/shotgun/pulseslug, /obj/item/ammo_casing/shotgun/frag12, /obj/item/ammo_casing/shotgun/ion, /obj/item/ammo_casing/shotgun/laserslug)
@@ -215,7 +213,7 @@
/datum/export/weapon/bow_teaching
cost = 500
- unit_name = "stone tablets"
+ unit_name = "bowyery tablet"
export_types = list(/obj/item/book/granter/crafting_recipe/bone_bow)
/datum/export/weapon/quiver
@@ -230,48 +228,48 @@
/datum/export/weapon/pistol
cost = 120
- unit_name = "illegal firearm"
+ unit_name = "nonstandard sidearm"
export_types = list(/obj/item/gun/ballistic/automatic/pistol)
/datum/export/weapon/revolver
cost = 200
- unit_name = "large handgun"
+ unit_name = "large-caliber revolver"
export_types = list(/obj/item/gun/ballistic/revolver)
exclude_types = list(/obj/item/gun/ballistic/revolver/russian, /obj/item/gun/ballistic/revolver/doublebarrel)
/datum/export/weapon/rocketlauncher
cost = 1000
- unit_name = "rocketlauncher"
+ unit_name = "PML-9 rocket-propelled grenade launcher"
export_types = list(/obj/item/gun/ballistic/rocketlauncher)
/datum/export/weapon/antitank
cost = 300
- unit_name = "hand cannon"
+ unit_name = "anti-tank pistol"
export_types = list(/obj/item/gun/ballistic/automatic/pistol/antitank/syndicate)
/datum/export/weapon/clownstuff
cost = 500
- unit_name = "clown war tech"
- export_types = list(/obj/item/pneumatic_cannon/pie/selfcharge, /obj/item/shield/energy/bananium, /obj/item/melee/transforming/energy/sword/bananium, )
+ unit_name = "clown combat equipment"
+ export_types = list(/obj/item/pneumatic_cannon/pie/selfcharge, /obj/item/shield/energy/bananium, /obj/item/melee/transforming/energy/sword/bananium)
/datum/export/weapon/bulldog
cost = 400
- unit_name = "drum loaded shotgun"
+ unit_name = "drum-fed compact combat shotgun"
export_types = list(/obj/item/gun/ballistic/automatic/shotgun/bulldog)
/datum/export/weapon/smg
cost = 350
- unit_name = "automatic c-20r"
+ unit_name = "C-20r sub-machine gun"
export_types = list(/obj/item/gun/ballistic/automatic/c20r)
/datum/export/weapon/duelsaber
- cost = 360 //Get it?
- unit_name = "energy saber"
+ cost = 360
+ unit_name = "double-bladed energy saber"
export_types = list(/obj/item/dualsaber)
/datum/export/weapon/esword
cost = 130
- unit_name = "energy sword"
+ unit_name = "energy saber"
export_types = list(/obj/item/melee/transforming/energy/sword/cx/traitor, /obj/item/melee/transforming/energy/sword/saber)
/datum/export/weapon/rapier
@@ -286,32 +284,32 @@
/datum/export/weapon/gloves
cost = 90
- unit_name = "star struck gloves"
+ unit_name = "anomalous armwraps"
export_types = list(/obj/item/clothing/gloves/fingerless/pugilist/rapid)
/datum/export/weapon/l6
cost = 500
- unit_name = "law 6 saw"
+ unit_name = "Aussec Armory L6 SAW"
export_types = list(/obj/item/gun/ballistic/automatic/l6_saw)
/datum/export/weapon/m90
cost = 400
- unit_name = "assault class weapon"
+ unit_name = "M90-gl carbine"
export_types = list(/obj/item/gun/ballistic/automatic/m90)
/datum/export/weapon/powerglove
cost = 100
- unit_name = "hydraulic glove"
+ unit_name = "pneumatic gauntlet"
export_types = list(/obj/item/melee/powerfist)
/datum/export/weapon/sniper
cost = 750
- unit_name = ".50 sniper"
+ unit_name = "anti-materiel rifle"
export_types = list(/obj/item/gun/ballistic/automatic/sniper_rifle/syndicate)
/datum/export/weapon/ebow
cost = 600
- unit_name = "mini crossbow"
+ unit_name = "compact energy crossbow"
export_types = list(/obj/item/gun/energy/kinetic_accelerator/crossbow)
/datum/export/weapon/m10mm
@@ -333,12 +331,12 @@
/datum/export/weapon/smg_mag
cost = 45
- unit_name = "smg magazine"
+ unit_name = "SMG/carbine magazine"
export_types = list(/obj/item/ammo_box/magazine/smgm45, /obj/item/ammo_box/magazine/m556)
/datum/export/weapon/l6sawammo
cost = 60
- unit_name = "law 6 saw ammo box"
+ unit_name = "L6 SAW ammo box"
export_types = list(/obj/item/ammo_box/magazine/mm195x129)
include_subtypes = TRUE
@@ -355,13 +353,13 @@
/datum/export/weapon/fletcher_ammo
cost = 60
- unit_name = "illegal ammo magazines"
+ unit_name = "flechette launcher magazine"
export_types = list(/obj/item/ammo_box/magazine/flechette)
include_subtypes = TRUE
/datum/export/weapon/dj_a_pizzabomb
cost = -6000
- unit_name = "Repair Costs"
+ unit_name = "undeclared ordinance and subsequent repair costs"
export_types = list(/obj/item/pizzabox/bomb, /obj/item/sbeacondrop/bomb)
/datum/export/weapon/real_toolbox
@@ -371,12 +369,12 @@
/datum/export/weapon/melee
cost = 50
- unit_name = "unlisted weapon"
+ unit_name = "any other melee weapon"
export_types = list(/obj/item/melee)
include_subtypes = TRUE
/datum/export/weapon/gun
cost = 50
- unit_name = "unlisted weapon"
+ unit_name = "any other weapon"
export_types = list(/obj/item/gun)
include_subtypes = TRUE
diff --git a/code/modules/cargo/packs/armory.dm b/code/modules/cargo/packs/armory.dm
index 2ef0abb000..9f8bb2f25f 100644
--- a/code/modules/cargo/packs/armory.dm
+++ b/code/modules/cargo/packs/armory.dm
@@ -158,11 +158,10 @@
/datum/supply_pack/security/armory/russian
name = "Russian Surplus Crate"
- desc = "Hello Comrade, we have the most modern russian military equipment the black market can offer, for the right price of course. Sadly we couldnt remove the lock so it requires Armory access to open."
+ desc = "Hello Comrade, we have the most modern Russian military equipment the black market can offer, for the right price of course. Sadly we couldn't remove the lock so it requires Armory access to open."
cost = 7500
contraband = TRUE
contains = list(/obj/item/reagent_containers/food/snacks/rationpack,
- /obj/item/ammo_box/magazine/m10mm/rifle,
/obj/item/clothing/suit/armor/vest/russian,
/obj/item/clothing/head/helmet/rus_helmet,
/obj/item/clothing/shoes/russian,
@@ -172,7 +171,10 @@
/obj/item/clothing/mask/russian_balaclava,
/obj/item/clothing/head/helmet/rus_ushanka,
/obj/item/clothing/suit/armor/vest/russian_coat,
- /obj/item/gun/ballistic/automatic/surplus)
+ /obj/effect/spawner/bundle/crate/mosin,
+ /obj/item/storage/toolbox/ammo,
+ /obj/effect/spawner/bundle/crate/surplusrifle,
+ /obj/item/storage/toolbox/ammo/surplus)
crate_name = "surplus military crate"
/datum/supply_pack/security/armory/russian/fill(obj/structure/closet/crate/C)
diff --git a/code/modules/cargo/packs/security.dm b/code/modules/cargo/packs/security.dm
index 738eb03fbf..cf9cc5e0d1 100644
--- a/code/modules/cargo/packs/security.dm
+++ b/code/modules/cargo/packs/security.dm
@@ -100,7 +100,7 @@
crate_name = "surplus russian clothing"
crate_type = /obj/structure/closet/crate/internals
-/datum/supply_pack/security/russianmosin
+/datum/supply_pack/security/russian_partisan
name = "Russian Partisan Gear"
desc = "An old russian partisan equipment crate, comes with a full russian outfit, a loaded surplus rifle and a second magazine."
contraband = TRUE
@@ -112,12 +112,17 @@
/obj/item/clothing/suit/armor/bulletproof,
/obj/item/clothing/head/helmet/alt,
/obj/item/clothing/gloves/tackler/combat/insulated,
- /obj/item/clothing/mask/gas,
- /obj/item/ammo_box/magazine/m10mm/rifle,
- /obj/item/gun/ballistic/automatic/surplus)
+ /obj/item/clothing/mask/gas)
crate_name = "surplus russian gear"
crate_type = /obj/structure/closet/crate/internals
+/datum/supply_pack/security/russian_partisan/fill(obj/structure/closet/crate/C)
+ ..()
+ if(prob(20))
+ new /obj/effect/spawner/bundle/crate/mosin(C)
+ else
+ new /obj/effect/spawner/bundle/crate/surplusrifle(C)
+
/datum/supply_pack/security/sechardsuit
name = "Sec Hardsuit"
desc = "One Sec Hardsuit with a small air tank and mask."
diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm
index 9b7e928852..e7aa447840 100644
--- a/code/modules/client/client_procs.dm
+++ b/code/modules/client/client_procs.dm
@@ -993,3 +993,6 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
screen -= S
qdel(S)
char_render_holders = null
+
+/client/proc/can_have_part(part_name)
+ return prefs.pref_species.mutant_bodyparts[part_name] || (part_name in GLOB.unlocked_mutant_parts)
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 1b6e1f9748..2fe674e59e 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -246,6 +246,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
/// Which of the 5 persistent scar slots we randomly roll to load for this round, if enabled. Actually rolled in [/datum/preferences/proc/load_character(slot)]
var/scars_index = 1
+ var/chosen_limb_id //body sprite selected to load for the users limbs, null means default, is sanitized when loaded
+
/datum/preferences/New(client/C)
parent = C
@@ -507,310 +509,25 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += ""
mutant_category = 0
- if(pref_species.mutant_bodyparts["tail_lizard"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Tail
"
-
- dat += "[features["tail_lizard"]]"
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
-
- if(pref_species.mutant_bodyparts["mam_tail"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Tail
"
-
- dat += "[features["mam_tail"]]"
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
- if(pref_species.mutant_bodyparts["tail_human"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Tail
"
-
- dat += "[features["tail_human"]]"
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
-
- if(pref_species.mutant_bodyparts["meat_type"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Meat Type
"
-
- dat += "[features["meat_type"]]"
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
- if(pref_species.mutant_bodyparts["snout"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Snout
"
-
- dat += "[features["snout"]]"
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
- if(pref_species.mutant_bodyparts["horns"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Horns
"
-
- dat += "[features["horns"]]"
- dat += " Change
"
-
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- if(pref_species.mutant_bodyparts["frills"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Frills
"
-
- dat += "[features["frills"]]"
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
-
- if(pref_species.mutant_bodyparts["spines"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Spines
"
-
- dat += "[features["spines"]]"
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
-
- if(pref_species.mutant_bodyparts["body_markings"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Body Markings
"
-
- dat += "[features["body_markings"]]"
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
- if(pref_species.mutant_bodyparts["mam_body_markings"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Species Markings
"
-
- dat += "[features["mam_body_markings"]]"
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
-
- if(pref_species.mutant_bodyparts["mam_ears"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Ears
"
-
- dat += "[features["mam_ears"]]"
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
-
- if(pref_species.mutant_bodyparts["ears"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Ears
"
-
- dat += "[features["ears"]]"
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
-
- if(pref_species.mutant_bodyparts["mam_snouts"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Snout
"
-
- dat += "[features["mam_snouts"]]"
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
- if(pref_species.mutant_bodyparts["legs"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Legs
"
-
- dat += "[features["legs"]]"
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
- if(pref_species.mutant_bodyparts["deco_wings"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Decorative wings
"
-
- dat += "[features["deco_wings"]]"
- dat += " Change
"
-
- if(pref_species.mutant_bodyparts["insect_wings"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Insect wings
"
-
- dat += "[features["insect_wings"]]"
- dat += " Change
"
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
- if(pref_species.mutant_bodyparts["insect_fluff"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Insect Fluff
"
-
- dat += "[features["insect_fluff"]]"
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
- if(pref_species.mutant_bodyparts["taur"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Tauric Body
"
-
- dat += "[features["taur"]]"
-
- if(pref_species.mutant_bodyparts["insect_markings"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Insect markings
"
-
- dat += "[features["insect_markings"]]
"
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
- if(pref_species.mutant_bodyparts["wings"] && GLOB.r_wings_list.len >1)
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Wings
"
-
- dat += "[features["wings"]]"
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
- if(pref_species.mutant_bodyparts["xenohead"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Caste Head
"
-
- dat += "[features["xenohead"]]"
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
- if(pref_species.mutant_bodyparts["xenotail"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Tail
"
-
- dat += "[features["xenotail"]]"
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
- if(pref_species.mutant_bodyparts["xenodorsal"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Dorsal Spines
"
-
- dat += "[features["xenodorsal"]]"
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
- if(pref_species.mutant_bodyparts["ipc_screen"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Screen
"
-
- dat += "[features["ipc_screen"]]"
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
- if(pref_species.mutant_bodyparts["ipc_antenna"])
- if(!mutant_category)
- dat += APPEARANCE_CATEGORY_COLUMN
-
- dat += "Antenna
"
-
- dat += "[features["ipc_antenna"]]"
-
- mutant_category++
- if(mutant_category >= MAX_MUTANT_ROWS)
- dat += ""
- mutant_category = 0
+ for(var/mutant_part in GLOB.all_mutant_parts)
+ if(parent.can_have_part(mutant_part))
+ if(!mutant_category)
+ dat += APPEARANCE_CATEGORY_COLUMN
+ dat += "[GLOB.all_mutant_parts[mutant_part]]
"
+ dat += "[features[mutant_part]]"
+ var/color_type = GLOB.colored_mutant_parts[mutant_part] //if it can be coloured, show the appropriate button
+ if(color_type)
+ dat += " Change
"
+ mutant_category++
+ if(mutant_category >= MAX_MUTANT_ROWS)
+ dat += ""
+ mutant_category = 0
+
+ if(length(pref_species.allowed_limb_ids))
+ if(!chosen_limb_id || !(chosen_limb_id in pref_species.allowed_limb_ids))
+ chosen_limb_id = pref_species.id
+ dat += "Body sprite
"
+ dat += "[chosen_limb_id]"
if(mutant_category)
dat += ""
@@ -856,7 +573,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/tauric_shape = FALSE
if(features["cock_taur"])
var/datum/sprite_accessory/penis/P = GLOB.cock_shapes_list[features["cock_shape"]]
- if(P.taur_icon && pref_species.mutant_bodyparts["taur"])
+ if(P.taur_icon && parent.can_have_part("taur"))
var/datum/sprite_accessory/taur/T = GLOB.taur_list[features["taur"]]
if(T.taur_mode & P.accepted_taurs)
tauric_shape = TRUE
@@ -1082,9 +799,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += ""
dat += "
|
"
-
+
dat += ""
-
+
if(!length(GLOB.loadout_categories[gear_category]))
dat += "No subcategories detected. Something is horribly wrong!"
else
@@ -1092,7 +809,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(!subcategories.Find(gear_subcategory))
gear_subcategory = subcategories[1]
- var/firstsubcat = FALSE
+ var/firstsubcat = TRUE
for(var/subcategory in subcategories)
if(firstsubcat)
firstsubcat = FALSE
@@ -1808,14 +1525,14 @@ GLOBAL_LIST_EMPTY(preferences_datums)
pref_species = new newtype()
//let's ensure that no weird shit happens on species swapping.
custom_species = null
- if(!pref_species.mutant_bodyparts["body_markings"])
+ if(!parent.can_have_part("body_markings"))
features["body_markings"] = "None"
- if(!pref_species.mutant_bodyparts["mam_body_markings"])
+ if(!parent.can_have_part("mam_body_markings"))
features["mam_body_markings"] = "None"
- if(pref_species.mutant_bodyparts["mam_body_markings"])
+ if(parent.can_have_part("mam_body_markings"))
if(features["mam_body_markings"] == "None")
features["mam_body_markings"] = "Plain"
- if(pref_species.mutant_bodyparts["tail_lizard"])
+ if(parent.can_have_part("tail_lizard"))
features["tail_lizard"] = "Smooth"
if(pref_species.id == "felinid")
features["mam_tail"] = "Cat"
@@ -1927,7 +1644,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("mam_tail")
var/list/snowflake_tails_list = list()
for(var/path in GLOB.mam_tails_list)
- var/datum/sprite_accessory/mam_tails/instance = GLOB.mam_tails_list[path]
+ var/datum/sprite_accessory/tails/mam_tails/instance = GLOB.mam_tails_list[path]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if(!show_mismatched_markings && S.recommended_species && !S.recommended_species.Find(pref_species.id))
@@ -1943,7 +1660,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
features["tail_human"] = "None"
features["tail_lizard"] = "None"
- if("meats")
+ if("meat_type")
var/new_meat
new_meat = input(user, "Choose your character's meat type:", "Character Preference") as null|anything in GLOB.meat_types
if(new_meat)
@@ -1952,7 +1669,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("snout")
var/list/snowflake_snouts_list = list()
for(var/path in GLOB.snouts_list)
- var/datum/sprite_accessory/mam_snouts/instance = GLOB.snouts_list[path]
+ var/datum/sprite_accessory/snouts/mam_snouts/instance = GLOB.snouts_list[path]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if(!show_mismatched_markings && S.recommended_species && !S.recommended_species.Find(pref_species.id))
@@ -1969,7 +1686,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("mam_snouts")
var/list/snowflake_mam_snouts_list = list()
for(var/path in GLOB.mam_snouts_list)
- var/datum/sprite_accessory/mam_snouts/instance = GLOB.mam_snouts_list[path]
+ var/datum/sprite_accessory/snouts/mam_snouts/instance = GLOB.mam_snouts_list[path]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if(!show_mismatched_markings && S.recommended_species && !S.recommended_species.Find(pref_species.id))
@@ -2048,7 +1765,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(new_deco_wings)
features["deco_wings"] = new_deco_wings
- if("insect_fluffs")
+ if("insect_fluff")
var/new_insect_fluff
new_insect_fluff = input(user, "Choose your character's wings:", "Character Preference") as null|anything in GLOB.insect_fluffs_list
if(new_insect_fluff)
@@ -2118,7 +1835,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("mam_ears")
var/list/snowflake_ears_list = list()
for(var/path in GLOB.mam_ears_list)
- var/datum/sprite_accessory/mam_ears/instance = GLOB.mam_ears_list[path]
+ var/datum/sprite_accessory/ears/mam_ears/instance = GLOB.mam_ears_list[path]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if(!show_mismatched_markings && S.recommended_species && !S.recommended_species.Find(pref_species.id))
@@ -2196,7 +1913,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("cock_shape")
var/new_shape
var/list/hockeys = list()
- if(pref_species.mutant_bodyparts["taur"])
+ if(parent.can_have_part("taur"))
var/datum/sprite_accessory/taur/T = GLOB.taur_list[features["taur"]]
for(var/A in GLOB.cock_shapes_list)
var/datum/sprite_accessory/penis/P = GLOB.cock_shapes_list[A]
@@ -2383,8 +2100,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
else
features["body_model"] = chosengender
gender = chosengender
- facial_hair_style = random_facial_hair_style(gender)
- hair_style = random_hair_style(gender)
if("body_size")
var/min = CONFIG_GET(number/body_size_min)
@@ -2410,6 +2125,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/selected_custom_speech_verb = input(user, "Choose your desired speech verb (none means your species speech verb)", "Character Preference") as null|anything in GLOB.speech_verbs
if(selected_custom_speech_verb)
custom_speech_verb = selected_custom_speech_verb
+
+ if("bodysprite")
+ var/selected_body_sprite = input(user, "Choose your desired body sprite", "Character Preference") as null|anything in pref_species.allowed_limb_ids
+ if(selected_body_sprite)
+ chosen_limb_id = selected_body_sprite //this gets sanitized before loading
else
switch(href_list["preference"])
//CITADEL PREFERENCES EDIT - I can't figure out how to modularize these, so they have to go here. :c -Pooj
@@ -2801,14 +2521,16 @@ GLOBAL_LIST_EMPTY(preferences_datums)
character.dna.features = features.Copy()
character.set_species(chosen_species, icon_update = FALSE, pref_load = TRUE)
+ if(chosen_limb_id && (chosen_limb_id in character.dna.species.allowed_limb_ids))
+ character.dna.species.mutant_bodyparts["limbs_id"] = chosen_limb_id
character.dna.real_name = character.real_name
character.dna.nameless = character.nameless
character.dna.custom_species = character.custom_species
- if(pref_species.mutant_bodyparts["meat_type"])
+ if((parent && parent.can_have_part("meat_type")) || pref_species.mutant_bodyparts["meat_type"])
character.type_of_meat = GLOB.meat_types[features["meat_type"]]
- if(character.dna.species.mutant_bodyparts["legs"] && (character.dna.features["legs"] == "Digitigrade" || character.dna.features["legs"] == "Avian"))
+ if(((parent && parent.can_have_part("legs")) || pref_species.mutant_bodyparts["legs"]) && (character.dna.features["legs"] == "Digitigrade" || character.dna.features["legs"] == "Avian"))
pref_species.species_traits |= DIGITIGRADE
else
pref_species.species_traits -= DIGITIGRADE
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index dffab645a4..55a594cf21 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -5,7 +5,7 @@
// You do not need to raise this if you are adding new values that have sane defaults.
// Only raise this value when changing the meaning/format/name/layout of an existing value
// where you would want the updater procs below to run
-#define SAVEFILE_VERSION_MAX 33
+#define SAVEFILE_VERSION_MAX 35
/*
SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn
@@ -200,6 +200,10 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
features["silicon_flavor_text"] = html_encode(features["silicon_flavor_text"])
features["ooc_notes"] = html_encode(features["ooc_notes"])
+ if(current_version < 35)
+ if(S["species"] == "lizard")
+ features["mam_snouts"] = features["snout"]
+
/datum/preferences/proc/load_path(ckey,filename="preferences.sav")
if(!ckey)
return
@@ -510,6 +514,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["scars3"] >> scars_list["3"]
S["scars4"] >> scars_list["4"]
S["scars5"] >> scars_list["5"]
+ S["chosen_limb_id"] >> chosen_limb_id
//Custom names
@@ -840,6 +845,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["feature_ooc_notes"], features["ooc_notes"])
+ WRITE_FILE(S["chosen_limb_id"], chosen_limb_id)
+
//Custom names
for(var/custom_name_id in GLOB.preferences_custom_names)
var/savefile_slot_name = custom_name_id + "_name" //TODO remove this
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index d540336b86..2fbe738acb 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -118,8 +118,7 @@
// Set the clothing's integrity back to 100%, remove all damage to bodyparts, and generally fix it up
/obj/item/clothing/proc/repair(mob/user, params)
- damaged_clothes = CLOTHING_PRISTINE
- update_clothes_damaged_state(FALSE)
+ update_clothes_damaged_state(CLOTHING_PRISTINE)
obj_integrity = max_integrity
name = initial(name) // remove "tattered" or "shredded" if there's a prefix
body_parts_covered = initial(body_parts_covered)
@@ -196,7 +195,7 @@
if(3 to INFINITY) // take better care of your shit, dude
name = "tattered [initial(name)]"
- update_clothes_damaged_state()
+ update_clothes_damaged_state(CLOTHING_DAMAGED)
/obj/item/clothing/Destroy()
user_vars_remembered = null //Oh god somebody put REFERENCES in here? not to worry, we'll clean it up
@@ -257,7 +256,7 @@
how_cool_are_your_threads += "Adding or removing items from [src] makes no noise.\n"
how_cool_are_your_threads += ""
. += how_cool_are_your_threads.Join()
-
+
if(LAZYLEN(armor_list))
armor_list.Cut()
if(armor.bio)
@@ -346,10 +345,16 @@
var/mob/M = loc
to_chat(M, "Your [name] starts to fall apart!")
-/obj/item/clothing/proc/update_clothes_damaged_state(damaging = TRUE)
- var/index = "[REF(initial(icon))]-[initial(icon_state)]"
- var/static/list/damaged_clothes_icons = list()
- if(damaging)
+//This mostly exists so subtypes can call appriopriate update icon calls on the wearer.
+/obj/item/clothing/proc/update_clothes_damaged_state(damaged_state = CLOTHING_DAMAGED)
+ damaged_clothes = damaged_state
+ update_icon()
+
+/obj/item/clothing/update_overlays()
+ . = ..()
+ if(damaged_clothes)
+ var/index = "[REF(initial(icon))]-[initial(icon_state)]"
+ var/static/list/damaged_clothes_icons = list()
var/icon/damaged_clothes_icon = damaged_clothes_icons[index]
if(!damaged_clothes_icon)
damaged_clothes_icon = icon(initial(icon), initial(icon_state), , 1) //we only want to apply damaged effect to the initial icon_state for each object
@@ -357,9 +362,7 @@
damaged_clothes_icon.Blend(icon('icons/effects/item_damage.dmi', "itemdamaged"), ICON_MULTIPLY) //adds damage effect and the remaining white areas become transparant
damaged_clothes_icon = fcopy_rsc(damaged_clothes_icon)
damaged_clothes_icons[index] = damaged_clothes_icon
- add_overlay(damaged_clothes_icon, TRUE)
- else
- cut_overlay(damaged_clothes_icons[index], TRUE)
+ . += damaged_clothes_icon
/*
SEE_SELF // can see self, no matter what
diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm
index 1c3ac0f340..b5d92fb780 100644
--- a/code/modules/clothing/gloves/miscellaneous.dm
+++ b/code/modules/clothing/gloves/miscellaneous.dm
@@ -199,12 +199,16 @@
/obj/item/clothing/gloves/evening
name = "evening gloves"
- desc = "Thin, pretty gloves intended for use in regal feminine attire, but knowing Space China these are just for some maid fetish."
+ desc = "Thin, pretty gloves intended for use in regal feminine attire. A tag on the hem claims they were 'maid' in Space China, these were probably intended for use in some maid fetish."
icon_state = "evening"
item_state = "evening"
- strip_delay = 40
- equip_delay_other = 20
+ transfer_prints = TRUE
cold_protection = HANDS
min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT
strip_mod = 0.9
- custom_price = PRICE_ALMOST_CHEAP
+
+/obj/item/clothing/gloves/evening/black
+ name = "midnight gloves"
+ desc = "Thin, pretty gloves intended for use in sexy feminine attire. A tag on the hem claims they pair great with black stockings."
+ icon_state = "eveningblack"
+ item_state = "eveningblack"
diff --git a/code/modules/clothing/gloves/tacklers.dm b/code/modules/clothing/gloves/tacklers.dm
index 11b2afa968..f4b4140a1a 100644
--- a/code/modules/clothing/gloves/tacklers.dm
+++ b/code/modules/clothing/gloves/tacklers.dm
@@ -72,6 +72,25 @@
siemens_coefficient = 0
permeability_coefficient = 0.05
+/obj/item/clothing/gloves/tackler/combat/insulated/infiltrator
+ name = "insidious guerrilla gloves"
+ desc = "Specialized combat gloves for carrying people around. Transfers tactical kidnapping and tackling knowledge to the user via the use of nanochips."
+ icon_state = "infiltrator"
+ item_state = "infiltrator"
+ siemens_coefficient = 0
+ permeability_coefficient = 0.05
+ resistance_flags = FIRE_PROOF | ACID_PROOF
+ var/carrytrait = TRAIT_QUICKER_CARRY
+
+/obj/item/clothing/gloves/tackler/combat/insulated/infiltrator/equipped(mob/user, slot)
+ . = ..()
+ if(slot == SLOT_GLOVES)
+ ADD_TRAIT(user, carrytrait, GLOVE_TRAIT)
+
+/obj/item/clothing/gloves/tackler/combat/insulated/infiltrator/dropped(mob/user)
+ . = ..()
+ REMOVE_TRAIT(user, carrytrait, GLOVE_TRAIT)
+
/obj/item/clothing/gloves/tackler/rocket
name = "rocket gloves"
desc = "The ultimate in high risk, high reward, perfect for when you need to stop a criminal from fifty feet away or die trying. Banned in most Spinward gridiron football and rugby leagues."
diff --git a/code/modules/clothing/masks/boxing.dm b/code/modules/clothing/masks/boxing.dm
index f11c89d00c..6701b53c10 100644
--- a/code/modules/clothing/masks/boxing.dm
+++ b/code/modules/clothing/masks/boxing.dm
@@ -12,6 +12,10 @@
/obj/item/clothing/mask/balaclava/attack_self(mob/user)
adjustmask(user)
+/obj/item/clothing/mask/balaclava/breath
+ name = "breathaclava"
+ clothing_flags = ALLOWINTERNALS
+
/obj/item/clothing/mask/infiltrator
name = "insidious balaclava"
desc = "An incredibly suspicious balaclava made with Syndicate nanofibers to absorb impacts slightly while obfuscating the voice and face using a garbled vocoder."
diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm
index 6364a9a1c1..d6853f52ca 100644
--- a/code/modules/clothing/suits/miscellaneous.dm
+++ b/code/modules/clothing/suits/miscellaneous.dm
@@ -625,7 +625,7 @@
desc = "An arctic white winter coat with a small blue caduceus instead of a plastic zipper tab. Snazzy."
icon_state = "coatmedical"
item_state = "coatmedical"
- allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
+ allowed = list(/obj/item/analyzer, /obj/item/sensor_device, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 50, "rad" = 0, "fire" = 0, "acid" = 45)
hoodtype = /obj/item/clothing/head/hooded/winterhood/medical
@@ -638,7 +638,7 @@
desc = "An arctic white winter coat with a small blue caduceus instead of a plastic zipper tab. The normal liner is replaced with an exceptionally thick, soft layer of fur."
icon_state = "coatcmo"
item_state = "coatcmo"
- allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
+ allowed = list(/obj/item/analyzer, /obj/item/sensor_device, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
armor = list("melee" = 5, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 50, "rad" = 0, "fire" = 0, "acid" = 0)
hoodtype = /obj/item/clothing/head/hooded/winterhood/cmo
@@ -651,7 +651,7 @@
desc = "A lab-grade winter coat made with acid resistant polymers. For the enterprising chemist who was exiled to a frozen wasteland on the go."
icon_state = "coatchemistry"
item_state = "coatchemistry"
- allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
+ allowed = list(/obj/item/analyzer, /obj/item/sensor_device, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 30, "rad" = 0, "fire" = 30, "acid" = 45)
hoodtype = /obj/item/clothing/head/hooded/winterhood/chemistry
@@ -664,7 +664,7 @@
desc = "A white winter coat with green markings. Warm, but wont fight off the common cold or any other disease. Might make people stand far away from you in the hallway. The zipper tab looks like an oversized bacteriophage."
icon_state = "coatviro"
item_state = "coatviro"
- allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
+ allowed = list(/obj/item/analyzer, /obj/item/sensor_device, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 30, "rad" = 0, "fire" = 0, "acid" = 0)
hoodtype = /obj/item/clothing/head/hooded/winterhood/viro
@@ -677,7 +677,7 @@
desc = "A winter coat with blue markings. Warm, but probably won't protect from biological agents. For the cozy doctor on the go."
icon_state = "coatparamed"
item_state = "coatparamed"
- allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
+ allowed = list(/obj/item/analyzer, /obj/item/sensor_device, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 50, "rad" = 0, "fire" = 0, "acid" = 45)
hoodtype = /obj/item/clothing/head/hooded/winterhood/paramedic
diff --git a/code/modules/events/alien_infestation.dm b/code/modules/events/alien_infestation.dm
index 69e9a974eb..993577cb30 100644
--- a/code/modules/events/alien_infestation.dm
+++ b/code/modules/events/alien_infestation.dm
@@ -3,7 +3,7 @@
typepath = /datum/round_event/ghost_role/alien_infestation
weight = 5
gamemode_blacklist = list("dynamic")
- min_players = 10
+ min_players = 25
max_occurrences = 1
/datum/round_event/ghost_role/alien_infestation
diff --git a/code/modules/events/brand_intelligence.dm b/code/modules/events/brand_intelligence.dm
index da5b4c0cb2..1c88e68377 100644
--- a/code/modules/events/brand_intelligence.dm
+++ b/code/modules/events/brand_intelligence.dm
@@ -27,7 +27,6 @@
"How do I vore people?",
"ERP?",
"Not epic bros...")
- threat = 5
/datum/round_event/brand_intelligence/announce(fake)
diff --git a/code/modules/events/pirates.dm b/code/modules/events/pirates.dm
index af44b54ed0..9ab5e8d517 100644
--- a/code/modules/events/pirates.dm
+++ b/code/modules/events/pirates.dm
@@ -25,7 +25,7 @@
ship_name = pick(strings(PIRATE_NAMES_FILE, "ship_names"))
/datum/round_event/pirates/announce(fake)
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
+ priority_announce("A business proposition has been downloaded and printed out at all communication consoles.", "Incoming Business Proposition", "commandreport")
if(fake)
return
threat_message = new
@@ -49,6 +49,7 @@
else
priority_announce("Trying to cheat us? You'll regret this!",sender_override = ship_name)
if(!shuttle_spawned)
+ priority_announce("You won't listen to reason? Then we'll take what's yours or die trying!",sender_override = ship_name)
spawn_shuttle()
/datum/round_event/pirates/start()
@@ -83,8 +84,7 @@
announce_to_ghosts(M)
else
announce_to_ghosts(spawner)
-
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") //CITADEL EDIT also metabreak here too
+ priority_announce("Unidentified ship detected near the station.")
//Shuttle equipment
diff --git a/code/modules/events/wizard/magicarp.dm b/code/modules/events/wizard/magicarp.dm
index 4d2e8e624c..57e2a2a051 100644
--- a/code/modules/events/wizard/magicarp.dm
+++ b/code/modules/events/wizard/magicarp.dm
@@ -30,7 +30,6 @@
icon_dead = "magicarp_dead"
icon_gib = "magicarp_gib"
ranged = 1
- threat = 4
retreat_distance = 2
minimum_distance = 0 //Between shots they can and will close in to nash
projectiletype = /obj/item/projectile/magic
@@ -52,7 +51,6 @@
color = "#00FFFF"
maxHealth = 75
health = 75
- threat = 7
/mob/living/simple_animal/hostile/carp/ranged/chaos/Shoot()
projectiletype = pick(allowed_projectile_types)
diff --git a/code/modules/events/wizard/shuffle.dm b/code/modules/events/wizard/shuffle.dm
index 3b5ea6b20a..18b8c8e21c 100644
--- a/code/modules/events/wizard/shuffle.dm
+++ b/code/modules/events/wizard/shuffle.dm
@@ -94,7 +94,7 @@
shuffle_inplace(mobs)
- var/obj/effect/proc_holder/spell/targeted/mind_transfer/swapper = new /obj/effect/proc_holder/spell/targeted/mind_transfer
+ var/obj/effect/proc_holder/spell/pointed/mind_transfer/swapper = new /obj/effect/proc_holder/spell/pointed/mind_transfer
while(mobs.len > 1)
var/mob/living/carbon/human/H = pick(mobs)
mobs -= H
diff --git a/code/modules/food_and_drinks/food/snacks.dm b/code/modules/food_and_drinks/food/snacks.dm
index 895699434a..4d5f4e2dd0 100644
--- a/code/modules/food_and_drinks/food/snacks.dm
+++ b/code/modules/food_and_drinks/food/snacks.dm
@@ -97,9 +97,12 @@ All foods are distributed among various categories. Use common sense.
return
-/obj/item/reagent_containers/food/snacks/attack(mob/living/M, mob/living/user, def_zone)
+/obj/item/reagent_containers/food/snacks/attack(mob/living/M, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
if(user.a_intent == INTENT_HARM)
return ..()
+ INVOKE_ASYNC(src, .proc/attempt_forcefeed, M, user)
+
+/obj/item/reagent_containers/food/snacks/proc/attempt_forcefeed(mob/living/M, mob/living/user)
if(!eatverb)
eatverb = pick("bite","chew","nibble","gnaw","gobble","chomp")
if(!reagents.total_volume) //Shouldn't be needed but it checks to see if it has anything left in it.
diff --git a/code/modules/holiday/halloween/halloween.dm b/code/modules/holiday/halloween/halloween.dm
index 6c9e527f38..d3b9b92b4f 100644
--- a/code/modules/holiday/halloween/halloween.dm
+++ b/code/modules/holiday/halloween/halloween.dm
@@ -190,7 +190,6 @@
icon_dead = "scary_clown"
icon_gib = "scary_clown"
speak = list("...", ". . .")
- threat = 3
maxHealth = 120
health = 120
emote_see = list("silently stares")
diff --git a/code/modules/hydroponics/gene_modder.dm b/code/modules/hydroponics/gene_modder.dm
index 4e545c13ee..a0c273613f 100644
--- a/code/modules/hydroponics/gene_modder.dm
+++ b/code/modules/hydroponics/gene_modder.dm
@@ -3,9 +3,9 @@
desc = "An advanced device designed to manipulate plant genetic makeup."
icon = 'icons/obj/hydroponics/equipment.dmi'
icon_state = "dnamod"
- density = TRUE
circuit = /obj/item/circuitboard/machine/plantgenes
- pass_flags = PASSTABLE
+ pass_flags = PASSTABLE | LETPASSTHROW
+ flags_1 = DEFAULT_RICOCHET_1
var/obj/item/seeds/seed
var/obj/item/disk/plantgene/disk
diff --git a/code/modules/hydroponics/grown/cannabis.dm b/code/modules/hydroponics/grown/cannabis.dm
index 621e79fb77..6525ac42d4 100644
--- a/code/modules/hydroponics/grown/cannabis.dm
+++ b/code/modules/hydroponics/grown/cannabis.dm
@@ -14,9 +14,7 @@
icon_dead = "cannabis-dead" // Same for the dead icon
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/cannabis/rainbow,
- /obj/item/seeds/cannabis/death,
- /obj/item/seeds/cannabis/white,
- /obj/item/seeds/cannabis/ultimate)
+ /obj/item/seeds/cannabis/death)
reagents_add = list(/datum/reagent/drug/space_drugs = 0.15, /datum/reagent/toxin/lipolicide = 0.35) // gives u the munchies
@@ -27,7 +25,7 @@
species = "megacannabis"
plantname = "Rainbow Weed"
product = /obj/item/reagent_containers/food/snacks/grown/cannabis/rainbow
- mutatelist = list()
+ mutatelist = list(/obj/item/seeds/cannabis/ultimate)
reagents_add = list(/datum/reagent/toxin/mindbreaker = 0.15, /datum/reagent/toxin/lipolicide = 0.35)
rarity = 40
@@ -38,7 +36,7 @@
species = "blackcannabis"
plantname = "Deathweed"
product = /obj/item/reagent_containers/food/snacks/grown/cannabis/death
- mutatelist = list()
+ mutatelist = list(/obj/item/seeds/cannabis/white)
reagents_add = list(/datum/reagent/toxin/cyanide = 0.35, /datum/reagent/drug/space_drugs = 0.15, /datum/reagent/toxin/lipolicide = 0.15)
rarity = 40
diff --git a/code/modules/hydroponics/grown/citrus.dm b/code/modules/hydroponics/grown/citrus.dm
index 6ac7bbcfcb..d130d50aa5 100644
--- a/code/modules/hydroponics/grown/citrus.dm
+++ b/code/modules/hydroponics/grown/citrus.dm
@@ -33,26 +33,6 @@
filling_color = "#00FF00"
juice_results = list(/datum/reagent/consumable/limejuice = 0)
-// Electric Lime
-/obj/item/seeds/lime/electric
- name = "pack of electric lime seeds"
- desc = "Electrically sour seeds."
- icon_state = "seed-electriclime"
- species = "electric lime"
- plantname = "Electric Lime Tree"
- growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi'
- icon_grow = "lime-grow"
- icon_dead = "lime-dead"
- icon_harvest = "lime-harvest"
- product = /obj/item/reagent_containers/food/snacks/grown/citrus/lime/electric
- genes = list(/datum/plant_gene/trait/repeated_harvest, /datum/plant_gene/trait/cell_charge, /datum/plant_gene/trait/glow/green)
-
-/obj/item/reagent_containers/food/snacks/grown/citrus/lime/electric
- seed = /obj/item/seeds/lime/electric
- name = "electric lime"
- desc = "It's so sour, you'll be shocked!"
- icon_state = "electriclime"
-
// Orange
/obj/item/seeds/orange
name = "pack of orange seeds"
diff --git a/code/modules/hydroponics/grown/garlic.dm b/code/modules/hydroponics/grown/garlic.dm
index 4184b85008..2cc3f41860 100644
--- a/code/modules/hydroponics/grown/garlic.dm
+++ b/code/modules/hydroponics/grown/garlic.dm
@@ -9,6 +9,9 @@
potency = 25
growthstages = 3
growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi'
+ icon_grow = "garlic-grow"
+ icon_harvest = "garlic-harvest"
+ icon_dead = "garlic-dead"
reagents_add = list(/datum/reagent/consumable/garlic = 0.15, /datum/reagent/consumable/nutriment = 0.1)
/obj/item/reagent_containers/food/snacks/grown/garlic
diff --git a/code/modules/hydroponics/grown/grass_carpet.dm b/code/modules/hydroponics/grown/grass_carpet.dm
index 3b5159465c..a74850f3be 100644
--- a/code/modules/hydroponics/grown/grass_carpet.dm
+++ b/code/modules/hydroponics/grown/grass_carpet.dm
@@ -51,6 +51,7 @@
icon_grow = "fairygrass-grow"
icon_dead = "fairygrass-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest, /datum/plant_gene/trait/glow/blue)
+ mutatelist = list (/obj/item/seeds/grass/carpet)
reagents_add = list(/datum/reagent/consumable/nutriment = 0.02, /datum/reagent/hydrogen = 0.05, /datum/reagent/drug/space_drugs = 0.15)
/obj/item/reagent_containers/food/snacks/grown/grass/fairy
@@ -99,7 +100,7 @@
species = "carpet"
plantname = "Carpet"
product = /obj/item/reagent_containers/food/snacks/grown/grass/carpet
- mutatelist = list()
+ mutatelist = list(/obj/item/seeds/grass/fairy)
rarity = 10
/obj/item/reagent_containers/food/snacks/grown/grass/carpet
diff --git a/code/modules/hydroponics/grown/tea_coffee.dm b/code/modules/hydroponics/grown/tea_coffee.dm
index de27d1eed7..223b2c7bce 100644
--- a/code/modules/hydroponics/grown/tea_coffee.dm
+++ b/code/modules/hydroponics/grown/tea_coffee.dm
@@ -44,7 +44,7 @@
filling_color = "#4582B4"
grind_results = list(/datum/reagent/toxin/teapowder = 0, /datum/reagent/medicine/salglu_solution = 0)
-// Kitty drugs
+// Catnip
/obj/item/seeds/tea/catnip
name = "pack of catnip seeds"
icon_state = "seed-catnip"
@@ -52,6 +52,9 @@
species = "catnip"
plantname = "Catnip Plant"
growthstages = 3
+ icon_grow = "catnip-grow"
+ icon_harvest = "catnip-harvest"
+ icon_dead = "tea-dead"
product = /obj/item/reagent_containers/food/snacks/grown/tea/catnip
reagents_add = list(/datum/reagent/pax/catnip = 0.1, /datum/reagent/consumable/nutriment/vitamin = 0.06, /datum/reagent/toxin/teapowder = 0.3)
rarity = 50
diff --git a/code/modules/hydroponics/hydroitemdefines.dm b/code/modules/hydroponics/hydroitemdefines.dm
index abf6632939..f6be9db9a2 100644
--- a/code/modules/hydroponics/hydroitemdefines.dm
+++ b/code/modules/hydroponics/hydroitemdefines.dm
@@ -103,6 +103,7 @@
throwforce = 5
throw_speed = 2
throw_range = 3
+ attack_speed = CLICK_CD_MELEE
w_class = WEIGHT_CLASS_BULKY
flags_1 = CONDUCT_1
armour_penetration = 20
@@ -125,9 +126,12 @@
playsound(src,pick('sound/misc/desceration-01.ogg','sound/misc/desceration-02.ogg','sound/misc/desceration-01.ogg') ,50, 1, -1)
return (BRUTELOSS)
-/obj/item/scythe/pre_attack(atom/A, mob/living/user, params)
+/obj/item/scythe/pre_attack(atom/A, mob/living/user, params, attackchain_flags, damage_multiplier)
+ . = ..()
+ if(. & STOP_ATTACK_PROC_CHAIN)
+ return
if(swiping || !istype(A, /obj/structure/spacevine) || get_turf(A) == get_turf(user))
- return ..()
+ return
else
var/turf/user_turf = get_turf(user)
var/dir_to_target = get_dir(user_turf, get_turf(A))
@@ -138,11 +142,12 @@
var/turf/T = get_step(user_turf, turn(dir_to_target, i))
for(var/obj/structure/spacevine/V in T)
if(user.Adjacent(V))
- melee_attack_chain(user, V)
+ melee_attack_chain(user, V, attackchain_flags = ATTACK_IGNORE_CLICKDELAY)
stam_gain += 5 //should be hitcost
swiping = FALSE
stam_gain += 2 //Initial hitcost
user.adjustStaminaLoss(-stam_gain)
+ user.DelayNextAction()
// *************************************
// Nutrient defines for hydroponics
@@ -192,4 +197,4 @@
/obj/item/reagent_containers/glass/bottle/killer/pestkiller
name = "bottle of pest spray"
desc = "Contains a pesticide."
- list_reagents = list(/datum/reagent/toxin/pestkiller = 50)
\ No newline at end of file
+ list_reagents = list(/datum/reagent/toxin/pestkiller = 50)
diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm
index 06179d1087..a208f2de3c 100644
--- a/code/modules/hydroponics/hydroponics.dm
+++ b/code/modules/hydroponics/hydroponics.dm
@@ -30,7 +30,7 @@
var/self_sufficiency_req = 20 //Required total dose to make a self-sufficient hydro tray. 1:1 with earthsblood.
var/self_sufficiency_progress = 0
var/self_sustaining = FALSE //If the tray generates nutrients and water on its own
-
+ var/canirrigate = TRUE //tin
/obj/machinery/hydroponics/constructable
name = "hydroponics tray"
@@ -847,12 +847,13 @@
if (!anchored)
to_chat(user, "Anchor the tray first!")
return
- using_irrigation = !using_irrigation
- O.play_tool_sound(src)
- user.visible_message("[user] [using_irrigation ? "" : "dis"]connects [src]'s irrigation hoses.", \
- "You [using_irrigation ? "" : "dis"]connect [src]'s irrigation hoses.")
- for(var/obj/machinery/hydroponics/h in range(1,src))
- h.update_icon()
+ if(canirrigate)
+ using_irrigation = !using_irrigation
+ O.play_tool_sound(src)
+ user.visible_message("[user] [using_irrigation ? "" : "dis"]connects [src]'s irrigation hoses.", \
+ "You [using_irrigation ? "" : "dis"]connect [src]'s irrigation hoses.")
+ for(var/obj/machinery/hydroponics/h in range(1,src))
+ h.update_icon()
else if(istype(O, /obj/item/shovel/spade))
if(!myseed && !weedlevel)
@@ -910,11 +911,14 @@
harvest = 0
lastproduce = age
if(istype(myseed, /obj/item/seeds/replicapod))
- to_chat(user, "You harvest from the [myseed.plantname].")
+ if(user)//runtimes
+ to_chat(user, "You harvest from the [myseed.plantname].")
else if(myseed.getYield() <= 0)
- to_chat(user, "You fail to harvest anything useful!")
+ if(user)
+ to_chat(user, "You fail to harvest anything useful!")
else
- to_chat(user, "You harvest [myseed.getYield()] items from the [myseed.plantname].")
+ if(user)
+ to_chat(user, "You harvest [myseed.getYield()] items from the [myseed.plantname].")
if(!myseed.get_gene(/datum/plant_gene/trait/repeated_harvest))
qdel(myseed)
myseed = null
diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm
index 5e49a32a23..c7314bf180 100644
--- a/code/modules/hydroponics/seeds.dm
+++ b/code/modules/hydroponics/seeds.dm
@@ -190,6 +190,31 @@ obj/item/seeds/proc/is_gene_forbidden(typepath)
parent.update_tray(user)
return result
+/obj/item/seeds/proc/harvest_userless()
+ var/obj/machinery/hydroponics/parent = loc //for ease of access
+ var/t_amount = 0
+ var/list/result = list()
+ var/output_loc = parent.loc
+ var/product_name
+ while(t_amount < getYield())
+ var/obj/item/reagent_containers/food/snacks/grown/t_prod = new product(output_loc, src)
+ if(parent.myseed.plantname != initial(parent.myseed.plantname))
+ t_prod.name = lowertext(parent.myseed.plantname)
+ if(productdesc)
+ t_prod.desc = productdesc
+ t_prod.seed.name = parent.myseed.name
+ t_prod.seed.desc = parent.myseed.desc
+ t_prod.seed.plantname = parent.myseed.plantname
+ result.Add(t_prod) // User gets a consumable
+ if(!t_prod)
+ return
+ t_amount++
+ product_name = parent.myseed.plantname
+ if(getYield() >= 1)
+ SSblackbox.record_feedback("tally", "food_harvested", getYield(), product_name)
+ parent.investigate_log("autmoatic harvest of [getYield()] of [src], with seed traits [english_list(genes)] and reagents_add [english_list(reagents_add)] and potency [potency].", INVESTIGATE_BOTANY)
+ parent.update_tray()
+ return result
/obj/item/seeds/proc/prepare_result(var/obj/item/reagent_containers/food/snacks/grown/T)
if(!T.reagents)
diff --git a/code/modules/instruments/songs/_song.dm b/code/modules/instruments/songs/_song.dm
index d842dbc003..a0d96658e6 100644
--- a/code/modules/instruments/songs/_song.dm
+++ b/code/modules/instruments/songs/_song.dm
@@ -2,6 +2,12 @@
#define MUSIC_MAXLINES 1000
#define MUSIC_MAXLINECHARS 300
+/**
+ * # Song datum
+ *
+ * These are the actual backend behind instruments.
+ * They attach to an atom and provide the editor + playback functionality.
+ */
/datum/song
/// Name of the song
var/name = "Untitled"
@@ -15,6 +21,9 @@
/// delay between notes in deciseconds
var/tempo = 5
+ /// How far we can be heard
+ var/instrument_range = 15
+
/// Are we currently playing?
var/playing = FALSE
@@ -53,17 +62,24 @@
/////////////////// Playing variables ////////////////
/**
- * Only used in synthesized playback - The chords we compiled. Non assoc list of lists:
- * list(list(key1, key2, key3..., tempo_divisor), list(key1, key2..., tempo_divisor), ...)
- * tempo_divisor always exists
- * if key1 (and so if there's no keys) doesn't exist it's a rest
+ * Build by compile_chords()
+ * Must be rebuilt on instrument switch.
* Compilation happens when we start playing and is cleared after we finish playing.
+ * Format: list of chord lists, with chordlists having (key1, key2, key3, tempodiv)
*/
var/list/compiled_chords
+ /// Current section of a long chord we're on, so we don't need to make a billion chords, one for every unit ticklag.
+ var/elapsed_delay
+ /// Amount of delay to wait before playing the next chord
+ var/delay_by
+ /// Current chord we're on.
+ var/current_chord
/// Channel as text = current volume percentage but it's 0 to 100 instead of 0 to 1.
var/list/channels_playing = list()
/// List of channels that aren't being used, as text. This is to prevent unnecessary freeing and reallocations from SSsounds/SSinstruments.
var/list/channels_idle = list()
+ /// Person playing us
+ var/mob/user_playing
//////////////////////////////////////////////////////
/// Last world.time we checked for who can hear us
@@ -72,8 +88,6 @@
var/list/hearing_mobs
/// If this is enabled, some things won't be strictly cleared when they usually are (liked compiled_chords on play stop)
var/debug_mode = FALSE
- /// Last time we processed decay
- var/last_process_decay
/// Max sound channels to occupy
var/max_sound_channels = CHANNELS_PER_INSTRUMENT
/// Current channels, so we can save a length() call.
@@ -113,7 +127,7 @@
var/cached_exponential_dropoff = 1.045
/////////////////////////////////////////////////////////////////////////
-/datum/song/New(atom/parent, list/instrument_ids)
+/datum/song/New(atom/parent, list/instrument_ids, new_range)
SSinstruments.on_song_new(src)
lines = list()
tempo = sanitize_tempo(tempo)
@@ -125,6 +139,8 @@
hearing_mobs = list()
volume = clamp(volume, min_volume, max_volume)
update_sustain()
+ if(new_range)
+ instrument_range = new_range
/datum/song/Destroy()
stop_playing()
@@ -135,12 +151,15 @@
parent = null
return ..()
+/**
+ * Checks and stores which mobs can hear us. Terminates sounds for mobs that leave our range.
+ */
/datum/song/proc/do_hearcheck()
last_hearcheck = world.time
var/list/old = hearing_mobs.Copy()
hearing_mobs.len = 0
var/turf/source = get_turf(parent)
- for(var/mob/M in get_hearers_in_view(15, source))
+ for(var/mob/M in get_hearers_in_view(instrument_range, source))
if(!(M?.client?.prefs?.toggles & SOUND_INSTRUMENTS))
continue
hearing_mobs[M] = get_dist(M, source)
@@ -148,10 +167,15 @@
for(var/i in exited)
terminate_sound_mob(i)
-/// I can either be a datum, id, or path (if the instrument has no id).
+/**
+ * Sets our instrument, caching anything necessary for faster accessing. Accepts an ID, typepath, or instantiated instrument datum.
+ */
/datum/song/proc/set_instrument(datum/instrument/I)
+ terminate_all_sounds()
+ var/old_legacy
if(using_instrument)
using_instrument.songs_using -= src
+ old_legacy = (using_instrument.instrument_flags & INSTRUMENT_LEGACY)
using_instrument = null
cached_samples = null
cached_legacy_ext = null
@@ -162,7 +186,7 @@
if(istype(I))
using_instrument = I
I.songs_using += src
- var/instrument_legacy = CHECK_BITFIELD(I.instrument_flags, INSTRUMENT_LEGACY)
+ var/instrument_legacy = (I.instrument_flags & INSTRUMENT_LEGACY)
if(instrument_legacy)
cached_legacy_ext = I.legacy_instrument_ext
cached_legacy_dir = I.legacy_instrument_path
@@ -170,23 +194,37 @@
else
cached_samples = I.samples
legacy = FALSE
+ if(isnull(old_legacy) || (old_legacy != instrument_legacy))
+ if(playing)
+ compile_chords()
-/// THIS IS A BLOCKING CALL.
+/**
+ * Attempts to start playing our song.
+ */
/datum/song/proc/start_playing(mob/user)
if(playing)
return
if(!using_instrument?.ready())
to_chat(user, "An error has occured with [src]. Please reset the instrument.")
return
+ compile_chords()
+ if(!length(compiled_chords))
+ to_chat(user, "Song is empty.")
+ return
playing = TRUE
- updateDialog()
+ updateDialog(user_playing)
//we can not afford to runtime, since we are going to be doing sound channel reservations and if we runtime it means we have a channel allocation leak.
//wrap the rest of the stuff to ensure stop_playing() is called.
- last_process_decay = world.time
+ do_hearcheck()
+ elapsed_delay = 0
+ delay_by = 0
+ current_chord = 1
+ user_playing = user
START_PROCESSING(SSinstruments, src)
- . = do_play_lines(user)
- stop_playing()
+/**
+ * Stops playing, terminating all sounds if in synthesized mode. Clears hearing_mobs.
+ */
/datum/song/proc/stop_playing()
if(!playing)
return
@@ -196,42 +234,93 @@
STOP_PROCESSING(SSinstruments, src)
terminate_all_sounds(TRUE)
hearing_mobs.len = 0
- updateDialog()
+ user_playing = null
-/// THIS IS A BLOCKING CALL.
-/datum/song/proc/do_play_lines(user)
- if(!playing)
+/**
+ * Processes our song.
+ */
+/datum/song/proc/process_song(wait)
+ if(!length(compiled_chords) || should_stop_playing(user_playing))
+ stop_playing()
return
- do_hearcheck()
- if(legacy)
- do_play_lines_legacy(user)
- else
- do_play_lines_synthesized(user)
+ var/list/chord = compiled_chords[current_chord]
+ if(++elapsed_delay >= delay_by)
+ play_chord(chord)
+ elapsed_delay = 0
+ delay_by = tempodiv_to_delay(chord[length(chord)])
+ current_chord++
+ if(current_chord > length(compiled_chords))
+ if(repeat)
+ repeat--
+ current_chord = 1
+ return
+ else
+ stop_playing()
+ return
+/**
+ * Converts a tempodiv to ticks to elapse before playing the next chord, taking into account our tempo.
+ */
+/datum/song/proc/tempodiv_to_delay(tempodiv)
+ if(!tempodiv)
+ tempodiv = 1 // no division by 0. some song converters tend to use 0 for when it wants to have no div, for whatever reason.
+ return max(1, round((tempo/tempodiv) / world.tick_lag, 1))
+
+/**
+ * Compiles chords.
+ */
+/datum/song/proc/compile_chords()
+ legacy? compile_legacy() : compile_synthesized()
+
+/**
+ * Plays a chord.
+ */
+/datum/song/proc/play_chord(list/chord)
+ // last value is timing information
+ for(var/i in 1 to (length(chord) - 1))
+ legacy? playkey_legacy(chord[i][1], chord[i][2], chord[i][3], user_playing) : playkey_synth(chord[i], user_playing)
+
+/**
+ * Checks if we should halt playback.
+ */
/datum/song/proc/should_stop_playing(mob/user)
return QDELETED(parent) || !using_instrument || !playing
+/**
+ * Sanitizes tempo to a value that makes sense and fits the current world.tick_lag.
+ */
/datum/song/proc/sanitize_tempo(new_tempo)
new_tempo = abs(new_tempo)
return clamp(round(new_tempo, world.tick_lag), world.tick_lag, 5 SECONDS)
+/**
+ * Gets our beats per minute based on our tempo.
+ */
/datum/song/proc/get_bpm()
return 600 / tempo
+/**
+ * Sets our tempo from a beats-per-minute, sanitizing it to a valid number first.
+ */
/datum/song/proc/set_bpm(bpm)
tempo = sanitize_tempo(600 / bpm)
-/// Updates the window for our user. Override in subtypes.
-/datum/song/proc/updateDialog(mob/user = usr)
+/**
+ * Updates the window for our users. Override down the line.
+ */
+/datum/song/proc/updateDialog(mob/user)
ui_interact(user)
/datum/song/process(wait)
if(!playing)
return PROCESS_KILL
- var/delay = world.time - last_process_decay
- process_decay(delay)
- last_process_decay = world.time
+ // it's expected this ticks at every world.tick_lag. if it lags, do not attempt to catch up.
+ process_song(world.tick_lag)
+ process_decay(world.tick_lag)
+/**
+ * Updates our cached linear/exponential falloff stuff, saving calculations down the line.
+ */
/datum/song/proc/update_sustain()
// Exponential is easy
cached_exponential_dropoff = sustain_exponential_dropoff
@@ -241,21 +330,33 @@
var/volume_decrease_per_decisecond = volume_diff / target_duration
cached_linear_dropoff = volume_decrease_per_decisecond
+/**
+ * Setter for setting output volume.
+ */
/datum/song/proc/set_volume(volume)
src.volume = clamp(volume, max(0, min_volume), min(100, max_volume))
update_sustain()
updateDialog()
+/**
+ * Setter for setting how low the volume has to get before a note is considered "dead" and dropped
+ */
/datum/song/proc/set_dropoff_volume(volume)
sustain_dropoff_volume = clamp(volume, INSTRUMENT_MIN_SUSTAIN_DROPOFF, 100)
update_sustain()
updateDialog()
+/**
+ * Setter for setting exponential falloff factor.
+ */
/datum/song/proc/set_exponential_drop_rate(drop)
sustain_exponential_dropoff = clamp(drop, INSTRUMENT_EXP_FALLOFF_MIN, INSTRUMENT_EXP_FALLOFF_MAX)
update_sustain()
updateDialog()
+/**
+ * Setter for setting linear falloff duration.
+ */
/datum/song/proc/set_linear_falloff_duration(duration)
sustain_linear_duration = clamp(duration, 0.1, INSTRUMENT_MAX_TOTAL_SUSTAIN)
update_sustain()
@@ -277,10 +378,8 @@
// subtype for handheld instruments, like violin
/datum/song/handheld
-/datum/song/handheld/updateDialog(mob/user = usr)
- if(user.machine != src)
- return
- parent.ui_interact(user)
+/datum/song/handheld/updateDialog(mob/user)
+ parent.ui_interact(user || usr)
/datum/song/handheld/should_stop_playing(mob/user)
. = ..()
@@ -292,10 +391,8 @@
// subtype for stationary structures, like pianos
/datum/song/stationary
-/datum/song/stationary/updateDialog(mob/user = usr)
- if(user.machine != src)
- return
- parent.ui_interact(user)
+/datum/song/stationary/updateDialog(mob/user)
+ parent.ui_interact(user || usr)
/datum/song/stationary/should_stop_playing(mob/user)
. = ..()
diff --git a/code/modules/instruments/songs/play_legacy.dm b/code/modules/instruments/songs/play_legacy.dm
index fa64656ebc..eee9be3cc7 100644
--- a/code/modules/instruments/songs/play_legacy.dm
+++ b/code/modules/instruments/songs/play_legacy.dm
@@ -1,48 +1,52 @@
-/// Playing legacy instruments - None of the "advanced" like sound reservations and decay are invoked.
-/datum/song/proc/do_play_lines_legacy(mob/user)
- while(repeat >= 0)
- var/cur_oct[7]
- var/cur_acc[7]
- for(var/i = 1 to 7)
- cur_oct[i] = 3
- cur_acc[i] = "n"
+/**
+ * Compiles our lines into "chords" with filenames for legacy playback. This makes there have to be a bit of lag at the beginning of the song, but repeats will not have to parse it again, and overall playback won't be impacted by as much lag.
+ */
+/datum/song/proc/compile_legacy()
+ if(!length(src.lines))
+ return
+ var/list/lines = src.lines //cache for hyepr speed!
+ compiled_chords = list()
+ var/list/octaves = list(3, 3, 3, 3, 3, 3, 3)
+ var/list/accents = list("n", "n", "n", "n", "n", "n", "n")
+ for(var/line in lines)
+ var/list/chords = splittext(lowertext(line), ",")
+ for(var/chord in chords)
+ var/list/compiled_chord = list()
+ var/tempodiv = 1
+ var/list/notes_tempodiv = splittext(chord, "/")
+ var/len = length(notes_tempodiv)
+ if(len >= 2)
+ tempodiv = text2num(notes_tempodiv[2])
+ if(len) //some dunkass is going to do ,,,, to make 3 rests instead of ,/1 because there's no standardization so let's be prepared for that.
+ var/list/notes = splittext(notes_tempodiv[1], "-")
+ for(var/note in notes)
+ if(length(note) == 0)
+ continue
+ // 1-7, A-G
+ var/key = text2ascii(note) - 96
+ if((key < 1) || (key > 7))
+ continue
+ for(var/i in 2 to length(note))
+ var/oct_acc = copytext(note, i, i + 1)
+ var/num = text2num(oct_acc)
+ if(!num) //it's an accidental
+ accents[key] = oct_acc //if they misspelled it/fucked up that's on them lmao, no safety checks.
+ else //octave
+ octaves[key] = clamp(num, octave_min, octave_max)
+ compiled_chord[++compiled_chord.len] = list(key, accents[key], octaves[key])
+ compiled_chord += tempodiv //this goes last
+ if(length(compiled_chord))
+ compiled_chords[++compiled_chords.len] = compiled_chord
- for(var/line in lines)
- for(var/beat in splittext(lowertext(line), ","))
- if(should_stop_playing(user))
- return
- var/list/notes = splittext(beat, "/")
- if(length(notes)) //because some jack-butts are going to do ,,,, to symbolize 3 rests instead of something reasonable like ,/1.
- for(var/note in splittext(notes[1], "-"))
- if(length(note) == 0)
- continue
- var/cur_note = text2ascii(note) - 96
- if(cur_note < 1 || cur_note > 7)
- continue
- for(var/i=2 to length(note))
- var/ni = copytext(note,i,i+1)
- if(!text2num(ni))
- if(ni == "#" || ni == "b" || ni == "n")
- cur_acc[cur_note] = ni
- else if(ni == "s")
- cur_acc[cur_note] = "#" // so shift is never required
- else
- cur_oct[cur_note] = text2num(ni)
- playnote_legacy(cur_note, cur_acc[cur_note], cur_oct[cur_note])
- if(notes.len >= 2 && text2num(notes[2]))
- sleep(sanitize_tempo(tempo / text2num(notes[2])))
- else
- sleep(tempo)
- if(should_stop_playing(user))
- return
- repeat--
- updateDialog()
- repeat = 0
-
-// note is a number from 1-7 for A-G
-// acc is either "b", "n", or "#"
-// oct is 1-8 (or 9 for C)
-/datum/song/proc/playnote_legacy(note, acc as text, oct)
+/**
+ * Proc to play a legacy note. Just plays the sound to hearing mobs (and does hearcheck if necessary), no fancy channel/sustain/management.
+ *
+ * Arguments:
+ * * note is a number from 1-7 for A-G
+ * * acc is either "b", "n", or "#"
+ * * oct is 1-8 (or 9 for C)
+ */
+/datum/song/proc/playkey_legacy(note, acc as text, oct, mob/user)
// handle accidental -> B<>C of E<>F
if(acc == "b" && (note == 3 || note == 6)) // C or F
if(note == 3)
diff --git a/code/modules/instruments/songs/play_synthesized.dm b/code/modules/instruments/songs/play_synthesized.dm
index 5e7c5652a0..4df54f5e6b 100644
--- a/code/modules/instruments/songs/play_synthesized.dm
+++ b/code/modules/instruments/songs/play_synthesized.dm
@@ -1,27 +1,7 @@
-/datum/song/proc/do_play_lines_synthesized(mob/user)
- compile_lines()
- while(repeat >= 0)
- if(should_stop_playing(user))
- return
- var/warned = FALSE
- for(var/_chord in compiled_chords)
- if(should_stop_playing(user))
- return
- var/list/chord = _chord
- var/tempodiv = chord[chord.len]
- for(var/i in 1 to chord.len - 1)
- var/key = chord[i]
- if(!playkey_synth(key))
- if(!warned)
- warned = TRUE
- to_chat(user, "Your instrument has ran out of channels. You might be playing your song too fast or be setting sustain to too high of a value. This warning will be suppressed for the rest of this cycle.")
- sleep(sanitize_tempo(tempo / (tempodiv || 1)))
- repeat--
- updateDialog()
- repeat = 0
-
-/// C-Db2-A-A4/2,A-B#4-C/3,/4,A,A-B-C as an example
-/datum/song/proc/compile_lines()
+/**
+ * Compiles our lines into "chords" with numbers. This makes there have to be a bit of lag at the beginning of the song, but repeats will not have to parse it again, and overall playback won't be impacted by as much lag.
+ */
+/datum/song/proc/compile_synthesized()
if(!length(src.lines))
return
var/list/lines = src.lines //cache for hyepr speed!
@@ -57,10 +37,12 @@
compiled_chord += tempodiv //this goes last
if(length(compiled_chord))
compiled_chords[++compiled_chords.len] = compiled_chord
- CHECK_TICK
- return compiled_chords
-/datum/song/proc/playkey_synth(key)
+/**
+ * Plays a specific numerical key from our instrument to anyone who can hear us.
+ * Does a hearing check if enough time has passed.
+ */
+/datum/song/proc/playkey_synth(key, mob/user)
if(can_noteshift)
key = clamp(key + note_shift, key_min, key_max)
if((world.time - MUSICIAN_HEARCHECK_MINDELAY) > last_hearcheck)
@@ -83,6 +65,9 @@
M.playsound_local(get_turf(parent), null, volume, FALSE, K.frequency, INSTRUMENT_DISTANCE_NO_FALLOFF, channel, null, copy, distance_multiplier = INSTRUMENT_DISTANCE_FALLOFF_BUFF)
// Could do environment and echo later but not for now
+/**
+ * Stops all sounds we are "responsible" for. Only works in synthesized mode.
+ */
/datum/song/proc/terminate_all_sounds(clear_channels = TRUE)
for(var/i in hearing_mobs)
terminate_sound_mob(i)
@@ -93,10 +78,16 @@
using_sound_channels = 0
SSsounds.free_datum_channels(src)
+/**
+ * Stops all sounds we are responsible for in a given person. Only works in synthesized mode.
+ */
/datum/song/proc/terminate_sound_mob(mob/M)
for(var/channel in channels_playing)
M.stop_sound_channel(text2num(channel))
+/**
+ * Pops a channel we have reserved so we don't have to release and re-request them from SSsounds every time we play a note. This is faster.
+ */
/datum/song/proc/pop_channel()
if(length(channels_idle)) //just pop one off of here if we have one available
. = text2num(channels_idle[1])
@@ -108,6 +99,12 @@
if(!isnull(.))
using_sound_channels++
+/**
+ * Decays our channels and updates their volumes to mobs who can hear us.
+ *
+ * Arguments:
+ * * wait_ds - the deciseconds we should decay by. This is to compensate for any lag, as otherwise songs would get pretty nasty during high time dilation.
+ */
/datum/song/proc/process_decay(wait_ds)
var/linear_dropoff = cached_linear_dropoff * wait_ds
var/exponential_dropoff = cached_exponential_dropoff ** wait_ds
diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm
index bd36218211..1238b37919 100644
--- a/code/modules/jobs/job_types/_job.dm
+++ b/code/modules/jobs/job_types/_job.dm
@@ -46,6 +46,7 @@
var/minimal_player_age = 0
var/outfit = null
+ var/plasma_outfit = null //the outfit given to plasmamen
var/exp_requirements = 0
diff --git a/code/modules/jobs/job_types/atmospheric_technician.dm b/code/modules/jobs/job_types/atmospheric_technician.dm
index 1962b8e8a9..bff56d1d16 100644
--- a/code/modules/jobs/job_types/atmospheric_technician.dm
+++ b/code/modules/jobs/job_types/atmospheric_technician.dm
@@ -12,6 +12,7 @@
exp_type = EXP_TYPE_CREW
outfit = /datum/outfit/job/atmos
+ plasma_outfit = /datum/outfit/plasmaman/atmospherics
access = list(ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_TECH_STORAGE, ACCESS_MAINT_TUNNELS,
ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_ATMOSPHERICS, ACCESS_MINERAL_STOREROOM)
diff --git a/code/modules/jobs/job_types/bartender.dm b/code/modules/jobs/job_types/bartender.dm
index e5cd015460..8290adbbd7 100644
--- a/code/modules/jobs/job_types/bartender.dm
+++ b/code/modules/jobs/job_types/bartender.dm
@@ -11,6 +11,7 @@
exp_type_department = EXP_TYPE_SERVICE // This is so the jobs menu can work properly
outfit = /datum/outfit/job/bartender
+ plasma_outfit = /datum/outfit/plasmaman/bar
access = list(ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_BAR, ACCESS_MINERAL_STOREROOM)
diff --git a/code/modules/jobs/job_types/botanist.dm b/code/modules/jobs/job_types/botanist.dm
index 65f3e7ca48..4c91f87791 100644
--- a/code/modules/jobs/job_types/botanist.dm
+++ b/code/modules/jobs/job_types/botanist.dm
@@ -10,6 +10,7 @@
selection_color = "#bbe291"
outfit = /datum/outfit/job/botanist
+ plasma_outfit = /datum/outfit/plasmaman/botany
access = list(ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_HYDROPONICS, ACCESS_MORGUE, ACCESS_MINERAL_STOREROOM)
diff --git a/code/modules/jobs/job_types/captain.dm b/code/modules/jobs/job_types/captain.dm
index 3733658c33..047a07062d 100644
--- a/code/modules/jobs/job_types/captain.dm
+++ b/code/modules/jobs/job_types/captain.dm
@@ -17,6 +17,7 @@
outfit = /datum/outfit/job/captain
+ plasma_outfit = /datum/outfit/plasmaman/captain
access = list() //See get_access()
minimal_access = list() //See get_access()
diff --git a/code/modules/jobs/job_types/cargo_technician.dm b/code/modules/jobs/job_types/cargo_technician.dm
index 840af56a0e..1f87a5265d 100644
--- a/code/modules/jobs/job_types/cargo_technician.dm
+++ b/code/modules/jobs/job_types/cargo_technician.dm
@@ -10,6 +10,7 @@
selection_color = "#ca8f55"
outfit = /datum/outfit/job/cargo_tech
+ plasma_outfit = /datum/outfit/plasmaman/cargo
access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_MINING,
ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM)
diff --git a/code/modules/jobs/job_types/chaplain.dm b/code/modules/jobs/job_types/chaplain.dm
index 5f66519365..a9e891a303 100644
--- a/code/modules/jobs/job_types/chaplain.dm
+++ b/code/modules/jobs/job_types/chaplain.dm
@@ -10,6 +10,7 @@
selection_color = "#dddddd"
outfit = /datum/outfit/job/chaplain
+ plasma_outfit = /datum/outfit/plasmaman/chaplain
access = list(ACCESS_MORGUE, ACCESS_CHAPEL_OFFICE, ACCESS_CREMATORIUM, ACCESS_THEATRE)
minimal_access = list(ACCESS_MORGUE, ACCESS_CHAPEL_OFFICE, ACCESS_CREMATORIUM, ACCESS_THEATRE)
diff --git a/code/modules/jobs/job_types/chemist.dm b/code/modules/jobs/job_types/chemist.dm
index b2699071e3..6d4204d041 100644
--- a/code/modules/jobs/job_types/chemist.dm
+++ b/code/modules/jobs/job_types/chemist.dm
@@ -12,6 +12,7 @@
exp_requirements = 60
outfit = /datum/outfit/job/chemist
+ plasma_outfit = /datum/outfit/plasmaman/chemist
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_CHEMISTRY, ACCESS_MINERAL_STOREROOM)
diff --git a/code/modules/jobs/job_types/chief_engineer.dm b/code/modules/jobs/job_types/chief_engineer.dm
index d8df767a9f..18be8c9835 100644
--- a/code/modules/jobs/job_types/chief_engineer.dm
+++ b/code/modules/jobs/job_types/chief_engineer.dm
@@ -17,6 +17,7 @@
exp_type_department = EXP_TYPE_ENGINEERING
outfit = /datum/outfit/job/ce
+ plasma_outfit = /datum/outfit/plasmaman/ce
access = list(ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_TECH_STORAGE, ACCESS_MAINT_TUNNELS,
ACCESS_EXTERNAL_AIRLOCKS, ACCESS_ATMOSPHERICS, ACCESS_EVA,
diff --git a/code/modules/jobs/job_types/chief_medical_officer.dm b/code/modules/jobs/job_types/chief_medical_officer.dm
index 9cbc15ca28..627a7a2ca1 100644
--- a/code/modules/jobs/job_types/chief_medical_officer.dm
+++ b/code/modules/jobs/job_types/chief_medical_officer.dm
@@ -17,6 +17,7 @@
exp_type_department = EXP_TYPE_MEDICAL
outfit = /datum/outfit/job/cmo
+ plasma_outfit = /datum/outfit/plasmaman/cmo
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_HEADS, ACCESS_MINERAL_STOREROOM,
ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_CMO, ACCESS_SURGERY, ACCESS_RC_ANNOUNCE,
diff --git a/code/modules/jobs/job_types/clown.dm b/code/modules/jobs/job_types/clown.dm
index 7ad7148614..dc2f60434c 100644
--- a/code/modules/jobs/job_types/clown.dm
+++ b/code/modules/jobs/job_types/clown.dm
@@ -10,6 +10,7 @@
selection_color = "#dddddd"
outfit = /datum/outfit/job/clown
+ plasma_outfit = /datum/outfit/plasmaman/clown
access = list(ACCESS_THEATRE)
minimal_access = list(ACCESS_THEATRE)
diff --git a/code/modules/jobs/job_types/cook.dm b/code/modules/jobs/job_types/cook.dm
index 5a5916cb7e..666ee8f036 100644
--- a/code/modules/jobs/job_types/cook.dm
+++ b/code/modules/jobs/job_types/cook.dm
@@ -11,6 +11,7 @@
var/cooks = 0 //Counts cooks amount
outfit = /datum/outfit/job/cook
+ plasma_outfit = /datum/outfit/plasmaman/chef
access = list(ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_KITCHEN, ACCESS_MORGUE, ACCESS_MINERAL_STOREROOM)
diff --git a/code/modules/jobs/job_types/curator.dm b/code/modules/jobs/job_types/curator.dm
index 47bfd4914a..254fc15bd4 100644
--- a/code/modules/jobs/job_types/curator.dm
+++ b/code/modules/jobs/job_types/curator.dm
@@ -10,6 +10,7 @@
selection_color = "#dddddd"
outfit = /datum/outfit/job/curator
+ plasma_outfit = /datum/outfit/plasmaman/curator
access = list(ACCESS_LIBRARY)
minimal_access = list(ACCESS_LIBRARY, ACCESS_CONSTRUCTION, ACCESS_MINING_STATION)
diff --git a/code/modules/jobs/job_types/detective.dm b/code/modules/jobs/job_types/detective.dm
index 463113f14c..65724765e1 100644
--- a/code/modules/jobs/job_types/detective.dm
+++ b/code/modules/jobs/job_types/detective.dm
@@ -14,6 +14,7 @@
exp_type = EXP_TYPE_CREW
outfit = /datum/outfit/job/detective
+ plasma_outfit = /datum/outfit/plasmaman/detective
access = list(ACCESS_SEC_DOORS, ACCESS_FORENSICS_LOCKERS, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS, ACCESS_COURT, ACCESS_BRIG, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_SEC_DOORS, ACCESS_FORENSICS_LOCKERS, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS, ACCESS_COURT, ACCESS_BRIG, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM)
diff --git a/code/modules/jobs/job_types/geneticist.dm b/code/modules/jobs/job_types/geneticist.dm
index a40ca0fca3..5ff1bebfbf 100644
--- a/code/modules/jobs/job_types/geneticist.dm
+++ b/code/modules/jobs/job_types/geneticist.dm
@@ -12,6 +12,7 @@
exp_requirements = 60
outfit = /datum/outfit/job/geneticist
+ plasma_outfit = /datum/outfit/plasmaman/genetics
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_CHEMISTRY, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_RESEARCH, ACCESS_XENOBIOLOGY, ACCESS_ROBOTICS, ACCESS_MINERAL_STOREROOM, ACCESS_TECH_STORAGE)
minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM)
diff --git a/code/modules/jobs/job_types/head_of_personnel.dm b/code/modules/jobs/job_types/head_of_personnel.dm
index 8015c19c36..41fb4b99da 100644
--- a/code/modules/jobs/job_types/head_of_personnel.dm
+++ b/code/modules/jobs/job_types/head_of_personnel.dm
@@ -17,6 +17,7 @@
exp_type_department = EXP_TYPE_SERVICE
outfit = /datum/outfit/job/hop
+ plasma_outfit = /datum/outfit/plasmaman/hop
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_COURT, ACCESS_WEAPONS,
ACCESS_MEDICAL, ACCESS_ENGINE, ACCESS_CHANGE_IDS, ACCESS_AI_UPLOAD, ACCESS_EVA, ACCESS_HEADS,
diff --git a/code/modules/jobs/job_types/head_of_security.dm b/code/modules/jobs/job_types/head_of_security.dm
index 3d7d07d894..cfd8d7f6c0 100644
--- a/code/modules/jobs/job_types/head_of_security.dm
+++ b/code/modules/jobs/job_types/head_of_security.dm
@@ -17,6 +17,8 @@
exp_type_department = EXP_TYPE_SECURITY
outfit = /datum/outfit/job/hos
+ plasma_outfit = /datum/outfit/plasmaman/hos
+
mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM)
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_WEAPONS, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP,
diff --git a/code/modules/jobs/job_types/janitor.dm b/code/modules/jobs/job_types/janitor.dm
index 2f6d6f0e32..c62c2e5b26 100644
--- a/code/modules/jobs/job_types/janitor.dm
+++ b/code/modules/jobs/job_types/janitor.dm
@@ -10,6 +10,7 @@
selection_color = "#bbe291"
outfit = /datum/outfit/job/janitor
+ plasma_outfit = /datum/outfit/plasmaman/janitor
access = list(ACCESS_JANITOR, ACCESS_MAINT_TUNNELS, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_JANITOR, ACCESS_MAINT_TUNNELS, ACCESS_MINERAL_STOREROOM)
diff --git a/code/modules/jobs/job_types/lawyer.dm b/code/modules/jobs/job_types/lawyer.dm
index 1a7499800b..17c376a5de 100644
--- a/code/modules/jobs/job_types/lawyer.dm
+++ b/code/modules/jobs/job_types/lawyer.dm
@@ -11,6 +11,7 @@
var/lawyers = 0 //Counts lawyer amount
outfit = /datum/outfit/job/lawyer
+ plasma_outfit = /datum/outfit/plasmaman/bar //yes, this is correct, there's no 'lawyer' plasmeme outfit
access = list(ACCESS_LAWYER, ACCESS_COURT, ACCESS_SEC_DOORS)
minimal_access = list(ACCESS_LAWYER, ACCESS_COURT, ACCESS_SEC_DOORS)
diff --git a/code/modules/jobs/job_types/medical_doctor.dm b/code/modules/jobs/job_types/medical_doctor.dm
index 5ec4b83b2f..d6a763acfe 100644
--- a/code/modules/jobs/job_types/medical_doctor.dm
+++ b/code/modules/jobs/job_types/medical_doctor.dm
@@ -10,6 +10,7 @@
selection_color = "#74b5e0"
outfit = /datum/outfit/job/doctor
+ plasma_outfit = /datum/outfit/plasmaman/medical
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_VIROLOGY, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CLONING, ACCESS_MINERAL_STOREROOM)
diff --git a/code/modules/jobs/job_types/mime.dm b/code/modules/jobs/job_types/mime.dm
index 4ba2489ab2..e00b3a1e29 100644
--- a/code/modules/jobs/job_types/mime.dm
+++ b/code/modules/jobs/job_types/mime.dm
@@ -10,6 +10,7 @@
selection_color = "#dddddd"
outfit = /datum/outfit/job/mime
+ plasma_outfit = /datum/outfit/plasmaman/mime
access = list(ACCESS_THEATRE)
minimal_access = list(ACCESS_THEATRE)
diff --git a/code/modules/jobs/job_types/research_director.dm b/code/modules/jobs/job_types/research_director.dm
index 7128fbe2c7..33f7df8260 100644
--- a/code/modules/jobs/job_types/research_director.dm
+++ b/code/modules/jobs/job_types/research_director.dm
@@ -17,6 +17,7 @@
exp_type = EXP_TYPE_CREW
outfit = /datum/outfit/job/rd
+ plasma_outfit = /datum/outfit/plasmaman/rd
access = list(ACCESS_RD, ACCESS_HEADS, ACCESS_TOX, ACCESS_GENETICS, ACCESS_MORGUE,
ACCESS_TOX_STORAGE, ACCESS_TELEPORTER, ACCESS_SEC_DOORS,
diff --git a/code/modules/jobs/job_types/roboticist.dm b/code/modules/jobs/job_types/roboticist.dm
index f5ae93bb6a..aa52b353df 100644
--- a/code/modules/jobs/job_types/roboticist.dm
+++ b/code/modules/jobs/job_types/roboticist.dm
@@ -12,6 +12,7 @@
exp_type = EXP_TYPE_CREW
outfit = /datum/outfit/job/roboticist
+ plasma_outfit = /datum/outfit/plasmaman/robotics
access = list(ACCESS_ROBOTICS, ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_TECH_STORAGE, ACCESS_MORGUE, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM, ACCESS_XENOBIOLOGY, ACCESS_GENETICS)
minimal_access = list(ACCESS_ROBOTICS, ACCESS_TECH_STORAGE, ACCESS_MORGUE, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM)
diff --git a/code/modules/jobs/job_types/scientist.dm b/code/modules/jobs/job_types/scientist.dm
index 476f740b9d..a851b333fe 100644
--- a/code/modules/jobs/job_types/scientist.dm
+++ b/code/modules/jobs/job_types/scientist.dm
@@ -12,6 +12,7 @@
exp_type = EXP_TYPE_CREW
outfit = /datum/outfit/job/scientist
+ plasma_outfit = /datum/outfit/plasmaman/science
access = list(ACCESS_ROBOTICS, ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_RESEARCH, ACCESS_XENOBIOLOGY, ACCESS_MINERAL_STOREROOM, ACCESS_TECH_STORAGE, ACCESS_GENETICS)
minimal_access = list(ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_RESEARCH, ACCESS_XENOBIOLOGY, ACCESS_MINERAL_STOREROOM)
diff --git a/code/modules/jobs/job_types/security_officer.dm b/code/modules/jobs/job_types/security_officer.dm
index 7e71b2d1f4..bc83eb752d 100644
--- a/code/modules/jobs/job_types/security_officer.dm
+++ b/code/modules/jobs/job_types/security_officer.dm
@@ -14,6 +14,7 @@
exp_type = EXP_TYPE_CREW
outfit = /datum/outfit/job/security
+ plasma_outfit = /datum/outfit/plasmaman/security
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_COURT, ACCESS_MAINT_TUNNELS, ACCESS_MORGUE, ACCESS_WEAPONS, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP, ACCESS_FORENSICS_LOCKERS, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_COURT, ACCESS_WEAPONS, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP, ACCESS_MINERAL_STOREROOM) // See /datum/job/officer/get_access()
diff --git a/code/modules/jobs/job_types/shaft_miner.dm b/code/modules/jobs/job_types/shaft_miner.dm
index ebf7ba0f1f..04d3fb53b8 100644
--- a/code/modules/jobs/job_types/shaft_miner.dm
+++ b/code/modules/jobs/job_types/shaft_miner.dm
@@ -12,6 +12,7 @@
outfit = /datum/outfit/job/miner
+ plasma_outfit = /datum/outfit/plasmaman/mining
access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_MINING,
ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM)
diff --git a/code/modules/jobs/job_types/station_engineer.dm b/code/modules/jobs/job_types/station_engineer.dm
index d3f5db7dbb..2396728ad8 100644
--- a/code/modules/jobs/job_types/station_engineer.dm
+++ b/code/modules/jobs/job_types/station_engineer.dm
@@ -12,6 +12,7 @@
exp_type = EXP_TYPE_CREW
outfit = /datum/outfit/job/engineer
+ plasma_outfit = /datum/outfit/plasmaman/engineering
access = list(ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_TECH_STORAGE, ACCESS_MAINT_TUNNELS,
ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_ATMOSPHERICS, ACCESS_TCOMSAT, ACCESS_MINERAL_STOREROOM)
diff --git a/code/modules/jobs/job_types/virologist.dm b/code/modules/jobs/job_types/virologist.dm
index 790e828931..3e9b3ba06c 100644
--- a/code/modules/jobs/job_types/virologist.dm
+++ b/code/modules/jobs/job_types/virologist.dm
@@ -12,6 +12,7 @@
exp_requirements = 60
outfit = /datum/outfit/job/virologist
+ plasma_outfit = /datum/outfit/plasmaman/viro
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_MEDICAL, ACCESS_VIROLOGY, ACCESS_MINERAL_STOREROOM)
diff --git a/code/modules/jobs/job_types/warden.dm b/code/modules/jobs/job_types/warden.dm
index 22e3f9b0f1..c909342d6f 100644
--- a/code/modules/jobs/job_types/warden.dm
+++ b/code/modules/jobs/job_types/warden.dm
@@ -14,6 +14,7 @@
exp_type = EXP_TYPE_CREW
outfit = /datum/outfit/job/warden
+ plasma_outfit = /datum/outfit/plasmaman/warden
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_MAINT_TUNNELS, ACCESS_MORGUE, ACCESS_WEAPONS, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP, ACCESS_FORENSICS_LOCKERS, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_WEAPONS, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP, ACCESS_MINERAL_STOREROOM) // See /datum/job/warden/get_access()
diff --git a/code/modules/mafia/controller.dm b/code/modules/mafia/controller.dm
index 5873decb8f..cd8c382f30 100644
--- a/code/modules/mafia/controller.dm
+++ b/code/modules/mafia/controller.dm
@@ -67,6 +67,8 @@
var/max_player = MAFIA_MAX_PLAYER_COUNT
///Required player count
var/required_player = 5
+ ///Prioritizes clients to have cool antag roles
+ var/low_pop_mode = FALSE
/datum/mafia_controller/New()
. = ..()
@@ -93,7 +95,7 @@
* * setup_list: list of all the datum setups (fancy list of roles) that would work for the game
* * ready_players: list of filtered, sane players (so not playing or disconnected) for the game to put into roles
*/
-/datum/mafia_controller/proc/prepare_game(setup_list,ready_players)
+/datum/mafia_controller/proc/prepare_game(setup_list, ready_players)
var/list/possible_maps = subtypesof(/datum/map_template/mafia)
var/turf/spawn_area = get_turf(locate(/obj/effect/landmark/mafia_game_area) in GLOB.landmarks_list)
@@ -116,18 +118,40 @@
landmarks += possible_spawn
current_setup_text = list()
+
+ var/list/boring_roles = list()
+ var/list/not_boring_roles = list()
+
for(var/rtype in setup_list)
for(var/i in 1 to setup_list[rtype])
- all_roles += new rtype(src)
+ var/datum/mafia_role/role = new rtype(src)
+ all_roles += role
+ if(role.role_type == TOWN_PROTECT || role.role_type == TOWN_INVEST || role.role_type == MAFIA_SPECIAL || role.role_type == MAFIA_REGULAR)
+ not_boring_roles += role
+ else
+ boring_roles += role
var/datum/mafia_role/rp = rtype
current_setup_text += "[initial(rp.name)] x[setup_list[rtype]]"
+
var/list/spawnpoints = landmarks.Copy()
- for(var/datum/mafia_role/role in all_roles)
- role.assigned_landmark = pick_n_take(spawnpoints)
- if(!debug)
+
+ if(length(ready_players) < 7 || low_pop_mode)
+ //do normal assign
+ for(var/datum/mafia_role/role in not_boring_roles)
+ role.assigned_landmark = pick_n_take(spawnpoints)
role.player_key = pick_n_take(ready_players)
- else
- role.player_key = pop(ready_players)
+ //shame!
+ for(var/datum/mafia_role/role in boring_roles)
+ role.assigned_landmark = pick_n_take(spawnpoints)
+ role.player_key = pick_n_take(ready_players)
+
+ else //go run the normal one
+ for(var/datum/mafia_role/role in all_roles)
+ role.assigned_landmark = pick_n_take(spawnpoints)
+ if(!debug)
+ role.player_key = pick_n_take(ready_players)
+ else
+ role.player_key = pop(ready_players)
/datum/mafia_controller/proc/send_message(msg,team)
for(var/datum/mafia_role/R in all_roles)
diff --git a/code/modules/mafia/map_pieces.dm b/code/modules/mafia/map_pieces.dm
index 3459603f3c..3339c596b4 100644
--- a/code/modules/mafia/map_pieces.dm
+++ b/code/modules/mafia/map_pieces.dm
@@ -73,7 +73,7 @@
description = "Vampires and changelings clash to find out who's the superior bloodsucking monster in this creepy castle map."
mappath = "_maps/map_files/Mafia/mafia_gothic.dmm"
-/datum/map_template/mafia/gothic
+/datum/map_template/mafia/reebe
name = "Reebe"
description = "Trouble in Reebe station! Copypaste guranteed by ClockCo™"
- mappath = "_maps/map_files/Mafia/mafia_reebe.dmm"
\ No newline at end of file
+ mappath = "_maps/map_files/Mafia/mafia_reebe.dmm"
diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm
index a09d890f69..a6f456ce6f 100644
--- a/code/modules/mining/equipment/kinetic_crusher.dm
+++ b/code/modules/mining/equipment/kinetic_crusher.dm
@@ -183,7 +183,6 @@
attack_verb = list("stabbed", "diced", "sliced", "cleaved", "chopped", "lacerated", "cut", "jabbed", "punctured")
icon_state = "crusher-glaive"
item_state = "crusher0-glaive"
- item_flags = ITEM_CAN_PARRY
block_parry_data = /datum/block_parry_data/crusherglaive
//ideas: altclick that lets you pummel people with the handguard/handle?
//parrying functionality?
@@ -217,6 +216,16 @@
if(owner.Adjacent(attacker) && (!attacker.anchored || ismegafauna(attacker))) // free backstab, if you perfect parry
attacker.dir = get_dir(owner,attacker)
+/// triggered on wield of two handed item
+/obj/item/kinetic_crusher/glaive/on_wield(obj/item/source, mob/user)
+ wielded = TRUE
+ item_flags |= (ITEM_CAN_PARRY)
+
+/// triggered on unwield of two handed item
+/obj/item/kinetic_crusher/glaive/on_unwield(obj/item/source, mob/user)
+ wielded = FALSE
+ item_flags &= ~(ITEM_CAN_PARRY)
+
/obj/item/kinetic_crusher/glaive/update_icon_state()
item_state = "crusher[wielded]-glaive" // this is not icon_state and not supported by 2hcomponent
diff --git a/code/modules/mining/equipment/wormhole_jaunter.dm b/code/modules/mining/equipment/wormhole_jaunter.dm
index c31008fa62..c17b62ba6c 100644
--- a/code/modules/mining/equipment/wormhole_jaunter.dm
+++ b/code/modules/mining/equipment/wormhole_jaunter.dm
@@ -35,18 +35,20 @@
return destinations
-/obj/item/wormhole_jaunter/proc/activate(mob/user, adjacent)
+/obj/item/wormhole_jaunter/proc/activate(mob/user, adjacent, force_entry = FALSE)
if(!turf_check(user))
return
var/list/L = get_destinations(user)
if(!L.len)
- to_chat(user, "The [src.name] found no beacons in the world to anchor a wormhole to.")
+ to_chat(user, "The [name] found no beacons in the world to anchor a wormhole to.")
return
var/chosen_beacon = pick(L)
- var/obj/effect/portal/jaunt_tunnel/J = new (get_turf(src), src, 100, null, FALSE, get_turf(chosen_beacon))
+ var/obj/effect/portal/jaunt_tunnel/J = new (get_turf(src), 100, null, FALSE, get_turf(chosen_beacon))
if(adjacent)
try_move_adjacent(J)
+ if(force_entry)
+ J.teleport(user, force = TRUE)
playsound(src,'sound/effects/sparks4.ogg',50,1)
qdel(src)
@@ -73,7 +75,7 @@
if(user.get_item_by_slot(SLOT_BELT) == src)
to_chat(user, "Your [name] activates, saving you from the chasm!")
SSblackbox.record_feedback("tally", "jaunter", 1, "Chasm") // chasm automatic activation
- activate(user, FALSE)
+ activate(user, FALSE, TRUE)
else
to_chat(user, "[src] is not attached to your belt, preventing it from saving you from the chasm. RIP.")
@@ -84,9 +86,10 @@
icon_state = "bhole3"
desc = "A stable hole in the universe made by a wormhole jaunter. Turbulent doesn't even begin to describe how rough passage through one of these is, but at least it will always get you somewhere near a beacon."
mech_sized = TRUE //save your ripley
+ teleport_channel = TELEPORT_CHANNEL_WORMHOLE
innate_accuracy_penalty = 6
-/obj/effect/portal/jaunt_tunnel/teleport(atom/movable/M)
+/obj/effect/portal/jaunt_tunnel/teleport(atom/movable/M, force = FALSE)
. = ..()
if(.)
// KERPLUNK
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/Citadel_Snowflake.dm b/code/modules/mob/dead/new_player/sprite_accessories/Citadel_Snowflake.dm
index 020776a75f..3c2c850e3c 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/Citadel_Snowflake.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/Citadel_Snowflake.dm
@@ -1,9 +1,9 @@
-/datum/sprite_accessory/mam_tails/shark/datashark
+/datum/sprite_accessory/tails/mam_tails/shark/datashark
name = "DataShark"
icon_state = "datashark"
ckeys_allowed = list("rubyflamewing")
-/datum/sprite_accessory/mam_tails_animated/shark/datashark
+/datum/sprite_accessory/tails_animated/mam_tails_animated/shark/datashark
name = "DataShark"
icon_state = "datashark"
ckeys_allowed = list("rubyflamewing")
@@ -14,19 +14,19 @@
ckeys_allowed = list("rubyflamewing")
//Sabresune
-/datum/sprite_accessory/mam_ears/sabresune
+/datum/sprite_accessory/ears/mam_ears/sabresune
name = "Sabresune"
icon_state = "sabresune"
ckeys_allowed = list("poojawa")
extra = TRUE
extra_color_src = MUTCOLORS3
-/datum/sprite_accessory/mam_tails/sabresune
+/datum/sprite_accessory/tails/mam_tails/sabresune
name = "Sabresune"
icon_state = "sabresune"
ckeys_allowed = list("poojawa")
-/datum/sprite_accessory/mam_tails_animated/sabresune
+/datum/sprite_accessory/tails_animated/mam_tails_animated/sabresune
name = "Sabresune"
icon_state = "sabresune"
ckeys_allowed = list("poojawa")
@@ -37,17 +37,17 @@
ckeys_allowed = list("poojawa")
//Lunasune
-/datum/sprite_accessory/mam_ears/lunasune
+/datum/sprite_accessory/ears/mam_ears/lunasune
name = "lunasune"
icon_state = "lunasune"
ckeys_allowed = list("invader4352")
-/datum/sprite_accessory/mam_tails/lunasune
+/datum/sprite_accessory/tails/mam_tails/lunasune
name = "lunasune"
icon_state = "lunasune"
ckeys_allowed = list("invader4352")
-/datum/sprite_accessory/mam_tails_animated/lunasune
+/datum/sprite_accessory/tails_animated/mam_tails_animated/lunasune
name = "lunasune"
icon_state = "lunasune"
ckeys_allowed = list("invader4352")
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm b/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm
index 6514cb4f80..4cb8d080ff 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm
@@ -76,6 +76,9 @@
//For soft-restricting markings to species IDs
var/list/recommended_species
+/datum/sprite_accessory/proc/is_not_visible(var/mob/living/carbon/human/H, var/tauric) //return if the accessory shouldn't be shown
+ return FALSE
+
/datum/sprite_accessory/underwear
icon = 'icons/mob/clothing/underwear.dmi'
var/has_color = FALSE
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm b/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm
index c8e7aca26d..899bf91081 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm
@@ -7,6 +7,9 @@
mutant_part_string = "xenodorsal"
relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER)
+/datum/sprite_accessory/xeno_dorsal/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
+ return (!H.dna.features["xenodorsal"] || H.dna.features["xenodorsal"] == "None" || (H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT)))
+
/datum/sprite_accessory/xeno_dorsal/standard
name = "Standard"
icon_state = "standard"
@@ -27,6 +30,9 @@
mutant_part_string = "tail"
relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER)
+/datum/sprite_accessory/xeno_tail/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
+ return (!H.dna.features["xenotail"] || H.dna.features["xenotail"] == "None" || H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT))
+
/datum/sprite_accessory/xeno_tail/none
name = "None"
relevant_layers = null
@@ -43,6 +49,10 @@
mutant_part_string = "xhead"
relevant_layers = list(BODY_ADJ_LAYER)
+/datum/sprite_accessory/xeno_head/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
+ var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
+ return (!H.dna.features["xenohead"] || H.dna.features["xenohead"] == "None" || H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || HD.status == BODYPART_ROBOTIC)
+
/datum/sprite_accessory/xeno_head/standard
name = "Standard"
icon_state = "standard"
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/body_markings.dm b/code/modules/mob/dead/new_player/sprite_accessories/body_markings.dm
index 9950f0d76a..a04838a360 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/body_markings.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/body_markings.dm
@@ -224,6 +224,9 @@
color_src = 0
relevant_layers = list(BODY_FRONT_LAYER)
+/datum/sprite_accessory/insect_fluff/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
+ return (!H.dna.features["insect_fluff"] || H.dna.features["insect_fluff"] == "None" || H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT))
+
/datum/sprite_accessory/insect_fluff/none
name = "None"
icon_state = "none"
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/ears.dm b/code/modules/mob/dead/new_player/sprite_accessories/ears.dm
index bc269ccf62..1e6c797364 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/ears.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/ears.dm
@@ -3,6 +3,10 @@
mutant_part_string = "ears"
relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER)
+/datum/sprite_accessory/ears/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
+ var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
+ return (!H.dna.features["ears"] || H.dna.features["ears"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEEARS)) || !HD || HD.status == BODYPART_ROBOTIC)
+
/datum/sprite_accessory/ears/none
name = "None"
icon_state = "none"
@@ -175,50 +179,54 @@
*************** Furry Ears ****************
*******************************************/
-/datum/sprite_accessory/mam_ears
+/datum/sprite_accessory/ears/mam_ears
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
mutant_part_string = "ears"
relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER)
-/datum/sprite_accessory/mam_ears/none
+/datum/sprite_accessory/ears/mam_ears/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
+ var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
+ return (!H.dna.features["mam_ears"] || H.dna.features["mam_ears"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEEARS)) || !HD || HD.status == BODYPART_ROBOTIC)
+
+/datum/sprite_accessory/ears/mam_ears/none
name = "None"
icon_state = "none"
relevant_layers = null
-/datum/sprite_accessory/mam_ears/axolotl
+/datum/sprite_accessory/ears/mam_ears/axolotl
name = "Axolotl"
icon_state = "axolotl"
-/datum/sprite_accessory/mam_ears/bat
+/datum/sprite_accessory/ears/mam_ears/bat
name = "Bat"
icon_state = "bat"
-/datum/sprite_accessory/mam_ears/bear
+/datum/sprite_accessory/ears/mam_ears/bear
name = "Bear"
icon_state = "bear"
-/datum/sprite_accessory/mam_ears/bigwolf
+/datum/sprite_accessory/ears/mam_ears/bigwolf
name = "Big Wolf"
icon_state = "bigwolf"
-/datum/sprite_accessory/mam_ears/bigwolfinner
+/datum/sprite_accessory/ears/mam_ears/bigwolfinner
name = "Big Wolf (ALT)"
icon_state = "bigwolfinner"
extra = TRUE
extra_color_src = NONE
-/datum/sprite_accessory/mam_ears/bigwolfdark
+/datum/sprite_accessory/ears/mam_ears/bigwolfdark
name = "Dark Big Wolf"
icon_state = "bigwolfdark"
-/datum/sprite_accessory/mam_ears/bigwolfinnerdark
+/datum/sprite_accessory/ears/mam_ears/bigwolfinnerdark
name = "Dark Big Wolf (ALT)"
icon_state = "bigwolfinnerdark"
extra = TRUE
extra_color_src = NONE
-/datum/sprite_accessory/mam_ears/cat
+/datum/sprite_accessory/ears/mam_ears/cat
name = "Cat"
icon_state = "cat"
icon = 'icons/mob/mutant_bodyparts.dmi'
@@ -226,100 +234,100 @@
extra = TRUE
extra_color_src = NONE
-/datum/sprite_accessory/mam_ears/catbig
+/datum/sprite_accessory/ears/mam_ears/catbig
name = "Cat, Big"
icon_state = "catbig"
-/datum/sprite_accessory/mam_ears/cow
+/datum/sprite_accessory/ears/mam_ears/cow
name = "Cow"
icon_state = "cow"
-/datum/sprite_accessory/mam_ears/curled
+/datum/sprite_accessory/ears/mam_ears/curled
name = "Curled Horn"
icon_state = "horn1"
color_src = MUTCOLORS3
-/datum/sprite_accessory/mam_ears/deer
+/datum/sprite_accessory/ears/mam_ears/deer
name = "Deer"
icon_state = "deer"
color_src = MUTCOLORS3
-/datum/sprite_accessory/mam_ears/eevee
+/datum/sprite_accessory/ears/mam_ears/eevee
name = "Eevee"
icon_state = "eevee"
-/datum/sprite_accessory/mam_ears/elf
+/datum/sprite_accessory/ears/mam_ears/elf
name = "Elf"
icon_state = "elf"
color_src = MUTCOLORS3
-/datum/sprite_accessory/mam_ears/elephant
+/datum/sprite_accessory/ears/mam_ears/elephant
name = "Elephant"
icon_state = "elephant"
-/datum/sprite_accessory/mam_ears/fennec
+/datum/sprite_accessory/ears/mam_ears/fennec
name = "Fennec"
icon_state = "fennec"
-/datum/sprite_accessory/mam_ears/fish
+/datum/sprite_accessory/ears/mam_ears/fish
name = "Fish"
icon_state = "fish"
-/datum/sprite_accessory/mam_ears/fox
+/datum/sprite_accessory/ears/mam_ears/fox
name = "Fox"
icon_state = "fox"
-/datum/sprite_accessory/mam_ears/husky
+/datum/sprite_accessory/ears/mam_ears/husky
name = "Husky"
icon_state = "wolf"
-/datum/sprite_accessory/mam_ears/kangaroo
+/datum/sprite_accessory/ears/mam_ears/kangaroo
name = "kangaroo"
icon_state = "kangaroo"
-/datum/sprite_accessory/mam_ears/jellyfish
+/datum/sprite_accessory/ears/mam_ears/jellyfish
name = "Jellyfish"
icon_state = "jellyfish"
color_src = HAIR
-/datum/sprite_accessory/mam_ears/lab
+/datum/sprite_accessory/ears/mam_ears/lab
name = "Dog, Long"
icon_state = "lab"
-/datum/sprite_accessory/mam_ears/murid
+/datum/sprite_accessory/ears/mam_ears/murid
name = "Murid"
icon_state = "murid"
-/datum/sprite_accessory/mam_ears/otie
+/datum/sprite_accessory/ears/mam_ears/otie
name = "Otusian"
icon_state = "otie"
-/datum/sprite_accessory/mam_ears/squirrel
+/datum/sprite_accessory/ears/mam_ears/squirrel
name = "Squirrel"
icon_state = "squirrel"
-/datum/sprite_accessory/mam_ears/pede
+/datum/sprite_accessory/ears/mam_ears/pede
name = "Scolipede"
icon_state = "pede"
-/datum/sprite_accessory/mam_ears/rabbit
+/datum/sprite_accessory/ears/mam_ears/rabbit
name = "Rabbit"
icon_state = "rabbit"
-/datum/sprite_accessory/mam_ears/sergal
+/datum/sprite_accessory/ears/mam_ears/sergal
name = "Sergal"
icon_state = "sergal"
-/datum/sprite_accessory/mam_ears/skunk
+/datum/sprite_accessory/ears/mam_ears/skunk
name = "skunk"
icon_state = "skunk"
-/datum/sprite_accessory/mam_ears/wolf
+/datum/sprite_accessory/ears/mam_ears/wolf
name = "Wolf"
icon_state = "wolf"
-/datum/sprite_accessory/mam_ears/bunny
+/datum/sprite_accessory/ears/mam_ears/bunny
name = "Bunny"
icon_state = "bunny"
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/frills.dm b/code/modules/mob/dead/new_player/sprite_accessories/frills.dm
index 0aaec309a4..18a76df116 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/frills.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/frills.dm
@@ -2,6 +2,10 @@
icon = 'icons/mob/mutant_bodyparts.dmi'
relevant_layers = list(BODY_ADJ_LAYER)
+/datum/sprite_accessory/frills/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
+ var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
+ return (!H.dna.features["frills"] || H.dna.features["frills"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || !HD || HD.status == BODYPART_ROBOTIC)
+
/datum/sprite_accessory/frills/none
name = "None"
icon_state = "none"
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/horns.dm b/code/modules/mob/dead/new_player/sprite_accessories/horns.dm
index b39f48f858..3a65eaebfa 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/horns.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/horns.dm
@@ -3,6 +3,10 @@
color_src = HORNCOLOR
relevant_layers = list(HORNS_LAYER)
+/datum/sprite_accessory/horns/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
+ var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
+ return (!H.dna.features["horns"] || H.dna.features["horns"] == "None" || H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || HD.status == BODYPART_ROBOTIC)
+
/datum/sprite_accessory/horns/none
name = "None"
icon_state = "none"
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/legs_and_taurs.dm b/code/modules/mob/dead/new_player/sprite_accessories/legs_and_taurs.dm
index 2ec6da2da8..d41f5ace22 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/legs_and_taurs.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/legs_and_taurs.dm
@@ -30,6 +30,9 @@
var/alt_taur_mode = NONE //Same as above.
var/hide_legs = USE_QUADRUPED_CLIP_MASK
+/datum/sprite_accessory/taur/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
+ return (!tauric || (H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)))
+
/datum/sprite_accessory/taur/New()
switch(hide_legs)
if(USE_QUADRUPED_CLIP_MASK)
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm b/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm
index 2c0db56ce4..f514ef54db 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm
@@ -3,6 +3,10 @@
mutant_part_string = "snout"
relevant_layers = list(BODY_ADJ_LAYER, BODY_FRONT_LAYER)
+/datum/sprite_accessory/snouts/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
+ var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
+ return ((H.wear_mask && (H.wear_mask.flags_inv & HIDESNOUT)) || (H.head && (H.head.flags_inv & HIDESNOUT)) || !HD || HD.status == BODYPART_ROBOTIC)
+
/datum/sprite_accessory/snouts/sharp
name = "Sharp"
icon_state = "sharp"
@@ -150,136 +154,140 @@
************** Mammal Snouts **************
*******************************************/
-/datum/sprite_accessory/mam_snouts
+/datum/sprite_accessory/snouts/mam_snouts
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_snouts.dmi'
- recommended_species = list("mammal", "slimeperson", "insect", "podweak")
+ recommended_species = list("mammal", "slimeperson", "insect", "podweak", "lizard")
mutant_part_string = "snout"
relevant_layers = list(BODY_ADJ_LAYER, BODY_FRONT_LAYER)
-/datum/sprite_accessory/mam_snouts/none
+/datum/sprite_accessory/snouts/mam_snouts/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
+ var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
+ return ((H.wear_mask && (H.wear_mask.flags_inv & HIDESNOUT)) || (H.head && (H.head.flags_inv & HIDESNOUT)) || !HD || HD.status == BODYPART_ROBOTIC)
+
+/datum/sprite_accessory/snouts/mam_snouts/none
name = "None"
icon_state = "none"
recommended_species = null
relevant_layers = null
-/datum/sprite_accessory/mam_snouts/bird
+/datum/sprite_accessory/snouts/mam_snouts/bird
name = "Beak"
icon_state = "bird"
-/datum/sprite_accessory/mam_snouts/bigbeak
+/datum/sprite_accessory/snouts/mam_snouts/bigbeak
name = "Big Beak"
icon_state = "bigbeak"
-/datum/sprite_accessory/mam_snouts/bug
+/datum/sprite_accessory/snouts/mam_snouts/bug
name = "Bug"
icon_state = "bug"
color_src = MUTCOLORS
extra2 = TRUE
extra2_color_src = MUTCOLORS3
-/datum/sprite_accessory/mam_snouts/elephant
+/datum/sprite_accessory/snouts/mam_snouts/elephant
name = "Elephant"
icon_state = "elephant"
extra = TRUE
extra_color_src = MUTCOLORS3
-/datum/sprite_accessory/mam_snouts/skulldog
+/datum/sprite_accessory/snouts/mam_snouts/skulldog
name = "Skulldog"
icon_state = "skulldog"
extra = TRUE
extra_color_src = MATRIXED
-/datum/sprite_accessory/mam_snouts/lcanid
+/datum/sprite_accessory/snouts/mam_snouts/lcanid
name = "Mammal, Long"
icon_state = "lcanid"
-/datum/sprite_accessory/mam_snouts/lcanidalt
+/datum/sprite_accessory/snouts/mam_snouts/lcanidalt
name = "Mammal, Long ALT"
icon_state = "lcanidalt"
-/datum/sprite_accessory/mam_snouts/scanid
+/datum/sprite_accessory/snouts/mam_snouts/scanid
name = "Mammal, Short"
icon_state = "scanid"
-/datum/sprite_accessory/mam_snouts/scanidalt
+/datum/sprite_accessory/snouts/mam_snouts/scanidalt
name = "Mammal, Short ALT"
icon_state = "scanidalt"
-/datum/sprite_accessory/mam_snouts/scanidalt2
+/datum/sprite_accessory/snouts/mam_snouts/scanidalt2
name = "Mammal, Short ALT 2"
icon_state = "scanidalt2"
-/datum/sprite_accessory/mam_snouts/wolf
+/datum/sprite_accessory/snouts/mam_snouts/wolf
name = "Mammal, Thick"
icon_state = "wolf"
-/datum/sprite_accessory/mam_snouts/wolfalt
+/datum/sprite_accessory/snouts/mam_snouts/wolfalt
name = "Mammal, Thick ALT"
icon_state = "wolfalt"
-/datum/sprite_accessory/mam_snouts/redpanda
+/datum/sprite_accessory/snouts/mam_snouts/redpanda
name = "WahCoon"
icon_state = "wah"
-/datum/sprite_accessory/mam_snouts/redpandaalt
+/datum/sprite_accessory/snouts/mam_snouts/redpandaalt
name = "WahCoon ALT"
icon_state = "wahalt"
-/datum/sprite_accessory/mam_snouts/rhino
+/datum/sprite_accessory/snouts/mam_snouts/rhino
name = "Horn"
icon_state = "rhino"
extra = TRUE
extra = MUTCOLORS3
-/datum/sprite_accessory/mam_snouts/rodent
+/datum/sprite_accessory/snouts/mam_snouts/rodent
name = "Rodent"
icon_state = "rodent"
-/datum/sprite_accessory/mam_snouts/husky
+/datum/sprite_accessory/snouts/mam_snouts/husky
name = "Husky"
icon_state = "husky"
-/datum/sprite_accessory/mam_snouts/otie
+/datum/sprite_accessory/snouts/mam_snouts/otie
name = "Otie"
icon_state = "otie"
-/datum/sprite_accessory/mam_snouts/pede
+/datum/sprite_accessory/snouts/mam_snouts/pede
name = "Scolipede"
icon_state = "pede"
-/datum/sprite_accessory/mam_snouts/sergal
+/datum/sprite_accessory/snouts/mam_snouts/sergal
name = "Sergal"
icon_state = "sergal"
-/datum/sprite_accessory/mam_snouts/shark
+/datum/sprite_accessory/snouts/mam_snouts/shark
name = "Shark"
icon_state = "shark"
-/datum/sprite_accessory/mam_snouts/hshark
+/datum/sprite_accessory/snouts/mam_snouts/hshark
name = "hShark"
icon_state = "hshark"
-/datum/sprite_accessory/mam_snouts/toucan
+/datum/sprite_accessory/snouts/mam_snouts/toucan
name = "Toucan"
icon_state = "toucan"
-/datum/sprite_accessory/mam_snouts/sharp
+/datum/sprite_accessory/snouts/mam_snouts/sharp
name = "Sharp"
icon_state = "sharp"
color_src = MUTCOLORS
-/datum/sprite_accessory/mam_snouts/round
+/datum/sprite_accessory/snouts/mam_snouts/round
name = "Round"
icon_state = "round"
color_src = MUTCOLORS
-/datum/sprite_accessory/mam_snouts/sharplight
+/datum/sprite_accessory/snouts/mam_snouts/sharplight
name = "Sharp + Light"
icon_state = "sharplight"
color_src = MUTCOLORS
-/datum/sprite_accessory/mam_snouts/roundlight
+/datum/sprite_accessory/snouts/mam_snouts/roundlight
name = "Round + Light"
icon_state = "roundlight"
color_src = MUTCOLORS
@@ -289,109 +297,109 @@
**************** Snouts *******************
*************but higher up*****************/
-/datum/sprite_accessory/mam_snouts/fbird
+/datum/sprite_accessory/snouts/mam_snouts/fbird
name = "Beak (Top)"
icon_state = "fbird"
-/datum/sprite_accessory/mam_snouts/fbigbeak
+/datum/sprite_accessory/snouts/mam_snouts/fbigbeak
name = "Big Beak (Top)"
icon_state = "fbigbeak"
-/datum/sprite_accessory/mam_snouts/fbug
+/datum/sprite_accessory/snouts/mam_snouts/fbug
name = "Bug (Top)"
icon_state = "fbug"
color_src = MUTCOLORS
extra2 = TRUE
extra2_color_src = MUTCOLORS3
-/datum/sprite_accessory/mam_snouts/felephant
+/datum/sprite_accessory/snouts/mam_snouts/felephant
name = "Elephant (Top)"
icon_state = "felephant"
extra = TRUE
extra_color_src = MUTCOLORS3
-/datum/sprite_accessory/mam_snouts/flcanid
+/datum/sprite_accessory/snouts/mam_snouts/flcanid
name = "Mammal, Long (Top)"
icon_state = "flcanid"
-/datum/sprite_accessory/mam_snouts/flcanidalt
+/datum/sprite_accessory/snouts/mam_snouts/flcanidalt
name = "Mammal, Long ALT (Top)"
icon_state = "flcanidalt"
-/datum/sprite_accessory/mam_snouts/fscanid
+/datum/sprite_accessory/snouts/mam_snouts/fscanid
name = "Mammal, Short (Top)"
icon_state = "fscanid"
-/datum/sprite_accessory/mam_snouts/fscanidalt
+/datum/sprite_accessory/snouts/mam_snouts/fscanidalt
name = "Mammal, Short ALT (Top)"
icon_state = "fscanidalt"
-/datum/sprite_accessory/mam_snouts/fscanidalt2
+/datum/sprite_accessory/snouts/mam_snouts/fscanidalt2
name = "Mammal, Short ALT 2 (Top)"
icon_state = "fscanidalt2"
-/datum/sprite_accessory/mam_snouts/fwolf
+/datum/sprite_accessory/snouts/mam_snouts/fwolf
name = "Mammal, Thick (Top)"
icon_state = "fwolf"
-/datum/sprite_accessory/mam_snouts/fwolfalt
+/datum/sprite_accessory/snouts/mam_snouts/fwolfalt
name = "Mammal, Thick ALT (Top)"
icon_state = "fwolfalt"
-/datum/sprite_accessory/mam_snouts/fredpanda
+/datum/sprite_accessory/snouts/mam_snouts/fredpanda
name = "WahCoon (Top)"
icon_state = "fwah"
-/datum/sprite_accessory/mam_snouts/frhino
+/datum/sprite_accessory/snouts/mam_snouts/frhino
name = "Horn (Top)"
icon_state = "frhino"
extra = TRUE
extra = MUTCOLORS3
-/datum/sprite_accessory/mam_snouts/frodent
+/datum/sprite_accessory/snouts/mam_snouts/frodent
name = "Rodent (Top)"
icon_state = "frodent"
-/datum/sprite_accessory/mam_snouts/fhusky
+/datum/sprite_accessory/snouts/mam_snouts/fhusky
name = "Husky (Top)"
icon_state = "fhusky"
-/datum/sprite_accessory/mam_snouts/fotie
+/datum/sprite_accessory/snouts/mam_snouts/fotie
name = "Otie (Top)"
icon_state = "fotie"
-/datum/sprite_accessory/mam_snouts/fpede
+/datum/sprite_accessory/snouts/mam_snouts/fpede
name = "Scolipede (Top)"
icon_state = "fpede"
-/datum/sprite_accessory/mam_snouts/fsergal
+/datum/sprite_accessory/snouts/mam_snouts/fsergal
name = "Sergal (Top)"
icon_state = "fsergal"
-/datum/sprite_accessory/mam_snouts/fshark
+/datum/sprite_accessory/snouts/mam_snouts/fshark
name = "Shark (Top)"
icon_state = "fshark"
-/datum/sprite_accessory/mam_snouts/ftoucan
+/datum/sprite_accessory/snouts/mam_snouts/ftoucan
name = "Toucan (Top)"
icon_state = "ftoucan"
-/datum/sprite_accessory/mam_snouts/fsharp
+/datum/sprite_accessory/snouts/mam_snouts/fsharp
name = "Sharp (Top)"
icon_state = "fsharp"
color_src = MUTCOLORS
-/datum/sprite_accessory/mam_snouts/fround
+/datum/sprite_accessory/snouts/mam_snouts/fround
name = "Round (Top)"
icon_state = "fround"
color_src = MUTCOLORS
-/datum/sprite_accessory/mam_snouts/fsharplight
+/datum/sprite_accessory/snouts/mam_snouts/fsharplight
name = "Sharp + Light (Top)"
icon_state = "fsharplight"
color_src = MUTCOLORS
-/datum/sprite_accessory/mam_snouts/froundlight
+/datum/sprite_accessory/snouts/mam_snouts/froundlight
name = "Round + Light (Top)"
icon_state = "froundlight"
color_src = MUTCOLORS
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/spines.dm b/code/modules/mob/dead/new_player/sprite_accessories/spines.dm
index 54749d5ea9..83415ed375 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/spines.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/spines.dm
@@ -2,10 +2,16 @@
icon = 'icons/mob/mutant_bodyparts.dmi'
relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER)
+/datum/sprite_accessory/spines/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
+ return (!H.dna.features["spines"] || H.dna.features["spines"] == "None" || H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR))
+
/datum/sprite_accessory/spines_animated
icon = 'icons/mob/mutant_bodyparts.dmi'
relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER)
+/datum/sprite_accessory/spines_animated/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
+ return ((!H.dna.features["spines"] || H.dna.features["spines"] == "None" || H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || H.dna.species.mutant_bodyparts["tail"])
+
/datum/sprite_accessory/spines/none
name = "None"
icon_state = "none"
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/synthliz.dm b/code/modules/mob/dead/new_player/sprite_accessories/synthliz.dm
index a2884ab944..16531d8f06 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/synthliz.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/synthliz.dm
@@ -1,24 +1,24 @@
//Synth snouts (This is the most important part)
-/datum/sprite_accessory/mam_snouts/synthliz
+/datum/sprite_accessory/snouts/mam_snouts/synthliz
recommended_species = list("synthliz")
icon = 'modular_citadel/icons/mob/synthliz_snouts.dmi'
color_src = MUTCOLORS
name = "Synthetic Lizard - Snout"
icon_state = "synthliz_basic"
-/datum/sprite_accessory/mam_snouts/synthliz/synthliz_under
+/datum/sprite_accessory/snouts/mam_snouts/synthliz/synthliz_under
icon = 'modular_citadel/icons/mob/synthliz_snouts.dmi'
color_src = MATRIXED
name = "Synthetic Lizard - Snout Under"
icon_state = "synthliz_under"
-/datum/sprite_accessory/mam_snouts/synthliz/synthliz_tert
+/datum/sprite_accessory/snouts/mam_snouts/synthliz/synthliz_tert
icon = 'modular_citadel/icons/mob/synthliz_snouts.dmi'
color_src = MATRIXED
name = "Synthetic Lizard - Snout Tertiary"
icon_state = "synthliz_tert"
-/datum/sprite_accessory/mam_snouts/synthliz/synthliz_tertunder
+/datum/sprite_accessory/snouts/mam_snouts/synthliz/synthliz_tertunder
icon = 'modular_citadel/icons/mob/synthliz_snouts.dmi'
color_src = MATRIXED
name = "Synthetic Lizard - Snout Tertiary Under"
@@ -42,14 +42,14 @@
icon_state = "synthlizpecslight"
//Synth tails
-/datum/sprite_accessory/mam_tails/synthliz
+/datum/sprite_accessory/tails/mam_tails/synthliz
recommended_species = list("synthliz")
icon = 'modular_citadel/icons/mob/synthliz_tails.dmi'
color_src = MUTCOLORS
name = "Synthetic Lizard"
icon_state = "synthliz"
-/datum/sprite_accessory/mam_tails_animated/synthliz
+/datum/sprite_accessory/tails_animated/mam_tails_animated/synthliz
recommended_species = list("synthliz")
icon = 'modular_citadel/icons/mob/synthliz_tails.dmi'
color_src = MUTCOLORS
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 33dbd7059f..812e0c052c 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/tails.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/tails.dm
@@ -3,6 +3,9 @@
mutant_part_string = "tail"
relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER)
+/datum/sprite_accessory/tails/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
+ return ((H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || tauric)
+
/datum/sprite_accessory/tails_animated
icon = 'icons/mob/mutant_bodyparts.dmi'
mutant_part_string = "tailwag"
@@ -12,6 +15,9 @@
************* Lizard Tails ****************
*******************************************/
+/datum/sprite_accessory/tails_animated/lizard/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
+ return (((H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || tauric) || H.dna.species.mutant_bodyparts["tail_lizard"])
+
/datum/sprite_accessory/tails/lizard/smooth
name = "Smooth"
icon_state = "smooth"
@@ -98,6 +104,9 @@
icon_state = "none"
relevant_layers = null
+/datum/sprite_accessory/tails_animated/human/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
+ return (((H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || tauric)|| H.dna.species.mutant_bodyparts["tail_human"])
+
/datum/sprite_accessory/tails/human/ailurus
name = "Red Panda"
icon_state = "wah"
@@ -122,22 +131,22 @@
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = MATRIXED
-/datum/sprite_accessory/mam_tails/batl
+/datum/sprite_accessory/tails/mam_tails/batl
name = "Bat (Long)"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
icon_state = "batl"
-/datum/sprite_accessory/mam_tails_animated/batl
+/datum/sprite_accessory/tails_animated/mam_tails_animated/batl
name = "Bat (Long)"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
icon_state = "batl"
-/datum/sprite_accessory/mam_tails/bats
+/datum/sprite_accessory/tails/mam_tails/bats
name = "Bat (Short)"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
icon_state = "bats"
-/datum/sprite_accessory/mam_tails_animated/bats
+/datum/sprite_accessory/tails_animated/mam_tails_animated/bats
name = "Bat (Short)"
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
icon_state = "bats"
@@ -518,368 +527,371 @@
************** Furry Tails ****************
*******************************************/
-/datum/sprite_accessory/mam_tails
+/datum/sprite_accessory/tails/mam_tails
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
recommended_species = list("mammal", "slimeperson", "podweak", "felinid", "insect")
mutant_part_string = "tail"
relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER)
-/datum/sprite_accessory/mam_tails/none
+/datum/sprite_accessory/tails/mam_tails/none
name = "None"
icon_state = "none"
recommended_species = null
relevant_layers = null
-/datum/sprite_accessory/mam_tails_animated
+/datum/sprite_accessory/tails_animated/mam_tails_animated
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
mutant_part_string = "tailwag"
relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER)
-/datum/sprite_accessory/mam_tails_animated/none
+/datum/sprite_accessory/tails_animated/mam_tails_animated/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
+ return (((H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || tauric) || H.dna.species.mutant_bodyparts["mam_tail"])
+
+/datum/sprite_accessory/tails_animated/mam_tails_animated/none
name = "None"
icon_state = "none"
relevant_layers = null
-/datum/sprite_accessory/mam_tails/ailurus
+/datum/sprite_accessory/tails/mam_tails/ailurus
name = "Red Panda"
icon_state = "wah"
extra = TRUE
-/datum/sprite_accessory/mam_tails_animated/ailurus
+/datum/sprite_accessory/tails_animated/mam_tails_animated/ailurus
name = "Red Panda"
icon_state = "wah"
extra = TRUE
-/datum/sprite_accessory/mam_tails/axolotl
+/datum/sprite_accessory/tails/mam_tails/axolotl
name = "Axolotl"
icon_state = "axolotl"
-/datum/sprite_accessory/mam_tails_animated/axolotl
+/datum/sprite_accessory/tails_animated/mam_tails_animated/axolotl
name = "Axolotl"
icon_state = "axolotl"
-/datum/sprite_accessory/mam_tails/batl
+/datum/sprite_accessory/tails/mam_tails/batl
name = "Bat (Long)"
icon_state = "batl"
-/datum/sprite_accessory/mam_tails_animated/batl
+/datum/sprite_accessory/tails_animated/mam_tails_animated/batl
name = "Bat (Long)"
icon_state = "batl"
-/datum/sprite_accessory/mam_tails/bats
+/datum/sprite_accessory/tails/mam_tails/bats
name = "Bat (Short)"
icon_state = "bats"
-/datum/sprite_accessory/mam_tails_animated/bats
+/datum/sprite_accessory/tails_animated/mam_tails_animated/bats
name = "Bat (Short)"
icon_state = "bats"
-/datum/sprite_accessory/mam_tails/bee
+/datum/sprite_accessory/tails/mam_tails/bee
name = "Bee"
icon_state = "bee"
-/datum/sprite_accessory/mam_tails_animated/bee
+/datum/sprite_accessory/tails_animated/mam_tails_animated/bee
name = "Bee"
icon_state = "bee"
-/datum/sprite_accessory/mam_tails/cat
+/datum/sprite_accessory/tails/mam_tails/cat
name = "Cat"
icon_state = "cat"
color_src = HAIR
-/datum/sprite_accessory/mam_tails_animated/cat
+/datum/sprite_accessory/tails_animated/mam_tails_animated/cat
name = "Cat"
icon_state = "cat"
color_src = HAIR
-/datum/sprite_accessory/mam_tails/catbig
+/datum/sprite_accessory/tails/mam_tails/catbig
name = "Cat, Big"
icon_state = "catbig"
-/datum/sprite_accessory/mam_tails_animated/catbig
+/datum/sprite_accessory/tails_animated/mam_tails_animated/catbig
name = "Cat, Big"
icon_state = "catbig"
-/datum/sprite_accessory/mam_tails/twocat
+/datum/sprite_accessory/tails/mam_tails/twocat
name = "Cat, Double"
icon_state = "twocat"
-/datum/sprite_accessory/mam_tails_animated/twocat
+/datum/sprite_accessory/tails_animated/mam_tails_animated/twocat
name = "Cat, Double"
icon_state = "twocat"
-/datum/sprite_accessory/mam_tails/corvid
+/datum/sprite_accessory/tails/mam_tails/corvid
name = "Corvid"
icon_state = "crow"
-/datum/sprite_accessory/mam_tails_animated/corvid
+/datum/sprite_accessory/tails_animated/mam_tails_animated/corvid
name = "Corvid"
icon_state = "crow"
-/datum/sprite_accessory/mam_tail/cow
+/datum/sprite_accessory/tails/mam_tail/cow
name = "Cow"
icon_state = "cow"
-/datum/sprite_accessory/mam_tails_animated/cow
+/datum/sprite_accessory/tails_animated/mam_tails_animated/cow
name = "Cow"
icon_state = "cow"
-/datum/sprite_accessory/mam_tails/eevee
+/datum/sprite_accessory/tails/mam_tails/eevee
name = "Eevee"
icon_state = "eevee"
-/datum/sprite_accessory/mam_tails_animated/eevee
+/datum/sprite_accessory/tails_animated/mam_tails_animated/eevee
name = "Eevee"
icon_state = "eevee"
-/datum/sprite_accessory/mam_tails/fennec
+/datum/sprite_accessory/tails/mam_tails/fennec
name = "Fennec"
icon_state = "fennec"
-/datum/sprite_accessory/mam_tails_animated/fennec
+/datum/sprite_accessory/tails_animated/mam_tails_animated/fennec
name = "Fennec"
icon_state = "fennec"
-/datum/sprite_accessory/mam_tails/human/fish
+/datum/sprite_accessory/tails/mam_tails/human/fish
name = "Fish"
icon_state = "fish"
-/datum/sprite_accessory/mam_tails_animated/human/fish
+/datum/sprite_accessory/tails_animated/mam_tails_animated/human/fish
name = "Fish"
icon_state = "fish"
-/datum/sprite_accessory/mam_tails/fox
+/datum/sprite_accessory/tails/mam_tails/fox
name = "Fox"
icon_state = "fox"
-/datum/sprite_accessory/mam_tails_animated/fox
+/datum/sprite_accessory/tails_animated/mam_tails_animated/fox
name = "Fox"
icon_state = "fox"
-/datum/sprite_accessory/mam_tails/hawk
+/datum/sprite_accessory/tails/mam_tails/hawk
name = "Hawk"
icon_state = "hawk"
-/datum/sprite_accessory/mam_tails_animated/hawk
+/datum/sprite_accessory/tails_animated/mam_tails_animated/hawk
name = "Hawk"
icon_state = "hawk"
-/datum/sprite_accessory/mam_tails/horse
+/datum/sprite_accessory/tails/mam_tails/horse
name = "Horse"
icon_state = "horse"
color_src = HAIR
-/datum/sprite_accessory/mam_tails_animated/horse
+/datum/sprite_accessory/tails_animated/mam_tails_animated/horse
name = "Horse"
icon_state = "horse"
color_src = HAIR
-/datum/sprite_accessory/mam_tails/husky
+/datum/sprite_accessory/tails/mam_tails/husky
name = "Husky"
icon_state = "husky"
-/datum/sprite_accessory/mam_tails_animated/husky
+/datum/sprite_accessory/tails_animated/mam_tails_animated/husky
name = "Husky"
icon_state = "husky"
-datum/sprite_accessory/mam_tails/insect
+datum/sprite_accessory/tails/mam_tails/insect
name = "Insect"
icon_state = "insect"
-/datum/sprite_accessory/mam_tails_animated/insect
+/datum/sprite_accessory/tails_animated/mam_tails_animated/insect
name = "Insect"
icon_state = "insect"
-/datum/sprite_accessory/mam_tails/kangaroo
+/datum/sprite_accessory/tails/mam_tails/kangaroo
name = "kangaroo"
icon_state = "kangaroo"
-/datum/sprite_accessory/mam_tails_animated/kangaroo
+/datum/sprite_accessory/tails_animated/mam_tails_animated/kangaroo
name = "kangaroo"
icon_state = "kangaroo"
-/datum/sprite_accessory/mam_tails/kitsune
+/datum/sprite_accessory/tails/mam_tails/kitsune
name = "Kitsune"
icon_state = "kitsune"
-/datum/sprite_accessory/mam_tails_animated/kitsune
+/datum/sprite_accessory/tails_animated/mam_tails_animated/kitsune
name = "Kitsune"
icon_state = "kitsune"
-/datum/sprite_accessory/mam_tails/lab
+/datum/sprite_accessory/tails/mam_tails/lab
name = "Lab"
icon_state = "lab"
-/datum/sprite_accessory/mam_tails_animated/lab
+/datum/sprite_accessory/tails_animated/mam_tails_animated/lab
name = "Lab"
icon_state = "lab"
-/datum/sprite_accessory/mam_tails/murid
+/datum/sprite_accessory/tails/mam_tails/murid
name = "Murid"
icon_state = "murid"
-/datum/sprite_accessory/mam_tails_animated/murid
+/datum/sprite_accessory/tails_animated/mam_tails_animated/murid
name = "Murid"
icon_state = "murid"
-/datum/sprite_accessory/mam_tails/otie
+/datum/sprite_accessory/tails/mam_tails/otie
name = "Otusian"
icon_state = "otie"
-/datum/sprite_accessory/mam_tails_animated/otie
+/datum/sprite_accessory/tails_animated/mam_tails_animated/otie
name = "Otusian"
icon_state = "otie"
-/datum/sprite_accessory/mam_tails/orca
+/datum/sprite_accessory/tails/mam_tails/orca
name = "Orca"
icon_state = "orca"
-/datum/sprite_accessory/mam_tails_animated/orca
+/datum/sprite_accessory/tails_animated/mam_tails_animated/orca
name = "Orca"
icon_state = "orca"
-/datum/sprite_accessory/mam_tails/pede
+/datum/sprite_accessory/tails/mam_tails/pede
name = "Scolipede"
icon_state = "pede"
-/datum/sprite_accessory/mam_tails_animated/pede
+/datum/sprite_accessory/tails_animated/mam_tails_animated/pede
name = "Scolipede"
icon_state = "pede"
-/datum/sprite_accessory/mam_tails/rabbit
+/datum/sprite_accessory/tails/mam_tails/rabbit
name = "Rabbit"
icon_state = "rabbit"
-/datum/sprite_accessory/mam_tails_animated/rabbit
+/datum/sprite_accessory/tails_animated/mam_tails_animated/rabbit
name = "Rabbit"
icon_state = "rabbit"
-/datum/sprite_accessory/mam_tails/sergal
+/datum/sprite_accessory/tails/mam_tails/sergal
name = "Sergal"
icon_state = "sergal"
-/datum/sprite_accessory/mam_tails_animated/sergal
+/datum/sprite_accessory/tails_animated/mam_tails_animated/sergal
name = "Sergal"
icon_state = "sergal"
-/datum/sprite_accessory/mam_tails/skunk
+/datum/sprite_accessory/tails/mam_tails/skunk
name = "Skunk"
icon_state = "skunk"
-/datum/sprite_accessory/mam_tails_animated/skunk
+/datum/sprite_accessory/tails_animated/mam_tails_animated/skunk
name = "Skunk"
icon_state = "skunk"
-/datum/sprite_accessory/mam_tails/smooth
+/datum/sprite_accessory/tails/mam_tails/smooth
name = "Smooth"
icon_state = "smooth"
color_src = MUTCOLORS
icon = 'icons/mob/mutant_bodyparts.dmi'
-/datum/sprite_accessory/mam_tails_animated/smooth
+/datum/sprite_accessory/tails_animated/mam_tails_animated/smooth
name = "Smooth"
icon_state = "smooth"
color_src = MUTCOLORS
icon = 'icons/mob/mutant_bodyparts.dmi'
-/datum/sprite_accessory/mam_tails_animated/spikes
+/datum/sprite_accessory/tails_animated/mam_tails_animated/spikes
name = "Spikes"
icon_state = "spikes"
color_src = MUTCOLORS
icon = 'icons/mob/mutant_bodyparts.dmi'
-/datum/sprite_accessory/mam_tails/spikes
+/datum/sprite_accessory/tails/mam_tails/spikes
name = "Spikes"
icon_state = "spikes"
color_src = MUTCOLORS
icon = 'icons/mob/mutant_bodyparts.dmi'
-/datum/sprite_accessory/mam_tails/shark
+/datum/sprite_accessory/tails/mam_tails/shark
name = "Shark"
icon_state = "shark"
-/datum/sprite_accessory/mam_tails_animated/shark
+/datum/sprite_accessory/tails_animated/mam_tails_animated/shark
name = "Shark"
icon_state = "shark"
-/datum/sprite_accessory/mam_tails/shepherd
+/datum/sprite_accessory/tails/mam_tails/shepherd
name = "Shepherd"
icon_state = "shepherd"
-/datum/sprite_accessory/mam_tails_animated/shepherd
+/datum/sprite_accessory/tails_animated/mam_tails_animated/shepherd
name = "Shepherd"
icon_state = "shepherd"
-/datum/sprite_accessory/mam_tails/straighttail
+/datum/sprite_accessory/tails/mam_tails/straighttail
name = "Straight Tail"
icon_state = "straighttail"
-/datum/sprite_accessory/mam_tails_animated/straighttail
+/datum/sprite_accessory/tails_animated/mam_tails_animated/straighttail
name = "Straight Tail"
icon_state = "straighttail"
-/datum/sprite_accessory/mam_tails/squirrel
+/datum/sprite_accessory/tails/mam_tails/squirrel
name = "Squirrel"
icon_state = "squirrel"
-/datum/sprite_accessory/mam_tails_animated/squirrel
+/datum/sprite_accessory/tails_animated/mam_tails_animated/squirrel
name = "Squirrel"
icon_state = "squirrel"
-/datum/sprite_accessory/mam_tails/tamamo_kitsune
+/datum/sprite_accessory/tails/mam_tails/tamamo_kitsune
name = "Tamamo Kitsune Tails"
icon_state = "9sune"
-/datum/sprite_accessory/mam_tails_animated/tamamo_kitsune
+/datum/sprite_accessory/tails_animated/mam_tails_animated/tamamo_kitsune
name = "Tamamo Kitsune Tails"
icon_state = "9sune"
-/datum/sprite_accessory/mam_tails/tentacle
+/datum/sprite_accessory/tails/mam_tails/tentacle
name = "Tentacle"
icon_state = "tentacle"
-/datum/sprite_accessory/mam_tails_animated/tentacle
+/datum/sprite_accessory/tails_animated/mam_tails_animated/tentacle
name = "Tentacle"
icon_state = "tentacle"
-/datum/sprite_accessory/mam_tails/tiger
+/datum/sprite_accessory/tails/mam_tails/tiger
name = "Tiger"
icon_state = "tiger"
-/datum/sprite_accessory/mam_tails_animated/tiger
+/datum/sprite_accessory/tails_animated/mam_tails_animated/tiger
name = "Tiger"
icon_state = "tiger"
-/datum/sprite_accessory/mam_tails/dtiger
+/datum/sprite_accessory/tails/mam_tails/dtiger
name = "Dark Tiger"
icon_state = "dtiger"
color_src = MUTCOLORS
icon = 'icons/mob/mutant_bodyparts.dmi'
-/datum/sprite_accessory/mam_tails_animated/dtiger
+/datum/sprite_accessory/tails_animated/mam_tails_animated/dtiger
name = "Dark Tiger"
icon_state = "dtiger"
color_src = MUTCOLORS
icon = 'icons/mob/mutant_bodyparts.dmi'
-/datum/sprite_accessory/mam_tails/ltiger
+/datum/sprite_accessory/tails/mam_tails/ltiger
name = "Light Tiger"
icon_state = "ltiger"
color_src = MUTCOLORS
icon = 'icons/mob/mutant_bodyparts.dmi'
-/datum/sprite_accessory/mam_tails_animated/ltiger
+/datum/sprite_accessory/tails_animated/mam_tails_animated/ltiger
name = "Light Tiger"
icon_state = "ltiger"
color_src = MUTCOLORS
icon = 'icons/mob/mutant_bodyparts.dmi'
-/datum/sprite_accessory/mam_tails/wolf
+/datum/sprite_accessory/tails/mam_tails/wolf
name = "Wolf"
icon_state = "wolf"
-/datum/sprite_accessory/mam_tails_animated/wolf
+/datum/sprite_accessory/tails_animated/mam_tails_animated/wolf
name = "Wolf"
icon_state = "wolf"
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/wings.dm b/code/modules/mob/dead/new_player/sprite_accessories/wings.dm
index 34767a10f1..fb03df88a1 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/wings.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/wings.dm
@@ -5,10 +5,16 @@
icon_state = "none"
relevant_layers = null
+/datum/sprite_accessory/wings/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
+ return (!H.dna.features["wings"] || H.dna.features["wings"] == "None" || (H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT) && (!H.wear_suit.species_exception || !is_type_in_list(src, H.wear_suit.species_exception))))
+
/datum/sprite_accessory/wings_open
icon = 'icons/mob/wings.dmi'
relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER)
+/datum/sprite_accessory/wings_open/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
+ return (H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT) && (!H.wear_suit.species_exception || !is_type_in_list(src, H.wear_suit.species_exception)) || H.dna.species.mutant_bodyparts["wings"])
+
/datum/sprite_accessory/wings_open/angel
name = "Angel"
icon_state = "angel"
diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm
index caebb9cf10..9ac270bf34 100644
--- a/code/modules/mob/inventory.dm
+++ b/code/modules/mob/inventory.dm
@@ -382,10 +382,20 @@
return 0
-//Outdated but still in use apparently. This should at least be a human proc.
-//Daily reminder to murder this - Remie.
+/**
+ * Used to return a list of equipped items on a mob; does not include held items (use get_all_gear)
+ *
+ * Argument(s):
+ * * Optional - include_pockets (TRUE/FALSE), whether or not to include the pockets and suit storage in the returned list
+ */
+
/mob/living/proc/get_equipped_items(include_pockets = FALSE)
- return
+ var/list/items = list()
+ for(var/obj/item/I in contents)
+ if(I.item_flags & IN_INVENTORY)
+ items += I
+ items -= held_items
+ return items
/mob/living/proc/unequip_everything()
var/list/items = list()
@@ -476,5 +486,19 @@
hand_bodyparts[i] = BP
..() //Don't redraw hands until we have organs for them
+
+//GetAllContents that is reasonable and not stupid
+/mob/living/carbon/proc/get_all_gear()
+ var/list/processing_list = get_equipped_items(include_pockets = TRUE) + held_items
+ listclearnulls(processing_list) // handles empty hands
+ var/i = 0
+ while(i < length(processing_list) )
+ var/atom/A = processing_list[++i]
+ if(SEND_SIGNAL(A, COMSIG_CONTAINS_STORAGE))
+ var/list/item_stuff = list()
+ SEND_SIGNAL(A, COMSIG_TRY_STORAGE_RETURN_INVENTORY, item_stuff)
+ processing_list += item_stuff
+ return processing_list
+
/mob/canReachInto(atom/user, atom/target, list/next, view_only, obj/item/tool)
return ..() && (user == src)
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index edb681e60f..b7d67e49a6 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -87,7 +87,7 @@
if(user != src && (user.a_intent == INTENT_HELP || user.a_intent == INTENT_DISARM))
for(var/datum/surgery/S in surgeries)
if(S.next_step(user,user.a_intent))
- return 1
+ return STOP_ATTACK_PROC_CHAIN
if(!all_wounds || !(user.a_intent == INTENT_HELP || user == src))
return ..()
@@ -95,7 +95,7 @@
for(var/i in shuffle(all_wounds))
var/datum/wound/W = i
if(W.try_treating(I, user))
- return 1
+ return STOP_ATTACK_PROC_CHAIN
return ..()
diff --git a/code/modules/mob/living/carbon/human/dummy.dm b/code/modules/mob/living/carbon/human/dummy.dm
index 1e2a375b39..2f5c94b784 100644
--- a/code/modules/mob/living/carbon/human/dummy.dm
+++ b/code/modules/mob/living/carbon/human/dummy.dm
@@ -21,7 +21,7 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
/mob/living/carbon/human/dummy/proc/wipe_state()
delete_equipment()
icon_render_key = null
- cut_overlays(TRUE)
+ cut_overlays()
//Inefficient pooling/caching way.
GLOBAL_LIST_EMPTY(human_dummy_list)
diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm
index cb0dbef332..04747ffcb4 100644
--- a/code/modules/mob/living/carbon/human/emote.dm
+++ b/code/modules/mob/living/carbon/human/emote.dm
@@ -7,6 +7,11 @@
message = "cries."
emote_type = EMOTE_AUDIBLE
+/datum/emote/living/carbon/human/cry/run_emote(mob/user, params)
+ . = ..()
+ if(. && isipcperson(user))
+ do_fake_sparks(5,FALSE,user)
+
/datum/emote/living/carbon/human/dap
key = "dap"
key_third_person = "daps"
@@ -187,3 +192,71 @@
key_third_person = "chimes"
message = "chimes."
sound = 'sound/machines/chime.ogg'
+
+//rock paper scissors emote handling
+/mob/living/carbon/human/proc/beginRockPaperScissors(var/chosen_move)
+ GLOB.rockpaperscissors_players[src] = list(chosen_move, ROCKPAPERSCISSORS_NOT_DECIDED)
+ do_after_advanced(src, ROCKPAPERSCISSORS_TIME_LIMIT, src, DO_AFTER_REQUIRES_USER_ON_TURF|DO_AFTER_NO_COEFFICIENT|DO_AFTER_NO_PROGRESSBAR|DO_AFTER_DISALLOW_MOVING_ABSOLUTE_USER, CALLBACK(src, .proc/rockpaperscissors_tick))
+ var/new_entry = GLOB.rockpaperscissors_players[src]
+ if(new_entry[2] == ROCKPAPERSCISSORS_NOT_DECIDED)
+ to_chat(src, "You put your hand back down.")
+ GLOB.rockpaperscissors_players -= src
+
+/mob/living/carbon/human/proc/rockpaperscissors_tick() //called every cycle of the progress bar for rock paper scissors while waiting for an opponent
+ var/mob/living/carbon/human/opponent
+ for(var/mob/living/carbon/human/potential_opponent in (GLOB.rockpaperscissors_players - src)) //dont play against yourself
+ if(get_dist(src, potential_opponent) <= ROCKPAPERSCISSORS_RANGE)
+ opponent = potential_opponent
+ break
+ if(opponent)
+ //we found an opponent before they found us
+ var/move_to_number = list("rock" = 0, "paper" = 1, "scissors" = 2)
+ var/our_move = move_to_number[GLOB.rockpaperscissors_players[src][1]]
+ var/their_move = move_to_number[GLOB.rockpaperscissors_players[opponent][1]]
+ var/result_us = ROCKPAPERSCISSORS_WIN
+ var/result_them = ROCKPAPERSCISSORS_LOSE
+ if(our_move == their_move)
+ result_us = ROCKPAPERSCISSORS_TIE
+ result_them = ROCKPAPERSCISSORS_TIE
+ else
+ if(((our_move + 1) % 3) == their_move)
+ result_us = ROCKPAPERSCISSORS_LOSE
+ result_them = ROCKPAPERSCISSORS_WIN
+ //we decided our results so set them in the list
+ GLOB.rockpaperscissors_players[src][2] = result_us
+ GLOB.rockpaperscissors_players[opponent][2] = result_them
+
+ //show what happened
+ src.visible_message("[src] makes [GLOB.rockpaperscissors_players[src][1]] with their hand!")
+ opponent.visible_message("[opponent] makes [GLOB.rockpaperscissors_players[opponent][1]] with their hands!")
+ switch(result_us)
+ if(ROCKPAPERSCISSORS_TIE)
+ src.visible_message("It was a tie!")
+ if(ROCKPAPERSCISSORS_WIN)
+ src.visible_message("[src] wins!")
+ if(ROCKPAPERSCISSORS_LOSE)
+ src.visible_message("[opponent] wins!")
+
+ //make the progress bar end so that each player can handle the result
+ return DO_AFTER_STOP
+
+ //no opponent was found, so keep searching
+ return DO_AFTER_PROCEED
+
+//the actual emotes
+/datum/emote/living/carbon/human/rockpaperscissors
+ message = "is attempting to play rock paper scissors!"
+
+/datum/emote/living/carbon/human/rockpaperscissors/rock
+ key = "rock"
+
+/datum/emote/living/carbon/human/rockpaperscissors/paper
+ key = "paper"
+
+/datum/emote/living/carbon/human/rockpaperscissors/scissors
+ key = "scissors"
+
+/datum/emote/living/carbon/human/rockpaperscissors/run_emote(mob/living/carbon/human/user, params)
+ if(!(user in GLOB.rockpaperscissors_players)) //no using the emote again while already playing!
+ . = ..()
+ user.beginRockPaperScissors(key)
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index de4b7a659f..18501b4ca2 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -299,10 +299,10 @@
/mob/living/carbon/human/ex_act(severity, target, origin)
- if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src))
+ if(TRAIT_BOMBIMMUNE in dna.species.species_traits)
return
..()
- if (!severity)
+ if (!severity || QDELETED(src))
return
var/brute_loss = 0
var/burn_loss = 0
diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm
index 1c776427cf..523369d10a 100644
--- a/code/modules/mob/living/carbon/human/inventory.dm
+++ b/code/modules/mob/living/carbon/human/inventory.dm
@@ -1,31 +1,17 @@
/mob/living/carbon/human/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE, clothing_check = FALSE, list/return_warning)
return dna.species.can_equip(I, slot, disable_warning, src, bypass_equip_delay_self, clothing_check, return_warning)
+/**
+ * Used to return a list of equipped items on a human mob; does not include held items (use get_all_gear)
+ *
+ * Argument(s):
+ * * Optional - include_pockets (TRUE/FALSE), whether or not to include the pockets and suit storage in the returned list
+ */
+
/mob/living/carbon/human/get_equipped_items(include_pockets = FALSE)
var/list/items = ..()
- if(belt)
- items += belt
- if(ears)
- items += ears
- if(glasses)
- items += glasses
- if(gloves)
- items += gloves
- if(shoes)
- items += shoes
- if(wear_id)
- items += wear_id
- if(wear_suit)
- items += wear_suit
- if(w_uniform)
- items += w_uniform
- if(include_pockets)
- if(l_store)
- items += l_store
- if(r_store)
- items += r_store
- if(s_store)
- items += s_store
+ if(!include_pockets)
+ items -= list(l_store, r_store, s_store)
return items
// Return the item currently in the slot ID
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 54c3b314b9..ed509f900a 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -114,6 +114,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
/// Our default override for typing indicator state
var/typing_indicator_state
+ //the ids you can use for your species, if empty, it means default only and not changeable
+ var/list/allowed_limb_ids
+
///////////
// PROCS //
///////////
@@ -121,9 +124,14 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
/datum/species/New()
if(!limbs_id) //if we havent set a limbs id to use, just use our own id
- limbs_id = id
+ mutant_bodyparts["limbs_id"] = id //done this way to be non-intrusive to the existing system
+ else
+ mutant_bodyparts["limbs_id"] = limbs_id
..()
+ //update our mutant bodyparts to include unlocked ones
+ mutant_bodyparts += GLOB.unlocked_mutant_parts
+
/proc/generate_selectable_species(clear = FALSE)
if(clear)
GLOB.roundstart_races = list()
@@ -639,106 +647,19 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(!mutant_bodyparts)
return
- var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
var/tauric = mutant_bodyparts["taur"] && H.dna.features["taur"] && H.dna.features["taur"] != "None"
- if(mutant_bodyparts["tail_lizard"])
- if((H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || tauric)
- bodyparts_to_add -= "tail_lizard"
-
- if(mutant_bodyparts["waggingtail_lizard"])
- if((H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || tauric)
- bodyparts_to_add -= "waggingtail_lizard"
- else if (mutant_bodyparts["tail_lizard"])
- bodyparts_to_add -= "waggingtail_lizard"
-
- if(mutant_bodyparts["tail_human"])
- if((H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || tauric)
- bodyparts_to_add -= "tail_human"
-
- if(mutant_bodyparts["waggingtail_human"])
- if((H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || tauric)
- bodyparts_to_add -= "waggingtail_human"
- else if (mutant_bodyparts["tail_human"])
- bodyparts_to_add -= "waggingtail_human"
-
- if(mutant_bodyparts["spines"])
- if(!H.dna.features["spines"] || H.dna.features["spines"] == "None" || H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR))
- bodyparts_to_add -= "spines"
-
- if(mutant_bodyparts["waggingspines"])
- if(!H.dna.features["spines"] || H.dna.features["spines"] == "None" || H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR))
- bodyparts_to_add -= "waggingspines"
- else if (mutant_bodyparts["tail"])
- bodyparts_to_add -= "waggingspines"
-
- if(mutant_bodyparts["snout"]) //Take a closer look at that snout!
- if((H.wear_mask && (H.wear_mask.flags_inv & HIDESNOUT)) || (H.head && (H.head.flags_inv & HIDESNOUT)) || !HD || HD.status == BODYPART_ROBOTIC)
- bodyparts_to_add -= "snout"
-
- if(mutant_bodyparts["frills"])
- if(!H.dna.features["frills"] || H.dna.features["frills"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || !HD || HD.status == BODYPART_ROBOTIC)
- bodyparts_to_add -= "frills"
-
- if(mutant_bodyparts["horns"])
- if(!H.dna.features["horns"] || H.dna.features["horns"] == "None" || H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || HD.status == BODYPART_ROBOTIC)
- bodyparts_to_add -= "horns"
-
- if(mutant_bodyparts["ears"])
- if(!H.dna.features["ears"] || H.dna.features["ears"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEEARS)) || !HD || HD.status == BODYPART_ROBOTIC)
- bodyparts_to_add -= "ears"
-
- if(mutant_bodyparts["wings"])
- if(!H.dna.features["wings"] || H.dna.features["wings"] == "None" || (H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT) && (!H.wear_suit.species_exception || !is_type_in_list(src, H.wear_suit.species_exception))))
- bodyparts_to_add -= "wings"
-
- if(mutant_bodyparts["wings_open"])
- if(H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT) && (!H.wear_suit.species_exception || !is_type_in_list(src, H.wear_suit.species_exception)))
- bodyparts_to_add -= "wings_open"
- else if (mutant_bodyparts["wings"])
- bodyparts_to_add -= "wings_open"
-
- if(mutant_bodyparts["insect_fluff"])
- if(!H.dna.features["insect_fluff"] || H.dna.features["insect_fluff"] == "None" || H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT))
- bodyparts_to_add -= "insect_fluff"
-
-//CITADEL EDIT
- //Race specific bodyparts:
- //Xenos
- if(mutant_bodyparts["xenodorsal"])
- if(!H.dna.features["xenodorsal"] || H.dna.features["xenodorsal"] == "None" || (H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT)))
- bodyparts_to_add -= "xenodorsal"
- if(mutant_bodyparts["xenohead"])//This is an overlay for different castes using different head crests
- if(!H.dna.features["xenohead"] || H.dna.features["xenohead"] == "None" || H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || HD.status == BODYPART_ROBOTIC)
- bodyparts_to_add -= "xenohead"
- if(mutant_bodyparts["xenotail"])
- if(!H.dna.features["xenotail"] || H.dna.features["xenotail"] == "None" || H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT))
- bodyparts_to_add -= "xenotail"
-
- //Other Races
- if(mutant_bodyparts["mam_tail"])
- if((H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || tauric)
- bodyparts_to_add -= "mam_tail"
-
- if(mutant_bodyparts["mam_waggingtail"])
- if((H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || tauric)
- bodyparts_to_add -= "mam_waggingtail"
- else if (mutant_bodyparts["mam_tail"])
- bodyparts_to_add -= "mam_waggingtail"
-
- if(mutant_bodyparts["mam_ears"])
- if(!H.dna.features["mam_ears"] || H.dna.features["mam_ears"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEEARS)) || !HD || HD.status == BODYPART_ROBOTIC)
- bodyparts_to_add -= "mam_ears"
-
- if(mutant_bodyparts["mam_snouts"]) //Take a closer look at that snout!
- if((H.wear_mask && (H.wear_mask.flags_inv & HIDESNOUT)) || (H.head && (H.head.flags_inv & HIDESNOUT)) || !HD || HD.status == BODYPART_ROBOTIC)
- bodyparts_to_add -= "mam_snouts"
-
- if(mutant_bodyparts["taur"])
- if(!tauric || (H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)))
- bodyparts_to_add -= "taur"
-
-//END EDIT
+ for(var/mutant_part in mutant_bodyparts)
+ var/reference_list = GLOB.mutant_reference_list[mutant_part]
+ if(reference_list)
+ var/datum/sprite_accessory/S
+ var/transformed_part = GLOB.mutant_transform_list[mutant_part]
+ if(transformed_part)
+ S = reference_list[H.dna.features[transformed_part]]
+ else
+ S = reference_list[H.dna.features[mutant_part]]
+ if(!S || S.is_not_visible(H, tauric))
+ bodyparts_to_add -= mutant_part
//Digitigrade legs are stuck in the phantom zone between true limbs and mutant bodyparts. Mainly it just needs more agressive updating than most limbs.
var/update_needed = FALSE
@@ -775,76 +696,22 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/list/dna_feature_as_text_string = list()
for(var/bodypart in bodyparts_to_add)
- var/datum/sprite_accessory/S
- switch(bodypart)
- if("tail_lizard")
- S = GLOB.tails_list_lizard[H.dna.features["tail_lizard"]]
- if("waggingtail_lizard")
- S = GLOB.animated_tails_list_lizard[H.dna.features["tail_lizard"]]
- if("tail_human")
- S = GLOB.tails_list_human[H.dna.features["tail_human"]]
- if("waggingtail_human")
- S = GLOB.animated_tails_list_human[H.dna.features["tail_human"]]
- if("spines")
- S = GLOB.spines_list[H.dna.features["spines"]]
- if("waggingspines")
- S = GLOB.animated_spines_list[H.dna.features["spines"]]
- if("snout")
- S = GLOB.snouts_list[H.dna.features["snout"]]
- if("frills")
- S = GLOB.frills_list[H.dna.features["frills"]]
- if("horns")
- S = GLOB.horns_list[H.dna.features["horns"]]
- if("ears")
- S = GLOB.ears_list[H.dna.features["ears"]]
- if("body_markings")
- S = GLOB.body_markings_list[H.dna.features["body_markings"]]
- if("wings")
- S = GLOB.wings_list[H.dna.features["wings"]]
- if("wingsopen")
- S = GLOB.wings_open_list[H.dna.features["wings"]]
- if("deco_wings")
- S = GLOB.deco_wings_list[H.dna.features["deco_wings"]]
- if("legs")
- S = GLOB.legs_list[H.dna.features["legs"]]
- if("insect_wings")
- S = GLOB.insect_wings_list[H.dna.features["insect_wings"]]
- if("insect_fluff")
- S = GLOB.insect_fluffs_list[H.dna.features["insect_fluff"]]
- if("insect_markings")
- S = GLOB.insect_markings_list[H.dna.features["insect_markings"]]
- if("caps")
- S = GLOB.caps_list[H.dna.features["caps"]]
- if("ipc_screen")
- S = GLOB.ipc_screens_list[H.dna.features["ipc_screen"]]
- if("ipc_antenna")
- S = GLOB.ipc_antennas_list[H.dna.features["ipc_antenna"]]
- if("mam_tail")
- S = GLOB.mam_tails_list[H.dna.features["mam_tail"]]
- if("mam_waggingtail")
- S = GLOB.mam_tails_animated_list[H.dna.features["mam_tail"]]
- if("mam_body_markings")
- S = GLOB.mam_body_markings_list[H.dna.features["mam_body_markings"]]
- if("mam_ears")
- S = GLOB.mam_ears_list[H.dna.features["mam_ears"]]
- if("mam_snouts")
- S = GLOB.mam_snouts_list[H.dna.features["mam_snouts"]]
- if("taur")
- S = GLOB.taur_list[H.dna.features["taur"]]
- if("xenodorsal")
- S = GLOB.xeno_dorsal_list[H.dna.features["xenodorsal"]]
- if("xenohead")
- S = GLOB.xeno_head_list[H.dna.features["xenohead"]]
- if("xenotail")
- S = GLOB.xeno_tail_list[H.dna.features["xenotail"]]
+ var/reference_list = GLOB.mutant_reference_list[bodypart]
+ if(reference_list)
+ var/datum/sprite_accessory/S
+ var/transformed_part = GLOB.mutant_transform_list[bodypart]
+ if(transformed_part)
+ S = reference_list[H.dna.features[transformed_part]]
+ else
+ S = reference_list[H.dna.features[bodypart]]
- if(!S || S.icon_state == "none")
- continue
+ if(!S || S.icon_state == "none")
+ continue
- for(var/L in S.relevant_layers)
- LAZYADD(relevant_layers["[L]"], S)
- if(!S.mutant_part_string)
- dna_feature_as_text_string[S] = bodypart
+ for(var/L in S.relevant_layers)
+ LAZYADD(relevant_layers["[L]"], S)
+ if(!S.mutant_part_string)
+ dna_feature_as_text_string[S] = bodypart
var/static/list/layer_text = list(
"[BODY_BEHIND_LAYER]" = "BEHIND",
@@ -2043,17 +1910,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
return
/**
-
-
-
* The human species version of [/mob/living/carbon/proc/get_biological_state]. Depends on the HAS_FLESH and HAS_BONE species traits, having bones lets you have bone wounds, having flesh lets you have burn, slash, and piercing wounds
-
-
-
*/
-
-
-
/datum/species/proc/get_biological_state(mob/living/carbon/human/H)
. = BIO_INORGANIC
if(HAS_FLESH in species_traits)
@@ -2069,7 +1927,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(HAS_TRAIT(H, TRAIT_NOBREATH))
return TRUE
-
/datum/species/proc/handle_environment(datum/gas_mixture/environment, mob/living/carbon/human/H)
if(!environment)
return
@@ -2261,7 +2118,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
/datum/species/proc/spec_stun(mob/living/carbon/human/H,amount)
if(H)
stop_wagging_tail(H)
-
. = stunmod * H.physiology.stun_mod * amount
//////////////
diff --git a/code/modules/mob/living/carbon/human/species_types/bugmen.dm b/code/modules/mob/living/carbon/human/species_types/bugmen.dm
index 2a955e28a4..16b371c772 100644
--- a/code/modules/mob/living/carbon/human/species_types/bugmen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/bugmen.dm
@@ -13,10 +13,11 @@
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/insect
liked_food = MEAT | FRUIT
disliked_food = TOXIC
- icon_limbs = DEFAULT_BODYPART_ICON_CITADEL
exotic_bloodtype = "BUG"
exotic_blood_color = BLOOD_COLOR_BUG
tail_type = "mam_tail"
wagging_type = "mam_waggingtail"
- species_type = "insect"
\ No newline at end of file
+ species_type = "insect"
+
+ allowed_limb_ids = list("insect","apid","moth","moth_not_greyscale")
diff --git a/code/modules/mob/living/carbon/human/species_types/ethereal.dm b/code/modules/mob/living/carbon/human/species_types/ethereal.dm
index cda6faded0..cd9b3b80c7 100644
--- a/code/modules/mob/living/carbon/human/species_types/ethereal.dm
+++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm
@@ -27,7 +27,7 @@
// Cold temperatures hurt faster as it is harder to move with out the heat energy
bodytemp_cold_damage_limit = (T20C - 10) // about 10c
*/
- hair_color = "fixedmutcolor"
+ hair_color = "mutcolor"
hair_alpha = 140
var/current_color
var/EMPeffect = FALSE
diff --git a/code/modules/mob/living/carbon/human/species_types/furrypeople.dm b/code/modules/mob/living/carbon/human/species_types/furrypeople.dm
index 7706d4a9d5..534536d6e7 100644
--- a/code/modules/mob/living/carbon/human/species_types/furrypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/furrypeople.dm
@@ -2,7 +2,6 @@
name = "Anthromorph"
id = "mammal"
default_color = "4B4B4B"
- icon_limbs = DEFAULT_BODYPART_ICON_CITADEL
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAIR,HORNCOLOR,WINGCOLOR,HAS_FLESH,HAS_BONE)
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BEAST
mutant_bodyparts = list("mcolor" = "FFFFFF","mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "deco_wings" = "None",
@@ -17,3 +16,5 @@
tail_type = "mam_tail"
wagging_type = "mam_waggingtail"
species_type = "furry"
+
+ allowed_limb_ids = list("mammal","aquatic","avian")
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/species_types/ipc.dm b/code/modules/mob/living/carbon/human/species_types/ipc.dm
index 3aef14c256..806782a8b2 100644
--- a/code/modules/mob/living/carbon/human/species_types/ipc.dm
+++ b/code/modules/mob/living/carbon/human/species_types/ipc.dm
@@ -3,7 +3,6 @@
id = "ipc"
say_mod = "beeps"
default_color = "00FF00"
- icon_limbs = DEFAULT_BODYPART_ICON_CITADEL
blacklisted = 0
sexes = 0
species_traits = list(MUTCOLORS,NOEYES,NOTRANSSTING,HAS_FLESH,HAS_BONE)
diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
index c762a52ffc..49c55f70b3 100644
--- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
@@ -504,7 +504,7 @@
else if (select_alteration == "Ears")
var/list/snowflake_ears_list = list("Normal" = null)
for(var/path in GLOB.mam_ears_list)
- var/datum/sprite_accessory/mam_ears/instance = GLOB.mam_ears_list[path]
+ var/datum/sprite_accessory/ears/mam_ears/instance = GLOB.mam_ears_list[path]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if((!S.ckeys_allowed) || (S.ckeys_allowed.Find(H.client.ckey)))
@@ -518,7 +518,7 @@
else if (select_alteration == "Snout")
var/list/snowflake_snouts_list = list("Normal" = null)
for(var/path in GLOB.mam_snouts_list)
- var/datum/sprite_accessory/mam_snouts/instance = GLOB.mam_snouts_list[path]
+ var/datum/sprite_accessory/snouts/mam_snouts/instance = GLOB.mam_snouts_list[path]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if((!S.ckeys_allowed) || (S.ckeys_allowed.Find(H.client.ckey)))
@@ -549,7 +549,7 @@
else if (select_alteration == "Tail")
var/list/snowflake_tails_list = list("Normal" = null)
for(var/path in GLOB.mam_tails_list)
- var/datum/sprite_accessory/mam_tails/instance = GLOB.mam_tails_list[path]
+ var/datum/sprite_accessory/tails/mam_tails/instance = GLOB.mam_tails_list[path]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if((!S.ckeys_allowed) || (S.ckeys_allowed.Find(H.client.ckey)))
diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
index d768788e87..a8e3f89957 100644
--- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
@@ -5,13 +5,12 @@
say_mod = "hisses"
default_color = "00FF00"
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,LIPS,HORNCOLOR,WINGCOLOR,HAS_FLESH,HAS_BONE)
- mutant_bodyparts = list("tail_lizard", "snout", "spines", "horns", "frills", "body_markings", "legs", "taur", "deco_wings")
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_REPTILE
mutanttongue = /obj/item/organ/tongue/lizard
mutanttail = /obj/item/organ/tail/lizard
coldmod = 1.5
heatmod = 0.67
- mutant_bodyparts = list("mcolor" = "0F0", "mcolor2" = "0F0", "mcolor3" = "0F0", "tail_lizard" = "Smooth", "snout" = "Round",
+ mutant_bodyparts = list("mcolor" = "0F0", "mcolor2" = "0F0", "mcolor3" = "0F0", "tail_lizard" = "Smooth", "mam_snouts" = "Round",
"horns" = "None", "frills" = "None", "spines" = "None", "body_markings" = "None",
"legs" = "Digitigrade", "taur" = "None", "deco_wings" = "None")
attack_verb = "slash"
@@ -52,6 +51,7 @@
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,DIGITIGRADE)
inherent_traits = list(TRAIT_CHUNKYFINGERS)
mutantlungs = /obj/item/organ/lungs/ashwalker
+ mutanteyes = /obj/item/organ/eyes/night_vision
burnmod = 0.9
brutemod = 0.9
species_language_holder = /datum/language_holder/lizard/ash
diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
index b61e29b685..8c30adb8f9 100644
--- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
@@ -57,89 +57,10 @@
..()
/datum/species/plasmaman/before_equip_job(datum/job/J, mob/living/carbon/human/H, visualsOnly = FALSE)
- var/current_job = J?.title
var/datum/outfit/plasmaman/O = new /datum/outfit/plasmaman
- switch(current_job)
- if("Chaplain")
- O = new /datum/outfit/plasmaman/chaplain
-
- if("Curator")
- O = new /datum/outfit/plasmaman/curator
-
- if("Janitor")
- O = new /datum/outfit/plasmaman/janitor
-
- if("Botanist")
- O = new /datum/outfit/plasmaman/botany
-
- if("Bartender", "Lawyer")
- O = new /datum/outfit/plasmaman/bar
-
- if("Cook")
- O = new /datum/outfit/plasmaman/chef
-
- if("Security Officer")
- O = new /datum/outfit/plasmaman/security
-
- if("Detective")
- O = new /datum/outfit/plasmaman/detective
-
- if("Warden")
- O = new /datum/outfit/plasmaman/warden
-
- if("Cargo Technician", "Quartermaster")
- O = new /datum/outfit/plasmaman/cargo
-
- if("Shaft Miner")
- O = new /datum/outfit/plasmaman/mining
-
- if("Medical Doctor")
- O = new /datum/outfit/plasmaman/medical
-
- if("Chemist")
- O = new /datum/outfit/plasmaman/chemist
-
- if("Geneticist")
- O = new /datum/outfit/plasmaman/genetics
-
- if("Roboticist")
- O = new /datum/outfit/plasmaman/robotics
-
- if("Virologist")
- O = new /datum/outfit/plasmaman/viro
-
- if("Scientist")
- O = new /datum/outfit/plasmaman/science
-
- if("Station Engineer")
- O = new /datum/outfit/plasmaman/engineering
-
- if("Atmospheric Technician")
- O = new /datum/outfit/plasmaman/atmospherics
-
- if("Captain")
- O = new /datum/outfit/plasmaman/captain
-
- if("Head of Personnel")
- O = new /datum/outfit/plasmaman/hop
-
- if("Head of Security")
- O = new /datum/outfit/plasmaman/hos
-
- if("Chief Engineer")
- O = new /datum/outfit/plasmaman/ce
-
- if("Chief Medical Officer")
- O = new /datum/outfit/plasmaman/cmo
-
- if("Research Director")
- O = new /datum/outfit/plasmaman/rd
-
- if("Mime")
- O = new /datum/outfit/plasmaman/mime
-
- if("Clown")
- O = new /datum/outfit/plasmaman/clown
+ if(J)
+ if(J.plasma_outfit)
+ O = new J.plasma_outfit
H.equipOutfit(O, visualsOnly)
H.internal = H.get_item_for_held_index(2)
diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm
index f5a2f807e4..0f62953e6c 100644
--- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm
@@ -21,6 +21,8 @@
species_type = "plant"
+ allowed_limb_ids = list("pod","mush")
+
/datum/species/pod/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
C.faction |= "plants"
diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
index b760af9850..228a69c30f 100644
--- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
@@ -82,13 +82,11 @@
M.AddSpell(SW)
shadowwalk = SW
-
/obj/item/organ/brain/nightmare/Remove(special = FALSE)
if(shadowwalk && owner)
owner.RemoveSpell(shadowwalk)
return ..()
-
/obj/item/organ/heart/nightmare
name = "heart of darkness"
desc = "An alien organ that twists and writhes when exposed to light."
diff --git a/code/modules/mob/living/carbon/human/species_types/skeletons.dm b/code/modules/mob/living/carbon/human/species_types/skeletons.dm
index 51d81bd4d3..1b6bef9dc6 100644
--- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm
+++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm
@@ -5,8 +5,8 @@
blacklisted = 0
sexes = 0
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/skeleton
- species_traits = list(NOBLOOD,NOGENITALS,NOAROUSAL,HAS_BONE)
- inherent_traits = list(TRAIT_NOBREATH,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_FAKEDEATH, TRAIT_CALCIUM_HEALER)
+ species_traits = list(NOBLOOD,NOGENITALS,NOAROUSAL,HAS_BONE,NOTRANSSTING)
+ inherent_traits = list(TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_CALCIUM_HEALER)
inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID
mutanttongue = /obj/item/organ/tongue/bone
damage_overlay_type = ""//let's not show bloody wounds or burns over bones.
@@ -19,12 +19,12 @@
/datum/species/skeleton/New()
if(SSevents.holidays && SSevents.holidays[HALLOWEEN]) //skeletons are stronger during the spooky season!
- inherent_traits |= list(TRAIT_RESISTHEAT,TRAIT_RESISTCOLD)
+ inherent_traits |= list(TRAIT_RESISTHEAT, TRAIT_NOBREATH, TRAIT_PIERCEIMMUNE, TRAIT_FAKEDEATH, TRAIT_RESISTCOLD, TRAIT_RADIMMUNE)
brutemod = 1
burnmod = 1
..()
-/datum/species/skeleton/greater/check_roundstart_eligible()
+/datum/species/skeleton/check_roundstart_eligible()
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
return TRUE
return ..()
diff --git a/code/modules/mob/living/carbon/human/species_types/synthliz.dm b/code/modules/mob/living/carbon/human/species_types/synthliz.dm
index 5ed806b302..70afa2f476 100644
--- a/code/modules/mob/living/carbon/human/species_types/synthliz.dm
+++ b/code/modules/mob/living/carbon/human/species_types/synthliz.dm
@@ -1,7 +1,6 @@
/datum/species/synthliz
name = "Synthetic Lizardperson"
id = "synthliz"
- icon_limbs = DEFAULT_BODYPART_ICON_CITADEL
say_mod = "beeps"
default_color = "00FF00"
species_traits = list(MUTCOLORS,NOTRANSSTING,EYECOLOR,LIPS,HAIR,HAS_FLESH,HAS_BONE)
@@ -22,4 +21,4 @@
tail_type = "mam_tail"
wagging_type = "mam_waggingtail"
- species_type = "robotic"
\ No newline at end of file
+ species_type = "robotic"
diff --git a/code/modules/mob/living/carbon/human/species_types/synths.dm b/code/modules/mob/living/carbon/human/species_types/synths.dm
index a1a2a33c54..3d55ce1027 100644
--- a/code/modules/mob/living/carbon/human/species_types/synths.dm
+++ b/code/modules/mob/living/carbon/human/species_types/synths.dm
@@ -61,7 +61,7 @@
mutant_organs = S.mutant_organs.Copy()
nojumpsuit = S.nojumpsuit
no_equip = S.no_equip.Copy()
- limbs_id = S.limbs_id
+ limbs_id = S.mutant_bodyparts["limbs_id"]
use_skintones = S.use_skintones
fixed_mut_color = S.fixed_mut_color
hair_color = S.hair_color
@@ -100,14 +100,12 @@
else
return ..()
-
/datum/species/synth/handle_body(mob/living/carbon/human/H)
if(fake_species)
fake_species.handle_body(H)
else
return ..()
-
/datum/species/synth/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour)
if(fake_species)
fake_species.handle_body(H,forced_colour)
diff --git a/code/modules/mob/living/carbon/human/species_types/xeno.dm b/code/modules/mob/living/carbon/human/species_types/xeno.dm
index db34d1ae45..ddd1c86f0a 100644
--- a/code/modules/mob/living/carbon/human/species_types/xeno.dm
+++ b/code/modules/mob/living/carbon/human/species_types/xeno.dm
@@ -4,7 +4,6 @@
id = "xeno"
say_mod = "hisses"
default_color = "00FF00"
- icon_limbs = DEFAULT_BODYPART_ICON_CITADEL
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,CAN_SCAR)
mutant_bodyparts = list("xenotail"="Xenomorph Tail","xenohead"="Standard","xenodorsal"="Standard", "mam_body_markings" = "Xeno","mcolor" = "0F0","mcolor2" = "0F0","mcolor3" = "0F0","taur" = "None", "legs" = "Digitigrade")
attack_verb = "slash"
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index e399ddf872..9b39438563 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -660,7 +660,7 @@ use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if
//produces a key based on the human's limbs
/mob/living/carbon/human/generate_icon_render_key()
- . = "[dna.species.limbs_id]"
+ . = "[dna.species.mutant_bodyparts["limbs_id"]]"
if(dna.check_mutation(HULK))
. += "-coloured-hulk"
diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm
index cc837a490c..50801e1c0d 100644
--- a/code/modules/mob/living/carbon/inventory.dm
+++ b/code/modules/mob/living/carbon/inventory.dm
@@ -117,18 +117,6 @@
if(!QDELETED(src))
update_inv_legcuffed()
-/mob/living/carbon/get_equipped_items(include_pockets = FALSE)
- var/list/items = list()
- if(back)
- items += back
- if(head)
- items += head
- if(wear_mask)
- items += wear_mask
- if(wear_neck)
- items += wear_neck
- return items
-
//handle stuff to update when a mob equips/unequips a mask.
/mob/living/proc/wear_mask_update(obj/item/clothing/C, toggle_off = 1)
update_inv_wear_mask()
diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm
index ad1a3bc9b9..fe5a78de21 100644
--- a/code/modules/mob/living/death.dm
+++ b/code/modules/mob/living/death.dm
@@ -8,8 +8,6 @@
spill_organs(no_brain, no_organs, no_bodyparts)
- release_vore_contents(silent = TRUE) // return of the bomb safe internals.
-
if(!no_bodyparts)
spread_bodyparts(no_brain, no_organs)
@@ -46,7 +44,6 @@
buckled.unbuckle_mob(src, force = TRUE)
dust_animation()
- release_vore_contents(silent = TRUE) //technically grief protection, I guess? if they're SM'd it doesn't matter seconds after anyway.
spawn_dust(just_ash)
QDEL_IN(src,5) // since this is sometimes called in the middle of movement, allow half a second for movement to finish, ghosting to happen and animation to play. Looks much nicer and doesn't cause multiple runtimes.
@@ -103,5 +100,5 @@
for(var/s in sharedSoullinks)
var/datum/soullink/S = s
S.sharerDies(gibbed)
-
+ release_vore_contents(silent = TRUE)
return TRUE
diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm
index 97de8bfd6c..a735baceae 100644
--- a/code/modules/mob/living/emote.dm
+++ b/code/modules/mob/living/emote.dm
@@ -9,6 +9,11 @@
key_third_person = "blushes"
message = "blushes."
+/datum/emote/living/blush/run_emote(mob/user, params)
+ . = ..()
+ if(. && isipcperson(user))
+ do_fake_sparks(5,FALSE,user)
+
/datum/emote/living/bow
key = "bow"
key_third_person = "bows"
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 0f55d5c408..2a461b5921 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -57,7 +57,7 @@
/mob/living/Bump(atom/A)
if(..()) //we are thrown onto something
return
- if (buckled || now_pushing)
+ if(buckled || now_pushing)
return
if(ismob(A))
var/mob/M = A
diff --git a/code/modules/mob/living/living_active_block.dm b/code/modules/mob/living/living_active_block.dm
index 729e7d3d7a..2493509e16 100644
--- a/code/modules/mob/living/living_active_block.dm
+++ b/code/modules/mob/living/living_active_block.dm
@@ -13,7 +13,7 @@
DelayNextAction(data.block_end_click_cd_add)
return TRUE
-/mob/living/proc/ACTIVE_BLOCK_START(obj/item/I)
+/mob/living/proc/active_block_start(obj/item/I)
if(combat_flags & (COMBAT_FLAG_ACTIVE_BLOCK_STARTING | COMBAT_FLAG_ACTIVE_BLOCKING))
return FALSE
if(!(I in held_items))
@@ -109,7 +109,7 @@
animate(src, pixel_x = get_standard_pixel_x_offset(), pixel_y = get_standard_pixel_y_offset(), time = 2.5, FALSE, SINE_EASING | EASE_IN, ANIMATION_END_NOW)
return
combat_flags &= ~(COMBAT_FLAG_ACTIVE_BLOCK_STARTING)
- ACTIVE_BLOCK_START(I)
+ active_block_start(I)
/**
* Gets the first item we can that can block, but if that fails, default to active held item.COMSIG_ENABLE_COMBAT_MODE
@@ -180,6 +180,12 @@
/// Apply the stamina damage to our user, notice how damage argument is stamina_amount.
/obj/item/proc/active_block_do_stamina_damage(mob/living/owner, atom/object, stamina_amount, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
+ if(istype(object, /obj/item/projectile))
+ var/obj/item/projectile/P = object
+ if(P.stamina)
+ var/blocked = active_block_calculate_final_damage(owner, object, P.stamina, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return)
+ var/stam = active_block_stamina_cost(owner, object, blocked, attack_text, ATTACK_TYPE_PROJECTILE, armour_penetration, attacker, def_zone, final_block_chance, block_return)
+ stamina_amount += stam
var/datum/block_parry_data/data = get_block_parry_data()
if(iscarbon(owner))
var/mob/living/carbon/C = owner
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 9018c49b2c..d8299d42ad 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -289,50 +289,57 @@
return FALSE
return ISINRANGE(T1.x, T0.x - interaction_range, T0.x + interaction_range) && ISINRANGE(T1.y, T0.y - interaction_range, T0.y + interaction_range)
-/mob/living/silicon/robot/attackby(obj/item/W, mob/user, params)
- if(istype(W, /obj/item/weldingtool) && (user.a_intent != INTENT_HARM || user == src))
+/mob/living/silicon/robot/proc/attempt_welder_repair(obj/item/weldingtool/W, mob/user)
+ if (!getBruteLoss())
+ to_chat(user, "[src] is already in good condition!")
+ return
+ if (!W.tool_start_check(user, amount=0)) //The welder has 1u of fuel consumed by it's afterattack, so we don't need to worry about taking any away.
+ return
+ user.DelayNextAction(CLICK_CD_MELEE)
+ if(src == user)
+ to_chat(user, "You start fixing yourself...")
+ if(!W.use_tool(src, user, 50))
+ return
+ adjustBruteLoss(-10)
+ else
+ to_chat(user, "You start fixing [src]...")
+ if(!do_after(user, 30, target = src))
+ return
+ adjustBruteLoss(-30)
+ updatehealth()
+ add_fingerprint(user)
+ visible_message("[user] has fixed some of the dents on [src].")
+
+/mob/living/silicon/robot/proc/attempt_cable_repair(obj/item/stack/cable_coil/W, mob/user)
+ if (getFireLoss() > 0 || getToxLoss() > 0)
user.DelayNextAction(CLICK_CD_MELEE)
- if (!getBruteLoss())
- to_chat(user, "[src] is already in good condition!")
- return
- if (!W.tool_start_check(user, amount=0)) //The welder has 1u of fuel consumed by it's afterattack, so we don't need to worry about taking any away.
- return
if(src == user)
to_chat(user, "You start fixing yourself...")
- if(!W.use_tool(src, user, 50))
+ if(!W.use_tool(src, user, 50, 1, skill_gain_mult = TRIVIAL_USE_TOOL_MULT))
+ to_chat(user, "You need more cable to repair [src]!")
return
- adjustBruteLoss(-10)
+ adjustFireLoss(-10)
+ adjustToxLoss(-10)
else
to_chat(user, "You start fixing [src]...")
- if(!do_after(user, 30, target = src))
+ if(!W.use_tool(src, user, 30, 1))
+ to_chat(user, "You need more cable to repair [src]!")
return
- adjustBruteLoss(-30)
- updatehealth()
- add_fingerprint(user)
- visible_message("[user] has fixed some of the dents on [src].")
+ adjustFireLoss(-30)
+ adjustToxLoss(-30)
+ updatehealth()
+ user.visible_message("[user] has fixed some of the burnt wires on [src].", "You fix some of the burnt wires on [src].")
+ else
+ to_chat(user, "The wires seem fine, there's no need to fix them.")
+
+/mob/living/silicon/robot/attackby(obj/item/W, mob/user, params)
+ if(istype(W, /obj/item/weldingtool) && (user.a_intent != INTENT_HARM || user == src))
+ INVOKE_ASYNC(src, .proc/attempt_welder_repair, W, user)
return
else if(istype(W, /obj/item/stack/cable_coil) && wiresexposed)
- user.DelayNextAction(CLICK_CD_MELEE)
- if (getFireLoss() > 0 || getToxLoss() > 0)
- if(src == user)
- to_chat(user, "You start fixing yourself...")
- if(!W.use_tool(src, user, 50, 1, skill_gain_mult = TRIVIAL_USE_TOOL_MULT))
- to_chat(user, "You need more cable to repair [src]!")
- return
- adjustFireLoss(-10)
- adjustToxLoss(-10)
- else
- to_chat(user, "You start fixing [src]...")
- if(!W.use_tool(src, user, 30, 1))
- to_chat(user, "You need more cable to repair [src]!")
- return
- adjustFireLoss(-30)
- adjustToxLoss(-30)
- updatehealth()
- user.visible_message("[user] has fixed some of the burnt wires on [src].", "You fix some of the burnt wires on [src].")
- else
- to_chat(user, "The wires seem fine, there's no need to fix them.")
+ INVOKE_ASYNC(src, .proc/attempt_cable_repair, W, user)
+ return
else if(istype(W, /obj/item/crowbar)) // crowbar means open or close the cover
if(opened)
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 7a9610fb53..c6aee397e4 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -430,3 +430,6 @@
/mob/living/silicon/handle_high_gravity(gravity)
return
+
+/mob/living/silicon/rust_heretic_act()
+ adjustBruteLoss(500)
diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm
index fe6792b5c2..a1772d9281 100644
--- a/code/modules/mob/living/simple_animal/bot/bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/bot.dm
@@ -1058,3 +1058,6 @@ Pass a positive integer as an argument to override a bot's default speed.
if(I)
I.icon_state = null
path.Cut(1, 2)
+
+/mob/living/silicon/rust_heretic_act()
+ adjustBruteLoss(500)
diff --git a/code/modules/mob/living/simple_animal/bot/cleanbot.dm b/code/modules/mob/living/simple_animal/bot/cleanbot.dm
index 5c83482bde..e7c5644e26 100644
--- a/code/modules/mob/living/simple_animal/bot/cleanbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/cleanbot.dm
@@ -313,7 +313,7 @@
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/cleanable/insectguts,
/obj/effect/decal/cleanable/semen,
- /obj/effect/decal/cleanable/femcum,
+ /obj/effect/decal/cleanable/semen/femcum,
/obj/effect/decal/cleanable/generic,
/obj/effect/decal/cleanable/glass,,
/obj/effect/decal/cleanable/cobweb,
diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm
index 354bc9ed0f..95bd8d8991 100644
--- a/code/modules/mob/living/simple_animal/constructs.dm
+++ b/code/modules/mob/living/simple_animal/constructs.dm
@@ -11,7 +11,6 @@
response_disarm_simple = "flail at"
response_harm_continuous = "punches"
response_harm_simple = "punch"
- threat = 1
speak_chance = 1
icon = 'icons/mob/mob.dmi'
speed = 0
@@ -122,7 +121,6 @@
desc = "A massive, armored construct built to spearhead attacks and soak up enemy fire."
icon_state = "behemoth"
icon_living = "behemoth"
- threat = 3
maxHealth = 150
health = 150
response_harm_continuous = "harmlessly punches"
@@ -187,7 +185,6 @@
desc = "A wicked, clawed shell constructed to assassinate enemies and sow chaos behind enemy lines."
icon_state = "floating"
icon_living = "floating"
- threat = 3
maxHealth = 65
health = 65
melee_damage_lower = 20
diff --git a/code/modules/mob/living/simple_animal/eldritch_demons.dm b/code/modules/mob/living/simple_animal/eldritch_demons.dm
new file mode 100644
index 0000000000..dbf62be16d
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/eldritch_demons.dm
@@ -0,0 +1,386 @@
+/mob/living/simple_animal/hostile/eldritch
+ name = "Demon"
+ real_name = "Demon"
+ desc = ""
+ gender = NEUTER
+ mob_biotypes = NONE
+ speak_emote = list("screams")
+ response_help_continuous = "thinks better of touching"
+ response_help_simple = "think better of touching"
+ response_disarm_continuous = "flails at"
+ response_disarm_simple = "flail at"
+ response_harm_continuous = "reaps"
+ response_harm_simple = "tears"
+ speak_chance = 1
+ icon = 'icons/mob/eldritch_mobs.dmi'
+ speed = 0
+ a_intent = INTENT_HARM
+ stop_automated_movement = 1
+ AIStatus = AI_OFF
+ attack_sound = 'sound/weapons/punch1.ogg'
+ see_in_dark = 7
+ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
+ damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
+ minbodytemp = 0
+ maxbodytemp = INFINITY
+ healable = 0
+ movement_type = GROUND
+ pressure_resistance = 100
+ del_on_death = TRUE
+ deathmessage = "implodes into itself"
+ faction = list("heretics")
+ simple_mob_flags = SILENCE_RANGED_MESSAGE
+ ///Innate spells that are supposed to be added when a beast is created
+ var/list/spells_to_add
+
+/mob/living/simple_animal/hostile/eldritch/Initialize()
+ . = ..()
+ add_spells()
+
+/**
+ * Add_spells
+ *
+ * Goes through spells_to_add and adds each spell to the mind.
+ */
+/mob/living/simple_animal/hostile/eldritch/proc/add_spells()
+ for(var/spell in spells_to_add)
+ AddSpell(new spell())
+
+/mob/living/simple_animal/hostile/eldritch/raw_prophet
+ name = "Raw Prophet"
+ real_name = "Raw Prophet"
+ desc = "Abomination made from severed limbs."
+ icon_state = "raw_prophet"
+ status_flags = CANPUSH
+ icon_living = "raw_prophet"
+ melee_damage_lower = 5
+ melee_damage_upper = 10
+ maxHealth = 50
+ health = 50
+ sight = SEE_MOBS|SEE_OBJS|SEE_TURFS
+ spells_to_add = list(/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash/long,/obj/effect/proc_holder/spell/pointed/manse_link,/obj/effect/proc_holder/spell/targeted/telepathy/eldritch,/obj/effect/proc_holder/spell/pointed/trigger/blind/eldritch)
+
+ var/list/linked_mobs = list()
+
+/mob/living/simple_animal/hostile/eldritch/raw_prophet/Initialize()
+ . = ..()
+ link_mob(src)
+
+/mob/living/simple_animal/hostile/eldritch/raw_prophet/Login()
+ . = ..()
+ client.change_view(10)
+
+/mob/living/simple_animal/hostile/eldritch/raw_prophet/proc/link_mob(mob/living/mob_linked)
+ if(QDELETED(mob_linked) || mob_linked.stat == DEAD)
+ return FALSE
+ if(HAS_TRAIT(mob_linked, TRAIT_MINDSHIELD)) //mindshield implant, no dice
+ return FALSE
+ if(mob_linked.anti_magic_check(FALSE, FALSE, TRUE, 0))
+ return FALSE
+ if(linked_mobs[mob_linked])
+ return FALSE
+
+ to_chat(mob_linked, "You feel something new enter your sphere of mind, you hear whispers of people far away, screeches of horror and a humming of welcome to [src]'s Mansus Link.")
+ var/datum/action/innate/mansus_speech/action = new(src)
+ linked_mobs[mob_linked] = action
+ action.Grant(mob_linked)
+ RegisterSignal(mob_linked, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETING) , .proc/unlink_mob)
+ return TRUE
+
+/mob/living/simple_animal/hostile/eldritch/raw_prophet/proc/unlink_mob(mob/living/mob_linked)
+ if(!linked_mobs[mob_linked])
+ return
+ UnregisterSignal(mob_linked, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETING))
+ var/datum/action/innate/mansus_speech/action = linked_mobs[mob_linked]
+ action.Remove(mob_linked)
+ qdel(action)
+ to_chat(mob_linked, "Your mind shatters as the [src]'s Mansus Link leaves your mind.")
+ mob_linked.emote("Scream")
+ //micro stun
+ mob_linked.AdjustParalyzed(0.5 SECONDS)
+ linked_mobs -= mob_linked
+
+/mob/living/simple_animal/hostile/eldritch/raw_prophet/death(gibbed)
+ for(var/linked_mob in linked_mobs)
+ unlink_mob(linked_mob)
+ return ..()
+
+/mob/living/simple_animal/hostile/eldritch/armsy
+ name = "Terror of the Night"
+ real_name = "Armsy"
+ desc = "Abomination made from severed limbs."
+ icon_state = "armsy_start"
+ icon_living = "armsy_start"
+ maxHealth = 200
+ health = 200
+ obj_damage = 80
+ melee_damage_lower = 10
+ melee_damage_upper = 15
+ move_resist = MOVE_FORCE_OVERPOWERING+1
+ movement_type = GROUND
+ environment_smash = ENVIRONMENT_SMASH_RWALLS
+ sight = SEE_MOBS
+ spells_to_add = list(/obj/effect/proc_holder/spell/targeted/worm_contract)
+ ranged = TRUE
+ ///Previous segment in the chain
+ var/mob/living/simple_animal/hostile/eldritch/armsy/back
+ ///Next segment in the chain
+ var/mob/living/simple_animal/hostile/eldritch/armsy/front
+ ///Your old location
+ var/oldloc
+ ///Allow / disallow pulling
+ var/allow_pulling = FALSE
+ ///How many arms do we have to eat to expand?
+ var/stacks_to_grow = 2
+ ///Currently eaten arms
+ var/current_stacks = 0
+
+//I tried Initalize but it didnt work, like at all. This proc just wouldnt fire if it was Initalize instead of New
+/mob/living/simple_animal/hostile/eldritch/armsy/Initialize(mapload,spawn_more = TRUE,len = 6)
+ . = ..()
+ if(len < 3)
+ stack_trace("Eldritch Armsy created with invalid len ([len]). Reverting to 3.")
+ len = 3 //code breaks below 3, let's just not allow it.
+ oldloc = loc
+ RegisterSignal(src,COMSIG_MOVABLE_MOVED,.proc/update_chain_links)
+ if(!spawn_more)
+ return
+ allow_pulling = TRUE
+ ///next link
+ var/mob/living/simple_animal/hostile/eldritch/armsy/next
+ ///previous link
+ var/mob/living/simple_animal/hostile/eldritch/armsy/prev
+ ///current link
+ var/mob/living/simple_animal/hostile/eldritch/armsy/current
+ for(var/i in 0 to len)
+ prev = current
+ //i tried using switch, but byond is really fucky and it didnt work as intended. Im sorry
+ if(i == 0)
+ current = new type(drop_location(),FALSE)
+ current.icon_state = "armsy_mid"
+ current.icon_living = "armsy_mid"
+ current.front = src
+ current.AIStatus = AI_OFF
+ back = current
+ else if(i < len)
+ current = new type(drop_location(),FALSE)
+ prev.back = current
+ prev.icon_state = "armsy_mid"
+ prev.icon_living = "armsy_mid"
+ prev.front = next
+ prev.AIStatus = AI_OFF
+ else
+ prev.icon_state = "armsy_end"
+ prev.icon_living = "armsy_end"
+ prev.front = next
+ prev.AIStatus = AI_OFF
+ next = prev
+
+//we are literally a vessel of otherworldly destruction, we bring our own gravity unto this plane
+/mob/living/simple_animal/hostile/eldritch/armsy/has_gravity(turf/T)
+ return TRUE
+
+
+/mob/living/simple_animal/hostile/eldritch/armsy/can_be_pulled()
+ return FALSE
+
+///Updates chain links to force move onto a single tile
+/mob/living/simple_animal/hostile/eldritch/armsy/proc/contract_next_chain_into_single_tile()
+ if(back)
+ back.forceMove(loc)
+ back.contract_next_chain_into_single_tile()
+ return
+
+///Updates the next mob in the chain to move to our last location, fixed the worm if somehow broken.
+/mob/living/simple_animal/hostile/eldritch/armsy/proc/update_chain_links()
+ gib_trail()
+ if(back && back.loc != oldloc)
+ back.Move(oldloc)
+ // self fixing properties if somehow broken
+ if(front && loc != front.oldloc)
+ forceMove(front.oldloc)
+ oldloc = loc
+
+/mob/living/simple_animal/hostile/eldritch/armsy/proc/gib_trail()
+ if(front) // head makes gibs
+ return
+ var/chosen_decal = pick(typesof(/obj/effect/decal/cleanable/blood/tracks))
+ var/obj/effect/decal/cleanable/blood/gibs/decal = new chosen_decal(drop_location())
+ decal.setDir(dir)
+
+/mob/living/simple_animal/hostile/eldritch/armsy/Destroy()
+ if(front)
+ front.icon_state = "armsy_end"
+ front.icon_living = "armsy_end"
+ front.back = null
+ if(back)
+ QDEL_NULL(back) // chain destruction baby
+ return ..()
+
+/mob/living/simple_animal/hostile/eldritch/armsy/BiologicalLife(seconds, times_fired)
+ adjustBruteLoss(-2)
+
+/mob/living/simple_animal/hostile/eldritch/armsy/proc/heal()
+ if(health == maxHealth)
+ if(back)
+ back.heal()
+ return
+ else
+ current_stacks++
+ if(current_stacks >= stacks_to_grow)
+ var/mob/living/simple_animal/hostile/eldritch/armsy/prev = new type(drop_location(),spawn_more = FALSE)
+ icon_state = "armsy_mid"
+ icon_living = "armsy_mid"
+ back = prev
+ prev.icon_state = "armsy_end"
+ prev.icon_living = "armsy_end"
+ prev.front = src
+ prev.AIStatus = AI_OFF
+ current_stacks = 0
+
+ adjustBruteLoss(-maxHealth * 0.5, FALSE)
+ adjustFireLoss(-maxHealth * 0.5 ,FALSE)
+
+
+/mob/living/simple_animal/hostile/eldritch/armsy/Shoot(atom/targeted_atom)
+ target = targeted_atom
+ AttackingTarget()
+
+
+/mob/living/simple_animal/hostile/eldritch/armsy/AttackingTarget()
+ if(istype(target,/obj/item/bodypart/r_arm) || istype(target,/obj/item/bodypart/l_arm))
+ qdel(target)
+ heal()
+ return
+ if(target == back || target == front)
+ return
+ if(back)
+ back.target = target
+ back.AttackingTarget()
+ if(!Adjacent(target))
+ return
+ do_attack_animation(target)
+ //have fun
+ //if(istype(target,/turf/closed/wall))
+ //var/turf/closed/wall = target
+ //wall.ScrapeAway()
+
+
+ if(iscarbon(target))
+ var/mob/living/carbon/C = target
+ if(HAS_TRAIT(C, TRAIT_NODISMEMBER))
+ return
+ var/list/parts = list()
+ for(var/X in C.bodyparts)
+ var/obj/item/bodypart/bodypart = X
+ if(bodypart.body_part != HEAD && bodypart.body_part != CHEST)
+ if(bodypart.dismemberable)
+ parts += bodypart
+ if(length(parts) && prob(10))
+ var/obj/item/bodypart/bodypart = pick(parts)
+ bodypart.dismember()
+
+ return ..()
+
+/mob/living/simple_animal/hostile/eldritch/armsy/prime
+ name = "Lord of the Night"
+ real_name = "Master of Decay"
+ maxHealth = 400
+ health = 400
+ melee_damage_lower = 20
+ melee_damage_upper = 25
+
+/mob/living/simple_animal/hostile/eldritch/armsy/prime/Initialize(mapload,spawn_more = TRUE,len = 9)
+ . = ..()
+ var/matrix/matrix_transformation = matrix()
+ matrix_transformation.Scale(1.4,1.4)
+ transform = matrix_transformation
+
+/mob/living/simple_animal/hostile/eldritch/armsy/primeproc/heal()
+ if(health == maxHealth)
+ if(back)
+ back.heal()
+ return
+ else
+ current_stacks++
+ if(current_stacks >= stacks_to_grow)
+ var/mob/living/simple_animal/hostile/eldritch/armsy/prev = new type(drop_location(),spawn_more = FALSE)
+ icon_state = "armsy_mid"
+ icon_living = "armsy_mid"
+ back = prev
+ prev.icon_state = "armsy_end"
+ prev.icon_living = "armsy_end"
+ prev.front = src
+ prev.AIStatus = AI_OFF
+ current_stacks = 0
+ var/matrix/matrix_transformation = matrix()
+ matrix_transformation.Scale(1.4,1.4)
+ transform = matrix_transformation
+
+ adjustBruteLoss(-maxHealth * 0.5, FALSE)
+ adjustFireLoss(-maxHealth * 0.5 ,FALSE)
+
+
+/mob/living/simple_animal/hostile/eldritch/rust_spirit
+ name = "Rust Walker"
+ real_name = "Rusty"
+ desc = "Incomprehensible abomination actively seeping life out of it's surrounding."
+ icon_state = "rust_walker_s"
+ status_flags = CANPUSH
+ icon_living = "rust_walker_s"
+ maxHealth = 75
+ health = 75
+ melee_damage_lower = 15
+ melee_damage_upper = 20
+ sight = SEE_TURFS
+ spells_to_add = list(/obj/effect/proc_holder/spell/aoe_turf/rust_conversion/small,/obj/effect/proc_holder/spell/aimed/rust_wave/short)
+
+/mob/living/simple_animal/hostile/eldritch/rust_spirit/setDir(newdir, ismousemovement)
+ . = ..()
+ if(newdir == NORTH)
+ icon_state = "rust_walker_n"
+ else if(newdir == SOUTH)
+ icon_state = "rust_walker_s"
+ update_icon()
+
+/mob/living/simple_animal/hostile/eldritch/rust_spirit/Moved()
+ . = ..()
+ playsound(src, 'sound/effects/footstep/rustystep1.ogg', 100, TRUE)
+
+/mob/living/simple_animal/hostile/eldritch/rust_spirit/Life()
+ if(stat == DEAD)
+ return ..()
+ var/turf/T = get_turf(src)
+ if(istype(T,/turf/open/floor/plating/rust))
+ adjustBruteLoss(-3, FALSE)
+ adjustFireLoss(-3, FALSE)
+ return ..()
+
+/mob/living/simple_animal/hostile/eldritch/ash_spirit
+ name = "Ash Man"
+ real_name = "Ashy"
+ desc = "Incomprehensible abomination actively seeping life out of it's surrounding."
+ icon_state = "ash_walker"
+ status_flags = CANPUSH
+ icon_living = "ash_walker"
+ maxHealth = 75
+ health = 75
+ melee_damage_lower = 15
+ melee_damage_upper = 20
+ sight = SEE_TURFS
+ spells_to_add = list(/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash,/obj/effect/proc_holder/spell/pointed/cleave/long,/obj/effect/proc_holder/spell/aoe_turf/fire_cascade)
+
+/mob/living/simple_animal/hostile/eldritch/stalker
+ name = "Flesh Stalker"
+ real_name = "Flesh Stalker"
+ desc = "Abomination made from severed limbs."
+ icon_state = "stalker"
+ status_flags = CANPUSH
+ icon_living = "stalker"
+ maxHealth = 150
+ health = 150
+ melee_damage_lower = 15
+ melee_damage_upper = 20
+ sight = SEE_MOBS
+ spells_to_add = list(/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash,/obj/effect/proc_holder/spell/targeted/shapeshift/eldritch,/obj/effect/proc_holder/spell/targeted/emplosion/eldritch)
diff --git a/code/modules/mob/living/simple_animal/friendly/gondola.dm b/code/modules/mob/living/simple_animal/friendly/gondola.dm
index 0cfea3548b..e29cbb8062 100644
--- a/code/modules/mob/living/simple_animal/friendly/gondola.dm
+++ b/code/modules/mob/living/simple_animal/friendly/gondola.dm
@@ -58,7 +58,7 @@
eyes_overlay.pixel_y = -8
moustache_overlay.pixel_y = -8
- cut_overlays(TRUE)
+ cut_overlays()
add_overlay(body_overlay)
add_overlay(eyes_overlay)
add_overlay(moustache_overlay)
diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm
index fb24b0fc09..7abecc7c81 100644
--- a/code/modules/mob/living/simple_animal/guardian/guardian.dm
+++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm
@@ -8,7 +8,6 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
name = "Guardian Spirit"
real_name = "Guardian Spirit"
desc = "A mysterious being that stands by its charge, ever vigilant."
- threat = 5
speak_emote = list("hisses")
gender = NEUTER
mob_biotypes = NONE
diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm
index 7120ab6d0a..86467624b5 100644
--- a/code/modules/mob/living/simple_animal/hostile/alien.dm
+++ b/code/modules/mob/living/simple_animal/hostile/alien.dm
@@ -7,7 +7,6 @@
icon_dead = "alienh_dead"
icon_gib = "syndicate_gib"
gender = FEMALE
- threat = 1
response_help_continuous = "pokes"
response_help_simple = "poke"
response_disarm_continuous = "shoves"
@@ -69,7 +68,6 @@
icon_state = "aliens"
icon_living = "aliens"
icon_dead = "aliens_dead"
- threat = 3
health = 150
maxHealth = 150
melee_damage_lower = 15
@@ -87,7 +85,6 @@
icon_living = "alienq"
icon_dead = "alienq_dead"
pixel_x = -16
- threat = 8
health = 250
maxHealth = 250
melee_damage_lower = 15
@@ -167,7 +164,6 @@
name = "lusty xenomorph maid"
melee_damage_lower = 0
melee_damage_upper = 0
- threat = -1
a_intent = INTENT_HELP
friendly_verb_continuous = "caresses"
friendly_verb_simple = "caress"
diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm
index da16ec581b..1be90a07f8 100644
--- a/code/modules/mob/living/simple_animal/hostile/bear.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bear.dm
@@ -2,7 +2,6 @@
/mob/living/simple_animal/hostile/bear
name = "space bear"
desc = "You don't need to be faster than a space bear, you just need to outrun your crewmates."
- threat = 1
icon_state = "bear"
icon_living = "bear"
icon_dead = "bear_dead"
diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm
index 5f3d4f11c1..0a3cde3ef8 100644
--- a/code/modules/mob/living/simple_animal/hostile/bees.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bees.dm
@@ -16,7 +16,6 @@
icon_state = ""
icon_living = ""
icon = 'icons/mob/bees.dmi'
- threat = 0.3
gender = FEMALE
speak_emote = list("buzzes")
emote_hear = list("buzzes")
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 cde63adffd..b4d60af198 100644
--- a/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm
@@ -1,7 +1,6 @@
/mob/living/simple_animal/hostile/boss
name = "A Perfectly Generic Boss Placeholder"
desc = ""
- threat = 10
robust_searching = TRUE
stat_attack = UNCONSCIOUS
status_flags = NONE
diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm
index f775d6600c..51a646f668 100644
--- a/code/modules/mob/living/simple_animal/hostile/carp.dm
+++ b/code/modules/mob/living/simple_animal/hostile/carp.dm
@@ -7,7 +7,6 @@
icon_living = "carp"
icon_dead = "carp_dead"
icon_gib = "carp_gib"
- threat = 0.1
mob_biotypes = MOB_ORGANIC|MOB_BEAST
speak_chance = 0
turns_per_move = 5
@@ -74,7 +73,6 @@
icon_living = "megacarp"
icon_dead = "megacarp_dead"
icon_gib = "megacarp_gib"
- threat = 3
regen_amount = 6
maxHealth = 30
@@ -98,7 +96,6 @@
name = "Cayenne"
desc = "A failed Syndicate experiment in weaponized space carp technology, it now serves as a lovable mascot."
gender = FEMALE
- threat = 5
regen_amount = 8
speak_emote = list("squeaks")
diff --git a/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm b/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm
index 48266e3e76..9b50587b3d 100644
--- a/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm
+++ b/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm
@@ -1,7 +1,6 @@
/mob/living/simple_animal/hostile/dark_wizard
name = "Dark Wizard"
desc = "Killing amateurs since the dawn of times."
- threat = 3
icon = 'icons/mob/simple_human.dmi'
icon_state = "dark_wizard"
icon_living = "dark_wizard"
diff --git a/code/modules/mob/living/simple_animal/hostile/faithless.dm b/code/modules/mob/living/simple_animal/hostile/faithless.dm
index 4f8d2fef6c..b44a2502ef 100644
--- a/code/modules/mob/living/simple_animal/hostile/faithless.dm
+++ b/code/modules/mob/living/simple_animal/hostile/faithless.dm
@@ -4,7 +4,6 @@
icon_state = "faithless"
icon_living = "faithless"
icon_dead = "faithless_dead"
- threat = 1
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
gender = MALE
speak_chance = 0
diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
index a253ecfd96..a8799f4e8c 100644
--- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
+++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
@@ -17,7 +17,6 @@
//basic spider mob, these generally guard nests
/mob/living/simple_animal/hostile/poison/giant_spider
- threat = 1
name = "giant spider"
desc = "Furry and black, it makes you shudder to look at it. This one has deep red eyes."
icon_state = "guard"
diff --git a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm
index f48eef083b..ec0b7acd07 100644
--- a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm
+++ b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm
@@ -9,7 +9,6 @@
icon_state = "crawling"
icon_living = "crawling"
icon_dead = "dead"
- threat = 0.5
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
speak_chance = 80
maxHealth = 220
diff --git a/code/modules/mob/living/simple_animal/hostile/headcrab.dm b/code/modules/mob/living/simple_animal/hostile/headcrab.dm
index 501534237a..ac53ff794b 100644
--- a/code/modules/mob/living/simple_animal/hostile/headcrab.dm
+++ b/code/modules/mob/living/simple_animal/hostile/headcrab.dm
@@ -6,7 +6,6 @@
icon_state = "headcrab"
icon_living = "headcrab"
icon_dead = "headcrab_dead"
- threat = 1
gender = NEUTER
health = 50
maxHealth = 50
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index 5ed3cd0cdd..186fe36a10 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -3,7 +3,6 @@
stop_automated_movement_when_pulled = 0
obj_damage = 40
environment_smash = ENVIRONMENT_SMASH_STRUCTURES //Bitflags. Set to ENVIRONMENT_SMASH_STRUCTURES to break closets,tables,racks, etc; ENVIRONMENT_SMASH_WALLS for walls; ENVIRONMENT_SMASH_RWALLS for rwalls
- var/threat = 0 // for dynamic
var/atom/target
var/ranged = FALSE
var/rapid = 0 //How many shots per volley.
@@ -600,6 +599,3 @@ mob/living/simple_animal/hostile/proc/DestroySurroundings() // for use with mega
. += M
else if (M.loc.type in hostile_machines)
. += M.loc
-
-/mob/living/simple_animal/hostile/proc/threat()
- return threat
diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm
index 55046d6555..362432b2af 100644
--- a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm
+++ b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm
@@ -11,7 +11,6 @@
icon_living = "leaper"
icon_dead = "leaper_dead"
mob_biotypes = MOB_ORGANIC|MOB_BEAST
- threat = 2
maxHealth = 300
health = 300
ranged = TRUE
diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/mega_arachnid.dm b/code/modules/mob/living/simple_animal/hostile/jungle/mega_arachnid.dm
index 99349168f0..31303bd7f1 100644
--- a/code/modules/mob/living/simple_animal/hostile/jungle/mega_arachnid.dm
+++ b/code/modules/mob/living/simple_animal/hostile/jungle/mega_arachnid.dm
@@ -8,7 +8,6 @@
icon_living = "arachnid"
icon_dead = "arachnid_dead"
mob_biotypes = MOB_ORGANIC|MOB_BUG
- threat = 2
melee_damage_lower = 30
melee_damage_upper = 30
maxHealth = 300
diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm b/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm
index 6efa0cf468..2d964f5721 100644
--- a/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm
+++ b/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm
@@ -14,7 +14,6 @@
icon_living = "mook"
icon_dead = "mook_dead"
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
- threat = 0.5
pixel_x = -16
maxHealth = 45
health = 45
diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm b/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm
index 0521afa9e9..7565a686bf 100644
--- a/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm
+++ b/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm
@@ -13,7 +13,6 @@
icon_state = "seedling"
icon_living = "seedling"
icon_dead = "seedling_dead"
- threat = 0.5
maxHealth = 100
health = 100
melee_damage_lower = 30
diff --git a/code/modules/mob/living/simple_animal/hostile/killertomato.dm b/code/modules/mob/living/simple_animal/hostile/killertomato.dm
index 9cb65d7c30..b86d5d87fc 100644
--- a/code/modules/mob/living/simple_animal/hostile/killertomato.dm
+++ b/code/modules/mob/living/simple_animal/hostile/killertomato.dm
@@ -5,7 +5,6 @@
icon_living = "tomato"
icon_dead = "tomato_dead"
gender = NEUTER
- threat = 0.3
speak_chance = 0
turns_per_move = 5
maxHealth = 30
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
index 5c1229c130..2a5f279386 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
@@ -23,7 +23,6 @@ Difficulty: Medium
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner
name = "blood-drunk miner"
desc = "A miner destined to wander forever, engaged in an endless hunt."
- threat = 15
health = 900
maxHealth = 900
icon_state = "miner"
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
index b191eaf3fb..519d6402e6 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
@@ -26,7 +26,6 @@ Difficulty: Hard
/mob/living/simple_animal/hostile/megafauna/bubblegum
name = "bubblegum"
desc = "In what passes for a hierarchy among slaughter demons, this one is king."
- threat = 35
health = 2500
maxHealth = 2500
attack_verb_continuous = "rends"
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
index 18abb019d3..883ad39261 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -24,7 +24,6 @@ Difficulty: Very Hard
/mob/living/simple_animal/hostile/megafauna/colossus
name = "colossus"
desc = "A monstrous creature protected by heavy shielding."
- threat = 40
health = 2500
maxHealth = 2500
attack_verb_continuous = "judges"
@@ -603,7 +602,6 @@ Difficulty: Very Hard
icon_state = "lightgeist"
icon_living = "lightgeist"
icon_dead = "butterfly_dead"
- threat = -0.7
turns_per_move = 1
response_help_continuous = "waves away"
response_help_simple = "wave away"
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
index a1ecde40b8..4dfd4561d6 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
@@ -38,7 +38,6 @@ Difficulty: Medium
/mob/living/simple_animal/hostile/megafauna/dragon
name = "ash drake"
desc = "Guardians of the necropolis."
- threat = 30
health = 2500
maxHealth = 2500
spacewalk = TRUE
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
index c00d7c3130..bd3a6e8232 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
@@ -37,7 +37,6 @@ Difficulty: Normal
/mob/living/simple_animal/hostile/megafauna/hierophant
name = "hierophant"
desc = "A massive metal club that hangs in the air as though waiting. It'll make you dance to its beat."
- threat = 30
health = 2500
maxHealth = 2500
attack_verb_continuous = "clubs"
@@ -662,7 +661,7 @@ Difficulty: Normal
continue
to_chat(M.occupant, "Your [M.name] is struck by a [name]!")
playsound(M,'sound/weapons/sear.ogg', 50, 1, -4)
- M.take_damage(damage, BURN, 0, 0)
+ M.take_damage(damage, BURN, 0, 0, null, 50)
/obj/effect/hierophant
name = "hierophant beacon"
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
index 78c02fb7a7..795184bad5 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
@@ -18,7 +18,6 @@ Difficulty: Medium
/mob/living/simple_animal/hostile/megafauna/legion
name = "Legion"
- threat = 30
health = 800
maxHealth = 800
spacewalk = TRUE
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 13738b20e1..61be1f6287 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
@@ -8,7 +8,6 @@
icon_aggro = "Basilisk_alert"
icon_dead = "Basilisk_dead"
icon_gib = "syndicate_gib"
- threat = 4
mob_biotypes = MOB_ORGANIC|MOB_BEAST
move_to_delay = 20
projectiletype = /obj/item/projectile/temp/basilisk
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm
index 11cc0fe67e..ed056c2ad9 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm
@@ -10,7 +10,6 @@
move_to_delay = 5
vision_range = 20
aggro_vision_range = 20
- threat = 1
maxHealth = 40 //easy to kill, but oh, will you be seeing a lot of them.
health = 40
melee_damage_lower = 10
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
index 87ec79abcf..e3edd171c0 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
@@ -11,7 +11,6 @@
robust_searching = TRUE
ranged_ignores_vision = TRUE
ranged = TRUE
- threat = 5
obj_damage = 5
vision_range = 6
aggro_vision_range = 18
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm
index 80489e0e40..d9f3cfba3d 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm
@@ -25,7 +25,6 @@
icon_aggro = "broodmother"
icon_dead = "egg_sac"
icon_gib = "syndicate_gib"
- threat = 10
maxHealth = 800
health = 800
melee_damage_lower = 30
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm
index 78b24acfb0..fce5b636e4 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm
@@ -24,7 +24,6 @@
icon_aggro = "herald"
icon_dead = "herald_dying"
icon_gib = "syndicate_gib"
- threat = 10
maxHealth = 800
health = 800
melee_damage_lower = 20
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm
index 31f925fb2b..15ed0135fe 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm
@@ -24,7 +24,6 @@
icon_aggro = "legionnaire"
icon_dead = "legionnaire_dead"
icon_gib = "syndicate_gib"
- threat = 10
maxHealth = 800
health = 800
melee_damage_lower = 30
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm
index cdef0c50d3..7995e4d20f 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm
@@ -24,7 +24,6 @@
icon_aggro = "pandora"
icon_dead = "pandora_dead"
icon_gib = "syndicate_gib"
- threat = 10
maxHealth = 800
health = 800
melee_damage_lower = 15
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goldgrub.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goldgrub.dm
index 4a3497055a..3845c6f406 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goldgrub.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goldgrub.dm
@@ -8,7 +8,6 @@
icon_aggro = "Goldgrub_alert"
icon_dead = "Goldgrub_dead"
icon_gib = "syndicate_gib"
- threat = 0.2
mob_biotypes = MOB_ORGANIC|MOB_BEAST
vision_range = 2
aggro_vision_range = 9
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm
index 5f6c21bbbd..fa67fd8e3b 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm
@@ -10,7 +10,6 @@
icon_gib = "syndicate_gib"
mob_biotypes = MOB_ORGANIC|MOB_BEAST
mouse_opacity = MOUSE_OPACITY_OPAQUE
- threat = 2
move_to_delay = 10
ranged = 1
ranged_cooldown_time = 60
@@ -201,6 +200,8 @@
L.Stun(75)
L.adjustBruteLoss(rand(15,20)) // Less stun more harm
latched = TRUE
+ for(var/obj/mecha/M in loc)
+ M.take_damage(20, BRUTE, null, null, null, 25)
if(!latched)
retract()
else
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm
index 16f892bbff..11ce4f9214 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm
@@ -9,7 +9,6 @@
icon_gib = "syndicate_gib"
mob_biotypes = MOB_ORGANIC
mouse_opacity = MOUSE_OPACITY_OPAQUE
- threat = 4
move_to_delay = 14
ranged = 1
vision_range = 4
@@ -241,7 +240,6 @@
icon_state = "legion"
icon_living = "legion"
icon_dead = "legion"
- threat = 5
health = 450
maxHealth = 450
melee_damage_lower = 20
diff --git a/code/modules/mob/living/simple_animal/hostile/netherworld.dm b/code/modules/mob/living/simple_animal/hostile/netherworld.dm
index e21e3e0693..92f331071a 100644
--- a/code/modules/mob/living/simple_animal/hostile/netherworld.dm
+++ b/code/modules/mob/living/simple_animal/hostile/netherworld.dm
@@ -10,7 +10,6 @@
obj_damage = 100
melee_damage_lower = 25
melee_damage_upper = 50
- threat = 2
attack_verb_continuous = "slashes"
attack_verb_simple = "slash"
attack_sound = 'sound/weapons/bladeslice.ogg'
diff --git a/code/modules/mob/living/simple_animal/hostile/pirate.dm b/code/modules/mob/living/simple_animal/hostile/pirate.dm
index 0544ddc676..74e37bea21 100644
--- a/code/modules/mob/living/simple_animal/hostile/pirate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/pirate.dm
@@ -10,7 +10,6 @@
turns_per_move = 5
response_help_continuous = "pushes"
response_help_simple = "push"
- threat = 3
speed = 0
maxHealth = 115
health = 115
diff --git a/code/modules/mob/living/simple_animal/hostile/russian.dm b/code/modules/mob/living/simple_animal/hostile/russian.dm
index f7a46658c4..e9879f38ec 100644
--- a/code/modules/mob/living/simple_animal/hostile/russian.dm
+++ b/code/modules/mob/living/simple_animal/hostile/russian.dm
@@ -10,7 +10,6 @@
speak_chance = 0
turns_per_move = 5
speed = 0
- threat = 1
maxHealth = 100
health = 100
harm_intent_damage = 5
diff --git a/code/modules/mob/living/simple_animal/hostile/sharks.dm b/code/modules/mob/living/simple_animal/hostile/sharks.dm
index 1263a23d26..af61149130 100644
--- a/code/modules/mob/living/simple_animal/hostile/sharks.dm
+++ b/code/modules/mob/living/simple_animal/hostile/sharks.dm
@@ -19,7 +19,6 @@
response_harm_continuous = "kicks"
response_harm_simple = "kick"
speed = 0
- threat = 1
maxHealth = 75
health = 75
harm_intent_damage = 18
diff --git a/code/modules/mob/living/simple_animal/hostile/skeleton.dm b/code/modules/mob/living/simple_animal/hostile/skeleton.dm
index 3091949552..ebacf1edef 100644
--- a/code/modules/mob/living/simple_animal/hostile/skeleton.dm
+++ b/code/modules/mob/living/simple_animal/hostile/skeleton.dm
@@ -11,7 +11,6 @@
speak_emote = list("rattles")
emote_see = list("rattles")
a_intent = INTENT_HARM
- threat = 0.5
maxHealth = 40
blood_volume = 0
health = 40
@@ -64,7 +63,6 @@
icon_state = "templar"
icon_living = "templar"
icon_dead = "templar_dead"
- threat = 1.5
maxHealth = 150
health = 150
weather_immunities = list("snow")
@@ -98,7 +96,6 @@
icon_state = "plasma_miner"
icon_living = "plasma_miner"
icon_dead = "plasma_miner"
- threat = 2
maxHealth = 150
health = 150
harm_intent_damage = 10
@@ -116,7 +113,6 @@
icon_state = "plasma_miner_tool"
icon_living = "plasma_miner_tool"
icon_dead = "plasma_miner_tool"
- threat = 3
maxHealth = 185
health = 185
harm_intent_damage = 15
diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm
index 3490d757a1..600d60eb4d 100644
--- a/code/modules/mob/living/simple_animal/hostile/statue.dm
+++ b/code/modules/mob/living/simple_animal/hostile/statue.dm
@@ -10,7 +10,6 @@
gender = NEUTER
a_intent = INTENT_HARM
mob_biotypes = MOB_HUMANOID
- threat = 3
response_help_continuous = "touches"
response_help_simple = "touch"
response_disarm_continuous = "pushes"
diff --git a/code/modules/mob/living/simple_animal/hostile/stickman.dm b/code/modules/mob/living/simple_animal/hostile/stickman.dm
index 226af952b1..6eeeabc877 100644
--- a/code/modules/mob/living/simple_animal/hostile/stickman.dm
+++ b/code/modules/mob/living/simple_animal/hostile/stickman.dm
@@ -5,7 +5,6 @@
icon_living = "stickman"
icon_dead = "stickman_dead"
icon_gib = "syndicate_gib"
- threat = 0.5
mob_biotypes = MOB_HUMANOID
gender = MALE
speak_chance = 0
diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
index fd37bb26aa..103868e1d3 100644
--- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
@@ -25,7 +25,6 @@
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
speak_chance = 0
turns_per_move = 5
- threat = 1
speed = 0
stat_attack = UNCONSCIOUS
robust_searching = 1
diff --git a/code/modules/mob/living/simple_animal/hostile/tree.dm b/code/modules/mob/living/simple_animal/hostile/tree.dm
index 2b9f4eea35..46a5a8ec68 100644
--- a/code/modules/mob/living/simple_animal/hostile/tree.dm
+++ b/code/modules/mob/living/simple_animal/hostile/tree.dm
@@ -7,7 +7,6 @@
icon_dead = "pine_1"
icon_gib = "pine_1"
gender = NEUTER
- threat = 1
speak_chance = 0
turns_per_move = 5
response_help_continuous = "brushes"
diff --git a/code/modules/mob/living/simple_animal/hostile/wizard.dm b/code/modules/mob/living/simple_animal/hostile/wizard.dm
index 57fb6f829d..b3523fc42c 100644
--- a/code/modules/mob/living/simple_animal/hostile/wizard.dm
+++ b/code/modules/mob/living/simple_animal/hostile/wizard.dm
@@ -8,7 +8,6 @@
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
speak_chance = 0
turns_per_move = 3
- threat = 3
speed = 0
maxHealth = 100
health = 100
diff --git a/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm b/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm
index dc6154c05e..bce1a01c8a 100644
--- a/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm
+++ b/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm
@@ -11,7 +11,6 @@
mob_biotypes = MOB_ORGANIC|MOB_BEAST
mouse_opacity = MOUSE_OPACITY_ICON
move_to_delay = 5
- threat = 1
friendly_verb_continuous = "floats near"
friendly_verb_simple = "float near"
speak_emote = list("puffs")
diff --git a/code/modules/mob/living/simple_animal/hostile/zombie.dm b/code/modules/mob/living/simple_animal/hostile/zombie.dm
index 6e4cbac022..1217084ce3 100644
--- a/code/modules/mob/living/simple_animal/hostile/zombie.dm
+++ b/code/modules/mob/living/simple_animal/hostile/zombie.dm
@@ -7,7 +7,6 @@
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
speak_chance = 0
stat_attack = UNCONSCIOUS //braains
- threat = 1
maxHealth = 100
health = 100
harm_intent_damage = 5
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 706bcc46f5..be0338a60e 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -146,6 +146,8 @@
var/bare_wound_bonus = 0
//If the attacks from this are sharp
var/sharpness = SHARP_NONE
+ //Generic flags
+ var/simple_mob_flags = NONE
/mob/living/simple_animal/Initialize()
. = ..()
diff --git a/code/modules/mob/living/ventcrawling.dm b/code/modules/mob/living/ventcrawling.dm
index 36a596f42e..6661d0ccea 100644
--- a/code/modules/mob/living/ventcrawling.dm
+++ b/code/modules/mob/living/ventcrawling.dm
@@ -19,8 +19,11 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, typecacheof(list(
to_chat(src, "You can't vent crawl while you're restrained!")
return
if(has_buckled_mobs())
- to_chat(src, "You can't vent crawl with other creatures on you!")
- return
+ // attempt once
+ unbuckle_all_mobs()
+ if(has_buckled_mobs())
+ to_chat(src, "You can't vent crawl with other creatures on you!")
+ return
if(buckled)
to_chat(src, "You can't vent crawl while buckled!")
return
diff --git a/code/modules/newscaster/newscaster_machine.dm b/code/modules/newscaster/newscaster_machine.dm
index cb2d49fc64..470b34e82c 100644
--- a/code/modules/newscaster/newscaster_machine.dm
+++ b/code/modules/newscaster/newscaster_machine.dm
@@ -95,6 +95,10 @@ GLOBAL_LIST_EMPTY(allCasters)
. = ..()
update_icon()
+/obj/machinery/newscaster/attack_ghost(mob/dead/observer/user)
+ if(istype(user))
+ user.read_news()
+
/obj/machinery/newscaster/ui_interact(mob/user)
. = ..()
if(ishuman(user) || issilicon(user))
diff --git a/code/modules/plumbing/ducts.dm b/code/modules/plumbing/ducts.dm
new file mode 100644
index 0000000000..8a27f2669c
--- /dev/null
+++ b/code/modules/plumbing/ducts.dm
@@ -0,0 +1,433 @@
+/*
+All the important duct code:
+/code/datums/components/plumbing/plumbing.dm
+/code/datums/ductnet.dm
+*/
+/obj/machinery/duct
+ name = "fluid duct"
+ icon = 'icons/obj/plumbing/fluid_ducts.dmi'
+ icon_state = "nduct"
+
+ ///bitfield with the directions we're connected in
+ var/connects
+ ///set to TRUE to disable smart duct behaviour
+ var/dumb = FALSE
+ ///wheter we allow our connects to be changed after initialization or not
+ var/lock_connects = FALSE
+ ///our ductnet, wich tracks what we're connected to
+ var/datum/ductnet/duct
+ ///amount we can transfer per process. note that the ductnet can carry as much as the lowest capacity duct
+ var/capacity = 10
+
+ ///the color of our duct
+ var/duct_color = null
+ ///TRUE to ignore colors, so yeah we also connect with other colors without issue
+ var/ignore_colors = FALSE
+ ///1,2,4,8,16
+ var/duct_layer = DUCT_LAYER_DEFAULT
+ ///whether we allow our layers to be altered
+ var/lock_layers = FALSE
+ ///TRUE to let colors connect when forced with a wrench, false to just not do that at all
+ var/color_to_color_support = TRUE
+ ///wheter to even bother with plumbing code or not
+ var/active = TRUE
+ ///track ducts we're connected to. Mainly for ducts we connect to that we normally wouldn't, like different layers and colors, for when we regenerate the ducts
+ var/list/neighbours = list()
+ ///wheter we just unanchored or drop whatever is in the variable. either is safe
+ var/drop_on_wrench = /obj/item/stack/ducts
+
+/obj/machinery/duct/Initialize(mapload, no_anchor, color_of_duct = "#ffffff", layer_of_duct = DUCT_LAYER_DEFAULT, force_connects)
+ . = ..()
+
+ if(no_anchor)
+ active = FALSE
+ set_anchored(FALSE)
+ else if(!can_anchor())
+ qdel(src)
+ CRASH("Overlapping ducts detected")
+
+ if(force_connects)
+ connects = force_connects //skip change_connects() because we're still initializing and we need to set our connects at one point
+ if(!lock_layers)
+ duct_layer = layer_of_duct
+ if(!ignore_colors)
+ duct_color = color_of_duct
+ if(duct_color)
+ add_atom_colour(duct_color, FIXED_COLOUR_PRIORITY)
+
+ handle_layer()
+
+ for(var/obj/machinery/duct/D in loc)
+ if(D == src)
+ continue
+ if(D.duct_layer & duct_layer)
+ disconnect_duct()
+
+ if(active)
+ attempt_connect()
+
+
+///start looking around us for stuff to connect to
+/obj/machinery/duct/proc/attempt_connect()
+
+ for(var/atom/movable/AM in loc)
+ var/datum/component/plumbing/P = AM.GetComponent(/datum/component/plumbing)
+ if(P?.active)
+ disconnect_duct() //let's not built under plumbing machinery
+ return
+ for(var/D in GLOB.cardinals)
+ if(dumb && !(D & connects))
+ continue
+ for(var/atom/movable/AM in get_step(src, D))
+ if(connect_network(AM, D))
+ add_connects(D)
+ update_icon()
+
+///see if whatever we found can be connected to
+/obj/machinery/duct/proc/connect_network(atom/movable/AM, direction, ignore_color)
+ if(istype(AM, /obj/machinery/duct))
+ return connect_duct(AM, direction, ignore_color)
+
+ var/plumber = AM.GetComponent(/datum/component/plumbing)
+ if(!plumber)
+ return
+ return connect_plumber(plumber, direction)
+
+///connect to a duct
+/obj/machinery/duct/proc/connect_duct(obj/machinery/duct/D, direction, ignore_color)
+ var/opposite_dir = turn(direction, 180)
+ if(!active || !D.active)
+ return
+
+ if(!dumb && D.dumb && !(opposite_dir & D.connects))
+ return
+ if(dumb && D.dumb && !(connects & D.connects)) //we eliminated a few more scenarios in attempt connect
+ return
+
+ if((duct == D.duct) && duct)//check if we're not just comparing two null values
+ add_neighbour(D, direction)
+
+ D.add_connects(opposite_dir)
+ D.update_icon()
+ return TRUE //tell the current pipe to also update it's sprite
+ if(!(D in neighbours)) //we cool
+ if((duct_color != D.duct_color) && !(ignore_colors || D.ignore_colors))
+ return
+ if(!(duct_layer & D.duct_layer))
+ return
+
+ if(D.duct)
+ if(duct)
+ duct.assimilate(D.duct)
+ else
+ D.duct.add_duct(src)
+ else
+ if(duct)
+ duct.add_duct(D)
+ else
+ create_duct()
+ duct.add_duct(D)
+ add_neighbour(D, direction)
+ //tell our buddy its time to pass on the torch of connecting to pipes. This shouldn't ever infinitely loop since it only works on pipes that havent been inductrinated
+ D.attempt_connect()
+
+ return TRUE
+
+///connect to a plumbing object
+/obj/machinery/duct/proc/connect_plumber(datum/component/plumbing/P, direction)
+ var/opposite_dir = turn(direction, 180)
+ if(duct_layer != DUCT_LAYER_DEFAULT) //plumbing devices don't support multilayering. 3 is the default layer so we only use that. We can change this later
+ return FALSE
+
+ if(!P.active)
+ return
+
+ var/comp_directions = P.supply_connects + P.demand_connects //they should never, ever have supply and demand connects overlap or catastrophic failure
+ if(opposite_dir & comp_directions)
+ if(!duct)
+ create_duct()
+ if(duct.add_plumber(P, opposite_dir))
+ neighbours[P.parent] = direction
+ return TRUE
+
+///we disconnect ourself from our neighbours. we also destroy our ductnet and tell our neighbours to make a new one
+/obj/machinery/duct/proc/disconnect_duct(skipanchor)
+ if(!skipanchor) //since set_anchored calls us too.
+ set_anchored(FALSE)
+ active = FALSE
+ if(duct)
+ duct.remove_duct(src)
+ lose_neighbours()
+ reset_connects(0)
+ update_icon()
+ if(ispath(drop_on_wrench) && !QDELING(src))
+ new drop_on_wrench(drop_location())
+ qdel(src)
+
+///''''''''''''''''optimized''''''''''''''''' proc for quickly reconnecting after a duct net was destroyed
+/obj/machinery/duct/proc/reconnect()
+ if(neighbours.len && !duct)
+ create_duct()
+ for(var/atom/movable/AM in neighbours)
+ if(istype(AM, /obj/machinery/duct))
+ var/obj/machinery/duct/D = AM
+ if(D.duct)
+ if(D.duct == duct) //we're already connected
+ continue
+ else
+ duct.assimilate(D.duct)
+ continue
+ else
+ duct.add_duct(D)
+ D.reconnect()
+ else
+ var/datum/component/plumbing/P = AM.GetComponent(/datum/component/plumbing)
+ if(AM in get_step(src, neighbours[AM])) //did we move?
+ if(P)
+ connect_plumber(P, neighbours[AM])
+ else
+ neighbours -= AM //we moved
+
+///Special proc to draw a new connect frame based on neighbours. not the norm so we can support multiple duct kinds
+/obj/machinery/duct/proc/generate_connects()
+ if(lock_connects)
+ return
+ connects = 0
+ for(var/A in neighbours)
+ connects |= neighbours[A]
+ update_icon()
+
+///create a new duct datum
+/obj/machinery/duct/proc/create_duct()
+ duct = new()
+ duct.add_duct(src)
+
+///add a duct as neighbour. this means we're connected and will connect again if we ever regenerate
+/obj/machinery/duct/proc/add_neighbour(obj/machinery/duct/D, direction)
+ if(!(D in neighbours))
+ neighbours[D] = direction
+ if(!(src in D.neighbours))
+ D.neighbours[src] = turn(direction, 180)
+
+///remove all our neighbours, and remove us from our neighbours aswell
+/obj/machinery/duct/proc/lose_neighbours()
+ for(var/obj/machinery/duct/D in neighbours)
+ D.neighbours.Remove(src)
+ neighbours = list()
+
+///add a connect direction
+/obj/machinery/duct/proc/add_connects(new_connects) //make this a define to cut proc calls?
+ if(!lock_connects)
+ connects |= new_connects
+
+///remove a connect direction
+/obj/machinery/duct/proc/remove_connects(dead_connects)
+ if(!lock_connects)
+ connects &= ~dead_connects
+
+///remove our connects
+/obj/machinery/duct/proc/reset_connects()
+ if(!lock_connects)
+ connects = 0
+
+///get a list of the ducts we can connect to if we are dumb
+/obj/machinery/duct/proc/get_adjacent_ducts()
+ var/list/adjacents = list()
+ for(var/A in GLOB.cardinals)
+ if(A & connects)
+ for(var/obj/machinery/duct/D in get_step(src, A))
+ if((turn(A, 180) & D.connects) && D.active)
+ adjacents += D
+ return adjacents
+
+/obj/machinery/duct/update_icon_state()
+ var/temp_icon = initial(icon_state)
+ for(var/D in GLOB.cardinals)
+ if(D & connects)
+ if(D == NORTH)
+ temp_icon += "_n"
+ if(D == SOUTH)
+ temp_icon += "_s"
+ if(D == EAST)
+ temp_icon += "_e"
+ if(D == WEST)
+ temp_icon += "_w"
+ icon_state = temp_icon
+
+///update the layer we are on
+/obj/machinery/duct/proc/handle_layer()
+ var/offset
+ switch(duct_layer)//it's a bitfield, but it's fine because it only works when there's one layer, and multiple layers should be handled differently
+ if(FIRST_DUCT_LAYER)
+ offset = -10
+ if(SECOND_DUCT_LAYER)
+ offset = -5
+ if(THIRD_DUCT_LAYER)
+ offset = 0
+ if(FOURTH_DUCT_LAYER)
+ offset = 5
+ if(FIFTH_DUCT_LAYER)
+ offset = 10
+ pixel_x = offset
+ pixel_y = offset
+
+
+/obj/machinery/duct/set_anchored(anchorvalue)
+ . = ..()
+ if(isnull(.))
+ return
+ if(anchorvalue)
+ active = TRUE
+ attempt_connect()
+ else
+ disconnect_duct(TRUE)
+
+/obj/machinery/duct/wrench_act(mob/living/user, obj/item/I) //I can also be the RPD
+ ..()
+ add_fingerprint(user)
+ I.play_tool_sound(src)
+ if(anchored || can_anchor())
+ set_anchored(!anchored)
+ user.visible_message( \
+ "[user] [anchored ? null : "un"]fastens \the [src].", \
+ "You [anchored ? null : "un"]fasten \the [src].", \
+ "You hear ratcheting.")
+ return TRUE
+///collection of all the sanity checks to prevent us from stacking ducts that shouldn't be stacked
+/obj/machinery/duct/proc/can_anchor(turf/T)
+ if(!T)
+ T = get_turf(src)
+ for(var/obj/machinery/duct/D in T)
+ if(!anchored || D == src)
+ continue
+ for(var/A in GLOB.cardinals)
+ if(A & connects && A & D.connects)
+ return FALSE
+ return TRUE
+
+/obj/machinery/duct/doMove(destination)
+ . = ..()
+ disconnect_duct()
+ anchored = FALSE
+
+/obj/machinery/duct/Destroy()
+ disconnect_duct()
+ return ..()
+
+/obj/machinery/duct/MouseDrop_T(atom/A, mob/living/user)
+ if(!istype(A, /obj/machinery/duct))
+ return
+ var/obj/machinery/duct/D = A
+ var/obj/item/I = user.get_active_held_item()
+ if(I?.tool_behaviour != TOOL_WRENCH)
+ to_chat(user, "You need to be holding a wrench in your active hand to do that!")
+ return
+ if(get_dist(src, D) != 1)
+ return
+ var/direction = get_dir(src, D)
+ if(!(direction in GLOB.cardinals))
+ return
+ if(duct_layer != D.duct_layer)
+ return
+
+ add_connects(direction) //the connect of the other duct is handled in connect_network, but do this here for the parent duct because it's not necessary in normal cases
+ add_neighbour(D, direction)
+ connect_network(D, direction, TRUE)
+ update_icon()
+
+///has a total of 5 layers and doesnt give a shit about color. its also dumb so doesnt autoconnect.
+/obj/machinery/duct/multilayered
+ name = "duct layer-manifold"
+ icon = 'icons/obj/2x2.dmi'
+ icon_state = "multiduct"
+ pixel_x = -15
+ pixel_y = -15
+
+ color_to_color_support = FALSE
+ duct_layer = FIRST_DUCT_LAYER | SECOND_DUCT_LAYER | THIRD_DUCT_LAYER | FOURTH_DUCT_LAYER | FIFTH_DUCT_LAYER
+ drop_on_wrench = null
+
+ lock_connects = TRUE
+ lock_layers = TRUE
+ ignore_colors = TRUE
+ dumb = TRUE
+
+ active = FALSE
+ anchored = FALSE
+
+/obj/machinery/duct/multilayered/Initialize(mapload, no_anchor, color_of_duct, layer_of_duct = DUCT_LAYER_DEFAULT, force_connects)
+ . = ..()
+ update_connects()
+
+/obj/machinery/duct/multilayered/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/update_icon_blocker)
+
+/obj/machinery/duct/multilayered/wrench_act(mob/living/user, obj/item/I)
+ . = ..()
+ update_connects()
+
+/obj/machinery/duct/multilayered/proc/update_connects()
+ if(dir & NORTH || dir & SOUTH)
+ connects = NORTH | SOUTH
+ else
+ connects = EAST | WEST
+
+///don't connect to other multilayered stuff because honestly it shouldn't be done and I dont wanna deal with it
+/obj/machinery/duct/multilayered/connect_duct(obj/machinery/duct/D, direction, ignore_color)
+ if(istype(D, /obj/machinery/duct/multilayered))
+ return
+ return ..()
+
+/obj/machinery/duct/multilayered/handle_layer()
+ return
+
+/obj/item/stack/ducts
+ name = "stack of duct"
+ desc = "A stack of fluid ducts."
+ singular_name = "duct"
+ icon = 'icons/obj/plumbing/fluid_ducts.dmi'
+ icon_state = "ducts"
+ custom_materials = list(/datum/material/iron=500)
+ w_class = WEIGHT_CLASS_TINY
+ novariants = FALSE
+ max_amount = 50
+ item_flags = NOBLUDGEON
+ merge_type = /obj/item/stack/ducts
+ ///Color of our duct
+ var/duct_color = "grey"
+ ///Default layer of our duct
+ var/duct_layer = "Default Layer"
+ ///Assoc index with all the available layers. yes five might be a bit much. Colors uses a global by the way
+ var/list/layers = list("First Layer" = FIRST_DUCT_LAYER, "Second Layer" = SECOND_DUCT_LAYER, "Default Layer" = DUCT_LAYER_DEFAULT,
+ "Fourth Layer" = FOURTH_DUCT_LAYER, "Fifth Layer" = FIFTH_DUCT_LAYER)
+
+/obj/item/stack/ducts/examine(mob/user)
+ . = ..()
+ . += "It's current color and layer are [duct_color] and [duct_layer]. Use in-hand to change."
+
+/obj/item/stack/ducts/attack_self(mob/user)
+ var/new_layer = input("Select a layer", "Layer") as null|anything in layers
+ if(new_layer)
+ duct_layer = new_layer
+ var/new_color = input("Select a color", "Color") as null|anything in GLOB.pipe_paint_colors
+ if(new_color)
+ duct_color = new_color
+ add_atom_colour(GLOB.pipe_paint_colors[new_color], FIXED_COLOUR_PRIORITY)
+
+/obj/item/stack/ducts/afterattack(atom/A, user, proximity)
+ . = ..()
+ if(!proximity)
+ return
+ if(istype(A, /obj/machinery/duct))
+ var/obj/machinery/duct/D = A
+ if(!D.anchored)
+ add(1)
+ qdel(D)
+ if(istype(A, /turf/open) && use(1))
+ var/turf/open/OT = A
+ new /obj/machinery/duct(OT, FALSE, GLOB.pipe_paint_colors[duct_color], layers[duct_layer])
+ playsound(get_turf(src), 'sound/machines/click.ogg', 50, TRUE)
+
+/obj/item/stack/ducts/fifty
+ amount = 50
diff --git a/code/modules/plumbing/plumbers/_plumb_machinery.dm b/code/modules/plumbing/plumbers/_plumb_machinery.dm
new file mode 100644
index 0000000000..0566945e3b
--- /dev/null
+++ b/code/modules/plumbing/plumbers/_plumb_machinery.dm
@@ -0,0 +1,98 @@
+/**Basic plumbing object.
+* It doesn't really hold anything special, YET.
+* Objects that are plumbing but not a subtype are as of writing liquid pumps and the reagent_dispenser tank
+* Also please note that the plumbing component is toggled on and off by the component using a signal from default_unfasten_wrench, so dont worry about it
+*/
+/obj/machinery/plumbing
+ name = "pipe thing"
+ icon = 'icons/obj/plumbing/plumbers.dmi'
+ icon_state = "pump"
+ density = TRUE
+ active_power_usage = 30
+ use_power = ACTIVE_POWER_USE
+ resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
+ ///Plumbing machinery is always gonna need reagents, so we might aswell put it here
+ var/buffer = 50
+ ///Flags for reagents, like INJECTABLE, TRANSPARENT bla bla everything thats in DEFINES/reagents.dm
+ var/reagent_flags = TRANSPARENT
+ ///wheter we partake in rcd construction or not
+ var/rcd_constructable = TRUE
+ ///cost of the plumbing rcd construction
+ var/rcd_cost = 15
+ ///delay of constructing it throught the plumbing rcd
+ var/rcd_delay = 10
+
+/obj/machinery/plumbing/Initialize(mapload, bolt = TRUE)
+ . = ..()
+ anchored = bolt
+ create_reagents(buffer, reagent_flags)
+ AddComponent(/datum/component/simple_rotation, ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS, null, CALLBACK(src, .proc/can_be_rotated))
+
+/obj/machinery/plumbing/proc/can_be_rotated(mob/user,rotation_type)
+ return TRUE
+
+
+/obj/machinery/plumbing/examine(mob/user)
+ . = ..()
+ . += "The maximum volume display reads: [reagents.maximum_volume] units."
+
+/obj/machinery/plumbing/wrench_act(mob/living/user, obj/item/I)
+ ..()
+ default_unfasten_wrench(user, I)
+ return TRUE
+
+/obj/machinery/plumbing/plunger_act(obj/item/plunger/P, mob/living/user, reinforced)
+ to_chat(user, "You start furiously plunging [name].")
+ if(do_after(user, 30, target = src))
+ to_chat(user, "You finish plunging the [name].")
+ reagents.reaction(get_turf(src), TOUCH) //splash on the floor
+ reagents.clear_reagents()
+
+/obj/machinery/plumbing/welder_act(mob/living/user, obj/item/I)
+ . = ..()
+ if(anchored)
+ to_chat(user, "The [name] needs to be unbolted to do that!You start slicing the [name] apart.You slice the [name] apart. target_temperature && acclimate_state != COOLING)
+ acclimate_state = COOLING
+ update_icon()
+ if(!emptying)
+ if(reagents.chem_temp >= target_temperature && target_temperature + allowed_temperature_difference >= reagents.chem_temp) //cooling here
+ emptying = TRUE
+ if(reagents.chem_temp <= target_temperature && target_temperature - allowed_temperature_difference <= reagents.chem_temp) //heating here
+ emptying = TRUE
+
+ reagents.adjust_thermal_energy((target_temperature - reagents.chem_temp) * heater_coefficient * SPECIFIC_HEAT_DEFAULT * reagents.total_volume) //keep constant with chem heater
+ reagents.handle_reactions()
+
+/obj/machinery/plumbing/acclimator/update_icon()
+ icon_state = initial(icon_state)
+ switch(acclimate_state)
+ if(COOLING)
+ icon_state += "_cold"
+ if(HEATING)
+ icon_state += "_hot"
+
+/obj/machinery/plumbing/acclimator/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "ChemAcclimator", name)
+ ui.open()
+
+/obj/machinery/plumbing/acclimator/ui_data(mob/user)
+ var/list/data = list()
+
+ data["enabled"] = enabled
+ data["chem_temp"] = reagents.chem_temp
+ data["target_temperature"] = target_temperature
+ data["allowed_temperature_difference"] = allowed_temperature_difference
+ data["acclimate_state"] = acclimate_state
+ data["max_volume"] = reagents.maximum_volume
+ data["reagent_volume"] = reagents.total_volume
+ data["emptying"] = emptying
+ return data
+
+/obj/machinery/plumbing/acclimator/ui_act(action, params)
+ if(..())
+ return
+ . = TRUE
+ switch(action)
+ if("set_target_temperature")
+ var/target = text2num(params["temperature"])
+ target_temperature = clamp(target, 0, 1000)
+ if("set_allowed_temperature_difference")
+ var/target = text2num(params["temperature"])
+ allowed_temperature_difference = clamp(target, 0, 1000)
+ if("toggle_power")
+ enabled = !enabled
+ if("change_volume")
+ var/target = text2num(params["volume"])
+ reagents.maximum_volume = clamp(round(target), 1, buffer)
+
+#undef COOLING
+#undef HEATING
+#undef NEUTRAL
diff --git a/code/modules/plumbing/plumbers/autohydro.dm b/code/modules/plumbing/plumbers/autohydro.dm
new file mode 100644
index 0000000000..dbc70dfcf5
--- /dev/null
+++ b/code/modules/plumbing/plumbers/autohydro.dm
@@ -0,0 +1,65 @@
+/obj/machinery/hydroponics/constructable/automagic
+ name = "automated hydroponics system"
+ desc = "The bane of botanists everywhere. Accepts chemical reagents via plumbing, automatically harvests and removes dead plants."
+ obj_flags = CAN_BE_HIT | UNIQUE_RENAME
+ circuit = /obj/item/circuitboard/machine/hydroponics/automagic
+ self_sufficiency_req = 400 //automating hydroponics makes gaia sad so she needs more drugs to turn they tray godly.
+ canirrigate = FALSE
+
+
+/obj/machinery/hydroponics/constructable/automagic/attackby(obj/item/O, mob/user, params)
+ if(istype(O, /obj/item/reagent_containers))
+ return FALSE //avoid fucky wuckies
+ ..()
+
+/obj/machinery/hydroponics/constructable/automagic/default_unfasten_wrench(mob/user, obj/item/I, time = 20)
+ . = ..()
+ if(. == SUCCESSFUL_UNFASTEN)
+ user.visible_message("[user.name] [anchored ? "fasten" : "unfasten"] [src]", \
+ "You [anchored ? "fasten" : "unfasten"] [src]")
+ var/datum/component/plumbing/CP = GetComponent(/datum/component/plumbing)
+ if(anchored)
+ CP.enable()
+ else
+ CP.disable()
+
+/obj/machinery/hydroponics/constructable/automagic/Destroy()
+ . = ..()
+ STOP_PROCESSING(SSobj, src)
+
+/obj/machinery/hydroponics/constructable/automagic/Initialize(mapload)
+ . = ..()
+ START_PROCESSING(SSobj, src)
+ create_reagents(100 , AMOUNT_VISIBLE)
+
+/obj/machinery/hydroponics/constructable/automagic/ComponentInitialize()
+ . = ..()
+ AddComponent(/datum/component/simple_rotation, ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS, null, CALLBACK(src, .proc/can_be_rotated))
+ AddComponent(/datum/component/plumbing/simple_demand)
+
+/obj/machinery/hydroponics/constructable/proc/can_be_rotated(mob/user, rotation_type)
+ return !anchored
+
+/obj/machinery/hydroponics/constructable/automagic/process()
+ if(reagents)
+ applyChemicals(reagents)
+ reagents.clear_reagents()
+ if(dead)
+ dead = 0
+ qdel(myseed)
+ myseed = null
+ update_icon()
+ name = initial(name)
+ desc = initial(desc)
+ if(harvest)
+ myseed.harvest_userless()
+ harvest = 0
+ lastproduce = age
+ if(!myseed.get_gene(/datum/plant_gene/trait/repeated_harvest))
+ qdel(myseed)
+ myseed = null
+ dead = 0
+ name = initial(name)
+ desc = initial(desc)
+ update_icon()
+ ..()
diff --git a/code/modules/plumbing/plumbers/bottler.dm b/code/modules/plumbing/plumbers/bottler.dm
new file mode 100644
index 0000000000..396c7cac22
--- /dev/null
+++ b/code/modules/plumbing/plumbers/bottler.dm
@@ -0,0 +1,79 @@
+/obj/machinery/plumbing/bottler
+ name = "chemical bottler"
+ desc = "Puts reagents into containers, like bottles and beakers."
+ icon_state = "bottler"
+ layer = ABOVE_ALL_MOB_LAYER
+ reagent_flags = TRANSPARENT | DRAINABLE
+ rcd_cost = 50
+ rcd_delay = 50
+ buffer = 100
+ ///how much do we fill
+ var/wanted_amount = 10
+ ///where things are sent
+ var/turf/goodspot = null
+ ///where things are taken
+ var/turf/inputspot = null
+ ///where beakers that are already full will be sent
+ var/turf/badspot = null
+
+/obj/machinery/plumbing/bottler/Initialize(mapload, bolt)
+ . = ..()
+ AddComponent(/datum/component/plumbing/simple_demand, bolt)
+ setDir(dir)
+
+/obj/machinery/plumbing/bottler/can_be_rotated(mob/user, rotation_type)
+ if(anchored)
+ to_chat(user, "It is fastened to the floor!")
+ return FALSE
+ return TRUE
+
+///changes the tile array
+/obj/machinery/plumbing/bottler/setDir(newdir)
+ . = ..()
+ switch(dir)
+ if(NORTH)
+ goodspot = get_step(get_turf(src), NORTH)
+ inputspot = get_step(get_turf(src), SOUTH)
+ badspot = get_step(get_turf(src), EAST)
+ if(SOUTH)
+ goodspot = get_step(get_turf(src), SOUTH)
+ inputspot = get_step(get_turf(src), NORTH)
+ badspot = get_step(get_turf(src), WEST)
+ if(WEST)
+ goodspot = get_step(get_turf(src), WEST)
+ inputspot = get_step(get_turf(src), EAST)
+ badspot = get_step(get_turf(src), NORTH)
+ if(EAST)
+ goodspot = get_step(get_turf(src), EAST)
+ inputspot = get_step(get_turf(src), WEST)
+ badspot = get_step(get_turf(src), SOUTH)
+
+///changing input ammount with a window
+/obj/machinery/plumbing/bottler/interact(mob/user)
+ . = ..()
+ wanted_amount = clamp(round(input(user,"maximum is 100u","set ammount to fill with") as num|null, 1), 1, 100)
+ reagents.clear_reagents()
+ to_chat(user, " The [src] will now fill for [wanted_amount]u.")
+
+/obj/machinery/plumbing/bottler/process()
+ if(stat & NOPOWER)
+ return
+ ///see if machine has enough to fill
+ if(reagents.total_volume >= wanted_amount && anchored)
+ var/obj/AM = pick(inputspot.contents)///pick a reagent_container that could be used
+ if(istype(AM, /obj/item/reagent_containers) && (!istype(AM, /obj/item/reagent_containers/hypospray/medipen)))
+ var/obj/item/reagent_containers/B = AM
+ ///see if it would overflow else inject
+ if((B.reagents.total_volume + wanted_amount) <= B.reagents.maximum_volume)
+ reagents.trans_to(B, wanted_amount)
+ B.forceMove(goodspot)
+ return
+ ///glass was full so we move it away
+ AM.forceMove(badspot)
+ if(istype(AM, /obj/item/slime_extract)) ///slime extracts need inject
+ AM.forceMove(goodspot)
+ reagents.trans_to(AM, wanted_amount)
+ return
+ if(istype(AM, /obj/item/slimecross/industrial)) ///no need to move slimecross industrial things
+ reagents.trans_to(AM, wanted_amount)
+ return
diff --git a/code/modules/plumbing/plumbers/destroyer.dm b/code/modules/plumbing/plumbers/destroyer.dm
new file mode 100644
index 0000000000..b61383ea4a
--- /dev/null
+++ b/code/modules/plumbing/plumbers/destroyer.dm
@@ -0,0 +1,21 @@
+/obj/machinery/plumbing/disposer
+ name = "chemical disposer"
+ desc = "Breaks down chemicals and annihilates them."
+ icon_state = "disposal"
+ ///we remove 10 reagents per second
+ var/disposal_rate = 10
+
+/obj/machinery/plumbing/disposer/Initialize(mapload, bolt)
+ . = ..()
+ AddComponent(/datum/component/plumbing/simple_demand, bolt)
+
+/obj/machinery/plumbing/disposer/process()
+ if(stat & NOPOWER)
+ return
+ if(reagents.total_volume)
+ if(icon_state != initial(icon_state) + "_working") //threw it here instead of update icon since it only has two states
+ icon_state = initial(icon_state) + "_working"
+ reagents.remove_any(disposal_rate)
+ else
+ if(icon_state != initial(icon_state))
+ icon_state = initial(icon_state)
diff --git a/code/modules/plumbing/plumbers/fermenter.dm b/code/modules/plumbing/plumbers/fermenter.dm
new file mode 100644
index 0000000000..b1e1e4b676
--- /dev/null
+++ b/code/modules/plumbing/plumbers/fermenter.dm
@@ -0,0 +1,59 @@
+/obj/machinery/plumbing/fermenter //FULLY AUTOMATIC BEER BREWING. TRULY, THE FUTURE.
+ name = "chemical fermenter"
+ desc = "Turns plants into various types of booze."
+ icon_state = "fermenter"
+ layer = ABOVE_ALL_MOB_LAYER
+ reagent_flags = TRANSPARENT | DRAINABLE
+ rcd_cost = 30
+ rcd_delay = 30
+ buffer = 400
+ ///input dir
+ var/eat_dir = SOUTH
+
+/obj/machinery/plumbing/fermenter/Initialize(mapload, bolt)
+ . = ..()
+ AddComponent(/datum/component/plumbing/simple_supply, bolt)
+
+/obj/machinery/plumbing/fermenter/can_be_rotated(mob/user,rotation_type)
+ if(anchored)
+ to_chat(user, "It is fastened to the floor!")
+ return FALSE
+ switch(eat_dir)
+ if(WEST)
+ eat_dir = NORTH
+ return TRUE
+ if(EAST)
+ eat_dir = SOUTH
+ return TRUE
+ if(NORTH)
+ eat_dir = EAST
+ return TRUE
+ if(SOUTH)
+ eat_dir = WEST
+ return TRUE
+
+/obj/machinery/plumbing/fermenter/CanPass(atom/movable/AM)
+ . = ..()
+ if(!anchored)
+ return
+ var/move_dir = get_dir(loc, AM.loc)
+ if(move_dir == eat_dir)
+ return TRUE
+
+/obj/machinery/plumbing/fermenter/Crossed(atom/movable/AM)
+ . = ..()
+ ferment(AM)
+
+/obj/machinery/plumbing/fermenter/proc/ferment(atom/AM)
+ if(stat & NOPOWER)
+ return
+ if(reagents.holder_full())
+ return
+ if(!isitem(AM))
+ return
+ if(istype(AM, /obj/item/reagent_containers/food/snacks/grown))
+ var/obj/item/reagent_containers/food/snacks/grown/G = AM
+ if(G.distill_reagent)
+ var/amount = G.seed.potency * 0.25
+ reagents.add_reagent(G.distill_reagent, amount)
+ qdel(G)
diff --git a/code/modules/plumbing/plumbers/filter.dm b/code/modules/plumbing/plumbers/filter.dm
new file mode 100644
index 0000000000..1ffd170507
--- /dev/null
+++ b/code/modules/plumbing/plumbers/filter.dm
@@ -0,0 +1,65 @@
+///chemical plumbing filter. If it's not filtered by left and right, it goes straight.
+/obj/machinery/plumbing/filter
+ name = "chemical filter"
+ desc = "A chemical filter for filtering chemicals. The left and right outputs appear to be from the perspective of the input port."
+ icon_state = "filter"
+ density = FALSE
+
+ ///whitelist of chems id's that go to the left side. Empty to disable port
+ var/list/left = list()
+ ///whitelist of chem id's that go to the right side. Empty to disable port
+ var/list/right = list()
+ ///whitelist of chems but their name instead of path
+ var/list/english_left = list()
+ ///whitelist of chems but their name instead of path
+ var/list/english_right = list()
+
+/obj/machinery/plumbing/filter/Initialize(mapload, bolt)
+ . = ..()
+ AddComponent(/datum/component/plumbing/filter, bolt)
+
+/obj/machinery/plumbing/filter/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "ChemFilter", name)
+ ui.open()
+
+/obj/machinery/plumbing/filter/ui_data(mob/user)
+ var/list/data = list()
+ data["left"] = english_left
+ data["right"] = english_right
+ return data
+
+/obj/machinery/plumbing/filter/ui_act(action, params)
+ if(..())
+ return
+ . = TRUE
+ switch(action)
+ if("add")
+ var/new_chem_name = params["name"]
+ var/chem_id = get_chem_id(new_chem_name)
+ if(chem_id)
+ switch(params["which"])
+ if("left")
+ if(!left.Find(chem_id))
+ english_left += new_chem_name
+ left += chem_id
+ if("right")
+ if(!right.Find(chem_id))
+ english_right += new_chem_name
+ right += chem_id
+ else
+ to_chat(usr, "No such known reagent exists!")
+
+ if("remove")
+ var/chem_name = params["reagent"]
+ var/chem_id = get_chem_id(chem_name)
+ switch(params["which"])
+ if("left")
+ if(english_left.Find(chem_name))
+ english_left -= chem_name
+ left -= chem_id
+ if("right")
+ if(english_right.Find(chem_name))
+ english_right -= chem_name
+ right -= chem_id
diff --git a/code/modules/plumbing/plumbers/grinder_chemical.dm b/code/modules/plumbing/plumbers/grinder_chemical.dm
new file mode 100644
index 0000000000..f39c79f906
--- /dev/null
+++ b/code/modules/plumbing/plumbers/grinder_chemical.dm
@@ -0,0 +1,64 @@
+/obj/machinery/plumbing/grinder_chemical
+ name = "chemical grinder"
+ desc = "chemical grinder."
+ icon_state = "grinder_chemical"
+ layer = ABOVE_ALL_MOB_LAYER
+ reagent_flags = TRANSPARENT | DRAINABLE
+ rcd_cost = 30
+ rcd_delay = 30
+ buffer = 400
+ var/eat_dir = NORTH
+
+/obj/machinery/plumbing/grinder_chemical/Initialize(mapload, bolt)
+ . = ..()
+ AddComponent(/datum/component/plumbing/simple_supply, bolt)
+
+/obj/machinery/plumbing/grinder_chemical/can_be_rotated(mob/user,rotation_type)
+ if(anchored)
+ to_chat(user, "It is fastened to the floor!")
+ return FALSE
+ switch(eat_dir)
+ if(WEST)
+ eat_dir = NORTH
+ return TRUE
+ if(EAST)
+ eat_dir = SOUTH
+ return TRUE
+ if(NORTH)
+ eat_dir = EAST
+ return TRUE
+ if(SOUTH)
+ eat_dir = WEST
+ return TRUE
+
+/obj/machinery/plumbing/grinder_chemical/CanPass(atom/movable/AM)
+ . = ..()
+ if(!anchored)
+ return
+ var/move_dir = get_dir(loc, AM.loc)
+ if(move_dir == eat_dir)
+ return TRUE
+
+/obj/machinery/plumbing/grinder_chemical/Crossed(atom/movable/AM)
+ . = ..()
+ grind(AM)
+
+/obj/machinery/plumbing/grinder_chemical/proc/grind(atom/AM)
+ if(stat & NOPOWER)
+ return
+ if(reagents.holder_full())
+ return
+ if(!isitem(AM))
+ return
+ var/obj/item/I = AM
+ if(I.juice_results || I.grind_results)
+ if(I.juice_results)
+ I.on_juice()
+ reagents.add_reagent_list(I.juice_results)
+ if(I.reagents)
+ I.reagents.trans_to(src, I.reagents.total_volume)
+ qdel(I)
+ return
+ I.on_grind()
+ reagents.add_reagent_list(I.grind_results)
+ qdel(I)
diff --git a/code/modules/plumbing/plumbers/medipenrefill.dm b/code/modules/plumbing/plumbers/medipenrefill.dm
new file mode 100644
index 0000000000..fb7553a4d5
--- /dev/null
+++ b/code/modules/plumbing/plumbers/medipenrefill.dm
@@ -0,0 +1,94 @@
+/obj/machinery/medipen_refiller
+ name = "Medipen Refiller"
+ desc = "A machine that refills used medipens with chemicals."
+ icon = 'icons/obj/machines/medipen_refiller.dmi'
+ icon_state = "medipen_refiller"
+ density = TRUE
+ circuit = /obj/item/circuitboard/machine/medipen_refiller
+ idle_power_usage = 100
+ /// list of medipen subtypes it can refill
+ var/list/allowed = list(/obj/item/reagent_containers/hypospray/medipen = /datum/reagent/medicine/epinephrine,
+ /obj/item/reagent_containers/hypospray/medipen/ekit = /datum/reagent/medicine/epinephrine,
+ /obj/item/reagent_containers/hypospray/medipen/firelocker = /datum/reagent/medicine/oxandrolone,
+ /obj/item/reagent_containers/hypospray/medipen/stimpack = /datum/reagent/medicine/ephedrine,
+ /obj/item/reagent_containers/hypospray/medipen/blood_loss = /datum/reagent/medicine/coagulant/weak)
+ /// var to prevent glitches in the animation
+ var/busy = FALSE
+
+/obj/machinery/medipen_refiller/Initialize()
+ . = ..()
+ create_reagents(100, TRANSPARENT)
+ for(var/obj/item/stock_parts/matter_bin/B in component_parts)
+ reagents.maximum_volume += 100 * B.rating
+ AddComponent(/datum/component/plumbing/simple_demand)
+
+
+/obj/machinery/medipen_refiller/RefreshParts()
+ var/new_volume = 100
+ for(var/obj/item/stock_parts/matter_bin/B in component_parts)
+ new_volume += 100 * B.rating
+ if(!reagents)
+ create_reagents(new_volume, TRANSPARENT)
+ reagents.maximum_volume = new_volume
+ return TRUE
+
+/// handles the messages and animation, calls refill to end the animation
+/obj/machinery/medipen_refiller/attackby(obj/item/I, mob/user, params)
+ if(busy)
+ to_chat(user, "The machine is busy.")
+ return
+ if(istype(I, /obj/item/reagent_containers) && I.is_open_container())
+ var/obj/item/reagent_containers/RC = I
+ var/units = RC.reagents.trans_to(src, RC.amount_per_transfer_from_this)
+ if(units)
+ to_chat(user, "You transfer [units] units of the solution to the [name].")
+ return
+ else
+ to_chat(user, "The [name] is full.")
+ return
+ if(istype(I, /obj/item/reagent_containers/hypospray/medipen))
+ var/obj/item/reagent_containers/hypospray/medipen/P = I
+ if(!(LAZYFIND(allowed, P.type)))
+ to_chat(user, "Error! Unknown schematics.")
+ return
+ if(P.reagents?.reagent_list.len)
+ to_chat(user, "The medipen is already filled.")
+ return
+ if(reagents.has_reagent(allowed[P.type], 10))
+ busy = TRUE
+ add_overlay("active")
+ addtimer(CALLBACK(src, .proc/refill, P, user), 20)
+ qdel(P)
+ return
+ to_chat(user, "There aren't enough reagents to finish this operation.")
+ return
+ ..()
+
+/obj/machinery/medipen_refiller/plunger_act(obj/item/plunger/P, mob/living/user, reinforced)
+ to_chat(user, "You start furiously plunging [name].")
+ if(do_after(user, 30, target = src))
+ to_chat(user, "You finish plunging the [name].")
+ reagents.clear_reagents()
+
+/obj/machinery/medipen_refiller/wrench_act(mob/living/user, obj/item/I)
+ ..()
+ default_unfasten_wrench(user, I)
+ return TRUE
+
+/obj/machinery/medipen_refiller/crowbar_act(mob/user, obj/item/I)
+ ..()
+ default_deconstruction_crowbar(I)
+ return TRUE
+
+/obj/machinery/medipen_refiller/screwdriver_act(mob/living/user, obj/item/I)
+ . = ..()
+ if(!.)
+ return default_deconstruction_screwdriver(user, "medipen_refiller_open", "medipen_refiller", I)
+
+/// refills the medipen
+/obj/machinery/medipen_refiller/proc/refill(obj/item/reagent_containers/hypospray/medipen/P, mob/user)
+ new P.type(loc)
+ reagents.remove_reagent(allowed[P.type], 10)
+ cut_overlays()
+ busy = FALSE
+ to_chat(user, "Medipen refilled.")
diff --git a/code/modules/plumbing/plumbers/pill_press.dm b/code/modules/plumbing/plumbers/pill_press.dm
new file mode 100644
index 0000000000..56510fac87
--- /dev/null
+++ b/code/modules/plumbing/plumbers/pill_press.dm
@@ -0,0 +1,127 @@
+///We take a constant input of reagents, and produce a pill once a set volume is reached
+/obj/machinery/plumbing/pill_press
+ name = "chemical press"
+ desc = "A press that makes pills, patches and bottles."
+ icon_state = "pill_press"
+ ///maximum size of a pill
+ var/max_pill_volume = 50
+ ///maximum size of a patch
+ var/max_patch_volume = 40
+ ///maximum size of a bottle
+ var/max_bottle_volume = 30
+ ///current operating product (pills or patches)
+ var/product = "pill"
+ ///the minimum size a pill or patch can be
+ var/min_volume = 5
+ ///the maximum size a pill or patch can be
+ var/max_volume = 50
+ ///selected size of the product
+ var/current_volume = 10
+ ///prefix for the product name
+ var/product_name = "factory"
+ ///the icon_state number for the pill.
+ var/pill_number = RANDOM_PILL_STYLE
+ ///list of id's and icons for the pill selection of the ui
+ var/list/pill_styles
+ ///list of products stored in the machine, so we dont have 610 pills on one tile
+ var/list/stored_products = list()
+ ///max amount of pills allowed on our tile before we start storing them instead
+ var/max_floor_products = 50 //haha massive pill piles
+
+/obj/machinery/plumbing/pill_press/examine(mob/user)
+ . = ..()
+ . += "The [name] currently has [stored_products.len] stored. There needs to be less than [max_floor_products ] on the floor to continue dispensing."
+
+/obj/machinery/plumbing/pill_press/Initialize(mapload, bolt)
+ . = ..()
+ AddComponent(/datum/component/plumbing/simple_demand, bolt)
+
+ //expertly copypasted from chemmasters
+ var/datum/asset/spritesheet/simple/assets = get_asset_datum(/datum/asset/spritesheet/simple/pills)
+ pill_styles = list()
+ for (var/x in 1 to PILL_STYLE_COUNT)
+ var/list/SL = list()
+ SL["id"] = x
+ SL["htmltag"] = assets.icon_tag("pill[x]")
+ pill_styles += list(SL)
+
+
+/obj/machinery/plumbing/pill_press/process()
+ if(stat & NOPOWER)
+ return
+ if(reagents.total_volume >= current_volume)
+ if (product == "pill")
+ var/obj/item/reagent_containers/pill/P = new(src)
+ reagents.trans_to(P, current_volume)
+ P.name = trim("[product_name] pill")
+ stored_products += P
+ if(pill_number == RANDOM_PILL_STYLE)
+ P.icon_state = "pill[rand(1,21)]"
+ else
+ P.icon_state = "pill[pill_number]"
+ if(P.icon_state == "pill4") //mirrored from chem masters
+ P.desc = "A tablet or capsule, but not just any, a red one, one taken by the ones not scared of knowledge, freedom, uncertainty and the brutal truths of reality."
+ else if (product == "patch")
+ var/obj/item/reagent_containers/pill/patch/P = new(src)
+ reagents.trans_to(P, current_volume)
+ P.name = trim("[product_name] patch")
+ stored_products += P
+ else if (product == "bottle")
+ var/obj/item/reagent_containers/glass/bottle/P = new(src)
+ reagents.trans_to(P, current_volume)
+ P.name = trim("[product_name] bottle")
+ stored_products += P
+ if(stored_products.len)
+ var/pill_amount = 0
+ for(var/obj/item/reagent_containers/pill/P in loc)
+ pill_amount++
+ if(pill_amount >= max_floor_products) //too much so just stop
+ break
+ if(pill_amount < max_floor_products)
+ var/atom/movable/AM = stored_products[1] //AM because forceMove is all we need
+ stored_products -= AM
+ AM.forceMove(drop_location())
+
+
+/obj/machinery/plumbing/pill_press/ui_assets(mob/user)
+ return list(
+ get_asset_datum(/datum/asset/spritesheet/simple/pills),
+ )
+
+/obj/machinery/plumbing/pill_press/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "ChemPress", name)
+ ui.open()
+
+/obj/machinery/plumbing/pill_press/ui_data(mob/user)
+ var/list/data = list()
+ data["pill_style"] = pill_number
+ data["current_volume"] = current_volume
+ data["product_name"] = product_name
+ data["pill_styles"] = pill_styles
+ data["product"] = product
+ data["min_volume"] = min_volume
+ data["max_volume"] = max_volume
+ return data
+
+/obj/machinery/plumbing/pill_press/ui_act(action, params)
+ if(..())
+ return
+ . = TRUE
+ switch(action)
+ if("change_pill_style")
+ pill_number = clamp(text2num(params["id"]), 1 , PILL_STYLE_COUNT)
+ if("change_current_volume")
+ current_volume = clamp(text2num(params["volume"]), min_volume, max_volume)
+ if("change_product_name")
+ product_name = html_encode(params["name"])
+ if("change_product")
+ product = params["product"]
+ if (product == "pill")
+ max_volume = max_pill_volume
+ else if (product == "patch")
+ max_volume = max_patch_volume
+ else if (product == "bottle")
+ max_volume = max_bottle_volume
+ current_volume = clamp(current_volume, min_volume, max_volume)
diff --git a/code/modules/plumbing/plumbers/pumps.dm b/code/modules/plumbing/plumbers/pumps.dm
new file mode 100644
index 0000000000..c24e48098d
--- /dev/null
+++ b/code/modules/plumbing/plumbers/pumps.dm
@@ -0,0 +1,64 @@
+///We pump liquids from activated(plungerated) geysers to a plumbing outlet. We don't need to be wired.
+/obj/machinery/plumbing/liquid_pump
+ name = "liquid pump"
+ desc = "Pump up those sweet liquids from under the surface. Uses thermal energy from geysers to power itself." //better than placing 200 cables, because it wasnt fun
+ icon = 'icons/obj/plumbing/plumbers.dmi'
+ icon_state = "pump"
+ anchored = FALSE
+ density = TRUE
+ idle_power_usage = 10
+ active_power_usage = 1000
+
+ rcd_cost = 30
+ rcd_delay = 40
+
+ ///units we pump per process (2 seconds)
+ var/pump_power = 2
+ ///set to true if the loop couldnt find a geyser in process, so it remembers and stops checking every loop until moved. more accurate name would be absolutely_no_geyser_under_me_so_dont_try
+ var/geyserless = FALSE
+ ///The geyser object
+ var/obj/structure/geyser/geyser
+ ///volume of our internal buffer
+ var/volume = 200
+
+/obj/machinery/plumbing/liquid_pump/Initialize(mapload, bolt)
+ . = ..()
+ AddComponent(/datum/component/plumbing/simple_supply, bolt)
+
+///please note that the component has a hook in the parent call, wich handles activating and deactivating
+/obj/machinery/plumbing/liquid_pump/default_unfasten_wrench(mob/user, obj/item/I, time = 20)
+ . = ..()
+ if(. == SUCCESSFUL_UNFASTEN)
+ geyser = null
+ update_icon()
+ geyserless = FALSE //we switched state, so lets just set this back aswell
+
+/obj/machinery/plumbing/liquid_pump/process()
+ if(!anchored || panel_open || geyserless)
+ return
+
+ if(!geyser)
+ for(var/obj/structure/geyser/G in loc.contents)
+ geyser = G
+ update_icon()
+ if(!geyser) //we didnt find one, abort
+ geyserless = TRUE
+ visible_message("The [name] makes a sad beep!")
+ playsound(src, 'sound/machines/buzz-sigh.ogg', 50)
+ return
+
+ pump()
+
+///pump up that sweet geyser nectar
+/obj/machinery/plumbing/liquid_pump/proc/pump()
+ if(!geyser || !geyser.reagents)
+ return
+ geyser.reagents.trans_to(src, pump_power)
+
+/obj/machinery/plumbing/liquid_pump/update_icon_state()
+ if(geyser)
+ icon_state = initial(icon_state) + "-on"
+ else if(panel_open)
+ icon_state = initial(icon_state) + "-open"
+ else
+ icon_state = initial(icon_state)
diff --git a/code/modules/plumbing/plumbers/reaction_chamber.dm b/code/modules/plumbing/plumbers/reaction_chamber.dm
new file mode 100644
index 0000000000..949543c300
--- /dev/null
+++ b/code/modules/plumbing/plumbers/reaction_chamber.dm
@@ -0,0 +1,63 @@
+///a reaction chamber for plumbing. pretty much everything can react, but this one keeps the reagents seperated and only reacts under your given terms
+/obj/machinery/plumbing/reaction_chamber
+ name = "reaction chamber"
+ desc = "Keeps chemicals seperated until given conditions are met."
+ icon_state = "reaction_chamber"
+ buffer = 200
+ reagent_flags = TRANSPARENT | NO_REACT
+
+ /**list of set reagents that the reaction_chamber allows in, and must all be present before mixing is enabled.
+ * example: list(/datum/reagent/water = 20, /datum/reagent/fuel/oil = 50)
+ */
+ var/list/required_reagents = list()
+ ///our reagent goal has been reached, so now we lock our inputs and start emptying
+ var/emptying = FALSE
+
+/obj/machinery/plumbing/reaction_chamber/Initialize(mapload, bolt)
+ . = ..()
+ AddComponent(/datum/component/plumbing/reaction_chamber, bolt)
+
+/obj/machinery/plumbing/reaction_chamber/on_reagent_change()
+ if(reagents.total_volume == 0 && emptying) //we were emptying, but now we aren't
+ emptying = FALSE
+ reagent_flags |= NO_REACT
+
+/obj/machinery/plumbing/reaction_chamber/power_change()
+ . = ..()
+ if(use_power != NO_POWER_USE)
+ icon_state = initial(icon_state) + "_on"
+ else
+ icon_state = initial(icon_state)
+
+/obj/machinery/plumbing/reaction_chamber/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "ChemReactionChamber", name)
+ ui.open()
+
+/obj/machinery/plumbing/reaction_chamber/ui_data(mob/user)
+ var/list/data = list()
+ var/list/text_reagents = list()
+ for(var/A in required_reagents) //make a list where the key is text, because that looks alot better in the ui than a typepath
+ var/datum/reagent/R = A
+ text_reagents[initial(R.name)] = required_reagents[R]
+
+ data["reagents"] = text_reagents
+ data["emptying"] = emptying
+ return data
+
+/obj/machinery/plumbing/reaction_chamber/ui_act(action, params)
+ if(..())
+ return
+ . = TRUE
+ switch(action)
+ if("remove")
+ var/reagent = get_chem_id(params["chem"])
+ if(reagent)
+ required_reagents.Remove(reagent)
+ if("add")
+ var/input_reagent = get_chem_id(params["chem"])
+ if(input_reagent && !required_reagents.Find(input_reagent))
+ var/input_amount = text2num(params["amount"])
+ if(input_amount)
+ required_reagents[input_reagent] = input_amount
diff --git a/code/modules/plumbing/plumbers/splitters.dm b/code/modules/plumbing/plumbers/splitters.dm
new file mode 100644
index 0000000000..a26813486c
--- /dev/null
+++ b/code/modules/plumbing/plumbers/splitters.dm
@@ -0,0 +1,50 @@
+///it splits the reagents however you want. So you can "every 60 units, 45 goes left and 15 goes straight". The side direction is EAST, you can change this in the component
+/obj/machinery/plumbing/splitter
+ name = "Chemical Splitter"
+ desc = "A chemical splitter for smart chemical factorization. Waits till a set of conditions is met and then stops all input and splits the buffer evenly or other in two ducts."
+ icon_state = "splitter"
+ buffer = 100
+ density = FALSE
+
+ ///constantly switches between TRUE and FALSE. TRUE means the batch tick goes straight, FALSE means the next batch goes in the side duct.
+ var/turn_straight = TRUE
+ ///how much we must transfer straight. note input can be as high as 10 reagents per process, usually
+ var/transfer_straight = 5
+ ///how much we must transfer to the side
+ var/transfer_side = 5
+ //the maximum you can set the transfer to
+ var/max_transfer = 9
+
+
+/obj/machinery/plumbing/splitter/Initialize(mapload, bolt)
+ . = ..()
+ AddComponent(/datum/component/plumbing/splitter, bolt)
+
+/obj/machinery/plumbing/splitter/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "ChemSplitter", name)
+ ui.open()
+
+/obj/machinery/plumbing/splitter/ui_data(mob/user)
+ var/list/data = list()
+ data["straight"] = transfer_straight
+ data["side"] = transfer_side
+ data["max_transfer"] = max_transfer
+ return data
+
+/obj/machinery/plumbing/splitter/ui_act(action, params)
+ if(..())
+ return
+ . = TRUE
+ switch(action)
+ if("set_amount")
+ var/direction = params["target"]
+ var/value = clamp(text2num(params["amount"]), 1, max_transfer)
+ switch(direction)
+ if("straight")
+ transfer_straight = value
+ if("side")
+ transfer_side = value
+ else
+ return FALSE
diff --git a/code/modules/plumbing/plumbers/synthesizer.dm b/code/modules/plumbing/plumbers/synthesizer.dm
new file mode 100644
index 0000000000..c2bc3439ff
--- /dev/null
+++ b/code/modules/plumbing/plumbers/synthesizer.dm
@@ -0,0 +1,111 @@
+///A single machine that produces a single chem. Can be placed in unison with others through plumbing to create chemical factories
+/obj/machinery/plumbing/synthesizer
+ name = "chemical synthesizer"
+ desc = "Produces a single chemical at a given volume. Must be plumbed. Most effective when working in unison with other chemical synthesizers, heaters and filters."
+
+ icon_state = "synthesizer"
+ icon = 'icons/obj/plumbing/plumbers.dmi'
+ rcd_cost = 25
+ rcd_delay = 15
+
+ ///Amount we produce for every process. Ideally keep under 5 since thats currently the standard duct capacity
+ var/amount = 1
+ ///The maximum we can produce for every process
+ buffer = 5
+ ///I track them here because I have no idea how I'd make tgui loop like that
+ var/static/list/possible_amounts = list(0,1,2,3,4,5)
+ ///The reagent we are producing. We are a typepath, but are also typecast because there's several occations where we need to use initial.
+ var/datum/reagent/reagent_id = null
+ ///straight up copied from chem dispenser. Being a subtype would be extremely tedious and making it global would restrict potential subtypes using different dispensable_reagents
+ var/list/dispensable_reagents = list(
+ /datum/reagent/aluminium,
+ /datum/reagent/bromine,
+ /datum/reagent/carbon,
+ /datum/reagent/chlorine,
+ /datum/reagent/copper,
+ /datum/reagent/consumable/ethanol,
+ /datum/reagent/fluorine,
+ /datum/reagent/hydrogen,
+ /datum/reagent/iodine,
+ /datum/reagent/iron,
+ /datum/reagent/lithium,
+ /datum/reagent/mercury,
+ /datum/reagent/nitrogen,
+ /datum/reagent/oxygen,
+ /datum/reagent/phosphorus,
+ /datum/reagent/potassium,
+ /datum/reagent/radium,
+ /datum/reagent/silicon,
+ /datum/reagent/silver,
+ /datum/reagent/sodium,
+ /datum/reagent/stable_plasma,
+ /datum/reagent/consumable/sugar,
+ /datum/reagent/sulfur,
+ /datum/reagent/toxin/acid,
+ /datum/reagent/water,
+ /datum/reagent/fuel,
+ )
+
+/obj/machinery/plumbing/synthesizer/Initialize(mapload, bolt)
+ . = ..()
+ AddComponent(/datum/component/plumbing/simple_supply, bolt)
+
+/obj/machinery/plumbing/synthesizer/process()
+ if(stat & NOPOWER || !reagent_id || !amount)
+ return
+ if(reagents.total_volume >= amount) //otherwise we get leftovers, and we need this to be precise
+ return
+ reagents.add_reagent(reagent_id, amount)
+
+/obj/machinery/plumbing/synthesizer/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "ChemSynthesizer", name)
+ ui.open()
+
+/obj/machinery/plumbing/synthesizer/ui_data(mob/user)
+ var/list/data = list()
+
+ var/is_hallucinating = user.hallucinating()
+ var/list/chemicals = list()
+
+ for(var/A in dispensable_reagents)
+ var/datum/reagent/R = GLOB.chemical_reagents_list[A]
+ if(R)
+ var/chemname = R.name
+ if(is_hallucinating && prob(5))
+ chemname = "[pick_list_replacements("hallucination.json", "chemicals")]"
+ chemicals.Add(list(list("title" = chemname, "id" = ckey(R.name))))
+ data["chemicals"] = chemicals
+ data["amount"] = amount
+ data["possible_amounts"] = possible_amounts
+
+ data["current_reagent"] = ckey(initial(reagent_id.name))
+ return data
+
+/obj/machinery/plumbing/synthesizer/ui_act(action, params)
+ if(..())
+ return
+ . = TRUE
+ switch(action)
+ if("amount")
+ var/new_amount = text2num(params["target"])
+ if(new_amount in possible_amounts)
+ amount = new_amount
+ . = TRUE
+ if("select")
+ var/new_reagent = GLOB.name2reagent[params["reagent"]]
+ if(new_reagent in dispensable_reagents)
+ reagent_id = new_reagent
+ . = TRUE
+ update_icon()
+ reagents.clear_reagents()
+
+/obj/machinery/plumbing/synthesizer/update_overlays()
+ . = ..()
+ var/mutable_appearance/r_overlay = mutable_appearance(icon, "[icon_state]_overlay")
+ if(reagent_id)
+ r_overlay.color = initial(reagent_id.color)
+ else
+ r_overlay.color = "#FFFFFF"
+ . += r_overlay
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index a70e508476..2480288484 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -1009,7 +1009,7 @@
. = UI_INTERACTIVE
/obj/machinery/power/apc/ui_act(action, params)
- if(..() || !can_use(usr, 1) || (locked && area.hasSiliconAccessInArea(usr, PRIVILEDGES_SILICON|PRIVILEDGES_DRONE) && !failure_timer && action != "toggle_nightshift") || (integration_cog && (is_servant_of_ratvar(usr))))
+ if(..() || !can_use(usr, 1) || (locked && !area.hasSiliconAccessInArea(usr, PRIVILEDGES_SILICON|PRIVILEDGES_DRONE) && !failure_timer && action != "toggle_nightshift" && (!integration_cog || !(is_servant_of_ratvar(usr)))))
return
switch(action)
if("lock")
diff --git a/code/modules/power/generator.dm b/code/modules/power/generator.dm
index 78a20e5b62..54b1362518 100644
--- a/code/modules/power/generator.dm
+++ b/code/modules/power/generator.dm
@@ -66,7 +66,7 @@
var/energy_transfer = delta_temperature*hot_air_heat_capacity*cold_air_heat_capacity/(hot_air_heat_capacity+cold_air_heat_capacity)
var/heat = energy_transfer*(1-efficiency)
- lastgen += energy_transfer*efficiency
+ lastgen += LOGISTIC_FUNCTION(1000000,0.0034,delta_temperature,2000)
hot_air.set_temperature(hot_air.return_temperature() - energy_transfer/hot_air_heat_capacity)
cold_air.set_temperature(cold_air.return_temperature() + heat/cold_air_heat_capacity)
diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm
index 8559b8ba45..fd8f900552 100644
--- a/code/modules/power/supermatter/supermatter.dm
+++ b/code/modules/power/supermatter/supermatter.dm
@@ -2,34 +2,54 @@
//Please do not bother them with bugs from this port, however, as it has been modified quite a bit.
//Modifications include removing the world-ending full supermatter variation, and leaving only the shard.
+//Zap constants, speeds up targeting
+
+#define BIKE (COIL + 1)
+#define COIL (ROD + 1)
+#define ROD (LIVING + 1)
+#define LIVING (MACHINERY + 1)
+#define MACHINERY (OBJECT + 1)
+#define OBJECT (LOWEST + 1)
+#define LOWEST (1)
+
#define PLASMA_HEAT_PENALTY 15 // Higher == Bigger heat and waste penalty from having the crystal surrounded by this gas. Negative numbers reduce penalty.
#define OXYGEN_HEAT_PENALTY 1
-#define CO2_HEAT_PENALTY 0.1
#define PLUOXIUM_HEAT_PENALTY -1
#define TRITIUM_HEAT_PENALTY 10
+#define CO2_HEAT_PENALTY 0.1
#define NITROGEN_HEAT_PENALTY -1.5
#define BZ_HEAT_PENALTY 5
+#define H2O_HEAT_PENALTY 8
+//#define FREON_HEAT_PENALTY -10 //very good heat absorbtion and less plasma and o2 generation
+//#define HYDROGEN_HEAT_PENALTY 10 // similar heat penalty as tritium (dangerous)
+
+//All of these get divided by 10-bzcomp * 5 before having 1 added and being multiplied with power to determine rads
+//Keep the negative values here above -10 and we won't get negative rads
#define OXYGEN_TRANSMIT_MODIFIER 1.5 //Higher == Bigger bonus to power generation.
#define PLASMA_TRANSMIT_MODIFIER 4
#define BZ_TRANSMIT_MODIFIER -2
+#define TRITIUM_TRANSMIT_MODIFIER 30 //We divide by 10, so this works out to 3
+#define PLUOXIUM_TRANSMIT_MODIFIER -5 //Should halve the power output
+#define H2O_TRANSMIT_MODIFIER 2
+//#define HYDROGEN_TRANSMIT_MODIFIER 25 //increase the radiation emission, but less than the trit (2.5)
-#define TRITIUM_RADIOACTIVITY_MODIFIER 3 //Higher == Crystal spews out more radiation
-#define BZ_RADIOACTIVITY_MODIFIER 5
-#define PLUOXIUM_RADIOACTIVITY_MODIFIER -2
+#define BZ_RADIOACTIVITY_MODIFIER 5 //Improves the effect of transmit modifiers
#define N2O_HEAT_RESISTANCE 6 //Higher == Gas makes the crystal more resistant against heat damage.
#define PLUOXIUM_HEAT_RESISTANCE 3
+//#define HYDROGEN_HEAT_RESISTANCE 2 // just a bit of heat resistance to spice it up
#define POWERLOSS_INHIBITION_GAS_THRESHOLD 0.20 //Higher == Higher percentage of inhibitor gas needed before the charge inertia chain reaction effect starts.
#define POWERLOSS_INHIBITION_MOLE_THRESHOLD 20 //Higher == More moles of the gas are needed before the charge inertia chain reaction effect starts. //Scales powerloss inhibition down until this amount of moles is reached
#define POWERLOSS_INHIBITION_MOLE_BOOST_THRESHOLD 500 //bonus powerloss inhibition boost if this amount of moles is reached
-#define MOLE_PENALTY_THRESHOLD 1800 //Higher == Shard can absorb more moles before triggering the high mole penalties.
+#define MOLE_PENALTY_THRESHOLD 1800 //Above this value we can get lord singulo and independent mol damage, below it we can heal damage
#define MOLE_HEAT_PENALTY 350 //Heat damage scales around this. Too hot setups with this amount of moles do regular damage, anything above and below is scaled
-#define POWER_PENALTY_THRESHOLD 5000 //Higher == Engine can generate more power before triggering the high power penalties.
-#define SEVERE_POWER_PENALTY_THRESHOLD 7000 //Same as above, but causes more dangerous effects
-#define CRITICAL_POWER_PENALTY_THRESHOLD 12000 //Even more dangerous effects, threshold for tesla delamination
+//Along with damage_penalty_point, makes flux anomalies.
+#define POWER_PENALTY_THRESHOLD 5000 //The cutoff on power properly doing damage, pulling shit around, and delamming into a tesla. Low chance of pyro anomalies, +2 bolts of electricity
+#define SEVERE_POWER_PENALTY_THRESHOLD 7000 //+1 bolt of electricity, allows for gravitational anomalies, and higher chances of pyro anomalies
+#define CRITICAL_POWER_PENALTY_THRESHOLD 9000 //+1 bolt of electricity.
#define HEAT_PENALTY_THRESHOLD 40 //Higher == Crystal safe operational temperature is higher.
#define DAMAGE_HARDCAP 0.002
#define DAMAGE_INCREASE_MULTIPLIER 0.25
@@ -66,6 +86,13 @@
#define SUPERMATTER_COUNTDOWN_TIME 30 SECONDS
+///to prevent accent sounds from layering
+#define SUPERMATTER_ACCENT_SOUND_MIN_COOLDOWN 2 SECONDS
+
+#define DEFAULT_ZAP_ICON_STATE "sm_arc"
+#define SLIGHTLY_CHARGED_ZAP_ICON_STATE "sm_arc_supercharged"
+#define OVER_9000_ZAP_ICON_STATE "sm_arc_dbz_referance" //Witty I know
+
GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
/obj/machinery/power/supermatter_crystal
@@ -76,89 +103,183 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
density = TRUE
anchored = TRUE
flags_1 = PREVENT_CONTENTS_EXPLOSION_1
- var/uid = 1
- var/static/gl_uid = 1
light_range = 4
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF
-
critical_machine = TRUE
+ ///The id of our supermatter
+ var/uid = 1
+ ///The amount of supermatters that have been created this round
+ var/static/gl_uid = 1
+ ///Tracks the bolt color we are using
+ var/zap_icon = DEFAULT_ZAP_ICON_STATE
+ ///The portion of the gasmix we're on that we should remove
var/gasefficency = 0.15
-
+ ///Used for changing icon states for diff base sprites
var/base_icon_state = "darkmatter"
+ ///Are we exploding?
var/final_countdown = FALSE
+ ///The amount of damage we have currently
var/damage = 0
+ ///The damage we had before this cycle. Used to limit the damage we can take each cycle, and for safe_alert
var/damage_archived = 0
+ ///Our "Shit is no longer fucked" message. We send it when damage is less then damage_archived
var/safe_alert = "Crystalline hyperstructure returning to safe operating parameters."
+ ///The point at which we should start sending messeges about the damage to the engi channels.
var/warning_point = 50
+ ///The alert we send when we've reached warning_point
var/warning_alert = "Danger! Crystal hyperstructure integrity faltering!"
- var/damage_penalty_point = 550
+ ///The point at which we start sending messages to the common channel
var/emergency_point = 700
+ ///The alert we send when we've reached emergency_point
var/emergency_alert = "CRYSTAL DELAMINATION IMMINENT."
+ ///The point at which we delam
var/explosion_point = 900
+ ///When we pass this amount of damage we start shooting bolts
+ var/damage_penalty_point = 550
- var/emergency_issued = FALSE
-
+ ///A scaling value that affects the severity of explosions.
var/explosion_power = 35
- var/temp_factor = 30
-
- var/lastwarning = 0 // Time in 1/10th of seconds since the last sent warning
+ ///Time in 1/10th of seconds since the last sent warning
+ var/lastwarning = 0
+ ///Refered to as eer on the moniter. This value effects gas output, heat, damage, and radiation.
var/power = 0
-
- var/n2comp = 0 // raw composition of each gas in the chamber, ranges from 0 to 1
-
- var/plasmacomp = 0
- var/o2comp = 0
- var/co2comp = 0
- var/n2ocomp = 0
- var/pluoxiumcomp = 0
- var/tritiumcomp = 0
- var/bzcomp = 0
-
- var/pluoxiumbonus = 0
-
+ ///Determines the rate of positve change in gas comp values
+ var/gas_change_rate = 0.05
+ ///The list of gases we will be interacting with in process_atoms()
+ var/list/gases_we_care_about = list(
+ /datum/gas/oxygen,
+ /datum/gas/water_vapor,
+ /datum/gas/plasma,
+ /datum/gas/carbon_dioxide,
+ /datum/gas/nitrous_oxide,
+ /datum/gas/nitrogen,
+ /datum/gas/pluoxium,
+ /datum/gas/tritium,
+ /datum/gas/bz,
+// /datum/gas/freon,
+// /datum/gas/hydrogen,
+ )
+ ///The list of gases mapped against their current comp. We use this to calculate different values the supermatter uses, like power or heat resistance. It doesn't perfectly match the air around the sm, instead moving up at a rate determined by gas_change_rate per call. Ranges from 0 to 1
+ var/list/gas_comp = list(
+ /datum/gas/oxygen = 0,
+ /datum/gas/water_vapor = 0,
+ /datum/gas/plasma = 0,
+ /datum/gas/carbon_dioxide = 0,
+ /datum/gas/nitrous_oxide = 0,
+ /datum/gas/nitrogen = 0,
+ /datum/gas/pluoxium = 0,
+ /datum/gas/tritium = 0,
+ /datum/gas/bz = 0,
+// /datum/gas/freon = 0,
+// /datum/gas/hydrogen = 0,
+ )
+ ///The list of gases mapped against their transmit values. We use it to determine the effect different gases have on radiation
+ var/list/gas_trans = list(
+ /datum/gas/oxygen = OXYGEN_TRANSMIT_MODIFIER,
+ /datum/gas/water_vapor = H2O_TRANSMIT_MODIFIER,
+ /datum/gas/plasma = PLASMA_TRANSMIT_MODIFIER,
+ /datum/gas/pluoxium = PLUOXIUM_TRANSMIT_MODIFIER,
+ /datum/gas/tritium = TRITIUM_TRANSMIT_MODIFIER,
+ /datum/gas/bz = BZ_TRANSMIT_MODIFIER,
+// /datum/gas/hydrogen = HYDROGEN_TRANSMIT_MODIFIER,
+ )
+ ///The list of gases mapped against their heat penaltys. We use it to determin molar and heat output
+ var/list/gas_heat = list(
+ /datum/gas/oxygen = OXYGEN_HEAT_PENALTY,
+ /datum/gas/water_vapor = H2O_HEAT_PENALTY,
+ /datum/gas/plasma = PLASMA_HEAT_PENALTY,
+ /datum/gas/carbon_dioxide = CO2_HEAT_PENALTY,
+ /datum/gas/nitrogen = NITROGEN_HEAT_PENALTY,
+ /datum/gas/pluoxium = PLUOXIUM_HEAT_PENALTY,
+ /datum/gas/tritium = TRITIUM_HEAT_PENALTY,
+ /datum/gas/bz = BZ_HEAT_PENALTY,
+// /datum/gas/freon = FREON_HEAT_PENALTY,
+// /datum/gas/hydrogen = HYDROGEN_HEAT_PENALTY,
+ )
+ ///The list of gases mapped against their heat resistance. We use it to moderate heat damage.
+ var/list/gas_resist = list(
+ /datum/gas/nitrous_oxide = N2O_HEAT_RESISTANCE,
+ /datum/gas/pluoxium = PLUOXIUM_HEAT_RESISTANCE,
+// /datum/gas/hydrogen = HYDROGEN_HEAT_RESISTANCE,
+ )
+ ///The list of gases mapped against their powermix ratio
+ var/list/gas_powermix = list(
+ /datum/gas/oxygen = 1,
+ /datum/gas/water_vapor = 1,
+ /datum/gas/plasma = 1,
+ /datum/gas/carbon_dioxide = 1,
+ /datum/gas/nitrogen = -1,
+ /datum/gas/pluoxium = -1,
+ /datum/gas/tritium = 1,
+ /datum/gas/bz = 1,
+// /datum/gas/freon = -1,
+// /datum/gas/hydrogen = 1,
+ )
+ ///The last air sample's total molar count, will always be above or equal to 0
var/combined_gas = 0
+ ///Affects the power gain the sm experiances from heat
var/gasmix_power_ratio = 0
+ ///Affects the amount of o2 and plasma the sm outputs, along with the heat it makes.
var/dynamic_heat_modifier = 1
+ ///Affects the amount of damage and minimum point at which the sm takes heat damage
var/dynamic_heat_resistance = 1
+ ///Uses powerloss_dynamic_scaling and combined_gas to lessen the effects of our powerloss functions
var/powerloss_inhibitor = 1
+ ///Based on co2 percentage, slowly moves between 0 and 1. We use it to calc the powerloss_inhibitor
var/powerloss_dynamic_scaling= 0
+ ///Affects the amount of radiation the sm makes. We multiply this with power to find the rads.
var/power_transmission_bonus = 0
+ ///Used to increase or lessen the amount of damage the sm takes from heat based on molar counts.
var/mole_heat_penalty = 0
-
-
+ ///Takes the energy throwing things into the sm generates and slowly turns it into actual power
var/matter_power = 0
+ ///The cutoff for a bolt jumping, grows with heat, lowers with higher mol count,
+ var/zap_cutoff = 1500
+ ///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
- //Temporary values so that we can optimize this
- //How much the bullets damage should be multiplied by when it is added to the internal variables
- var/config_bullet_energy = 2
- //How much of the power is left after processing is finished?
-// var/config_power_reduction_per_tick = 0.5
- //How much hallucination should it produce per unit of power?
- var/config_hallucination_power = 0.1
-
+ ///Our internal radio
var/obj/item/radio/radio
+ ///The key our internal radio uses
var/radio_key = /obj/item/encryptionkey/headset_eng
+ ///The engineering channel
var/engineering_channel = "Engineering"
+ ///The common channel
var/common_channel = null
- //for logging
+ ///Boolean used for logging if we've been powered
var/has_been_powered = FALSE
+ ///Boolean used for logging if we've passed the emergency point
var/has_reached_emergency = FALSE
- // For making hugbox supermatter
- var/takes_damage = TRUE
- var/produces_gas = TRUE
+ ///An effect we show to admins and ghosts the percentage of delam we're at
var/obj/effect/countdown/supermatter/countdown
+ ///Used along with a global var to track if we can give out the sm sliver stealing objective
var/is_main_engine = FALSE
-
+ ///Our soundloop
var/datum/looping_sound/supermatter/soundloop
-
+ ///Can it be moved?
var/moveable = FALSE
+ ///cooldown tracker for accent sounds
+ var/last_accent_sound = 0
+
+ //For making hugbox supermatters
+ ///Disables all methods of taking damage
+ var/takes_damage = TRUE
+ ///Disables the production of gas, and pretty much any handling of it we do.
+ var/produces_gas = TRUE
+ ///Disables power changes
+ var/power_changes = TRUE
+ ///Disables the sm's proccessing totally.
+ var/processes = TRUE
+
/obj/machinery/power/supermatter_crystal/Initialize()
. = ..()
uid = gl_uid++
@@ -174,6 +295,9 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
if(is_main_engine)
GLOB.main_supermatter_engine = src
+ AddElement(/datum/element/bsa_blocker)
+ RegisterSignal(src, COMSIG_ATOM_BSA_BEAM, .proc/call_explode)
+
soundloop = new(list(src), TRUE)
/obj/machinery/power/supermatter_crystal/Destroy()
@@ -184,12 +308,11 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
QDEL_NULL(countdown)
if(is_main_engine && GLOB.main_supermatter_engine == src)
GLOB.main_supermatter_engine = null
- QDEL_NULL(soundloop)
return ..()
/obj/machinery/power/supermatter_crystal/examine(mob/user)
. = ..()
- if (iscarbon(user))
+ if (istype(user, /mob/living/carbon))
var/mob/living/carbon/C = user
if (!istype(C.glasses, /obj/item/clothing/glasses/meson) && (get_dist(user, src) < HALLUCINATION_RANGE(power)))
. += "You get headaches just from looking at it."
@@ -202,16 +325,17 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
if(!air)
return SUPERMATTER_ERROR
- if(get_integrity() < SUPERMATTER_DELAM_PERCENT)
+ var/integrity = get_integrity()
+ if(integrity < SUPERMATTER_DELAM_PERCENT)
return SUPERMATTER_DELAMINATING
- if(get_integrity() < SUPERMATTER_EMERGENCY_PERCENT)
+ if(integrity < SUPERMATTER_EMERGENCY_PERCENT)
return SUPERMATTER_EMERGENCY
- if(get_integrity() < SUPERMATTER_DANGER_PERCENT)
+ if(integrity < SUPERMATTER_DANGER_PERCENT)
return SUPERMATTER_DANGER
- if((get_integrity() < SUPERMATTER_WARNING_PERCENT) || (air.return_temperature() > CRITICAL_TEMPERATURE))
+ if((integrity < SUPERMATTER_WARNING_PERCENT) || (air.return_temperature() > CRITICAL_TEMPERATURE))
return SUPERMATTER_WARNING
if(air.return_temperature() > (CRITICAL_TEMPERATURE * 0.8))
@@ -238,23 +362,26 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
integrity = integrity < 0 ? 0 : integrity
return integrity
+/obj/machinery/power/supermatter_crystal/update_overlays()
+ . = ..()
+ if(final_countdown)
+ . += "casuality_field"
+
/obj/machinery/power/supermatter_crystal/proc/countdown()
set waitfor = FALSE
if(final_countdown) // We're already doing it go away
return
final_countdown = TRUE
-
- var/image/causality_field = image(icon, null, "causality_field")
- add_overlay(causality_field, TRUE)
+ update_icon()
var/speaking = "[emergency_alert] The supermatter has reached critical integrity failure. Emergency causality destabilization field has been activated."
radio.talk_into(src, speaking, common_channel, language = get_selected_language())
for(var/i in SUPERMATTER_COUNTDOWN_TIME to 0 step -10)
if(damage < explosion_point) // Cutting it a bit close there engineers
radio.talk_into(src, "[safe_alert] Failsafe has been disengaged.", common_channel)
- cut_overlay(causality_field, TRUE)
final_countdown = FALSE
+ update_icon()
return
else if((i % 50) != 0 && i > 50) // A message once every 5 seconds until the final 5 seconds which count down individualy
sleep(10)
@@ -287,48 +414,65 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "delam", /datum/mood_event/delam)
if(combined_gas > MOLE_PENALTY_THRESHOLD)
investigate_log("has collapsed into a singularity.", INVESTIGATE_SUPERMATTER)
- if(T)
+ if(T) //If something fucks up we blow anyhow. This fix is 4 years old and none ever said why it's here. help.
var/obj/singularity/S = new(T)
S.energy = 800
S.consume(src)
- else
- investigate_log("has exploded.", INVESTIGATE_SUPERMATTER)
- explosion(get_turf(T), explosion_power * max(gasmix_power_ratio, 0.205) * 0.5 , explosion_power * max(gasmix_power_ratio, 0.205) + 2, explosion_power * max(gasmix_power_ratio, 0.205) + 4 , explosion_power * max(gasmix_power_ratio, 0.205) + 6, 1, 1)
- if(power > POWER_PENALTY_THRESHOLD)
- investigate_log("has spawned additional energy balls.", INVESTIGATE_SUPERMATTER)
+ return //No boom for me sir
+ else if(power > POWER_PENALTY_THRESHOLD)
+ investigate_log("has spawned additional energy balls.", INVESTIGATE_SUPERMATTER)
+ if(T)
var/obj/singularity/energy_ball/E = new(T)
E.energy = power
- qdel(src)
+ investigate_log("has exploded.", INVESTIGATE_SUPERMATTER)
+ //Dear mappers, balance the sm max explosion radius to 17.5, 37, 39, 41
+ explosion(get_turf(T), explosion_power * max(gasmix_power_ratio, 0.205) * 0.5 , explosion_power * max(gasmix_power_ratio, 0.205) + 2, explosion_power * max(gasmix_power_ratio, 0.205) + 4 , explosion_power * max(gasmix_power_ratio, 0.205) + 6, 1, 1)
+ qdel(src)
-/obj/machinery/power/supermatter_crystal/proc/consume_turf(turf/T)
- var/oldtype = T.type
- var/turf/newT = T.ScrapeAway()
- if(newT.type == oldtype)
- return
- playsound(T, 'sound/effects/supermatter.ogg', 50, 1)
- T.visible_message("[T] smacks into [src] and rapidly flashes to ash.",\
- "You hear a loud crack as you are washed with a wave of heat.")
- CALCULATE_ADJACENT_TURFS(T)
+
+//this is here to eat arguments
+/obj/machinery/power/supermatter_crystal/proc/call_explode()
+ explode()
/obj/machinery/power/supermatter_crystal/process_atmos()
+ if(!processes) //Just fuck me up bro
+ return
var/turf/T = loc
- if(isnull(T)) // We have a null turf...something is wrong, stop processing this entity.
+ if(isnull(T))// We have a null turf...something is wrong, stop processing this entity.
return PROCESS_KILL
- if(!istype(T)) //We are in a crate or somewhere that isn't turf, if we return to turf resume processing but for now.
+ if(!istype(T))//We are in a crate or somewhere that isn't turf, if we return to turf resume processing but for now.
return //Yeah just stop.
- if(istype(T, /turf/closed))
- consume_turf(T)
+ if(isclosedturf(T))
+ var/turf/did_it_melt = T.Melt()
+ if(!isclosedturf(did_it_melt)) //In case some joker finds way to place these on indestructible walls
+ visible_message("[src] melts through [T]!")
+ return
+
+ //We vary volume by power, and handle OH FUCK FUSION IN COOLING LOOP noises.
if(power)
- soundloop.volume = min(40, (round(power/100)/50)+1) // 5 +1 volume per 20 power. 2500 power is max
+ soundloop.volume = clamp((50 + (power / 50)), 50, 100)
+ if(damage >= 300)
+ soundloop.mid_sounds = list('sound/machines/sm/loops/delamming.ogg' = 1)
+ else
+ soundloop.mid_sounds = list('sound/machines/sm/loops/calm.ogg' = 1)
+
+ //We play delam/neutral sounds at a rate determined by power and damage
+ if(last_accent_sound < world.time && prob(20))
+ var/aggression = min(((damage / 800) * (power / 2500)), 1.0) * 100
+ if(damage >= 300)
+ playsound(src, "smdelam", max(50, aggression), FALSE, 10)
+ else
+ playsound(src, "smcalm", max(50, aggression), FALSE, 10)
+ var/next_sound = round((100 - aggression) * 5)
+ last_accent_sound = world.time + max(SUPERMATTER_ACCENT_SOUND_MIN_COOLDOWN, next_sound)
//Ok, get the air from the turf
var/datum/gas_mixture/env = T.return_air()
var/datum/gas_mixture/removed
-
if(produces_gas)
//Remove gas from surrounding area
removed = env.remove(gasefficency * env.total_moles())
@@ -336,141 +480,240 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
// Pass all the gas related code an empty gas container
removed = new()
damage_archived = damage
+
+ /********
+ EXPERIMENTAL, HUGBOXY AS HELL CITADEL CHANGES: Even in a vaccum, update gas composition and modifiers.
+ This means that the SM will usually have a very small explosion if it ends up being breached to space,
+ and CO2 tesla delaminations basically require multiple grounding rods to stabilize it long enough to not have it vent.
+ *********/
+
if(!removed || !removed.total_moles() || isspaceturf(T)) //we're in space or there is no gas to process
if(takes_damage)
damage += max((power / 1000) * DAMAGE_INCREASE_MULTIPLIER, 0.1) // always does at least some damage
+ combined_gas = max(0, combined_gas - 0.5) // Slowly wear off.
+ for(var/gasID in gases_we_care_about)
+ gas_comp[gasID] = max(0, gas_comp[gasID] - 0.05) //slowly ramp down
else
if(takes_damage)
//causing damage
+ //Due to DAMAGE_INCREASE_MULTIPLIER, we only deal one 4th of the damage the statements otherwise would cause
+
+ //((((some value between 0.5 and 1 * temp - ((273.15 + 40) * some values between 1 and 10)) * some number between 0.25 and knock your socks off / 150) * 0.25
+ //Heat and mols account for each other, a lot of hot mols are more damaging then a few
+ //Mols start to have a positive effect on damage after 350
damage = max(damage + (max(clamp(removed.total_moles() / 200, 0.5, 1) * removed.return_temperature() - ((T0C + HEAT_PENALTY_THRESHOLD)*dynamic_heat_resistance), 0) * mole_heat_penalty / 150 ) * DAMAGE_INCREASE_MULTIPLIER, 0)
+ //Power only starts affecting damage when it is above 5000
damage = max(damage + (max(power - POWER_PENALTY_THRESHOLD, 0)/500) * DAMAGE_INCREASE_MULTIPLIER, 0)
+ //Molar count only starts affecting damage when it is above 1800
damage = max(damage + (max(combined_gas - MOLE_PENALTY_THRESHOLD, 0)/80) * DAMAGE_INCREASE_MULTIPLIER, 0)
+ //There might be a way to integrate healing and hurting via heat
//healing damage
if(combined_gas < MOLE_PENALTY_THRESHOLD)
- damage = max(damage + (min(removed.return_temperature() - (T0C + HEAT_PENALTY_THRESHOLD), 0) / 150 ), 0)
+ //Only has a net positive effect when the temp is below 313.15, heals up to 2 damage. Psycologists increase this temp min by up to 45
+ damage = max(damage + (min(removed.return_temperature() - (T0C + HEAT_PENALTY_THRESHOLD), 0) / 150), 0)
- //capping damage
- damage = min(damage_archived + (DAMAGE_HARDCAP * explosion_point),damage)
- if(damage > damage_archived && prob(10))
- playsound(get_turf(src), 'sound/effects/empulse.ogg', 50, 1)
+ //caps damage rate
- //calculating gas related values
- combined_gas = max(removed.total_moles(), 0)
+ //Takes the lower number between archived damage + (1.8) and damage
+ //This means we can only deal 1.8 damage per function call
+ damage = min(damage_archived + (DAMAGE_HARDCAP * explosion_point), damage)
- plasmacomp = max(removed.get_moles(/datum/gas/plasma)/combined_gas, 0)
- o2comp = max(removed.get_moles(/datum/gas/oxygen)/combined_gas, 0)
- co2comp = max(removed.get_moles(/datum/gas/carbon_dioxide)/combined_gas, 0)
- tritiumcomp = max(removed.get_moles(/datum/gas/tritium)/combined_gas, 0)
- bzcomp = max(removed.get_moles(/datum/gas/bz)/combined_gas, 0)
+ //calculating gas related values
+ //Wanna know a secret? See that max() to zero? it's used for error checking. If we get a mol count in the negative, we'll get a divide by zero error
+ combined_gas = max(removed.total_moles(), 0)
- pluoxiumcomp = max(removed.get_moles(/datum/gas/pluoxium)/combined_gas, 0)
- n2ocomp = max(removed.get_moles(/datum/gas/nitrous_oxide)/combined_gas, 0)
- n2comp = max(removed.get_moles(/datum/gas/nitrogen)/combined_gas, 0)
+ //This is more error prevention, according to all known laws of atmos, gas_mix.remove() should never make negative mol values.
+ //But this is tg
- if(pluoxiumcomp >= 0.15)
- pluoxiumbonus = 1 //makes pluoxium only work at 15%+
- else
- pluoxiumbonus = 0
+ //Lets get the proportions of the gasses in the mix and then slowly move our comp to that value
+ //Can cause an overestimation of mol count, should stabalize things though.
+ //Prevents huge bursts of gas/heat when a large amount of something is introduced
+ //They range between 0 and 1
+ for(var/gasID in gases_we_care_about)
+ gas_comp[gasID] += clamp(max(removed.get_moles(gasID)/combined_gas, 0) - gas_comp[gasID], -1, gas_change_rate)
- gasmix_power_ratio = min(max(plasmacomp + o2comp + co2comp + tritiumcomp + bzcomp - pluoxiumcomp - n2comp, 0), 1)
+ var/list/heat_mod = gases_we_care_about.Copy()
+ var/list/transit_mod = gases_we_care_about.Copy()
+ var/list/resistance_mod = gases_we_care_about.Copy()
- dynamic_heat_modifier = max((plasmacomp * PLASMA_HEAT_PENALTY) + (o2comp * OXYGEN_HEAT_PENALTY) + (co2comp * CO2_HEAT_PENALTY) + (tritiumcomp * TRITIUM_HEAT_PENALTY) + ((pluoxiumcomp * PLUOXIUM_HEAT_PENALTY) * pluoxiumbonus) + (n2comp * NITROGEN_HEAT_PENALTY) + (bzcomp * BZ_HEAT_PENALTY), 0.5)
- dynamic_heat_resistance = max((n2ocomp * N2O_HEAT_RESISTANCE) + ((pluoxiumcomp * PLUOXIUM_HEAT_RESISTANCE) * pluoxiumbonus), 1)
+ //We're concerned about pluoxium being too easy to abuse at low percents, so we make sure there's a substantial amount.
+ var/pluoxiumbonus = (gas_comp[/datum/gas/pluoxium] >= 0.15) //makes pluoxium only work at 15%+
+ var/h2obonus = 1 - (gas_comp[/datum/gas/water_vapor] * 0.25)//At max this value should be 0.75
+// var/freonbonus = (gas_comp[/datum/gas/freon] <= 0.03) //Let's just yeet power output if this shit is high
- power_transmission_bonus = max((plasmacomp * PLASMA_TRANSMIT_MODIFIER) + (o2comp * OXYGEN_TRANSMIT_MODIFIER) + (bzcomp * BZ_TRANSMIT_MODIFIER), 0)
+ heat_mod[/datum/gas/pluoxium] = pluoxiumbonus
+ transit_mod[/datum/gas/pluoxium] = pluoxiumbonus
+ resistance_mod[/datum/gas/pluoxium] = pluoxiumbonus
- //more moles of gases are harder to heat than fewer, so let's scale heat damage around them
- mole_heat_penalty = max(combined_gas / MOLE_HEAT_PENALTY, 0.25)
+ //No less then zero, and no greater then one, we use this to do explosions and heat to power transfer
+ //Be very careful with modifing this var by large amounts, and for the love of god do not push it past 1
+ gasmix_power_ratio = 0
+ for(var/gasID in gas_powermix)
+ gasmix_power_ratio += gas_comp[gasID] * gas_powermix[gasID]
+ gasmix_power_ratio = clamp(gasmix_power_ratio, 0, 1)
- if (combined_gas > POWERLOSS_INHIBITION_MOLE_THRESHOLD && co2comp > POWERLOSS_INHIBITION_GAS_THRESHOLD)
- powerloss_dynamic_scaling = clamp(powerloss_dynamic_scaling + clamp(co2comp - powerloss_dynamic_scaling, -0.02, 0.02), 0, 1)
- else
- powerloss_dynamic_scaling = clamp(powerloss_dynamic_scaling - 0.05,0, 1)
- powerloss_inhibitor = clamp(1-(powerloss_dynamic_scaling * clamp(combined_gas/POWERLOSS_INHIBITION_MOLE_BOOST_THRESHOLD,1 ,1.5)),0 ,1)
+ //Minimum value of -10, maximum value of 23. Effects plasma and o2 output and the output heat
+ dynamic_heat_modifier = 0
+ for(var/gasID in gas_heat)
+ dynamic_heat_modifier += gas_comp[gasID] * gas_heat[gasID] * (isnull(heat_mod[gasID]) ? 1 : heat_mod[gasID])
+ dynamic_heat_modifier *= h2obonus
+ dynamic_heat_modifier = max(dynamic_heat_modifier, 0.5)
- if(matter_power)
- var/removed_matter = max(matter_power/MATTER_POWER_CONVERSION, 40)
- power = max(power + removed_matter, 0)
- matter_power = max(matter_power - removed_matter, 0)
+ //Value between 1 and 10. Effects the damage heat does to the crystal
+ dynamic_heat_resistance = 0
+ for(var/gasID in gas_resist)
+ dynamic_heat_resistance += gas_comp[gasID] * gas_resist[gasID] * (isnull(resistance_mod[gasID]) ? 1 : resistance_mod[gasID])
+ dynamic_heat_resistance = max(dynamic_heat_resistance, 1)
- var/temp_factor = 50
+ //Value between -5 and 30, used to determine radiation output as it concerns things like collectors.
+ power_transmission_bonus = 0
+ for(var/gasID in gas_trans)
+ power_transmission_bonus += gas_comp[gasID] * gas_trans[gasID] * (isnull(transit_mod[gasID]) ? 1 : transit_mod[gasID])
+ power_transmission_bonus *= h2obonus
- if(gasmix_power_ratio > 0.8)
- // with a perfect gas mix, make the power less based on heat
- icon_state = "[base_icon_state]_glow"
- else
- // in normal mode, base the produced energy around the heat
- temp_factor = 30
- icon_state = base_icon_state
+ //more moles of gases are harder to heat than fewer, so let's scale heat damage around them
+ mole_heat_penalty = max(combined_gas / MOLE_HEAT_PENALTY, 0.25)
- power = max( (removed.return_temperature() * temp_factor / T0C) * gasmix_power_ratio + power, 0) //Total laser power plus an overload
+ //Ramps up or down in increments of 0.02 up to the proportion of co2
+ //Given infinite time, powerloss_dynamic_scaling = co2comp
+ //Some value between 0 and 1
+ if (combined_gas > POWERLOSS_INHIBITION_MOLE_THRESHOLD && gas_comp[/datum/gas/carbon_dioxide] > POWERLOSS_INHIBITION_GAS_THRESHOLD) //If there are more then 20 mols, and more then 20% co2
+ powerloss_dynamic_scaling = clamp(powerloss_dynamic_scaling + clamp(gas_comp[/datum/gas/carbon_dioxide] - powerloss_dynamic_scaling, -0.02, 0.02), 0, 1)
+ else
+ powerloss_dynamic_scaling = clamp(powerloss_dynamic_scaling - 0.05, 0, 1)
+ //Ranges from 0 to 1(1-(value between 0 and 1 * ranges from 1 to 1.5(mol / 500)))
+ //We take the mol count, and scale it to be our inhibitor
+ powerloss_inhibitor = clamp(1-(powerloss_dynamic_scaling * clamp(combined_gas/POWERLOSS_INHIBITION_MOLE_BOOST_THRESHOLD, 1, 1.5)), 0, 1)
- if(prob(50))
- radiation_pulse(src, power * (1 + (tritiumcomp * TRITIUM_RADIOACTIVITY_MODIFIER) + ((pluoxiumcomp * PLUOXIUM_RADIOACTIVITY_MODIFIER) * pluoxiumbonus) * (power_transmission_bonus/(10-(bzcomp * BZ_RADIOACTIVITY_MODIFIER))))) // Rad Modifiers BZ(500%), Tritium(300%), and Pluoxium(-200%)
- if(bzcomp >= 0.4 && prob(30 * bzcomp))
- fire_nuclear_particle() // Start to emit radballs at a maximum of 30% chance per tick
+ //Releases stored power into the general pool
+ //We get this by consuming shit or being scalpeled
+ if(matter_power && power_changes)
+ //We base our removed power off one 10th of the matter_power.
+ var/removed_matter = max(matter_power/MATTER_POWER_CONVERSION, 40)
+ //Adds at least 40 power
+ power = max(power + removed_matter, 0)
+ //Removes at least 40 matter power
+ matter_power = max(matter_power - removed_matter, 0)
- var/device_energy = power * REACTION_POWER_MODIFIER
+ var/temp_factor = 50
+ if(gasmix_power_ratio > 0.8)
+ //with a perfect gas mix, make the power more based on heat
+ icon_state = "[base_icon_state]_glow"
+ else
+ //in normal mode, power is less effected by heat
+ temp_factor = 30
+ icon_state = base_icon_state
- //To figure out how much temperature to add each tick, consider that at one atmosphere's worth
- //of pure oxygen, with all four lasers firing at standard energy and no N2 present, at room temperature
- //that the device energy is around 2140. At that stage, we don't want too much heat to be put out
- //Since the core is effectively "cold"
+ //if there is more pluox and n2 then anything else, we receive no power increase from heat
+ if(power_changes)
+ power = max((removed.return_temperature() * temp_factor / T0C) * gasmix_power_ratio + power, 0)
- //Also keep in mind we are only adding this temperature to (efficiency)% of the one tile the rock
- //is on. An increase of 4*C @ 25% efficiency here results in an increase of 1*C / (#tilesincore) overall.
- removed.set_temperature(removed.return_temperature() + ((device_energy * dynamic_heat_modifier) / THERMAL_RELEASE_MODIFIER))
+ if(prob(50))
+ //(1 + (tritRad + pluoxDampen * bzDampen * o2Rad * plasmaRad / (10 - bzrads))) * freonbonus
+ radiation_pulse(src, power * max(0, (1 + (power_transmission_bonus/(10-(gas_comp[/datum/gas/bz] * BZ_RADIOACTIVITY_MODIFIER)))) * 1))//freonbonus))// RadModBZ(500%)
+ if(gas_comp[/datum/gas/bz] >= 0.4 && prob(30 * gas_comp[/datum/gas/bz]))
+ src.fire_nuclear_particle() // Start to emit radballs at a maximum of 30% chance per tick
- removed.set_temperature(max(0, min(removed.return_temperature(), 2500 * dynamic_heat_modifier)))
+ //Power * 0.55 * a value between 1 and 0.8
+ var/device_energy = power * REACTION_POWER_MODIFIER
- //Calculate how much gas to release
- removed.adjust_moles(/datum/gas/plasma, max((device_energy * dynamic_heat_modifier) / PLASMA_RELEASE_MODIFIER, 0))
+ //To figure out how much temperature to add each tick, consider that at one atmosphere's worth
+ //of pure oxygen, with all four lasers firing at standard energy and no N2 present, at room temperature
+ //that the device energy is around 2140. At that stage, we don't want too much heat to be put out
+ //Since the core is effectively "cold"
- removed.adjust_moles(/datum/gas/oxygen, max(((device_energy + removed.return_temperature() * dynamic_heat_modifier) - T0C) / OXYGEN_RELEASE_MODIFIER, 0))
+ //Also keep in mind we are only adding this temperature to (efficiency)% of the one tile the rock
+ //is on. An increase of 4*C @ 25% efficiency here results in an increase of 1*C / (#tilesincore) overall.
+ //Power * 0.55 * (some value between 1.5 and 23) / 5
+ removed.set_temperature(removed.return_temperature() + ((device_energy * dynamic_heat_modifier) / THERMAL_RELEASE_MODIFIER))
+ //We can only emit so much heat, that being 57500
+ removed.set_temperature(max(0, min(removed.return_temperature(), 2500 * dynamic_heat_modifier)))
- if(produces_gas)
- env.merge(removed)
- air_update_turf()
+ //Calculate how much gas to release
+ //Varies based on power and gas content
+ removed.adjust_moles(/datum/gas/plasma, max((device_energy * dynamic_heat_modifier) / PLASMA_RELEASE_MODIFIER, 0))
+ //Varies based on power, gas content, and heat
+ removed.adjust_moles(/datum/gas/oxygen, max(((device_energy + removed.return_temperature() * dynamic_heat_modifier) - T0C) / OXYGEN_RELEASE_MODIFIER, 0))
- for(var/mob/living/carbon/human/l in fov_viewers(HALLUCINATION_RANGE(power), src)) // If they can see it without mesons on. Bad on them.
+ if(produces_gas)
+ env.merge(removed)
+ air_update_turf()
+
+ /*********
+ END CITADEL CHANGES
+ *********/
+
+ //Makes em go mad and accumulate rads.
+ 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)))
- l.hallucination += power * config_hallucination_power * D
- l.hallucination = clamp(0, 200, l.hallucination)
-
+ 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)))
var/rads = (power / 10) * sqrt( 1 / max(get_dist(l, src),1) )
l.rad_act(rads)
- power -= ((power/500)**3) * powerloss_inhibitor
+ //Transitions between one function and another, one we use for the fast inital startup, the other is used to prevent errors with fusion temperatures.
+ //Use of the second function improves the power gain imparted by using co2
+ if(power_changes)
+ power = max(power - min(((power/500)**3) * powerloss_inhibitor, power * 0.83 * powerloss_inhibitor),0)
+ //After this point power is lowered
+ //This wraps around to the begining of the function
+ //Handle high power zaps/anomaly generation
+ if(power > POWER_PENALTY_THRESHOLD || damage > damage_penalty_point) //If the power is above 5000 or if the damage is above 550
+ var/range = 4
+ zap_cutoff = 1500
+ if(removed && removed.return_pressure() > 0 && removed.return_temperature() > 0)
+ //You may be able to freeze the zapstate of the engine with good planning, we'll see
+ zap_cutoff = clamp(3000 - (power * (removed.total_moles()) / 10) / removed.return_temperature(), 350, 3000)//If the core is cold, it's easier to jump, ditto if there are a lot of mols
+ //We should always be able to zap our way out of the default enclosure
+ //See supermatter_zap() for more details
+ range = clamp(power / removed.return_pressure() * 10, 2, 7)
+ var/flags = ZAP_SUPERMATTER_FLAGS
+ var/zap_count = 0
+ //Deal with power zaps
+ switch(power)
+ if(POWER_PENALTY_THRESHOLD to SEVERE_POWER_PENALTY_THRESHOLD)
+ zap_icon = DEFAULT_ZAP_ICON_STATE
+ zap_count = 2
+ if(SEVERE_POWER_PENALTY_THRESHOLD to CRITICAL_POWER_PENALTY_THRESHOLD)
+ zap_icon = SLIGHTLY_CHARGED_ZAP_ICON_STATE
+ //Uncaps the zap damage, it's maxed by the input power
+ //Objects take damage now
+ flags |= (ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE)
+ zap_count = 3
+ if(CRITICAL_POWER_PENALTY_THRESHOLD to INFINITY)
+ zap_icon = OVER_9000_ZAP_ICON_STATE
+ //It'll stun more now, and damage will hit harder, gloves are no garentee.
+ //Machines go boom
+ flags |= (ZAP_MOB_STUN | ZAP_MACHINE_EXPLOSIVE | ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE)
+ zap_count = 4
+ //Now we deal with damage shit
+ if (damage > damage_penalty_point && prob(20))
+ zap_count += 1
- if(power > POWER_PENALTY_THRESHOLD || damage > damage_penalty_point)
+ if(zap_count >= 1)
+ playsound(src.loc, 'sound/weapons/emitter2.ogg', 100, TRUE, extrarange = 10)
+ for(var/i in 1 to zap_count)
+ supermatter_zap(src, range, clamp(power*2, 4000, 20000), flags)
- if(power > POWER_PENALTY_THRESHOLD)
- playsound(src.loc, 'sound/weapons/emitter2.ogg', 100, 1, extrarange = 10)
- supermatter_zap(src, 5, min(power*2, 20000))
- supermatter_zap(src, 5, min(power*2, 20000))
- if(power > SEVERE_POWER_PENALTY_THRESHOLD)
- supermatter_zap(src, 5, min(power*2, 20000))
- if(power > CRITICAL_POWER_PENALTY_THRESHOLD)
- supermatter_zap(src, 5, min(power*2, 20000))
- else if (damage > damage_penalty_point && prob(20))
- playsound(src.loc, 'sound/weapons/emitter2.ogg', 100, 1, extrarange = 10)
- supermatter_zap(src, 5, clamp(power*2, 4000, 20000))
-
- if(prob(15) && power > POWER_PENALTY_THRESHOLD)
- supermatter_pull(src, power/750)
if(prob(5))
supermatter_anomaly_gen(src, FLUX_ANOMALY, rand(5, 10))
if(power > SEVERE_POWER_PENALTY_THRESHOLD && prob(5) || prob(1))
supermatter_anomaly_gen(src, GRAVITATIONAL_ANOMALY, rand(5, 10))
- if(power > SEVERE_POWER_PENALTY_THRESHOLD && prob(2) || prob(0.3) && power > POWER_PENALTY_THRESHOLD)
+ if((power > SEVERE_POWER_PENALTY_THRESHOLD && prob(2)) || (prob(0.3) && power > POWER_PENALTY_THRESHOLD))
supermatter_anomaly_gen(src, PYRO_ANOMALY, rand(5, 10))
+
+ if(prob(15))
+ supermatter_pull(loc, min(power/850, 3))//850, 1700, 2550
+
+ //Tells the engi team to get their butt in gear
if(damage > warning_point) // while the core is still damaged and it's still worth noting its status
if((REALTIMEOFDAY - lastwarning) / 10 >= WARNING_DELAY)
alarm()
+ //Oh shit it's bad, time to freak out
if(damage > emergency_point)
radio.talk_into(src, "[emergency_alert] Integrity: [get_integrity()]%", common_channel)
lastwarning = REALTIMEOFDAY
@@ -493,7 +736,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
if(combined_gas > MOLE_PENALTY_THRESHOLD)
radio.talk_into(src, "Warning: Critical coolant mass reached.", engineering_channel)
-
+ //Boom (Mind blown)
if(damage > explosion_point)
countdown()
@@ -503,16 +746,17 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
var/turf/L = loc
if(!istype(L))
return FALSE
- if(!istype(Proj.firer, /obj/machinery/power/emitter))
+ if(!istype(Proj.firer, /obj/machinery/power/emitter) && power_changes)
investigate_log("has been hit by [Proj] fired by [key_name(Proj.firer)]", INVESTIGATE_SUPERMATTER)
if(Proj.flag != "bullet")
- power += Proj.damage * config_bullet_energy
- if(!has_been_powered)
- investigate_log("has been powered for the first time.", INVESTIGATE_SUPERMATTER)
- message_admins("[src] has been powered for the first time [ADMIN_JMP(src)].")
- has_been_powered = TRUE
+ if(power_changes) //This needs to be here I swear
+ power += Proj.damage * bullet_energy
+ if(!has_been_powered)
+ investigate_log("has been powered for the first time.", INVESTIGATE_SUPERMATTER)
+ message_admins("[src] has been powered for the first time [ADMIN_JMP(src)].")
+ has_been_powered = TRUE
else if(takes_damage)
- matter_power += Proj.damage * config_bullet_energy
+ matter_power += Proj.damage * bullet_energy
return BULLET_ACT_HIT
/obj/machinery/power/supermatter_crystal/singularity_act()
@@ -529,15 +773,15 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
/obj/machinery/power/supermatter_crystal/blob_act(obj/structure/blob/B)
if(B && !isspaceturf(loc)) //does nothing in space
- playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1)
+ playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, TRUE)
damage += B.obj_integrity * 0.5 //take damage equal to 50% of remaining blob health before it tried to eat us
if(B.obj_integrity > 100)
B.visible_message("\The [B] strikes at \the [src] and flinches away!",\
- "You hear a loud crack as you are washed with a wave of heat.")
+ "You hear a loud crack as you are washed with a wave of heat.")
B.take_damage(100, BURN)
else
B.visible_message("\The [B] strikes at \the [src] and rapidly flashes to ash.",\
- "You hear a loud crack as you are washed with a wave of heat.")
+ "You hear a loud crack as you are washed with a wave of heat.")
Consume(B)
/obj/machinery/power/supermatter_crystal/attack_tk(mob/user)
@@ -546,11 +790,10 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
log_game("[key_name(C)] has been disintegrated by a telekenetic grab on a supermatter crystal.")
to_chat(C, "That was a really dense idea.")
C.visible_message("A bright flare of radiation is seen from [C]'s head, shortly before you hear a sickening sizzling!")
+ C.ghostize()
var/obj/item/organ/brain/rip_u = locate(/obj/item/organ/brain) in C.internal_organs
- rip_u.Remove()
+ rip_u.Remove(C)
qdel(rip_u)
- return
- return ..()
/obj/machinery/power/supermatter_crystal/attack_paw(mob/user)
dust_mob(user, cause = "monkey attack")
@@ -559,9 +802,14 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
dust_mob(user, cause = "alien attack")
/obj/machinery/power/supermatter_crystal/attack_animal(mob/living/simple_animal/S)
+ var/murder
+ if(!S.melee_damage_upper && !S.melee_damage_lower)
+ murder = S.friendly_verb_continuous
+ else
+ murder = S.attack_verb_continuous
dust_mob(S, \
- "[S] unwisely [S.attack_verb_continuous] [src], and [S.p_their()] body burns brilliantly before flashing into ash!", \
- "You unwisely [S.attack_verb_simple] [src], and your vision glows brightly as your body crumbles to dust. Oops.", \
+ "[S] unwisely [murder] [src], and [S.p_their()] body burns brilliantly before flashing into ash!", \
+ "You unwisely touch [src], and your vision glows brightly as your body crumbles to dust. Oops.", \
"simple animal attack")
/obj/machinery/power/supermatter_crystal/attack_robot(mob/user)
@@ -571,65 +819,103 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
/obj/machinery/power/supermatter_crystal/attack_ai(mob/user)
return
-/obj/machinery/power/supermatter_crystal/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/machinery/power/supermatter_crystal/on_attack_hand(mob/living/user)
. = ..()
- if(.)
- return
dust_mob(user, cause = "hand")
/obj/machinery/power/supermatter_crystal/proc/dust_mob(mob/living/nom, vis_msg, mob_msg, cause)
- if(nom.incorporeal_move || nom.status_flags & GODMODE)
+ if(nom.incorporeal_move || nom.status_flags & GODMODE) //try to keep supermatter sliver's + hemostat's dust conditions in sync with this too
return
if(!vis_msg)
- vis_msg = "[nom] reaches out and touches [src], inducing a resonance... [nom.p_their()] body starts to glow and bursts into flames before flashing into ash"
+ vis_msg = "[nom] reaches out and touches [src], inducing a resonance... [nom.p_their()] body starts to glow and burst into flames before flashing into dust!"
if(!mob_msg)
mob_msg = "You reach out and touch [src]. Everything starts burning and all you can hear is ringing. Your last thought is \"That was not a wise decision.\""
if(!cause)
cause = "contact"
- nom.visible_message(vis_msg, mob_msg, "You hear an unearthly noise as a wave of heat washes over you.")
+ nom.visible_message(vis_msg, mob_msg, "You hear an unearthly noise as a wave of heat washes over you.")
investigate_log("has been attacked ([cause]) by [key_name(nom)]", INVESTIGATE_SUPERMATTER)
- playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1)
+ playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, TRUE)
Consume(nom)
/obj/machinery/power/supermatter_crystal/attackby(obj/item/W, mob/living/user, params)
if(!istype(W) || (W.item_flags & ABSTRACT) || !istype(user))
return
- if (istype(W, /obj/item/melee/roastingstick))
+ if(istype(W, /obj/item/melee/roastingstick))
return ..()
+ if(istype(W, /obj/item/clothing/mask/cigarette))
+ var/obj/item/clothing/mask/cigarette/cig = W
+ var/clumsy = HAS_TRAIT(user, TRAIT_CLUMSY)
+ if(clumsy)
+ var/which_hand = BODY_ZONE_L_ARM
+ if(!(user.active_hand_index % 2))
+ which_hand = BODY_ZONE_R_ARM
+ var/obj/item/bodypart/dust_arm = user.get_bodypart(which_hand)
+ dust_arm.dismember()
+ user.visible_message("The [W] flashes out of existence on contact with \the [src], resonating with a horrible sound...",\
+ "Oops! The [W] flashes out of existence on contact with \the [src], taking your arm with it! That was clumsy of you!")
+ playsound(src, 'sound/effects/supermatter.ogg', 150, TRUE)
+ Consume(dust_arm)
+ qdel(W)
+ return
+ if(cig.lit || user.a_intent != INTENT_HELP)
+ user.visible_message("A hideous sound echoes as [W] is ashed out on contact with \the [src]. That didn't seem like a good idea...")
+ playsound(src, 'sound/effects/supermatter.ogg', 150, TRUE)
+ Consume(W)
+ radiation_pulse(src, 150, 4)
+ return ..()
+ else
+ cig.light()
+ user.visible_message("As [user] lights \their [W] on \the [src], silence fills the room...",\
+ "Time seems to slow to a crawl as you touch \the [src] with \the [W].\n\The [W] flashes alight with an eerie energy as you nonchalantly lift your hand away from \the [src]. Damn.")
+ playsound(src, 'sound/effects/supermatter.ogg', 50, TRUE)
+ radiation_pulse(src, 50, 3)
+ return
if(istype(W, /obj/item/scalpel/supermatter))
+ var/obj/item/scalpel/supermatter/scalpel = W
to_chat(user, "You carefully begin to scrape \the [src] with \the [W]...")
if(W.use_tool(src, user, 60, volume=100))
- to_chat(user, "You extract a sliver from \the [src]. \The [src] begins to react violently!")
- new /obj/item/nuke_core/supermatter_sliver(drop_location())
- matter_power += 200
+ if (scalpel.usesLeft)
+ to_chat(user, "You extract a sliver from \the [src]. \The [src] begins to react violently!")
+ new /obj/item/nuke_core/supermatter_sliver(drop_location())
+ matter_power += 800
+ scalpel.usesLeft--
+ if (!scalpel.usesLeft)
+ to_chat(user, "A tiny piece of \the [W] falls off, rendering it useless!")
+ else
+ to_chat(user, "You fail to extract a sliver from \The [src]! \the [W] isn't sharp enough anymore.")
else if(user.dropItemToGround(W))
user.visible_message("As [user] touches \the [src] with \a [W], silence fills the room...",\
"You touch \the [src] with \the [W], and everything suddenly goes silent.\n\The [W] flashes into dust as you flinch away from \the [src].",\
- "Everything suddenly goes silent.")
+ "Everything suddenly goes silent.")
investigate_log("has been attacked ([W]) by [key_name(user)]", INVESTIGATE_SUPERMATTER)
Consume(W)
- playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1)
+ playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, TRUE)
radiation_pulse(src, 150, 4)
+ else if(Adjacent(user)) //if the item is stuck to the person, kill the person too instead of eating just the item.
+ var/vis_msg = "[user] reaches out and touches [src] with [W], inducing a resonance... [W] starts to glow briefly before the light continues up to [user]'s body. [user.p_they(TRUE)] bursts into flames before flashing into dust!"
+ var/mob_msg = "You reach out and touch [src] with [W]. Everything starts burning and all you can hear is ringing. Your last thought is \"That was not a wise decision.\""
+ dust_mob(user, vis_msg, mob_msg)
+
/obj/machinery/power/supermatter_crystal/wrench_act(mob/user, obj/item/tool)
+ ..()
if (moveable)
default_unfasten_wrench(user, tool, time = 20)
return TRUE
/obj/machinery/power/supermatter_crystal/Bumped(atom/movable/AM)
if(isliving(AM))
- AM.visible_message("\The [AM] slams into \the [src] inducing a resonance... [AM.p_their()] body starts to glow and catch flame before flashing into ash.",\
+ AM.visible_message("\The [AM] slams into \the [src] inducing a resonance... [AM.p_their()] body starts to glow and burst into flames before flashing into dust!",\
"You slam into \the [src] as your ears are filled with unearthly ringing. Your last thought is \"Oh, fuck.\"",\
- "You hear an unearthly noise as a wave of heat washes over you.")
+ "You hear an unearthly noise as a wave of heat washes over you.")
else if(isobj(AM) && !iseffect(AM))
AM.visible_message("\The [AM] smacks into \the [src] and rapidly flashes to ash.", null,\
- "You hear a loud crack as you are washed with a wave of heat.")
+ "You hear a loud crack as you are washed with a wave of heat.")
else
return
- playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1)
-
+ playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, TRUE)
Consume(AM)
/obj/machinery/power/supermatter_crystal/intercept_zImpact(atom/movable/AM, levels)
@@ -645,7 +931,8 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
message_admins("[src] has consumed [key_name_admin(user)] [ADMIN_JMP(src)].")
investigate_log("has consumed [key_name(user)].", INVESTIGATE_SUPERMATTER)
user.dust(force = TRUE)
- matter_power += 200
+ if(power_changes)
+ matter_power += 200
else if(istype(AM, /obj/singularity))
return
else if(isobj(AM))
@@ -656,19 +943,29 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
message_admins("[src] has consumed [AM], [suspicion] [ADMIN_JMP(src)].")
investigate_log("has consumed [AM] - [suspicion].", INVESTIGATE_SUPERMATTER)
qdel(AM)
- if(!iseffect(AM))
+ if(!iseffect(AM) && power_changes)
matter_power += 200
//Some poor sod got eaten, go ahead and irradiate people nearby.
radiation_pulse(src, 3000, 2, TRUE)
- var/list/viewers = fov_viewers(world.view, src)
for(var/mob/living/L in range(10))
investigate_log("has irradiated [key_name(L)] after consuming [AM].", INVESTIGATE_SUPERMATTER)
+ var/list/viewers = fov_viewers(world.view, src)
if(L in viewers)
L.show_message("As \the [src] slowly stops resonating, you find your skin covered in new radiation burns.", MSG_VISUAL,\
"The unearthly ringing subsides and you notice you have new radiation burns.", MSG_AUDIBLE)
else
- L.show_message("You hear an unearthly ringing and notice your skin is covered in fresh radiation burns.", MSG_AUDIBLE)
+ L.show_message("You hear an unearthly ringing and notice your skin is covered in fresh radiation burns.", MSG_AUDIBLE)
+
+/obj/machinery/power/supermatter_crystal/proc/consume_turf(turf/T)
+ var/oldtype = T.type
+ var/turf/newT = T.ScrapeAway()
+ if(newT.type == oldtype)
+ return
+ playsound(T, 'sound/effects/supermatter.ogg', 50, 1)
+ T.visible_message("[T] smacks into [src] and rapidly flashes to ash.",\
+ "You hear a loud crack as you are washed with a wave of heat.")
+ CALCULATE_ADJACENT_TURFS(T)
//Do not blow up our internal radio
/obj/machinery/power/supermatter_crystal/contents_explosion(severity, target)
@@ -685,6 +982,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
anchored = FALSE
gasefficency = 0.125
explosion_power = 12
+ layer = ABOVE_MOB_LAYER
moveable = TRUE
/obj/machinery/power/supermatter_crystal/shard/engine
@@ -699,6 +997,8 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
name = "anchored supermatter shard"
takes_damage = FALSE
produces_gas = FALSE
+ power_changes = FALSE
+ processes = FALSE //SHUT IT DOWN
moveable = FALSE
anchored = TRUE
@@ -707,101 +1007,183 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
base_icon_state = "darkmatter"
icon_state = "darkmatter"
-/obj/machinery/power/supermatter_crystal/proc/supermatter_pull(turf/center, pull_range = 10)
- playsound(src.loc, 'sound/weapons/marauder.ogg', 100, 1, extrarange = 7)
- for(var/atom/P in orange(pull_range,center))
- if(ismovable(P))
- var/atom/movable/pulled_object = P
- if(ishuman(P))
- var/mob/living/carbon/human/H = P
- H.apply_effect(40, EFFECT_KNOCKDOWN, 0)
- if(pulled_object && !pulled_object.anchored && !ishuman(P))
- step_towards(pulled_object,center)
- step_towards(pulled_object,center)
- step_towards(pulled_object,center)
- step_towards(pulled_object,center)
+/obj/machinery/power/supermatter_crystal/proc/supermatter_pull(turf/center, pull_range = 3)
+ playsound(center, 'sound/weapons/marauder.ogg', 100, TRUE, extrarange = pull_range - world.view)
+ for(var/atom/movable/P in orange(pull_range,center))
+ if((P.anchored || P.move_resist >= MOVE_FORCE_EXTREMELY_STRONG)) //move resist memes.
+ if(istype(P, /obj/structure/closet))
+ var/obj/structure/closet/toggle = P
+ toggle.open()
+ continue
+ if(ismob(P))
+ var/mob/M = P
+ if(M.mob_negates_gravity())
+ continue //You can't pull someone nailed to the deck
+ step_towards(P,center)
/obj/machinery/power/supermatter_crystal/proc/supermatter_anomaly_gen(turf/anomalycenter, type = FLUX_ANOMALY, anomalyrange = 5)
var/turf/L = pick(orange(anomalyrange, anomalycenter))
if(L)
switch(type)
if(FLUX_ANOMALY)
- var/obj/effect/anomaly/flux/A = new(L, 300)
+ var/obj/effect/anomaly/flux/A = new(L, 300, FALSE)
A.explosive = FALSE
if(GRAVITATIONAL_ANOMALY)
- new /obj/effect/anomaly/grav(L, 250)
+ new /obj/effect/anomaly/grav(L, 250, FALSE)
if(PYRO_ANOMALY)
- new /obj/effect/anomaly/pyro(L, 200)
+ new /obj/effect/anomaly/pyro(L, 200, FALSE)
-/obj/machinery/power/supermatter_crystal/proc/supermatter_zap(atom/zapstart, range = 3, power)
- . = zapstart.dir
- if(power < 1000)
+/obj/machinery/power/supermatter_crystal/proc/supermatter_zap(atom/zapstart = src, range = 5, zap_str = 4000, zap_flags = ZAP_SUPERMATTER_FLAGS, list/targets_hit = list())
+ if(QDELETED(zapstart))
return
+ . = zapstart.dir
+ //If the strength of the zap decays past the cutoff, we stop
+ if(zap_str < zap_cutoff)
+ return
+ var/atom/target
+ var/target_type = LOWEST
+ var/list/arctargets = list()
+ //Making a new copy so additons further down the recursion do not mess with other arcs
+ //Lets put this ourself into the do not hit list, so we don't curve back to hit the same thing twice with one arc
+ for(var/test in oview(zapstart, range))
+ if(!(zap_flags & ZAP_ALLOW_DUPLICATES) && LAZYACCESS(targets_hit, test))
+ continue
- var/target_atom
- var/mob/living/target_mob
- var/obj/machinery/target_machine
- var/obj/structure/target_structure
- var/list/arctargetsmob = list()
- var/list/arctargetsmachine = list()
- var/list/arctargetsstructure = list()
+ if(istype(test, /obj/vehicle/ridden/bicycle/))
+ var/obj/vehicle/ridden/bicycle/bike = test
+ if(!(bike.obj_flags & BEING_SHOCKED) && bike.can_buckle)//God's not on our side cause he hates idiots.
+ if(target_type != BIKE)
+ arctargets = list()
+ arctargets += test
+ target_type = BIKE
- if(prob(20)) //let's not hit all the engineers with every beam and/or segment of the arc
- for(var/mob/living/Z in oview(zapstart, range+2))
- arctargetsmob += Z
- if(arctargetsmob.len)
- var/mob/living/H = pick(arctargetsmob)
- var/atom/A = H
- target_mob = H
- target_atom = A
+ if(target_type > COIL)
+ continue
- else
- for(var/obj/machinery/X in oview(zapstart, range+2))
- arctargetsmachine += X
- if(arctargetsmachine.len)
- var/obj/machinery/M = pick(arctargetsmachine)
- var/atom/A = M
- target_machine = M
- target_atom = A
+ if(istype(test, /obj/machinery/power/tesla_coil/))
+ var/obj/machinery/power/tesla_coil/coil = test
+ if(coil.anchored && !(coil.obj_flags & BEING_SHOCKED) && !coil.panel_open && prob(70))//Diversity of death
+ if(target_type != COIL)
+ arctargets = list()
+ arctargets += test
+ target_type = COIL
- else
- for(var/obj/structure/Y in oview(zapstart, range+2))
- arctargetsstructure += Y
- if(arctargetsstructure.len)
- var/obj/structure/O = pick(arctargetsstructure)
- var/atom/A = O
- target_structure = O
- target_atom = A
+ if(target_type > ROD)
+ continue
- if(target_atom)
- zapstart.Beam(target_atom, icon_state="nzcrentrs_power", time=5)
- var/zapdir = get_dir(zapstart, target_atom)
+ if(istype(test, /obj/machinery/power/grounding_rod/))
+ var/obj/machinery/power/grounding_rod/rod = test
+ //We're adding machine damaging effects, rods need to be surefire
+ if(rod.anchored && !rod.panel_open)
+ if(target_type != ROD)
+ arctargets = list()
+ arctargets += test
+ target_type = ROD
+
+ if(target_type > LIVING)
+ continue
+
+ if(istype(test, /mob/living/))
+ var/mob/living/alive = test
+ if(!(HAS_TRAIT(alive, TRAIT_TESLA_SHOCKIMMUNE)) && !(alive.flags_1 & SHOCKED_1) && alive.stat != DEAD && prob(20))//let's not hit all the engineers with every beam and/or segment of the arc
+ if(target_type != LIVING)
+ arctargets = list()
+ arctargets += test
+ target_type = LIVING
+
+ if(target_type > MACHINERY)
+ continue
+
+ if(istype(test, /obj/machinery/))
+ var/obj/machinery/machine = test
+ if(!(machine.obj_flags & BEING_SHOCKED) && prob(40))
+ if(target_type != MACHINERY)
+ arctargets = list()
+ arctargets += test
+ target_type = MACHINERY
+
+ if(target_type > OBJECT)
+ continue
+
+ if(istype(test, /obj/))
+ var/obj/object = test
+ if(!(object.obj_flags & BEING_SHOCKED))
+ if(target_type != OBJECT)
+ arctargets = list()
+ arctargets += test
+ target_type = OBJECT
+
+ if(arctargets.len)//Pick from our pool
+ target = pick(arctargets)
+
+ if(!QDELETED(target))//If we found something
+ //Do the animation to zap to it from here
+ if(!(zap_flags & ZAP_ALLOW_DUPLICATES))
+ LAZYSET(targets_hit, target, TRUE)
+ zapstart.Beam(target, icon_state=zap_icon, time=5)
+ var/zapdir = get_dir(zapstart, target)
if(zapdir)
. = zapdir
- if(target_mob)
- target_mob.electrocute_act(rand(5,10), "Supermatter Discharge Bolt", 1, SHOCK_NOSTUN)
- if(prob(15))
- supermatter_zap(target_mob, 5, power / 2)
- supermatter_zap(target_mob, 5, power / 2)
- else
- supermatter_zap(target_mob, 5, power / 1.5)
+ //Going boom should be rareish
+ if(prob(80))
+ zap_flags &= ~ZAP_MACHINE_EXPLOSIVE
+ if(target_type == COIL)
+ //In the best situation we can expect this to grow up to 2120kw before a delam/IT'S GONE TOO FAR FRED SHUT IT DOWN
+ //The formula for power gen is zap_str * zap_mod / 2 * capacitor rating, between 1 and 4
+ var/multi = 10
+ switch(power)//Between 7k and 9k it's 20, above that it's 40
+ if(SEVERE_POWER_PENALTY_THRESHOLD to CRITICAL_POWER_PENALTY_THRESHOLD)
+ multi = 20
+ if(CRITICAL_POWER_PENALTY_THRESHOLD to INFINITY)
+ multi = 40
+ target.zap_act(zap_str * multi, zap_flags, list())
+ zap_str /= 3 //Coils should take a lot out of the power of the zap
- else if(target_machine)
- if(prob(15))
- supermatter_zap(target_machine, 5, power / 2)
- supermatter_zap(target_machine, 5, power / 2)
- else
- supermatter_zap(target_machine, 5, power / 1.5)
+ else if(target_type == ROD)
+ //We can expect this to do very little, maybe shock the poor soul buckled to it, but that's all.
+ //This is one of our endpoints, if the bolt hits a grounding rod, it stops jumping
+ target.zap_act(zap_str, zap_flags, list())
+ return
+
+ else if(isliving(target))//If we got a fleshbag on our hands
+ var/mob/living/creature = target
+ creature.set_shocked()
+ addtimer(CALLBACK(creature, /mob/living/proc/reset_shocked), 10)
+ //3 shots a human with no resistance. 2 to crit, one to death. This is at at least 10000 power.
+ //There's no increase after that because the input power is effectivly capped at 10k
+ //Does 1.5 damage at the least
+ var/shock_damage = ((zap_flags & ZAP_MOB_DAMAGE) ? (power / 200) - 10 : rand(5,10))
+ creature.electrocute_act(shock_damage, "Supermatter Discharge Bolt", 1, ((zap_flags & ZAP_MOB_STUN) ? SHOCK_TESLA : SHOCK_NOSTUN))
+ zap_str /= 1.5 //Meatsacks are conductive, makes working in pairs more destructive
- else if(target_structure)
- if(prob(15))
- supermatter_zap(target_structure, 5, power / 2)
- supermatter_zap(target_structure, 5, power / 2)
else
- supermatter_zap(target_structure, 5, power / 1.5)
+ target.zap_act(zap_str, zap_flags, list())
+ zap_str /= 2 // worse then living things, better then coils
+ //This gotdamn variable is a boomer and keeps giving me problems
+ var/turf/T = get_turf(target)
+ var/pressure = 1
+ if(T && T.return_air())
+ pressure = max(1,T.return_air().return_pressure())
+ //We get our range with the strength of the zap and the pressure, the higher the former and the lower the latter the better
+ var/new_range = clamp(zap_str / pressure * 10, 2, 7)
+ var/zap_count = 1
+ if(prob(5))
+ zap_str -= (zap_str/10)
+ zap_count += 1
+ for(var/j in 1 to zap_count)
+ if(zap_count > 1)
+ targets_hit = targets_hit.Copy() //Pass by ref begone
+ supermatter_zap(target, new_range, zap_str, zap_flags, targets_hit)
#undef HALLUCINATION_RANGE
#undef GRAVITATIONAL_ANOMALY
#undef FLUX_ANOMALY
#undef PYRO_ANOMALY
+#undef BIKE
+#undef COIL
+#undef ROD
+#undef LIVING
+#undef MACHINERY
+#undef OBJECT
+#undef LOWEST
diff --git a/code/modules/projectiles/ammunition/ballistic/revolver.dm b/code/modules/projectiles/ammunition/ballistic/revolver.dm
index 693b258e3d..c13a3c953d 100644
--- a/code/modules/projectiles/ammunition/ballistic/revolver.dm
+++ b/code/modules/projectiles/ammunition/ballistic/revolver.dm
@@ -14,9 +14,13 @@
/obj/item/ammo_casing/a357/match
name = ".357 match bullet casing"
desc = "A .357 bullet casing, manufactured to exceedingly high standards."
- caliber = "357"
projectile_type = /obj/item/projectile/bullet/a357/match
+/obj/item/ammo_casing/a357/dumdum
+ name = ".357 DumDum bullet casing"
+ desc = "A .357 bullet casing. Usage of this ammunition will constitute a war crime in your area."
+ projectile_type = /obj/item/projectile/bullet/a357/dumdum
+
// 7.62x38mmR (Nagant Revolver)
/obj/item/ammo_casing/n762
@@ -68,4 +72,4 @@
/obj/item/ammo_casing/c38/dumdum
name = ".38 DumDum bullet casing"
desc = "A .38 DumDum bullet casing."
- projectile_type = /obj/item/projectile/bullet/c38/dumdum
\ No newline at end of file
+ projectile_type = /obj/item/projectile/bullet/c38/dumdum
diff --git a/code/modules/projectiles/boxes_magazines/_box_magazine.dm b/code/modules/projectiles/boxes_magazines/_box_magazine.dm
index 9ea030da99..78ca6e9280 100644
--- a/code/modules/projectiles/boxes_magazines/_box_magazine.dm
+++ b/code/modules/projectiles/boxes_magazines/_box_magazine.dm
@@ -20,6 +20,7 @@
var/caliber
var/multiload = 1
var/start_empty = 0
+ var/load_delay = 0 //how long do we take to load (deciseconds)
var/list/bullet_cost
var/list/base_cost// override this one as well if you override bullet_cost
@@ -75,12 +76,19 @@
return 1
/obj/item/ammo_box/attackby(obj/item/A, mob/user, params, silent = FALSE, replace_spent = 0)
+ if(INTERACTING_WITH(user, src) || INTERACTING_WITH(user, A))
+ to_chat(user, "You're already doing that!")
+ return FALSE
var/num_loaded = 0
if(!can_load(user))
return
if(istype(A, /obj/item/ammo_box))
var/obj/item/ammo_box/AM = A
for(var/obj/item/ammo_casing/AC in AM.stored_ammo)
+ if(load_delay || AM.load_delay)
+ var/loadtime = max(AM.load_delay, load_delay)
+ if(!do_after(user, loadtime, target = src))
+ return FALSE
var/did_load = give_round(AC, replace_spent)
if(did_load)
AM.stored_ammo -= AC
diff --git a/code/modules/projectiles/boxes_magazines/ammo_boxes.dm b/code/modules/projectiles/boxes_magazines/ammo_boxes.dm
index 987efc0404..8cd49bdf16 100644
--- a/code/modules/projectiles/boxes_magazines/ammo_boxes.dm
+++ b/code/modules/projectiles/boxes_magazines/ammo_boxes.dm
@@ -16,6 +16,11 @@
name = "speed loader (.357 AP)"
ammo_type = /obj/item/ammo_casing/a357/ap
+/obj/item/ammo_box/a357/dumdum
+ name = "speed loader (.357 DumDum)"
+ desc = "Designed to quickly reload revolvers. Usage of these rounds will constitute a war crime in your area."
+ ammo_type = /obj/item/ammo_casing/a357/dumdum
+
/obj/item/ammo_box/c38
name = "speed loader (.38 rubber)"
desc = "Designed to quickly reload revolvers."
@@ -144,10 +149,15 @@
icon = 'icons/obj/ammo.dmi'
icon_state = "shotgunclip"
caliber = "shotgun" // slapped in to allow shell mix n match
+ slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_POCKET
+ w_class = WEIGHT_CLASS_NORMAL
+ w_volume = ITEM_VOLUME_STRIPPER_CLIP
ammo_type = /obj/item/ammo_casing/shotgun
max_ammo = 4
var/pixeloffsetx = 4
start_empty = TRUE
+ multiload = FALSE
+ load_delay = 6 //6ds
/obj/item/ammo_box/shotgun/update_overlays()
. = ..()
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index ee073dbfcd..8cddd5d02f 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -62,7 +62,8 @@
var/no_pin_required = FALSE //whether the gun can be fired without a pin
var/obj/item/flashlight/gun_light
- var/can_flashlight = 0
+ var/can_flashlight = FALSE
+ var/gunlight_state = "flight"
var/obj/item/kitchen/knife/bayonet
var/mutable_appearance/knife_overlay
var/can_bayonet = FALSE
@@ -417,14 +418,7 @@
return
to_chat(user, "You attach \the [K] to the front of \the [src].")
bayonet = K
- var/state = "bayonet" //Generic state.
- if(bayonet.icon_state in icon_states('icons/obj/guns/bayonets.dmi')) //Snowflake state?
- state = bayonet.icon_state
- var/icon/bayonet_icons = 'icons/obj/guns/bayonets.dmi'
- knife_overlay = mutable_appearance(bayonet_icons, state)
- knife_overlay.pixel_x = knife_x_offset
- knife_overlay.pixel_y = knife_y_offset
- add_overlay(knife_overlay, TRUE)
+ update_icon()
else if(istype(I, /obj/item/screwdriver))
if(gun_light)
var/obj/item/flashlight/seclite/S = gun_light
@@ -439,8 +433,7 @@
var/obj/item/kitchen/knife/K = bayonet
K.forceMove(get_turf(user))
bayonet = null
- cut_overlay(knife_overlay, TRUE)
- knife_overlay = null
+ update_icon()
else
return ..()
@@ -468,22 +461,35 @@
set_light(gun_light.brightness_on, gun_light.flashlight_power, gun_light.light_color)
else
set_light(0)
- cut_overlays(flashlight_overlay, TRUE)
- var/state = "flight[gun_light.on? "_on":""]" //Generic state.
+ else
+ set_light(0)
+ update_icon()
+ for(var/X in actions)
+ var/datum/action/A = X
+ A.UpdateButtonIcon()
+
+/obj/item/gun/update_overlays()
+ . = ..()
+ if(gun_light)
+ var/mutable_appearance/flashlight_overlay
+ var/state = "[gunlight_state][gun_light.on? "_on":""]" //Generic state.
if(gun_light.icon_state in icon_states('icons/obj/guns/flashlights.dmi')) //Snowflake state?
state = gun_light.icon_state
flashlight_overlay = mutable_appearance('icons/obj/guns/flashlights.dmi', state)
flashlight_overlay.pixel_x = flight_x_offset
flashlight_overlay.pixel_y = flight_y_offset
- add_overlay(flashlight_overlay, TRUE)
- else
- set_light(0)
- cut_overlays(flashlight_overlay, TRUE)
- flashlight_overlay = null
- update_icon(TRUE)
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
+ . += flashlight_overlay
+
+ if(bayonet)
+ var/mutable_appearance/knife_overlay
+ var/state = "bayonet" //Generic state.
+ if(bayonet.icon_state in icon_states('icons/obj/guns/bayonets.dmi')) //Snowflake state?
+ state = bayonet.icon_state
+ var/icon/bayonet_icons = 'icons/obj/guns/bayonets.dmi'
+ knife_overlay = mutable_appearance(bayonet_icons, state)
+ knife_overlay.pixel_x = knife_x_offset
+ knife_overlay.pixel_y = knife_y_offset
+ . += knife_overlay
/obj/item/gun/item_action_slot_check(slot, mob/user, datum/action/A)
if(istype(A, /datum/action/item_action/toggle_scope_zoom) && slot != SLOT_HANDS)
diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm
index fa8099a257..1aefa51a51 100644
--- a/code/modules/projectiles/guns/ballistic.dm
+++ b/code/modules/projectiles/guns/ballistic.dm
@@ -53,6 +53,8 @@
..()
if (istype(A, /obj/item/ammo_box/magazine))
var/obj/item/ammo_box/magazine/AM = A
+ if(AM.load_delay && !do_after(user, AM.load_delay, target = src))
+ return FALSE
if (!magazine && istype(AM, mag_type))
if(user.transferItemToLoc(AM, src))
magazine = AM
diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm
index b31fd2d1e0..9210e66f22 100644
--- a/code/modules/projectiles/guns/ballistic/automatic.dm
+++ b/code/modules/projectiles/guns/ballistic/automatic.dm
@@ -18,13 +18,15 @@
/obj/item/gun/ballistic/automatic/proto/unrestricted
pin = /obj/item/firing_pin
-/obj/item/gun/ballistic/automatic/update_icon()
- ..()
+/obj/item/gun/ballistic/automatic/update_overlays()
+ . = ..()
if(automatic_burst_overlay)
if(!select)
- add_overlay("[initial(icon_state)]semi")
+ . += ("[initial(icon_state)]semi")
if(select == 1)
- add_overlay("[initial(icon_state)]burst")
+ . += "[initial(icon_state)]burst"
+
+/obj/item/gun/ballistic/automatic/update_icon_state()
icon_state = "[initial(icon_state)][magazine ? "-[magazine.max_ammo]" : ""][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]"
/obj/item/gun/ballistic/automatic/attackby(obj/item/A, mob/user, params)
@@ -115,8 +117,7 @@
. = ..()
empty_alarm()
-/obj/item/gun/ballistic/automatic/c20r/update_icon()
- ..()
+/obj/item/gun/ballistic/automatic/c20r/update_icon_state()
icon_state = "c20r[magazine ? "-[CEILING(get_ammo(0)/4, 1)*4]" : ""][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]"
/obj/item/gun/ballistic/automatic/wt550
@@ -141,9 +142,8 @@
. = ..()
spread = 0
-/obj/item/gun/ballistic/automatic/wt550/update_icon()
- ..()
- icon_state = "wt550[magazine ? "-[CEILING(( (get_ammo(FALSE) / magazine.max_ammo) * 20) /4, 1)*4]" : "-0"]" //Sprites only support up to 20.
+/obj/item/gun/ballistic/automatic/wt550/update_icon_state()
+ icon_state = "wt550[magazine ? "-[CEILING(((get_ammo(FALSE) / magazine.max_ammo) * 20) /4, 1)*4]" : "-0"]" //Sprites only support up to 20.
/obj/item/gun/ballistic/automatic/mini_uzi
name = "\improper Type U3 Uzi"
@@ -160,6 +160,7 @@
mag_type = /obj/item/ammo_box/magazine/m556
fire_sound = 'sound/weapons/gunshot_smg.ogg'
can_suppress = FALSE
+ automatic_burst_overlay = FALSE
var/obj/item/gun/ballistic/revolver/grenadelauncher/underbarrel
burst_size = 3
burst_shot_delay = 2
@@ -191,18 +192,19 @@
underbarrel.attackby(A, user, params)
else
..()
-/obj/item/gun/ballistic/automatic/m90/update_icon()
- ..()
- cut_overlays()
+/obj/item/gun/ballistic/automatic/m90/update_overlays()
+ . = ..()
switch(select)
if(0)
- add_overlay("[initial(icon_state)]semi")
+ . += "[initial(icon_state)]semi"
if(1)
- add_overlay("[initial(icon_state)]burst")
+ . += "[initial(icon_state)]burst"
if(2)
- add_overlay("[initial(icon_state)]gren")
+ . += "[initial(icon_state)]gren"
+
+/obj/item/gun/ballistic/automatic/m90/update_icon_state()
icon_state = "[initial(icon_state)][magazine ? "" : "-e"]"
- return
+
/obj/item/gun/ballistic/automatic/m90/burst_select()
var/mob/living/carbon/human/user = usr
switch(select)
@@ -257,6 +259,7 @@
weapon_weight = WEAPON_MEDIUM
mag_type = /obj/item/ammo_box/magazine/m12g
fire_sound = 'sound/weapons/gunshot.ogg'
+ automatic_burst_overlay = FALSE
can_suppress = FALSE
burst_size = 1
pin = /obj/item/firing_pin/implant/pindicate
@@ -269,10 +272,13 @@
. = ..()
update_icon()
-/obj/item/gun/ballistic/automatic/shotgun/bulldog/update_icon()
- cut_overlays()
+/obj/item/gun/ballistic/automatic/shotgun/bulldog/update_icon_state()
+ return
+
+/obj/item/gun/ballistic/automatic/shotgun/bulldog/update_overlays()
+ . = ..()
if(magazine)
- add_overlay("[magazine.icon_state]")
+ . += "[magazine.icon_state]"
icon_state = "bulldog[chambered ? "" : "-e"]"
/obj/item/gun/ballistic/automatic/shotgun/bulldog/afterattack()
@@ -298,6 +304,7 @@
burst_shot_delay = 1
spread = 7
pin = /obj/item/firing_pin/implant/pindicate
+ automatic_burst_overlay = FALSE
/obj/item/gun/ballistic/automatic/l6_saw/unrestricted
pin = /obj/item/firing_pin
@@ -316,7 +323,7 @@
playsound(user, 'sound/weapons/sawclose.ogg', 60, 1)
update_icon()
-/obj/item/gun/ballistic/automatic/l6_saw/update_icon()
+/obj/item/gun/ballistic/automatic/l6_saw/update_icon_state()
icon_state = "l6[cover_open ? "open" : "closed"][magazine ? CEILING(get_ammo(0)/12.5, 1)*25 : "-empty"][suppressed ? "-suppressed" : ""]"
item_state = "l6[cover_open ? "openmag" : "closedmag"]"
@@ -369,9 +376,10 @@
zoom_amt = 10 //Long range, enough to see in front of you, but no tiles behind you.
zoom_out_amt = 13
slot_flags = ITEM_SLOT_BACK
+ automatic_burst_overlay = FALSE
actions_types = list()
-/obj/item/gun/ballistic/automatic/sniper_rifle/update_icon()
+/obj/item/gun/ballistic/automatic/sniper_rifle/update_icon_state()
if(magazine)
icon_state = "sniper-mag"
else
@@ -397,9 +405,10 @@
can_suppress = TRUE
w_class = WEIGHT_CLASS_HUGE
slot_flags = ITEM_SLOT_BACK
+ automatic_burst_overlay = FALSE
actions_types = list()
-/obj/item/gun/ballistic/automatic/surplus/update_icon()
+/obj/item/gun/ballistic/automatic/surplus/update_icon_state()
if(magazine)
icon_state = "surplus"
else
@@ -413,6 +422,7 @@
icon_state = "oldrifle"
item_state = "arg"
mag_type = /obj/item/ammo_box/magazine/recharge
+ automatic_burst_overlay = FALSE
fire_delay = 2
can_suppress = FALSE
burst_size = 1
@@ -420,7 +430,5 @@
fire_sound = 'sound/weapons/laser.ogg'
casing_ejector = FALSE
-/obj/item/gun/ballistic/automatic/laser/update_icon()
- ..()
+/obj/item/gun/ballistic/automatic/laser/update_icon_state()
icon_state = "oldrifle[magazine ? "-[CEILING(get_ammo(0)/4, 1)*4]" : ""]"
- return
diff --git a/code/modules/projectiles/guns/ballistic/launchers.dm b/code/modules/projectiles/guns/ballistic/launchers.dm
index 004f78235a..9e03207888 100644
--- a/code/modules/projectiles/guns/ballistic/launchers.dm
+++ b/code/modules/projectiles/guns/ballistic/launchers.dm
@@ -42,8 +42,7 @@
actions_types = list()
casing_ejector = FALSE
-/obj/item/gun/ballistic/automatic/gyropistol/update_icon()
- ..()
+/obj/item/gun/ballistic/automatic/gyropistol/update_icon_state()
icon_state = "[initial(icon_state)][magazine ? "loaded" : ""]"
/obj/item/gun/ballistic/automatic/speargun
@@ -54,6 +53,7 @@
w_class = WEIGHT_CLASS_BULKY
force = 10
can_suppress = FALSE
+ automatic_burst_overlay = FALSE
mag_type = /obj/item/ammo_box/magazine/internal/speargun
fire_sound = 'sound/weapons/grenadelaunch.ogg'
burst_size = 1
@@ -62,8 +62,9 @@
actions_types = list()
casing_ejector = FALSE
-/obj/item/gun/ballistic/automatic/speargun/update_icon()
- return
+/obj/item/gun/ballistic/automatic/speargun/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/update_icon_blocker)
/obj/item/gun/ballistic/automatic/speargun/attack_self()
return
@@ -137,7 +138,7 @@
chamber_round()
update_icon()
-/obj/item/gun/ballistic/rocketlauncher/update_icon()
+/obj/item/gun/ballistic/rocketlauncher/update_icon_state()
icon_state = "[initial(icon_state)]-[chambered ? "1" : "0"]"
/obj/item/gun/ballistic/rocketlauncher/suicide_act(mob/living/user)
diff --git a/code/modules/projectiles/guns/ballistic/magweapon.dm b/code/modules/projectiles/guns/ballistic/magweapon.dm
index 74b8b210a7..4e27a73300 100644
--- a/code/modules/projectiles/guns/ballistic/magweapon.dm
+++ b/code/modules/projectiles/guns/ballistic/magweapon.dm
@@ -75,8 +75,7 @@
recoil = 2
weapon_weight = WEAPON_HEAVY
-/obj/item/gun/ballistic/automatic/magrifle/hyperburst/update_icon()
- ..()
+/obj/item/gun/ballistic/automatic/magrifle/hyperburst/update_icon_state()
icon_state = "hyperburst[magazine ? "-[get_ammo()]" : ""][chambered ? "" : "-e"]"
///magpistol///
@@ -92,12 +91,14 @@
fire_delay = 2
inaccuracy_modifier = 0.25
cell_type = /obj/item/stock_parts/cell/magnetic/pistol
+ automatic_burst_overlay = FALSE
-/obj/item/gun/ballistic/automatic/magrifle/pistol/update_icon()
- ..()
- cut_overlays()
+/obj/item/gun/ballistic/automatic/magrifle/pistol/update_overlays()
+ . = ..()
if(magazine)
- add_overlay("magpistol-magazine")
+ . += "magpistol-magazine"
+
+/obj/item/gun/ballistic/automatic/magrifle/pistol/update_icon_state()
icon_state = "[initial(icon_state)][chambered ? "" : "-e"]"
/obj/item/gun/ballistic/automatic/magrifle/pistol/nopin
diff --git a/code/modules/projectiles/guns/ballistic/pistol.dm b/code/modules/projectiles/guns/ballistic/pistol.dm
index cdaadb5c3b..e775fdc05a 100644
--- a/code/modules/projectiles/guns/ballistic/pistol.dm
+++ b/code/modules/projectiles/guns/ballistic/pistol.dm
@@ -8,12 +8,12 @@
burst_size = 1
fire_delay = 0
actions_types = list()
+ automatic_burst_overlay = FALSE
/obj/item/gun/ballistic/automatic/pistol/no_mag
spawnwithmagazine = FALSE
-/obj/item/gun/ballistic/automatic/pistol/update_icon()
- ..()
+/obj/item/gun/ballistic/automatic/pistol/update_icon_state()
icon_state = "[initial(icon_state)][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]"
/obj/item/gun/ballistic/automatic/pistol/suppressed/Initialize(mapload)
@@ -28,6 +28,7 @@
icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi'
icon_state = "cde"
can_unsuppress = TRUE
+ automatic_burst_overlay = FALSE
obj_flags = UNIQUE_RENAME
unique_reskin = list("Default" = "cde",
"N-99" = "n99",
@@ -38,20 +39,18 @@
"PX4 Storm" = "px4"
)
-/obj/item/gun/ballistic/automatic/pistol/modular/update_icon()
- ..()
+/obj/item/gun/ballistic/automatic/pistol/modular/update_icon_state()
if(current_skin)
icon_state = "[unique_reskin[current_skin]][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]"
else
icon_state = "[initial(icon_state)][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]"
+
+/obj/item/gun/ballistic/automatic/pistol/modular/update_overlays()
+ . = ..()
if(magazine && suppressed)
- cut_overlays()
- add_overlay("[unique_reskin[current_skin]]-magazine-sup") //Yes, this means the default iconstate can't have a magazine overlay
+ . += "[unique_reskin[current_skin]]-magazine-sup" //Yes, this means the default iconstate can't have a magazine overlay
else if (magazine)
- cut_overlays()
- add_overlay("[unique_reskin[current_skin]]-magazine")
- else
- cut_overlays()
+ . += "[unique_reskin[current_skin]]-magazine"
/obj/item/gun/ballistic/automatic/pistol/m1911
name = "\improper M1911"
@@ -77,14 +76,14 @@
force = 14
mag_type = /obj/item/ammo_box/magazine/m50
can_suppress = FALSE
+ automatic_burst_overlay = FALSE
-/obj/item/gun/ballistic/automatic/pistol/deagle/update_icon()
- ..()
+/obj/item/gun/ballistic/automatic/pistol/deagle/update_overlays()
+ . = ..()
if(magazine)
- cut_overlays()
- add_overlay("deagle_magazine")
- else
- cut_overlays()
+ . += "deagle_magazine"
+
+/obj/item/gun/ballistic/automatic/pistol/deagle/update_icon_state()
icon_state = "[initial(icon_state)][chambered ? "" : "-e"]"
/obj/item/gun/ballistic/automatic/pistol/deagle/gold
@@ -142,14 +141,14 @@
actions_types = list()
fire_sound = 'sound/weapons/blastcannon.ogg'
spread = 20 //damn thing has no rifling.
+ automatic_burst_overlay = FALSE
-/obj/item/gun/ballistic/automatic/pistol/antitank/update_icon()
- ..()
+/obj/item/gun/ballistic/automatic/pistol/antitank/update_overlays()
+ . = ..()
if(magazine)
- cut_overlays()
- add_overlay("atp-mag")
- else
- cut_overlays()
+ . += "atp-mag"
+
+/obj/item/gun/ballistic/automatic/pistol/antitank/update_icon_state()
icon_state = "[initial(icon_state)][chambered ? "" : "-e"]"
/obj/item/gun/ballistic/automatic/pistol/antitank/syndicate
diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm
index a5ed45dd48..6f1fb96af5 100644
--- a/code/modules/projectiles/guns/ballistic/revolver.dm
+++ b/code/modules/projectiles/guns/ballistic/revolver.dm
@@ -348,10 +348,10 @@
else
to_chat(user, "You need at least ten lengths of cable if you want to make a sling!")
-/obj/item/gun/ballistic/revolver/doublebarrel/improvised/update_icon()
- ..()
+/obj/item/gun/ballistic/revolver/doublebarrel/improvised/update_overlays()
+ . = ..()
if(slung)
- icon_state += "sling"
+ . += "[icon_state]sling"
/obj/item/gun/ballistic/revolver/doublebarrel/improvised/sawoff(mob/user)
. = ..()
diff --git a/code/modules/projectiles/guns/ballistic/shotgun.dm b/code/modules/projectiles/guns/ballistic/shotgun.dm
index 873b129c8f..ecf6e538b8 100644
--- a/code/modules/projectiles/guns/ballistic/shotgun.dm
+++ b/code/modules/projectiles/guns/ballistic/shotgun.dm
@@ -164,10 +164,10 @@
else
to_chat(user, "You need at least ten lengths of cable if you want to make a sling!")
-/obj/item/gun/ballistic/shotgun/boltaction/improvised/update_icon()
- ..()
+/obj/item/gun/ballistic/shotgun/boltaction/improvised/update_overlays()
+ . = ..()
if(slung)
- icon_state += "sling"
+ . += "[icon_state]sling"
/obj/item/gun/ballistic/shotgun/boltaction/enchanted
name = "enchanted bolt action rifle"
@@ -272,7 +272,7 @@
spread = 2
update_icon()
-/obj/item/gun/ballistic/shotgun/automatic/combat/compact/update_icon()
+/obj/item/gun/ballistic/shotgun/automatic/combat/compact/update_icon_state()
icon_state = "[current_skin ? unique_reskin[current_skin] : "cshotgun"][stock ? "" : "c"]"
//Dual Feed Shotgun
diff --git a/code/modules/projectiles/guns/ballistic/toy.dm b/code/modules/projectiles/guns/ballistic/toy.dm
index 1f66cfdf8a..e7f26670d4 100644
--- a/code/modules/projectiles/guns/ballistic/toy.dm
+++ b/code/modules/projectiles/guns/ballistic/toy.dm
@@ -27,9 +27,9 @@
burst_size = 1
fire_delay = 0
actions_types = list()
+ automatic_burst_overlay = FALSE
-/obj/item/gun/ballistic/automatic/toy/pistol/update_icon()
- ..()
+/obj/item/gun/ballistic/automatic/toy/pistol/update_icon_state()
icon_state = "[initial(icon_state)][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]"
/obj/item/gun/ballistic/automatic/toy/pistol/riot
diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm
index c2b821dfcf..17dcfa96e6 100644
--- a/code/modules/projectiles/guns/energy.dm
+++ b/code/modules/projectiles/guns/energy.dm
@@ -29,7 +29,6 @@
var/charge_sections = 4
ammo_x_offset = 2
var/shaded_charge = FALSE //if this gun uses a stateful charge bar for more detail
- var/old_ratio = 0 // stores the gun's previous ammo "ratio" to see if it needs an updated icon
var/selfcharge = EGUN_NO_SELFCHARGE // EGUN_SELFCHARGE if true, EGUN_SELFCHARGE_BORG drains the cyborg's cell to recharge its own
var/charge_tick = 0
var/charge_delay = 4
@@ -64,10 +63,20 @@
START_PROCESSING(SSobj, src)
update_icon()
+/obj/item/gun/energy/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/update_icon_updates_onmob)
+
/obj/item/gun/energy/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
+/obj/item/gun/energy/handle_atom_del(atom/A)
+ if(A == cell)
+ cell = null
+ update_icon()
+ return ..()
+
/obj/item/gun/energy/examine(mob/user)
. = ..()
if(!right_click_overridden)
@@ -226,46 +235,47 @@
#undef DECREMENT_OR_WRAP
#undef IS_VALID_INDEX
-/obj/item/gun/energy/update_icon(force_update)
- if(QDELETED(src))
+/obj/item/gun/energy/update_icon_state()
+ if(initial(item_state))
return
..()
+ var/ratio = get_charge_ratio()
+ var/new_item_state = ""
+ new_item_state = initial(icon_state)
+ if(modifystate)
+ var/obj/item/ammo_casing/energy/shot = ammo_type[current_firemode_index]
+ new_item_state += "[shot.select_name]"
+ new_item_state += "[ratio]"
+ item_state = new_item_state
+
+/obj/item/gun/energy/update_overlays()
+ . = ..()
+ if(QDELETED(src))
+ return
if(!automatic_charge_overlays)
return
- var/ratio = can_shoot() ? CEILING(clamp(cell.charge / cell.maxcharge, 0, 1) * charge_sections, 1) : 0
- // Sets the ratio to 0 if the gun doesn't have enough charge to fire, or if it's power cell is removed.
- // TG issues #5361 & #47908
- if(ratio == old_ratio && !force_update)
- return
- old_ratio = ratio
- cut_overlays()
- var/iconState = "[icon_state]_charge"
- var/itemState = null
- if(!initial(item_state))
- itemState = icon_state
+ var/overlay_icon_state = "[icon_state]_charge"
+ var/ratio = get_charge_ratio()
if (modifystate)
var/obj/item/ammo_casing/energy/shot = ammo_type[current_firemode_index]
- add_overlay("[icon_state]_[shot.select_name]")
- iconState += "_[shot.select_name]"
- if(itemState)
- itemState += "[shot.select_name]"
+ . += "[icon_state]_[shot.select_name]"
+ overlay_icon_state += "_[shot.select_name]"
if(ratio == 0)
- add_overlay("[icon_state]_empty")
+ . += "[icon_state]_empty"
else
if(!shaded_charge)
- var/mutable_appearance/charge_overlay = mutable_appearance(icon, iconState)
+ var/mutable_appearance/charge_overlay = mutable_appearance(icon, overlay_icon_state)
for(var/i = ratio, i >= 1, i--)
charge_overlay.pixel_x = ammo_x_offset * (i - 1)
charge_overlay.pixel_y = ammo_y_offset * (i - 1)
- add_overlay(charge_overlay)
+ . += charge_overlay
else
- add_overlay("[icon_state]_charge[ratio]")
- if(itemState)
- itemState += "[ratio]"
- item_state = itemState
- if(ismob(loc)) //forces inhands to update
- var/mob/M = loc
- M.update_inv_hands()
+ . += "[icon_state]_charge[ratio]"
+
+///Used by update_icon_state() and update_overlays()
+/obj/item/gun/energy/proc/get_charge_ratio()
+ return can_shoot() ? CEILING(clamp(cell.charge / cell.maxcharge, 0, 1) * charge_sections, 1) : 0
+ // Sets the ratio to 0 if the gun doesn't have enough charge to fire, or if its power cell is removed.
/obj/item/gun/energy/suicide_act(mob/living/user)
if (istype(user) && can_shoot() && can_trigger_gun(user) && user.get_bodypart(BODY_ZONE_HEAD))
diff --git a/code/modules/projectiles/guns/energy/dueling.dm b/code/modules/projectiles/guns/energy/dueling.dm
index 80bb269b21..04eff5afa9 100644
--- a/code/modules/projectiles/guns/energy/dueling.dm
+++ b/code/modules/projectiles/guns/energy/dueling.dm
@@ -207,12 +207,11 @@
to_chat(user,"You switch [src] setting to [setting] mode.")
update_icon()
-/obj/item/gun/energy/dueling/update_icon(force_update)
+/obj/item/gun/energy/dueling/update_overlays(force_update)
. = ..()
if(setting_overlay)
- cut_overlay(setting_overlay)
setting_overlay.icon_state = setting_iconstate()
- add_overlay(setting_overlay)
+ . += setting_overlay
/obj/item/gun/energy/dueling/Destroy()
if(duel)
@@ -363,8 +362,7 @@
STR.max_items = 2
STR.can_hold = typecacheof(/obj/item/gun/energy/dueling)
-/obj/item/storage/lockbox/dueling/update_icon()
- cut_overlays()
+/obj/item/storage/lockbox/dueling/update_icon_state()
var/locked = SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED)
if(locked)
icon_state = "medalbox+l"
diff --git a/code/modules/projectiles/guns/energy/energy_gun.dm b/code/modules/projectiles/guns/energy/energy_gun.dm
index 1b835d35a4..2c9794f391 100644
--- a/code/modules/projectiles/guns/energy/energy_gun.dm
+++ b/code/modules/projectiles/guns/energy/energy_gun.dm
@@ -19,17 +19,13 @@
cell_type = /obj/item/stock_parts/cell{charge = 600; maxcharge = 600}
ammo_x_offset = 2
charge_sections = 3
+ gunlight_state = "mini-light"
can_flashlight = 0 // Can't attach or detach the flashlight, and override it's icon update
/obj/item/gun/energy/e_gun/mini/Initialize()
gun_light = new /obj/item/flashlight/seclite(src)
return ..()
-/obj/item/gun/energy/e_gun/mini/update_icon()
- ..()
- if(gun_light && gun_light.on)
- add_overlay("mini-light")
-
/obj/item/gun/energy/e_gun/stun
name = "tactical energy gun"
desc = "Military issue energy gun, is able to fire stun rounds."
@@ -138,15 +134,15 @@
return
fail_chance = min(fail_chance + round(15/severity), 100)
-/obj/item/gun/energy/e_gun/nuclear/update_icon()
- ..()
+/obj/item/gun/energy/e_gun/nuclear/update_overlays()
+ . = ..()
if(crit_fail)
- add_overlay("[icon_state]_fail_3")
+ . += "[icon_state]_fail_3"
else
switch(fail_tick)
if(0)
- add_overlay("[icon_state]_fail_0")
+ . += "[icon_state]_fail_0"
if(1 to 150)
- add_overlay("[icon_state]_fail_1")
+ . += "[icon_state]_fail_1"
if(151 to INFINITY)
- add_overlay("[icon_state]_fail_2")
+ . += "[icon_state]_fail_2"
diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
index 0c723199a1..c1f47ccd1a 100644
--- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
+++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
@@ -46,13 +46,6 @@
range = 4
log_override = TRUE
-/obj/item/gun/energy/kinetic_accelerator/premiumka/update_icon()
- ..()
- if(!can_shoot())
- add_overlay("[icon_state]_empty")
- else
- cut_overlays()
-
/obj/item/gun/energy/kinetic_accelerator/getinaccuracy(mob/living/user, bonus_spread, stamloss)
var/old_fire_delay = fire_delay //It's pretty irrelevant tbh but whatever.
fire_delay = overheat_time
@@ -186,12 +179,10 @@
update_icon()
overheat = FALSE
-/obj/item/gun/energy/kinetic_accelerator/update_icon()
- ..()
+/obj/item/gun/energy/kinetic_accelerator/update_overlays()
+ . = ..()
if(!can_shoot())
- add_overlay("[icon_state]_empty")
- else
- cut_overlays()
+ . += "[icon_state]_empty"
//Casing
/obj/item/ammo_casing/energy/kinetic
diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm
index 20e847326e..19ca42022d 100644
--- a/code/modules/projectiles/guns/energy/special.dm
+++ b/code/modules/projectiles/guns/energy/special.dm
@@ -34,11 +34,11 @@
pin = null
ammo_x_offset = 1
-/obj/item/gun/energy/decloner/update_icon()
+/obj/item/gun/energy/decloner/update_overlays()
..()
var/obj/item/ammo_casing/energy/shot = ammo_type[current_firemode_index]
if(!QDELETED(cell) && (cell.charge > shot.e_cost))
- add_overlay("decloner_spin")
+ . += "decloner_spin"
/obj/item/gun/energy/floragun
name = "floral somatoray"
@@ -134,9 +134,10 @@
tool_behaviour = TOOL_WELDER
toolspeed = 0.7 //plasmacutters can be used as welders, and are faster than standard welders
-/obj/item/gun/energy/plasmacutter/Initialize()
+/obj/item/gun/energy/plasmacutter/ComponentInitialize()
. = ..()
AddComponent(/datum/component/butchering, 25, 105, 0, 'sound/weapons/plasma_cutter.ogg')
+ AddElement(/datum/element/update_icon_blocker)
/obj/item/gun/energy/plasmacutter/examine(mob/user)
. = ..()
@@ -166,9 +167,6 @@
/obj/item/gun/energy/plasmacutter/use(amount)
return cell.use(amount * 100)
-/obj/item/gun/energy/plasmacutter/update_icon()
- return
-
/obj/item/gun/energy/plasmacutter/adv
name = "advanced plasma cutter"
icon_state = "adv_plasmacutter"
@@ -183,11 +181,12 @@
icon_state = "wormhole_projector"
pin = null
inaccuracy_modifier = 0.25
+ automatic_charge_overlays = FALSE
var/obj/effect/portal/p_blue
var/obj/effect/portal/p_orange
var/atmos_link = FALSE
-/obj/item/gun/energy/wormhole_projector/update_icon()
+/obj/item/gun/energy/wormhole_projector/update_icon_state()
icon_state = "[initial(icon_state)][current_firemode_index]"
item_state = icon_state
@@ -256,8 +255,9 @@
can_charge = 0
use_cyborg_cell = 1
-/obj/item/gun/energy/printer/update_icon()
- return
+/obj/item/gun/energy/printer/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/update_icon_blocker)
/obj/item/gun/energy/printer/emp_act()
return
@@ -321,14 +321,14 @@
inaccuracy_modifier = 0.25
cell_type = /obj/item/stock_parts/cell/super
ammo_type = list(/obj/item/ammo_casing/energy/emitter)
+ automatic_charge_overlays = FALSE
-/obj/item/gun/energy/emitter/update_icon()
- ..()
+/obj/item/gun/energy/emitter/update_icon_state()
var/obj/item/ammo_casing/energy/shot = ammo_type[current_firemode_index]
if(!QDELETED(cell) && (cell.charge > shot.e_cost))
- add_overlay("emitter_carbine_empty")
+ icon_state = "emitter_carbine_empty"
else
- add_overlay("emitter_carbine")
+ icon_state = "emitter_carbine"
//the pickle ray
/obj/item/gun/energy/pickle_gun
diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm
index fd09aa7f9d..5e250d44e2 100644
--- a/code/modules/projectiles/guns/misc/beam_rifle.dm
+++ b/code/modules/projectiles/guns/misc/beam_rifle.dm
@@ -35,6 +35,7 @@
slowdown = 1
item_flags = NO_MAT_REDEMPTION | SLOWS_WHILE_IN_HAND | NEEDS_PERMIT
pin = null
+ automatic_charge_overlays = FALSE
var/aiming = FALSE
var/aiming_time = 14
var/aiming_time_fire_threshold = 5
@@ -152,13 +153,13 @@
current_zoom_x = 0
current_zoom_y = 0
-/obj/item/gun/energy/beam_rifle/update_icon()
- cut_overlays()
+/obj/item/gun/energy/beam_rifle/update_overlays()
+ . = ..()
var/obj/item/ammo_casing/energy/primary_ammo = ammo_type[1]
if(!QDELETED(cell) && (cell.charge > primary_ammo.e_cost))
- add_overlay(charged_overlay)
+ . += charged_overlay
else
- add_overlay(drained_overlay)
+ . += drained_overlay
/obj/item/gun/energy/beam_rifle/attack_self(mob/user)
if(!structure_piercing)
diff --git a/code/modules/projectiles/guns/misc/blastcannon.dm b/code/modules/projectiles/guns/misc/blastcannon.dm
index 1c8d519ba8..60b7565333 100644
--- a/code/modules/projectiles/guns/misc/blastcannon.dm
+++ b/code/modules/projectiles/guns/misc/blastcannon.dm
@@ -41,18 +41,16 @@
user.put_in_hands(bomb)
user.visible_message("[user] detaches [bomb] from [src].")
bomb = null
+ name = initial(name)
+ desc = initial(desc)
update_icon()
return ..()
-/obj/item/gun/blastcannon/update_icon()
+/obj/item/gun/blastcannon/update_icon_state()
if(bomb)
icon_state = icon_state_loaded
- name = "blast cannon"
- desc = "A makeshift device used to concentrate a bomb's blast energy to a narrow wave."
else
icon_state = initial(icon_state)
- name = initial(name)
- desc = initial(desc)
/obj/item/gun/blastcannon/attackby(obj/O, mob/user)
if(istype(O, /obj/item/transfer_valve))
@@ -65,6 +63,8 @@
return FALSE
user.visible_message("[user] attaches [T] to [src]!")
bomb = T
+ name = "blast cannon"
+ desc = "A makeshift device used to concentrate a bomb's blast energy to a narrow wave."
update_icon()
return TRUE
return ..()
diff --git a/code/modules/projectiles/projectile/bullets/revolver.dm b/code/modules/projectiles/projectile/bullets/revolver.dm
index 95d43ba1ce..ec3cadc31a 100644
--- a/code/modules/projectiles/projectile/bullets/revolver.dm
+++ b/code/modules/projectiles/projectile/bullets/revolver.dm
@@ -126,4 +126,15 @@
ricochet_auto_aim_angle = 50
ricochet_auto_aim_range = 6
ricochet_incidence_leeway = 80
- ricochet_decay_chance = 1
\ No newline at end of file
+ ricochet_decay_chance = 1
+
+/obj/item/projectile/bullet/a357/dumdum
+ name = ".357 DumDum bullet" // the warcrime bullet
+ damage = 40
+ armour_penetration = -20
+ wound_bonus = 45
+ bare_wound_bonus = 45
+ sharpness = SHARP_EDGED
+ embedding = list(embed_chance=90, fall_chance=2, jostle_chance=5, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=5, jostle_pain_mult=6, rip_time=10)
+ wound_falloff_tile = -1
+ embed_falloff_tile = -5
diff --git a/code/modules/projectiles/projectile/special/plasma.dm b/code/modules/projectiles/projectile/special/plasma.dm
index 33559fa92c..77509cb574 100644
--- a/code/modules/projectiles/projectile/special/plasma.dm
+++ b/code/modules/projectiles/projectile/special/plasma.dm
@@ -2,7 +2,7 @@
name = "plasma blast"
icon_state = "plasmacutter"
damage_type = BRUTE
- damage = 20
+ damage = 10
range = 4
dismemberment = 20
impact_effect_type = /obj/effect/temp_visual/impact_effect/purple_laser
@@ -32,12 +32,12 @@
return BULLET_ACT_FORCE_PIERCE
/obj/item/projectile/plasma/adv
- damage = 28
+ damage = 14
range = 5
mine_range = 5
/obj/item/projectile/plasma/adv/mech
- damage = 40
+ damage = 20
range = 9
mine_range = 3
@@ -52,4 +52,4 @@
dismemberment = 0
damage = 10
range = 4
- mine_range = 0
\ No newline at end of file
+ mine_range = 0
diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm
index c2662a8342..c489edf88e 100644
--- a/code/modules/reagents/chemistry/holder.dm
+++ b/code/modules/reagents/chemistry/holder.dm
@@ -1165,3 +1165,9 @@
random_reagents += R
var/picked_reagent = pick(random_reagents)
return picked_reagent
+
+/proc/get_chem_id(chem_name)
+ for(var/X in GLOB.chemical_reagents_list)
+ var/datum/reagent/R = GLOB.chemical_reagents_list[X]
+ if(ckey(chem_name) == ckey(lowertext(R.name)))
+ return X
diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm
index 207325e1b3..32ac7cecba 100644
--- a/code/modules/reagents/chemistry/machinery/chem_master.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_master.dm
@@ -1,5 +1,3 @@
-#define PILL_STYLE_COUNT 22 //Update this if you add more pill icons or you die
-#define RANDOM_PILL_STYLE 22 //Dont change this one though
/obj/machinery/chem_master
name = "ChemMaster 3000"
diff --git a/code/modules/reagents/chemistry/machinery/smoke_machine.dm b/code/modules/reagents/chemistry/machinery/smoke_machine.dm
index a539897c9d..d22523c4b8 100644
--- a/code/modules/reagents/chemistry/machinery/smoke_machine.dm
+++ b/code/modules/reagents/chemistry/machinery/smoke_machine.dm
@@ -36,6 +36,14 @@
for(var/obj/item/stock_parts/matter_bin/B in component_parts)
reagents.maximum_volume += REAGENTS_BASE_VOLUME * B.rating
+/obj/machinery/smoke_machine/ComponentInitialize()
+ . = ..()
+ AddComponent(/datum/component/simple_rotation, ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS, null, CALLBACK(src, .proc/can_be_rotated))
+ AddComponent(/datum/component/plumbing/simple_demand) //this SURELY CANT' LEAD TO BAD THINGS HAPPENING.
+
+/obj/machinery/smoke_machine/proc/can_be_rotated(mob/user, rotation_type)
+ return !anchored
+
/obj/machinery/smoke_machine/update_icon_state()
if((!is_operational()) || (!on) || (reagents.total_volume == 0))
if (panel_open)
diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm
index a85ac8b085..672127cb11 100644
--- a/code/modules/reagents/chemistry/reagents.dm
+++ b/code/modules/reagents/chemistry/reagents.dm
@@ -8,6 +8,7 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
if (length(initial(R.name)))
.[ckey(initial(R.name))] = t
+
//Various reagents
//Toxin & acid reagents
//Hydroponics stuff
@@ -52,6 +53,14 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
var/metabolizing = FALSE
var/chemical_flags // See fermi/readme.dm REAGENT_DEAD_PROCESS, REAGENT_DONOTSPLIT, REAGENT_ONLYINVERSE, REAGENT_ONMOBMERGE, REAGENT_INVISIBLE, REAGENT_FORCEONNEW, REAGENT_SNEAKYNAME
var/value = REAGENT_VALUE_NONE //How much does it sell for in cargo?
+ var/datum/material/material //are we made of material?
+
+/datum/reagent/New()
+ . = ..()
+
+ if(material)
+ material = SSmaterials.GetMaterialRef(material)
+
/datum/reagent/Destroy() // This should only be called by the holder, so it's already handled clearing its references
. = ..()
@@ -220,4 +229,3 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
bloodsuckerdatum.handle_eat_human_food(disgust, blood_puke, force)
if(blood_change)
bloodsuckerdatum.AddBloodVolume(blood_change)
-
diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm
index a6e78ae98c..18203f1a4c 100644
--- a/code/modules/reagents/chemistry/reagents/food_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm
@@ -132,8 +132,8 @@
"You're covered in boiling oil!")
M.emote("scream")
playsound(M, 'sound/machines/fryer/deep_fryer_emerge.ogg', 25, TRUE)
- var/oil_damage = max((holder.chem_temp / fry_temperature) * 0.33,1) //Damage taken per unit
- M.adjustFireLoss(oil_damage * max(reac_volume,20)) //Damage caps at 20
+ var/oil_damage = min((holder.chem_temp / fry_temperature) * 0.33,1) //Damage taken per unit
+ M.adjustFireLoss(oil_damage * min(reac_volume,20)) //Damage caps at 20
else
..()
return TRUE
diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
index 8bb34c0a82..37010cbbb5 100644
--- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
@@ -515,12 +515,13 @@
overdose_threshold = 30
pH = 2
value = REAGENT_VALUE_UNCOMMON
+ var/healing = 0.5
/datum/reagent/medicine/omnizine/on_mob_life(mob/living/carbon/M)
- M.adjustToxLoss(-0.5*REM, 0)
- M.adjustOxyLoss(-0.5*REM, 0)
- M.adjustBruteLoss(-0.5*REM, 0)
- M.adjustFireLoss(-0.5*REM, 0)
+ M.adjustToxLoss(-healing*REM, 0)
+ M.adjustOxyLoss(-healing*REM, 0)
+ M.adjustBruteLoss(-healing*REM, 0)
+ M.adjustFireLoss(-healing*REM, 0)
..()
. = 1
@@ -532,6 +533,12 @@
..()
. = 1
+/datum/reagent/medicine/omnizine/protozine
+ name = "Protozine"
+ description = "A less environmentally friendly and somewhat weaker variant of omnizine."
+ color = "#d8c7b7"
+ healing = 0.2
+
/datum/reagent/medicine/calomel
name = "Calomel"
description = "Quickly purges the body of all chemicals. Toxin damage is dealt if the patient is in good condition."
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index b6de7b2eab..5c01fd8cf6 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -313,6 +313,13 @@
metabolization_rate = 45 * REAGENTS_METABOLISM
. = 1
+/datum/reagent/water/hollowwater
+ name = "Hollow Water"
+ description = "An ubiquitous chemical substance that is composed of hydrogen and oxygen, but it looks kinda hollow."
+ color = "#88878777"
+ taste_description = "emptyiness"
+
+
/datum/reagent/water/holywater
name = "Holy Water"
description = "Water blessed by some deity."
@@ -883,7 +890,7 @@
if(istype(O, /obj/item/stack/sheet/metal))
var/obj/item/stack/sheet/metal/M = O
reac_volume = min(reac_volume, M.amount)
- new/obj/item/stack/tile/bronze(get_turf(M), reac_volume)
+ new/obj/item/stack/sheet/bronze(get_turf(M), reac_volume)
M.use(reac_volume)
/datum/reagent/nitrogen
@@ -950,6 +957,7 @@
color = "#1C1300" // rgb: 30, 20, 0
taste_description = "sour chalk"
pH = 5
+ material = /datum/material/diamond
/datum/reagent/carbon/reaction_turf(turf/T, reac_volume)
if(!isspaceturf(T))
@@ -1072,6 +1080,7 @@
pH = 6
overdose_threshold = 30
color = "#c2391d"
+ material = /datum/material/iron
/datum/reagent/iron/on_mob_life(mob/living/carbon/C)
if((HAS_TRAIT(C, TRAIT_NOMARROW)))
@@ -1103,6 +1112,7 @@
reagent_state = SOLID
color = "#F7C430" // rgb: 247, 196, 48
taste_description = "expensive metal"
+ material = /datum/material/gold
/datum/reagent/silver
name = "Silver"
@@ -1110,6 +1120,7 @@
reagent_state = SOLID
color = "#D0D0D0" // rgb: 208, 208, 208
taste_description = "expensive yet reasonable metal"
+ material = /datum/material/silver
/datum/reagent/silver/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
if(M.has_bane(BANE_SILVER))
@@ -1123,6 +1134,7 @@
color = "#B8B8C0" // rgb: 184, 184, 192
taste_description = "the inside of a reactor"
pH = 4
+ material = /datum/material/uranium
/datum/reagent/uranium/on_mob_life(mob/living/carbon/M)
M.apply_effect(1/M.metabolism_efficiency,EFFECT_IRRADIATE,0)
@@ -1144,6 +1156,7 @@
taste_description = "fizzling blue"
pH = 12
value = REAGENT_VALUE_RARE
+ material = /datum/material/bluespace
/datum/reagent/bluespace/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
if(method == TOUCH || method == VAPOR)
@@ -1182,6 +1195,7 @@
color = "#A8A8A8" // rgb: 168, 168, 168
taste_mult = 0
pH = 10
+ material = /datum/material/glass
/datum/reagent/fuel
name = "Welding fuel"
@@ -2206,6 +2220,66 @@
color = "#f7685e"
metabolization_rate = REAGENTS_METABOLISM * 0.25
+/datum/reagent/wittel
+ name = "Wittel"
+ description = "An extremely rare metallic-white substance only found on demon-class planets."
+ color = "#FFFFFF" // rgb: 255, 255, 255
+ taste_mult = 0 // oderless and tasteless
+
+/datum/reagent/metalgen
+ name = "Metalgen"
+ data = list("material"=null)
+ description = "A purple metal morphic liquid, said to impose it's metallic properties on whatever it touches."
+ color = "#b000aa"
+ taste_mult = 0 // oderless and tasteless
+ var/applied_material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR
+ var/minumum_material_amount = 100
+
+/datum/reagent/metalgen/reaction_obj(obj/O, volume)
+ metal_morph(O)
+ return
+
+/datum/reagent/metalgen/reaction_turf(turf/T, volume)
+ metal_morph(T)
+ return
+
+///turn an object into a special material
+/datum/reagent/metalgen/proc/metal_morph(atom/A)
+ var/metal_ref = data["material"]
+ if(!metal_ref)
+ return
+ var/metal_amount = 0
+
+ for(var/B in A.custom_materials) //list with what they're made of
+ metal_amount += A.custom_materials[B]
+
+ if(!metal_amount)
+ metal_amount = minumum_material_amount //some stuff doesn't have materials at all. To still give them properties, we give them a material. Basically doesnt exist
+
+ var/list/metal_dat = list()
+ metal_dat[metal_ref] = metal_amount //if we pass the list directly, byond turns metal_ref into "metal_ref" kjewrg8fwcyvf
+
+ A.material_flags = applied_material_flags
+ A.set_custom_materials(metal_dat)
+
+/datum/reagent/gravitum
+ name = "Gravitum"
+ description = "A rare kind of null fluid, capable of temporalily removing all weight of whatever it touches." //i dont even
+ color = "#050096" // rgb: 5, 0, 150
+ taste_mult = 0 // oderless and tasteless
+ metabolization_rate = 0.1 * REAGENTS_METABOLISM //20 times as long, so it's actually viable to use
+ var/time_multiplier = 1 MINUTES //1 minute per unit of gravitum on objects. Seems overpowered, but the whole thing is very niche
+
+/datum/reagent/gravitum/reaction_obj(obj/O, volume)
+ O.AddElement(/datum/element/forced_gravity, 0)
+
+ addtimer(CALLBACK(O, .proc/_RemoveElement, /datum/element/forced_gravity, 0), volume * time_multiplier)
+
+/datum/reagent/gravitum/on_mob_add(mob/living/L)
+ L.AddElement(/datum/element/forced_gravity, 0) //0 is the gravity, and in this case weightless
+
+/datum/reagent/gravitum/on_mob_end_metabolize(mob/living/L)
+ L.RemoveElement(/datum/element/forced_gravity, 0)
//body bluids
/datum/reagent/consumable/semen
@@ -2218,6 +2292,7 @@
color = "#FFFFFF" // rgb: 255, 255, 255
can_synth = FALSE
nutriment_factor = 0.5 * REAGENTS_METABOLISM
+ var/decal_path = /obj/effect/decal/cleanable/semen
/datum/reagent/consumable/semen/reaction_turf(turf/T, reac_volume)
if(!istype(T))
@@ -2227,7 +2302,7 @@
var/obj/effect/decal/cleanable/semen/S = locate() in T
if(!S)
- S = new(T)
+ S = new decal_path(T)
if(data["blood_DNA"])
S.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"]))
@@ -2251,51 +2326,20 @@
blood_DNA |= S.blood_DNA
return ..()
-/datum/reagent/consumable/femcum
+/datum/reagent/consumable/semen/femcum
name = "Female Ejaculate"
description = "Vaginal lubricant found in most mammals and other animals of similar nature. Where you found this is your own business."
taste_description = "something with a tang" // wew coders who haven't eaten out a girl.
- taste_mult = 2
- data = list("donor"=null,"viruses"=null,"donor_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null)
- reagent_state = LIQUID
color = "#AAAAAA77"
- can_synth = FALSE
- nutriment_factor = 0.5 * REAGENTS_METABOLISM
+ decal_path = /obj/effect/decal/cleanable/semen/femcum
-/obj/effect/decal/cleanable/femcum
+/obj/effect/decal/cleanable/semen/femcum
name = "female ejaculate"
- desc = null
- gender = PLURAL
- density = 0
- layer = ABOVE_NORMAL_TURF_LAYER
- icon = 'icons/obj/genitals/effects.dmi'
icon_state = "fem1"
random_icon_states = list("fem1", "fem2", "fem3", "fem4")
blood_state = null
bloodiness = null
-/obj/effect/decal/cleanable/femcum/Initialize(mapload)
- . = ..()
- dir = GLOB.cardinals
- add_blood_DNA(list("Non-human DNA" = "A+"))
-
-/obj/effect/decal/cleanable/femcum/replace_decal(obj/effect/decal/cleanable/femcum/F)
- if(F.blood_DNA)
- blood_DNA |= F.blood_DNA
- return ..()
-
-/datum/reagent/consumable/femcum/reaction_turf(turf/T, reac_volume)
- if(!istype(T))
- return
- if(reac_volume < 10)
- return
-
- var/obj/effect/decal/cleanable/femcum/S = locate() in T
- if(!S)
- S = new(T)
- if(data["blood_DNA"])
- S.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"]))
-
/datum/reagent/determination
name = "Determination"
description = "For when you need to push on a little more. Do NOT allow near plants."
@@ -2331,6 +2375,32 @@
M.adjustStaminaLoss(-0.25*REM) // the more wounds, the more stamina regen
..()
+datum/reagent/eldritch
+ name = "Eldritch Essence"
+ description = "Strange liquid that defies the laws of physics"
+ taste_description = "Ag'hsj'saje'sh"
+ color = "#1f8016"
+
+/datum/reagent/eldritch/on_mob_life(mob/living/carbon/M)
+ if(IS_HERETIC(M))
+ M.drowsyness = max(M.drowsyness-5, 0)
+ M.AdjustAllImmobility(-40, FALSE)
+ M.adjustStaminaLoss(-15, FALSE)
+ M.adjustToxLoss(-3, FALSE)
+ M.adjustOxyLoss(-3, FALSE)
+ M.adjustBruteLoss(-3, FALSE)
+ M.adjustFireLoss(-3, FALSE)
+ if(ishuman(M) && M.blood_volume < BLOOD_VOLUME_NORMAL)
+ M.blood_volume += 3
+ else
+ M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3, 150)
+ M.adjustToxLoss(2, FALSE)
+ M.adjustFireLoss(2, FALSE)
+ M.adjustOxyLoss(2, FALSE)
+ M.adjustBruteLoss(2, FALSE)
+ holder.remove_reagent(type, 1)
+ return TRUE
+
/datum/reagent/cellulose
name = "Cellulose Fibers"
description = "A crystaline polydextrose polymer, plants swear by this stuff."
@@ -2338,6 +2408,7 @@
color = "#E6E6DA"
taste_mult = 0
+
/datum/reagent/hairball
name = "Hairball"
description = "A bundle of keratinous bits and fibers, not easily digestible."
diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
index 8dca028b4a..07934d9880 100644
--- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
@@ -64,6 +64,7 @@
toxpwr = 3
pH = 4
value = REAGENT_VALUE_RARE //sheets are worth more
+ material = /datum/material/plasma
/datum/reagent/toxin/plasma/on_mob_life(mob/living/carbon/C)
if(holder.has_reagent(/datum/reagent/medicine/epinephrine))
diff --git a/code/modules/reagents/chemistry/recipes/medicine.dm b/code/modules/reagents/chemistry/recipes/medicine.dm
index bb9a951cac..9e0c78d2e6 100644
--- a/code/modules/reagents/chemistry/recipes/medicine.dm
+++ b/code/modules/reagents/chemistry/recipes/medicine.dm
@@ -219,6 +219,12 @@
results = list(/datum/reagent/medicine/strange_reagent = 3)
required_reagents = list(/datum/reagent/medicine/omnizine = 1, /datum/reagent/water/holywater = 1, /datum/reagent/toxin/mutagen = 1)
+/datum/chemical_reaction/strange_reagent/alt
+ name = "Strange Reagent"
+ id = /datum/reagent/medicine/strange_reagent
+ results = list(/datum/reagent/medicine/strange_reagent = 2)
+ required_reagents = list(/datum/reagent/medicine/omnizine/protozine = 1, /datum/reagent/water/holywater = 1, /datum/reagent/toxin/mutagen = 1)
+
/datum/chemical_reaction/mannitol
name = "Mannitol"
id = /datum/reagent/medicine/mannitol
@@ -345,4 +351,20 @@
/datum/chemical_reaction/medmesh/on_reaction(datum/reagents/holder, created_volume)
var/location = get_turf(holder.my_atom)
for(var/i = 1, i <= created_volume, i++)
- new /obj/item/stack/medical/mesh/advanced(location)
\ No newline at end of file
+ new /obj/item/stack/medical/mesh/advanced(location)
+
+/datum/chemical_reaction/suture
+ required_reagents = list(/datum/reagent/cellulose = 2, /datum/reagent/medicine/styptic_powder = 2)
+
+/datum/chemical_reaction/suture/on_reaction(datum/reagents/holder, created_volume)
+ var/location = get_turf(holder.my_atom)
+ for(var/i = 1, i <= created_volume, i++)
+ new /obj/item/stack/medical/suture/(location)
+
+/datum/chemical_reaction/mesh
+ required_reagents = list(/datum/reagent/cellulose = 2, /datum/reagent/medicine/silver_sulfadiazine = 2)
+
+/datum/chemical_reaction/mesh/on_reaction(datum/reagents/holder, created_volume)
+ var/location = get_turf(holder.my_atom)
+ for(var/i = 1, i <= created_volume, i++)
+ new /obj/item/stack/medical/mesh/(location)
diff --git a/code/modules/reagents/chemistry/recipes/others.dm b/code/modules/reagents/chemistry/recipes/others.dm
index 09b7eabbc1..92861a94ed 100644
--- a/code/modules/reagents/chemistry/recipes/others.dm
+++ b/code/modules/reagents/chemistry/recipes/others.dm
@@ -1,3 +1,34 @@
+/datum/chemical_reaction/metalgen
+ name = "metalgen"
+ id = /datum/reagent/metalgen
+ required_reagents = list(/datum/reagent/wittel = 1, /datum/reagent/bluespace = 1, /datum/reagent/toxin/mutagen = 1)
+ results = list(/datum/reagent/metalgen = 1)
+
+/datum/chemical_reaction/metalgen_imprint
+ name = "metalgen imprint"
+ id = /datum/reagent/metalgen
+ required_reagents = list(/datum/reagent/metalgen = 1, /datum/reagent/liquid_dark_matter = 1)
+ results = list(/datum/reagent/metalgen = 1)
+
+/datum/chemical_reaction/holywater
+ name = "Holy Water"
+ id = /datum/reagent/water/holywater
+ results = list(/datum/reagent/water/holywater = 1)
+ required_reagents = list(/datum/reagent/water/hollowwater = 1)
+ required_catalysts = list(/datum/reagent/water/holywater = 1)
+
+/datum/chemical_reaction/metalgen_imprint/on_reaction(datum/reagents/holder, created_volume)
+ var/datum/reagent/metalgen/MM = holder.get_reagent(/datum/reagent/metalgen)
+ for(var/datum/reagent/R in holder.reagent_list)
+ if(R.material && R.volume >= 40)
+ MM.data["material"] = R.material
+ holder.remove_reagent(R.type, 40)
+
+/datum/chemical_reaction/gravitum
+ name = "gravitum"
+ id = /datum/reagent/gravitum
+ required_reagents = list(/datum/reagent/wittel = 1, /datum/reagent/sorium = 10)
+ results = list(/datum/reagent/gravitum = 10)
/datum/chemical_reaction/sterilizine
name = "Sterilizine"
@@ -711,7 +742,7 @@
/datum/chemical_reaction/slime_extractification/on_reaction(datum/reagents/holder, created_volume)
var/location = get_turf(holder.my_atom)
new /obj/item/slime_extract/grey(location)
-
+
// Liquid Carpets
/datum/chemical_reaction/carpet
diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm
index 9b25a80680..926ed27854 100644
--- a/code/modules/reagents/reagent_containers/spray.dm
+++ b/code/modules/reagents/reagent_containers/spray.dm
@@ -19,6 +19,10 @@
var/stream_range = 1 //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.
var/spray_delay = 3 //The amount of sleep() delay between each chempuff step.
+ /// Last world.time of spray
+ var/last_spray = 0
+ /// Spray cooldown
+ var/spray_cooldown = CLICK_CD_MELEE
var/can_fill_from_container = TRUE
amount_per_transfer_from_this = 5
volume = 250
@@ -27,8 +31,6 @@
/obj/item/reagent_containers/spray/afterattack(atom/A, mob/user)
. = ..()
- if(!user.CheckActionCooldown(CLICK_CD_MELEE))
- return
if(istype(A, /obj/structure/sink) || istype(A, /obj/structure/janitorialcart) || istype(A, /obj/machinery/hydroponics))
return
@@ -49,7 +51,8 @@
to_chat(user, "[src] is empty!")
return
- spray(A)
+ if(!spray(A))
+ return
playsound(src.loc, 'sound/effects/spray2.ogg', 50, 1, -6)
user.last_action = world.time
@@ -64,10 +67,10 @@
if(reagents.has_reagent(/datum/reagent/lube))
message_admins("[ADMIN_LOOKUPFLW(user)] fired Space lube from \a [src] at [ADMIN_VERBOSEJMP(T)].")
log_game("[key_name(user)] fired Space lube from \a [src] at [AREACOORD(T)].")
- return
-
/obj/item/reagent_containers/spray/proc/spray(atom/A)
+ if((last_spray + spray_cooldown) > world.time)
+ return
var/range = clamp(get_dist(src, A), 1, current_range)
var/obj/effect/decal/chempuff/D = new /obj/effect/decal/chempuff(get_turf(src))
D.create_reagents(amount_per_transfer_from_this, NONE, NO_REAGENTS_VALUE)
@@ -79,10 +82,11 @@
reagents.trans_to(D, amount_per_transfer_from_this, 1/range)
D.color = mix_color_from_reagents(D.reagents.reagent_list)
var/wait_step = max(round(2+ spray_delay * INVERSE(range)), 2)
- do_spray(A, wait_step, D, range, puff_reagent_left)
+ last_spray = world.time
+ INVOKE_ASYNC(src, .proc/do_spray, A, wait_step, D, range, puff_reagent_left)
+ return TRUE
/obj/item/reagent_containers/spray/proc/do_spray(atom/A, wait_step, obj/effect/decal/chempuff/D, range, puff_reagent_left)
- set waitfor = FALSE
var/range_left = range
for(var/i=0, i[user.name] [anchored ? "fasten" : "unfasten"] [src]", \
+ "You [anchored ? "fasten" : "unfasten"] [src]")
+ var/datum/component/plumbing/CP = GetComponent(/datum/component/plumbing)
+ if(anchored)
+ CP.enable()
+ else
+ CP.disable()
+
+/obj/structure/reagent_dispensers/plumbed/ComponentInitialize()
+ AddComponent(/datum/component/plumbing/simple_supply)
+
+/obj/structure/reagent_dispensers/plumbed/storage
+ name = "stationairy storage tank"
+ icon_state = "tank_stationairy"
+ reagent_id = null //start empty
+
+/obj/structure/reagent_dispensers/plumbed/storage/ComponentInitialize()
+ AddComponent(/datum/component/plumbing/tank)
+
//////////////
//Fuel Tanks//
//////////////
@@ -271,5 +304,3 @@
icon_state = "bluekeg"
reagent_id = /datum/reagent/consumable/ethanol/neurotoxin
tank_volume = 100 //2.5x less than the other kegs because it's harder to get
-
-
diff --git a/code/modules/research/designs/machine_desings/machine_designs_medical.dm b/code/modules/research/designs/machine_desings/machine_designs_medical.dm
index 329fb7bf6e..84a3ed10d5 100644
--- a/code/modules/research/designs/machine_desings/machine_designs_medical.dm
+++ b/code/modules/research/designs/machine_desings/machine_designs_medical.dm
@@ -105,3 +105,11 @@
build_path = /obj/item/circuitboard/machine/bloodbankgen
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
category = list ("Medical Machinery")
+
+/datum/design/board/medipen_refiller
+ name = "Machine Design (Medipen Refiller)"
+ desc = "The circuit board for a Medipen Refiller."
+ id = "medipen_refiller"
+ build_path = /obj/item/circuitboard/machine/medipen_refiller
+ category = list ("Medical Machinery")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
diff --git a/code/modules/research/designs/machine_desings/machine_designs_service.dm b/code/modules/research/designs/machine_desings/machine_designs_service.dm
index 5cbff1c66a..af4f650793 100644
--- a/code/modules/research/designs/machine_desings/machine_designs_service.dm
+++ b/code/modules/research/designs/machine_desings/machine_designs_service.dm
@@ -81,6 +81,14 @@
category = list ("Hydroponics Machinery")
departmental_flags = DEPARTMENTAL_FLAG_SERVICE
+/datum/design/board/hydroponics/auto
+ name = "Machine Design (Automatic Hydroponics Tray Board)"
+ desc = "The circuit board for an automatic hydroponics tray. GIVE ME THE PLANT, CAPTAIN."
+ id = "autohydrotray"
+ build_path = /obj/machinery/hydroponics/constructable/automagic
+ category = list ("Hydroponics Machinery")
+ departmental_flags = DEPARTMENTAL_FLAG_SERVICE | DEPARTMENTAL_FLAG_MEDICAL
+
/datum/design/board/monkey_recycler
name = "Machine Design (Monkey Recycler Board)"
desc = "The circuit board for a monkey recycler."
diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm
index e1e55f3476..0a9fce2e67 100644
--- a/code/modules/research/designs/medical_designs.dm
+++ b/code/modules/research/designs/medical_designs.dm
@@ -961,3 +961,158 @@
build_path = /obj/item/bodypart/r_arm/robot/surplus_upgraded
category = list("Medical Designs")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
+
+
+/datum/design/acclimator
+ name = "Plumbing Acclimator"
+ desc = "A heating and cooling device for pipes!"
+ id = "acclimator"
+ build_type = PROTOLATHE
+ materials = list(/datum/material/iron = 1000, /datum/material/glass = 500)
+ construction_time = 15
+ build_path = /obj/machinery/plumbing/acclimator
+ category = list("Misc","Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
+
+/datum/design/disposer
+ name = "Plumbing Disposer"
+ desc = "Using the power of Science, dissolves reagents into nothing (almost)."
+ id = "disposer"
+ build_type = PROTOLATHE
+ materials = list(/datum/material/iron = 500, /datum/material/glass = 100)
+ construction_time = 15
+ build_path = /obj/machinery/plumbing/disposer
+ category = list("Misc","Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
+
+/datum/design/plumb_filter
+ name = "Plumbing Filter"
+ desc = "Filters out chemicals by their NTDB ID."
+ id = "plumb_filter"
+ build_type = PROTOLATHE
+ materials = list(/datum/material/iron = 1000, /datum/material/glass = 500)
+ construction_time = 15
+ build_path = /obj/machinery/plumbing/filter
+ category = list("Misc","Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
+
+/datum/design/plumb_synth
+ name = "Plumbing Synthesizer"
+ desc = "Using standard mass-energy dynamic autoconverters, generates reagents from power and puts them in a pipe."
+ id = "plumb_synth"
+ build_type = PROTOLATHE
+ materials = list(/datum/material/iron = 5000, /datum/material/glass = 1000, /datum/material/plastic = 1000)
+ construction_time = 15
+ build_path = /obj/machinery/plumbing/synthesizer
+ category = list("Misc","Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
+
+/datum/design/plumb_grinder
+ name = "Plumbing-Linked Autogrinder"
+ desc = "Automatically extracts reagents from an item by grinding it. Think of the possibilities! Note: does not grind people."
+ id = "plumb_grinder"
+ build_type = PROTOLATHE
+ materials = list(/datum/material/iron = 2000, /datum/material/glass = 1500)
+ construction_time = 15
+ build_path = /obj/machinery/plumbing/grinder_chemical
+ category = list("Misc","Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
+
+/datum/design/reaction_chamber
+ name = "Plumbing Reaction Chamber"
+ desc = "You can set a list of allowed reagents and amounts. Once the chamber has these reagents, will let the products through."
+ id = "reaction_chamber"
+ build_type = PROTOLATHE
+ materials = list(/datum/material/iron = 1000, /datum/material/glass = 500)
+ construction_time = 15
+ build_path = /obj/machinery/plumbing/reaction_chamber
+ category = list("Misc","Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
+
+/datum/design/duct_print
+ name = "Plumbing Ducts"
+ desc = "Ducts for plumbing! Now lathed for efficiency."
+ id = "duct_print"
+ build_type = PROTOLATHE
+ materials = list(/datum/material/plastic = 400)
+ construction_time = 1
+ build_path = /obj/item/stack/ducts
+ category = list("Misc","Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
+
+/datum/design/plumb_splitter
+ name = "Plumbing Chemical Splitter"
+ desc = "A splitter. Has 2 outputs. Can be configured to allow a certain amount through each side."
+ id = "plumb_splitter"
+ build_type = PROTOLATHE
+ materials = list(/datum/material/iron = 750, /datum/material/glass = 250)
+ construction_time = 15
+ build_path = /obj/machinery/plumbing/splitter
+ category = list("Misc","Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
+
+/datum/design/pill_press
+ name = "Plumbing Automatic Pill Former"
+ desc = "Automatically forms pills to the required parameters with piped reagents! A good replacement for those lazy, useless chemists."
+ id = "pill_press"
+ build_type = PROTOLATHE
+ materials = list(/datum/material/iron = 1000, /datum/material/glass = 500)
+ construction_time = 15
+ build_path = /obj/machinery/plumbing/pill_press
+ category = list("Misc","Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
+
+/datum/design/plumb_pump
+ name = "Liquid Extraction Pump"
+ desc = "Use it for extracting liquids from lavaland's geysers!"
+ id = "plumb_pump"
+ build_type = PROTOLATHE
+ materials = list(/datum/material/iron = 1000, /datum/material/glass = 500)
+ construction_time = 15
+ build_path = /obj/machinery/plumbing/liquid_pump
+ category = list("Misc","Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
+
+/datum/design/plumb_in
+ name = "Plumbing Input Device"
+ desc = "A big piped funnel for putting stuff in the pipe network."
+ id = "plumb_in"
+ build_type = PROTOLATHE
+ materials = list(/datum/material/iron = 400, /datum/material/glass = 400)
+ construction_time = 15
+ build_path = /obj/machinery/plumbing/input
+ category = list("Misc","Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
+
+/datum/design/plumb_out
+ name = "Plumbing Output Device"
+ desc = "A big piped funnel for taking stuff out of the pipe network."
+ id = "plumb_out"
+ build_type = PROTOLATHE
+ materials = list(/datum/material/iron = 400, /datum/material/glass = 400)
+ construction_time = 15
+ build_path = /obj/machinery/plumbing/output
+ category = list("Misc","Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
+
+/datum/design/plumb_tank
+ name = "Plumbed Storage Tank"
+ desc = "A tank for storing plumbed reagents."
+ id = "plumb_tank"
+ build_type = PROTOLATHE
+ materials = list(/datum/material/iron = 10000, /datum/material/glass = 10000, /datum/material/plastic = 4000)
+ construction_time = 15
+ build_path = /obj/machinery/plumbing/tank
+ category = list("Misc","Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
+
+/datum/design/plumb_rcd
+ name = "Plumbed Autoconstruction Device"
+ desc = "A RCD for plumbing machines! Cannot make ducts."
+ id = "plumb_rcd"
+ build_type = PROTOLATHE
+ materials = list(/datum/material/iron = 20000, /datum/material/glass = 10000, /datum/material/plastic = 20000, /datum/material/titanium = 2000, /datum/material/diamond = 800, /datum/material/gold = 2000, /datum/material/silver = 2000)
+ construction_time = 150
+ build_path = /obj/item/construction/plumbing
+ category = list("Misc","Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
diff --git a/code/modules/research/nanites/extra_settings/text.dm b/code/modules/research/nanites/extra_settings/text.dm
index 56aa3dd07f..d3cad27bcf 100644
--- a/code/modules/research/nanites/extra_settings/text.dm
+++ b/code/modules/research/nanites/extra_settings/text.dm
@@ -10,6 +10,9 @@
/datum/nanite_extra_setting/text/get_copy()
return new /datum/nanite_extra_setting/text(value)
+/datum/nanite_extra_setting/text/get_value()
+ return html_encode(value)
+
/datum/nanite_extra_setting/text/get_frontend_list(name)
return list(list(
"name" = name,
diff --git a/code/modules/research/nanites/nanite_programs/suppression.dm b/code/modules/research/nanites/nanite_programs/suppression.dm
index 3b0d6d0d06..d2aa243fee 100644
--- a/code/modules/research/nanites/nanite_programs/suppression.dm
+++ b/code/modules/research/nanites/nanite_programs/suppression.dm
@@ -176,7 +176,7 @@
sent_message = message_setting.get_value()
if(host_mob.stat == DEAD)
return
- to_chat(host_mob, "You hear a strange, robotic voice in your head... \"[sent_message]\"")
+ to_chat(host_mob, "You hear a strange, robotic voice in your head... \"[html_encode(sent_message)]\"")
/datum/nanite_program/comm/hallucination
name = "Hallucination"
diff --git a/code/modules/research/techweb/nodes/medical_nodes.dm b/code/modules/research/techweb/nodes/medical_nodes.dm
index 3a9e654b81..150e420c09 100644
--- a/code/modules/research/techweb/nodes/medical_nodes.dm
+++ b/code/modules/research/techweb/nodes/medical_nodes.dm
@@ -24,6 +24,23 @@
design_ids = list("defib_decay", "defib_shock", "defib_heal", "defib_speed")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
+/datum/techweb_node/plumbing
+ id = "plumbing"
+ display_name = "Reagent Plumbing Technology"
+ description = "Plastic tubes, and machinery used for manipulating things in them."
+ prereq_ids = list("base")
+ design_ids = list("acclimator", "disposer", "plumb_filter", "plumb_synth", "plumb_grinder", "reaction_chamber", "duct_print", "plumb_splitter", "pill_press", "plumb_pump", "plumb_in", "plumb_out", "plumb_tank", "medipen_refiller")
+ research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000)
+
+
+/datum/techweb_node/advplumbing
+ id = "advplumbing"
+ display_name = "Advanced Plumbing Technology"
+ description = "Plumbing RCD."
+ prereq_ids = list("plumbing", "adv_engi")
+ design_ids = list("plumb_rcd", "autohydrotray")
+ research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
+
//////////////////////Cybernetics/////////////////////
/datum/techweb_node/surplus_limbs
diff --git a/code/modules/ruins/lavaland_ruin_code.dm b/code/modules/ruins/lavaland_ruin_code.dm
index 45b6939f42..e572f1ee02 100644
--- a/code/modules/ruins/lavaland_ruin_code.dm
+++ b/code/modules/ruins/lavaland_ruin_code.dm
@@ -93,7 +93,7 @@
/obj/item/stack/sheet/mineral/adamantine = /datum/species/golem/adamantine,
/obj/item/stack/sheet/plastic = /datum/species/golem/plastic,
/obj/item/stack/tile/brass = /datum/species/golem/clockwork,
- /obj/item/stack/tile/bronze = /datum/species/golem/bronze,
+ /obj/item/stack/sheet/bronze = /datum/species/golem/bronze,
/obj/item/stack/sheet/cardboard = /datum/species/golem/cardboard,
/obj/item/stack/sheet/leather = /datum/species/golem/leather,
/obj/item/stack/sheet/bone = /datum/species/golem/bone,
diff --git a/code/modules/ruins/spaceruin_code/clericsden.dm b/code/modules/ruins/spaceruin_code/clericsden.dm
index 7d1fda6740..3fe4cad794 100644
--- a/code/modules/ruins/spaceruin_code/clericsden.dm
+++ b/code/modules/ruins/spaceruin_code/clericsden.dm
@@ -21,7 +21,6 @@
desc = "A weaker construct meant to scour ruins for objects of Nar'Sie's affection. Those barbed claws are no joke."
icon_state = "proteon"
icon_living = "proteon"
- threat = 0.4
maxHealth = 35
health = 35
melee_damage_lower = 8
diff --git a/code/modules/shuttle/shuttle_creation/shuttle_creator.dm b/code/modules/shuttle/shuttle_creation/shuttle_creator.dm
index f5a11db60f..b3d99f22ab 100644
--- a/code/modules/shuttle/shuttle_creation/shuttle_creator.dm
+++ b/code/modules/shuttle/shuttle_creation/shuttle_creator.dm
@@ -43,6 +43,7 @@ GLOBAL_LIST_EMPTY(custom_shuttle_machines) //Machines that require updating (He
. = ..()
internal_shuttle_creator = new()
internal_shuttle_creator.owner_rsd = src
+ desc += " Attention, the max size of the shuttle is [SHUTTLE_CREATOR_MAX_SIZE]."
overlay_holder = new()
/obj/item/shuttle_creator/Destroy()
@@ -237,13 +238,13 @@ GLOBAL_LIST_EMPTY(custom_shuttle_machines) //Machines that require updating (He
port.register()
- icon_state = "rsd_used"
+ icon_state = "rsd_empty"
//Clear highlights
overlay_holder.clear_highlights()
GLOB.custom_shuttle_count ++
- message_admins("[ADMIN_LOOKUPFLW(user)] created a new shuttle with a [src] at [ADMIN_VERBOSEJMP(user)] ([GLOB.custom_shuttle_count] custom shuttles, limit is [CUSTOM_SHUTTLE_LIMIT])")
- log_game("[key_name(user)] created a new shuttle with a [src] at [AREACOORD(user)] ([GLOB.custom_shuttle_count] custom shuttles, limit is [CUSTOM_SHUTTLE_LIMIT])")
+ message_admins("[ADMIN_LOOKUPFLW(user)] created a new shuttle with a [src] at [ADMIN_VERBOSEJMP(user)] ([GLOB.custom_shuttle_count] custom shuttles)")
+ log_game("[key_name(user)] created a new shuttle with a [src] at [AREACOORD(user)] ([GLOB.custom_shuttle_count] custom shuttles)")
return TRUE
/obj/item/shuttle_creator/proc/create_shuttle_area(mob/user)
@@ -350,7 +351,7 @@ GLOBAL_LIST_EMPTY(custom_shuttle_machines) //Machines that require updating (He
loggedOldArea = get_area(get_turf(user))
loggedTurfs |= turfs
overlay_holder.highlight_area(turfs)
- //TODO READD THIS SHIT: icon_state = "rsd_used"
+ //TODO READD THIS SHIT: icon_state = "rsd_empty"
to_chat(user, "You add the area into the buffer of the [src], you made add more areas or select an airlock to act as a docking port to complete the shuttle.")
return turfs
diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm
index 57502e2cd5..2272a14612 100644
--- a/code/modules/spells/spell.dm
+++ b/code/modules/spells/spell.dm
@@ -224,7 +224,15 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
/obj/effect/proc_holder/spell/proc/choose_targets(mob/user = usr) //depends on subtype - /targeted or /aoe_turf
return
-/obj/effect/proc_holder/spell/proc/can_target(mob/living/target)
+/**
+ * can_target: Checks if we are allowed to cast the spell on a target.
+ *
+ * Arguments:
+ * * target The atom that is being targeted by the spell.
+ * * user The mob using the spell.
+ * * silent If the checks should not give any feedback messages.
+ */
+/obj/effect/proc_holder/spell/proc/can_target(atom/target, mob/user, silent = FALSE)
return TRUE
/obj/effect/proc_holder/spell/proc/start_recharge()
@@ -296,6 +304,13 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
/obj/effect/proc_holder/spell/proc/cast(list/targets,mob/user = usr)
return
+/obj/effect/proc_holder/spell/proc/view_or_range(distance = world.view, center=usr, type="view")
+ switch(type)
+ if("view")
+ . = view(distance,center)
+ if("range")
+ . = range(distance,center)
+
/obj/effect/proc_holder/spell/proc/revert_cast(mob/user = usr) //resets recharge or readds a charge
switch(charge_type)
if("recharge")
@@ -345,7 +360,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
switch(max_targets)
if(0) //unlimited
for(var/mob/living/target in view_or_range(range, user, selection_type))
- if(!can_target(target))
+ if(!can_target(target, user, TRUE))
continue
targets += target
if(1) //single target can be picked
@@ -357,7 +372,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
for(var/mob/living/M in view_or_range(range, user, selection_type))
if(!include_user && user == M)
continue
- if(!can_target(M))
+ if(!can_target(M, user, TRUE))
continue
possible_targets += M
@@ -365,7 +380,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
//Adds a safety check post-input to make sure those targets are actually in range.
var/mob/M
if(!random_target)
- M = input("Choose the target for the spell.", "Targeting") as null|mob in possible_targets
+ M = input("Choose the target for the spell.", "Targeting") as null|mob in sortNames(possible_targets)
else
switch(random_target_priority)
if(TARGET_RANDOM)
@@ -385,7 +400,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
else
var/list/possible_targets = list()
for(var/mob/living/target in view_or_range(range, user, selection_type))
- if(!can_target(target))
+ if(!can_target(target, user, TRUE))
continue
possible_targets += target
for(var/i=1,i<=max_targets,i++)
@@ -411,7 +426,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
var/list/targets = list()
for(var/turf/target in view_or_range(range,user,selection_type))
- if(!can_target(target))
+ if(!can_target(target, user, TRUE))
continue
if(!(target in view_or_range(inner_radius,user,selection_type)))
targets += target
diff --git a/code/modules/spells/spell_types/cone_spells.dm b/code/modules/spells/spell_types/cone_spells.dm
new file mode 100644
index 0000000000..63bae4b7cf
--- /dev/null
+++ b/code/modules/spells/spell_types/cone_spells.dm
@@ -0,0 +1,117 @@
+/obj/effect/proc_holder/spell/cone
+ name = "Cone of Nothing"
+ desc = "Does nothing in a cone! Wow!"
+ school = "evocation"
+ charge_max = 100
+ clothes_req = FALSE
+ invocation = "FUKAN NOTHAN"
+ invocation_type = "shout"
+ sound = 'sound/magic/forcewall.ogg'
+ action_icon_state = "shield"
+ range = -1
+ cooldown_min = 0.5 SECONDS
+ ///This controls how many levels the cone has, increase this value to make a bigger cone.
+ var/cone_levels = 3
+ ///This value determines if the cone penetrates walls.
+ var/respect_density = FALSE
+
+/obj/effect/proc_holder/spell/cone/choose_targets(mob/user = usr)
+ perform(null, user=user)
+
+///This proc creates a list of turfs that are hit by the cone
+/obj/effect/proc_holder/spell/cone/proc/cone_helper(var/turf/starter_turf, var/dir_to_use, var/cone_levels = 3)
+ var/list/turfs_to_return = list()
+ var/turf/turf_to_use = starter_turf
+ var/turf/left_turf
+ var/turf/right_turf
+ var/right_dir
+ var/left_dir
+ switch(dir_to_use)
+ if(NORTH)
+ left_dir = WEST
+ right_dir = EAST
+ if(SOUTH)
+ left_dir = EAST
+ right_dir = WEST
+ if(EAST)
+ left_dir = NORTH
+ right_dir = SOUTH
+ if(WEST)
+ left_dir = SOUTH
+ right_dir = NORTH
+
+
+ for(var/i in 1 to cone_levels)
+ var/list/level_turfs = list()
+ turf_to_use = get_step(turf_to_use, dir_to_use)
+ level_turfs += turf_to_use
+ if(i != 1)
+ left_turf = get_step(turf_to_use, left_dir)
+ level_turfs += left_turf
+ right_turf = get_step(turf_to_use, right_dir)
+ level_turfs += right_turf
+ for(var/left_i in 1 to i -calculate_cone_shape(i))
+ if(left_turf.density && respect_density)
+ break
+ left_turf = get_step(left_turf, left_dir)
+ level_turfs += left_turf
+ for(var/right_i in 1 to i -calculate_cone_shape(i))
+ if(right_turf.density && respect_density)
+ break
+ right_turf = get_step(right_turf, right_dir)
+ level_turfs += right_turf
+ turfs_to_return += list(level_turfs)
+ if(i == cone_levels)
+ continue
+ if(turf_to_use.density && respect_density)
+ break
+ return turfs_to_return
+
+/obj/effect/proc_holder/spell/cone/cast(list/targets,mob/user = usr)
+ var/list/cone_turfs = cone_helper(get_turf(user), user.dir, cone_levels)
+ for(var/list/turf_list in cone_turfs)
+ do_cone_effects(turf_list)
+
+///This proc does obj, mob and turf cone effects on all targets in a list
+/obj/effect/proc_holder/spell/cone/proc/do_cone_effects(list/target_turf_list, level)
+ for(var/target_turf in target_turf_list)
+ if(!target_turf) //if turf is no longer there
+ continue
+ do_turf_cone_effect(target_turf, level)
+ if(isopenturf(target_turf))
+ var/turf/open/open_turf = target_turf
+ for(var/movable_content in open_turf)
+ if(isobj(movable_content))
+ do_obj_cone_effect(movable_content, level)
+ else if(isliving(movable_content))
+ do_mob_cone_effect(movable_content, level)
+
+///This proc deterimines how the spell will affect turfs.
+/obj/effect/proc_holder/spell/cone/proc/do_turf_cone_effect(turf/target_turf, level)
+ return
+
+///This proc deterimines how the spell will affect objects.
+/obj/effect/proc_holder/spell/cone/proc/do_obj_cone_effect(obj/target_obj, level)
+ return
+
+///This proc deterimines how the spell will affect mobs.
+/obj/effect/proc_holder/spell/cone/proc/do_mob_cone_effect(mob/living/target_mob, level)
+ return
+
+///This proc adjusts the cones width depending on the level.
+/obj/effect/proc_holder/spell/cone/proc/calculate_cone_shape(current_level)
+ var/end_taper_start = round(cone_levels * 0.8)
+ if(current_level > end_taper_start)
+ return (current_level % end_taper_start) * 2 //someone more talented and probably come up with a better formula.
+ else
+ return 2
+
+///This type of cone gradually affects each level of the cone instead of affecting the entire area at once.
+/obj/effect/proc_holder/spell/cone/staggered
+
+/obj/effect/proc_holder/spell/cone/staggered/cast(list/targets,mob/user = usr)
+ var/level_counter = 0
+ var/list/cone_turfs = cone_helper(get_turf(user), user.dir, cone_levels)
+ for(var/list/turf_list in cone_turfs)
+ level_counter++
+ addtimer(CALLBACK(src, .proc/do_cone_effects, turf_list, level_counter), 2 * level_counter)
diff --git a/code/modules/spells/spell_types/dumbfire.dm b/code/modules/spells/spell_types/dumbfire.dm
index 6931b4ac31..424c702a31 100644
--- a/code/modules/spells/spell_types/dumbfire.dm
+++ b/code/modules/spells/spell_types/dumbfire.dm
@@ -49,8 +49,8 @@
var/projectile_type = text2path(proj_type)
projectile = new projectile_type(user)
else if(istype(proj_type, /obj/effect/proc_holder/spell))
- projectile = new /obj/effect/proc_holder/spell/targeted/trigger(user)
- var/obj/effect/proc_holder/spell/targeted/trigger/T = projectile
+ projectile = new /obj/effect/proc_holder/spell/pointed/trigger(user)
+ var/obj/effect/proc_holder/spell/pointed/trigger/T = projectile
T.linked_spells += proj_type
else
projectile = new proj_type(user)
diff --git a/code/modules/spells/spell_types/ethereal_jaunt.dm b/code/modules/spells/spell_types/ethereal_jaunt.dm
index 8cf51d45c6..9d91b6534d 100644
--- a/code/modules/spells/spell_types/ethereal_jaunt.dm
+++ b/code/modules/spells/spell_types/ethereal_jaunt.dm
@@ -17,7 +17,7 @@
action_icon_state = "jaunt"
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/cast(list/targets,mob/user = usr) //magnets, so mostly hardcoded
- playsound(get_turf(user), 'sound/magic/ethereal_enter.ogg', 50, 1, -1)
+ play_sound("enter",user)
for(var/mob/living/target in targets)
INVOKE_ASYNC(src, .proc/do_jaunt, target)
@@ -42,7 +42,7 @@
ADD_TRAIT(target, TRAIT_MOBILITY_NOMOVE, src)
target.update_mobility()
holder.reappearing = 1
- playsound(get_turf(target), 'sound/magic/ethereal_exit.ogg', 50, 1, -1)
+ play_sound("exit",target)
sleep(25 - jaunt_in_time)
new jaunt_in_type(mobloc, holder.dir)
target.setDir(holder.dir)
@@ -63,6 +63,13 @@
steam.set_up(10, 0, mobloc)
steam.start()
+/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/proc/play_sound(type,mob/living/target)
+ switch(type)
+ if("enter")
+ playsound(get_turf(target), 'sound/magic/ethereal_enter.ogg', 50, TRUE, -1)
+ if("exit")
+ playsound(get_turf(target), 'sound/magic/ethereal_exit.ogg', 50, TRUE, -1)
+
/obj/effect/dummy/phased_mob/spell_jaunt
name = "water"
icon = 'icons/effects/effects.dmi'
diff --git a/code/modules/spells/spell_types/mind_transfer.dm b/code/modules/spells/spell_types/mind_transfer.dm
deleted file mode 100644
index d2ef015d1d..0000000000
--- a/code/modules/spells/spell_types/mind_transfer.dm
+++ /dev/null
@@ -1,88 +0,0 @@
-/obj/effect/proc_holder/spell/targeted/mind_transfer
- name = "Mind Transfer"
- desc = "This spell allows the user to switch bodies with a target."
-
- school = "transmutation"
- charge_max = 600
- clothes_req = NONE
- invocation = "GIN'YU CAPAN"
- invocation_type = "whisper"
- range = 1
- cooldown_min = 200 //100 deciseconds reduction per rank
- var/unconscious_amount_caster = 400 //how much the caster is stunned for after the spell
- var/unconscious_amount_victim = 400 //how much the victim is stunned for after the spell
-
- action_icon_state = "mindswap"
-
-/*
-Urist: I don't feel like figuring out how you store object spells so I'm leaving this for you to do.
-Make sure spells that are removed from spell_list are actually removed and deleted when mind transferring.
-Also, you never added distance checking after target is selected. I've went ahead and did that.
-*/
-/obj/effect/proc_holder/spell/targeted/mind_transfer/cast(list/targets, mob/living/user = usr, distanceoverride, silent = FALSE)
- if(!targets.len)
- if(!silent)
- to_chat(user, "No mind found!")
- return
-
- if(targets.len > 1)
- if(!silent)
- to_chat(user, "Too many minds! You're not a hive damnit!")
- return
-
- var/mob/living/target = targets[1]
-
- var/t_He = target.p_they(TRUE)
- var/t_is = target.p_are()
-
- if(!(target in oview(range)) && !distanceoverride)//If they are not in overview after selection. Do note that !() is necessary for in to work because ! takes precedence over it.
- if(!silent)
- to_chat(user, "[t_He] [t_is] too far away!")
- return
-
- if(ismegafauna(target))
- if(!silent)
- to_chat(user, "This creature is too powerful to control!")
- return
-
- if(target.stat == DEAD)
- if(!silent)
- to_chat(user, "You don't particularly want to be dead!")
- return
-
- if(!target.key || !target.mind)
- if(!silent)
- to_chat(user, "[t_He] appear[target.p_s()] to be catatonic! Not even magic can affect [target.p_their()] vacant mind.")
- return
-
- if(user.suiciding)
- if(!silent)
- to_chat(user, "You're killing yourself! You can't concentrate enough to do this!")
- return
-
- var/datum/mind/TM = target.mind
- if(target.anti_magic_check(TRUE, FALSE) || TM.has_antag_datum(/datum/antagonist/wizard) || TM.has_antag_datum(/datum/antagonist/cult) || TM.has_antag_datum(/datum/antagonist/clockcult) || TM.has_antag_datum(/datum/antagonist/changeling) || TM.has_antag_datum(/datum/antagonist/rev) || target.key[1] == "@")
- if(!silent)
- to_chat(user, "[target.p_their(TRUE)] mind is resisting your spell!")
- return
-
- var/mob/living/victim = target//The target of the spell whos body will be transferred to.
- var/mob/living/caster = user//The wizard/whomever doing the body transferring.
-
- //MIND TRANSFER BEGIN
- var/mob/dead/observer/ghost = victim.ghostize(FALSE, TRUE)
- caster.mind.transfer_to(victim)
-
- ghost.mind.transfer_to(caster)
- if(ghost.key)
- ghost.transfer_ckey(caster) //have to transfer the key since the mind was not active
- qdel(ghost)
-
- //MIND TRANSFER END
-
- //Here we knock both mobs out for a time.
- caster.Unconscious(unconscious_amount_caster)
- victim.Unconscious(unconscious_amount_victim)
- SEND_SOUND(caster, sound('sound/magic/mandswap.ogg'))
- SEND_SOUND(victim, sound('sound/magic/mandswap.ogg'))// only the caster and victim hear the sounds, that way no one knows for sure if the swap happened
- return TRUE
diff --git a/code/modules/spells/spell_types/barnyard.dm b/code/modules/spells/spell_types/pointed/barnyard.dm
similarity index 52%
rename from code/modules/spells/spell_types/barnyard.dm
rename to code/modules/spells/spell_types/pointed/barnyard.dm
index 4b972e8030..61e3cf7127 100644
--- a/code/modules/spells/spell_types/barnyard.dm
+++ b/code/modules/spells/spell_types/pointed/barnyard.dm
@@ -1,51 +1,54 @@
-/obj/effect/proc_holder/spell/targeted/barnyardcurse
+/obj/effect/proc_holder/spell/pointed/barnyardcurse
name = "Curse of the Barnyard"
desc = "This spell dooms an unlucky soul to possess the speech and facial attributes of a barnyard animal."
school = "transmutation"
charge_type = "recharge"
charge_max = 150
charge_counter = 0
- clothes_req = NONE
- stat_allowed = 0
+ clothes_req = FALSE
+ stat_allowed = FALSE
invocation = "KN'A FTAGHU, PUCK 'BTHNK!"
invocation_type = "shout"
range = 7
cooldown_min = 30
- selection_type = "range"
- var/list/compatible_mobs = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
-
+ ranged_mousepointer = 'icons/effects/mouse_pointers/barn_target.dmi'
action_icon_state = "barn"
+ active_msg = "You prepare to curse a target..."
+ deactive_msg = "You dispel the curse..."
+ /// List of mobs which are allowed to be a target of the spell
+ var/static/list/compatible_mobs_typecache = typecacheof(list(/mob/living/carbon/human, /mob/living/carbon/monkey))
-/obj/effect/proc_holder/spell/targeted/barnyardcurse/cast(list/targets, mob/user = usr)
+/obj/effect/proc_holder/spell/pointed/barnyardcurse/cast(list/targets, mob/user)
if(!targets.len)
- to_chat(user, "No target found in range.")
- return
+ to_chat(user, "No target found in range!")
+ return FALSE
+ if(!can_target(targets[1], user))
+ return FALSE
var/mob/living/carbon/target = targets[1]
-
- if(!(target.type in compatible_mobs))
- to_chat(user, "You are unable to curse [target]'s head!")
- return
-
- if(!(target in oview(range)))
- to_chat(user, "[target.p_theyre(TRUE)] too far away!")
- return
-
if(target.anti_magic_check())
to_chat(user, "The spell had no effect!")
target.visible_message("[target]'s face bursts into flames, which instantly burst outward, leaving [target] unharmed!", \
- "Your face starts burning up, but the flames are repulsed by your anti-magic protection!")
- return
+ "Your face starts burning up, but the flames are repulsed by your anti-magic protection!")
+ return FALSE
var/list/masks = list(/obj/item/clothing/mask/pig/cursed, /obj/item/clothing/mask/cowmask/cursed, /obj/item/clothing/mask/horsehead/cursed)
-
var/choice = pick(masks)
var/obj/item/clothing/mask/magichead = new choice(get_turf(target))
- magichead.flags_inv = null
+
target.visible_message("[target]'s face bursts into flames, and a barnyard animal's head takes its place!", \
"Your face burns up, and shortly after the fire you realise you have the face of a barnyard animal!")
if(!target.dropItemToGround(target.wear_mask))
qdel(target.wear_mask)
- target.equip_to_slot_if_possible(magichead, SLOT_WEAR_MASK, 1, 1)
-
+ target.equip_to_slot_if_possible(magichead, ITEM_SLOT_MASK, 1, 1)
target.flash_act()
+
+/obj/effect/proc_holder/spell/pointed/barnyardcurse/can_target(atom/target, mob/user, silent)
+ . = ..()
+ if(!.)
+ return FALSE
+ if(!is_type_in_typecache(target, compatible_mobs_typecache))
+ if(!silent)
+ to_chat(user, "You are unable to curse [target]!")
+ return FALSE
+ return TRUE
diff --git a/code/modules/spells/spell_types/pointed/blind.dm b/code/modules/spells/spell_types/pointed/blind.dm
new file mode 100644
index 0000000000..a773c5ad8d
--- /dev/null
+++ b/code/modules/spells/spell_types/pointed/blind.dm
@@ -0,0 +1,35 @@
+/obj/effect/proc_holder/spell/pointed/trigger/blind
+ name = "Blind"
+ desc = "This spell temporarily blinds a single target."
+ school = "transmutation"
+ charge_max = 300
+ clothes_req = FALSE
+ invocation = "STI KALY"
+ invocation_type = "whisper"
+ message = "Your eyes cry out in pain!"
+ cooldown_min = 50 //12 deciseconds reduction per rank
+ starting_spells = list("/obj/effect/proc_holder/spell/targeted/inflict_handler/blind", "/obj/effect/proc_holder/spell/targeted/genetic/blind")
+ ranged_mousepointer = 'icons/effects/mouse_pointers/blind_target.dmi'
+ action_icon_state = "blind"
+ active_msg = "You prepare to blind a target..."
+
+/obj/effect/proc_holder/spell/targeted/inflict_handler/blind
+ amt_eye_blind = 10
+ amt_eye_blurry = 20
+ sound = 'sound/magic/blind.ogg'
+
+/obj/effect/proc_holder/spell/targeted/genetic/blind
+ mutations = list(BLINDMUT)
+ duration = 300
+ charge_max = 400 // needs to be higher than the duration or it'll be permanent
+ sound = 'sound/magic/blind.ogg'
+
+/obj/effect/proc_holder/spell/pointed/trigger/blind/can_target(atom/target, mob/user, silent)
+ . = ..()
+ if(!.)
+ return FALSE
+ if(!isliving(target))
+ if(!silent)
+ to_chat(user, "You can only blind living beings!")
+ return FALSE
+ return TRUE
diff --git a/code/modules/spells/spell_types/pointed/mind_transfer.dm b/code/modules/spells/spell_types/pointed/mind_transfer.dm
new file mode 100644
index 0000000000..28d646f6b6
--- /dev/null
+++ b/code/modules/spells/spell_types/pointed/mind_transfer.dm
@@ -0,0 +1,103 @@
+/obj/effect/proc_holder/spell/pointed/mind_transfer
+ name = "Mind Transfer"
+ desc = "This spell allows the user to switch bodies with a target next to him."
+ school = "transmutation"
+ charge_max = 600
+ clothes_req = FALSE
+ invocation = "GIN'YU CAPAN"
+ invocation_type = "whisper"
+ range = 1
+ cooldown_min = 200 //100 deciseconds reduction per rank
+ ranged_mousepointer = 'icons/effects/mouse_pointers/mindswap_target.dmi'
+ action_icon_state = "mindswap"
+ active_msg = "You prepare to swap minds with a target..."
+ /// For how long is the caster stunned for after the spell
+ var/unconscious_amount_caster = 40 SECONDS
+ /// For how long is the victim stunned for after the spell
+ var/unconscious_amount_victim = 40 SECONDS
+
+/obj/effect/proc_holder/spell/pointed/mind_transfer/cast(list/targets, mob/living/user, silent = FALSE)
+ if(!targets.len)
+ if(!silent)
+ to_chat(user, "No mind found!")
+ return FALSE
+ if(targets.len > 1)
+ if(!silent)
+ to_chat(user, "Too many minds! You're not a hive damnit!")
+ return FALSE
+ if(!can_target(targets[1], user, silent))
+ return FALSE
+
+ var/mob/living/victim = targets[1] //The target of the spell whos body will be transferred to.
+ var/datum/mind/VM = victim.mind
+ if(victim.anti_magic_check(TRUE, FALSE) || VM.has_antag_datum(/datum/antagonist/wizard) || VM.has_antag_datum(/datum/antagonist/cult) || VM.has_antag_datum(/datum/antagonist/changeling) || VM.has_antag_datum(/datum/antagonist/rev) || victim.key[1] == "@")
+ if(!silent)
+ to_chat(user, "[victim.p_their(TRUE)] mind is resisting your spell!")
+ return FALSE
+ if(istype(victim, /mob/living/simple_animal/hostile/guardian))
+ var/mob/living/simple_animal/hostile/guardian/stand = victim
+ if(stand.summoner)
+ victim = stand.summoner
+
+ //You should not be able to enter one of the most powerful side-antags as a fucking wizard.
+ if(istype(victim,/mob/living/simple_animal/slaughter))
+ to_chat(user, "The devilish contract doesn't include the 'mind swappable' package, please try again another lifetime.")
+ return
+
+ //MIND TRANSFER BEGIN
+ var/mob/dead/observer/ghost = victim.ghostize()
+ user.mind.transfer_to(victim)
+
+ ghost.mind.transfer_to(user)
+ if(ghost.key)
+ user.key = ghost.key //have to transfer the key since the mind was not active
+ qdel(ghost)
+ //MIND TRANSFER END
+
+ //Here we knock both mobs out for a time.
+ user.Unconscious(unconscious_amount_caster)
+ victim.Unconscious(unconscious_amount_victim)
+ SEND_SOUND(user, sound('sound/magic/mandswap.ogg'))
+ SEND_SOUND(victim, sound('sound/magic/mandswap.ogg')) // only the caster and victim hear the sounds, that way no one knows for sure if the swap happened
+ return TRUE
+
+/obj/effect/proc_holder/spell/pointed/mind_transfer/can_target(atom/target, mob/user, silent)
+ . = ..()
+ if(!.)
+ return FALSE
+ if(!isliving(target))
+ if(!silent)
+ to_chat(user, "You can only swap minds with living beings!")
+ return FALSE
+ if(user == target)
+ if(!silent)
+ to_chat(user, "You can't swap minds with yourself!")
+ return FALSE
+
+ var/mob/living/victim = target
+ var/t_He = victim.p_they(TRUE)
+
+ if(ismegafauna(victim))
+ if(!silent)
+ to_chat(user, "This creature is too powerful to control!")
+ return FALSE
+ if(victim.stat == DEAD)
+ if(!silent)
+ to_chat(user, "You don't particularly want to be dead!")
+ return FALSE
+ if(!victim.key || !victim.mind)
+ if(!silent)
+ to_chat(user, "[t_He] appear[victim.p_s()] to be catatonic! Not even magic can affect [victim.p_their()] vacant mind.")
+ return FALSE
+ if(user.suiciding)
+ if(!silent)
+ to_chat(user, "You're killing yourself! You can't concentrate enough to do this!")
+ return FALSE
+ if(istype(victim, /mob/living/simple_animal/hostile/guardian))
+ var/mob/living/simple_animal/hostile/guardian/stand = victim
+ if(stand.summoner)
+ if(stand.summoner == user)
+ if(!silent)
+ to_chat(user, "Swapping minds with your own guardian would just put you back into your own head!")
+ return FALSE
+ return TRUE
diff --git a/code/modules/spells/spell_types/pointed/pointed.dm b/code/modules/spells/spell_types/pointed/pointed.dm
new file mode 100644
index 0000000000..7b942dee27
--- /dev/null
+++ b/code/modules/spells/spell_types/pointed/pointed.dm
@@ -0,0 +1,105 @@
+/obj/effect/proc_holder/spell/pointed
+ name = "pointed spell"
+ ranged_mousepointer = 'icons/effects/mouse_pointers/throw_target.dmi'
+ action_icon_state = "projectile"
+ /// Message showing to the spell owner upon deactivating pointed spell.
+ var/deactive_msg = "You dispel the magic..."
+ /// Message showing to the spell owner upon activating pointed spell.
+ var/active_msg = "You prepare to use the spell on a target..."
+ /// Variable dictating if the user is allowed to cast a spell on himself.
+ var/self_castable = FALSE
+ /// Variable dictating if the spell will use turf based aim assist
+ var/aim_assist = TRUE
+
+/obj/effect/proc_holder/spell/pointed/Trigger(mob/user, skip_can_cast = TRUE)
+ if(!istype(user))
+ return
+ var/msg
+ if(!can_cast(user))
+ msg = "You can no longer cast [name]!"
+ remove_ranged_ability(msg)
+ return
+ if(active)
+ msg = "[deactive_msg]"
+ remove_ranged_ability(msg)
+ else
+ msg = "[active_msg] Left-click to activate spell on a target!"
+ add_ranged_ability(user, msg, TRUE)
+ on_activation(user)
+
+/obj/effect/proc_holder/spell/pointed/on_lose(mob/living/user)
+ remove_ranged_ability()
+
+/obj/effect/proc_holder/spell/pointed/remove_ranged_ability(msg)
+ . = ..()
+ on_deactivation(ranged_ability_user)
+
+/obj/effect/proc_holder/spell/pointed/add_ranged_ability(mob/living/user, msg, forced)
+ . = ..()
+ on_activation(user)
+
+/**
+ * on_activation: What happens upon pointed spell activation.
+ *
+ * Arguments:
+ * * user The mob interacting owning the spell.
+ */
+/obj/effect/proc_holder/spell/pointed/proc/on_activation(mob/user)
+ return
+
+/**
+ * on_activation: What happens upon pointed spell deactivation.
+ *
+ * Arguments:
+ * * user The mob interacting owning the spell.
+ */
+/obj/effect/proc_holder/spell/pointed/proc/on_deactivation(mob/user)
+ return
+
+/obj/effect/proc_holder/spell/pointed/update_icon()
+ if(!action)
+ return
+ if(active)
+ action.button_icon_state = "[action_icon_state]1"
+ else
+ action.button_icon_state = "[action_icon_state]"
+ action.UpdateButtonIcon()
+
+/obj/effect/proc_holder/spell/pointed/InterceptClickOn(mob/living/caller, params, atom/target)
+ if(..())
+ return TRUE
+ if(aim_assist && isturf(target))
+ var/list/possible_targets = list()
+ for(var/A in target)
+ if(intercept_check(caller, A, TRUE))
+ possible_targets += A
+ if(possible_targets.len == 1)
+ target = possible_targets[1]
+ if(!intercept_check(caller, target))
+ return TRUE
+ if(!cast_check(FALSE, caller))
+ return TRUE
+ perform(list(target), user = caller)
+ remove_ranged_ability()
+ return TRUE // Do not do any underlying actions after the spell cast
+
+/**
+ * intercept_check: Specific spell checks for InterceptClickOn() targets.
+ *
+ * Arguments:
+ * * user The mob using the ranged spell via intercept.
+ * * target The atom that is being targeted by the spell via intercept.
+ * * silent If the checks should produce not any feedback messages for the user.
+ */
+/obj/effect/proc_holder/spell/pointed/proc/intercept_check(mob/user, atom/target, silent = FALSE)
+ if(!self_castable && target == user)
+ if(!silent)
+ to_chat(user, "You cannot cast the spell on yourself!")
+ return FALSE
+ if(!(target in view_or_range(range, user, selection_type)))
+ if(!silent)
+ to_chat(user, "[target.p_theyre(TRUE)] too far away!")
+ return FALSE
+ if(!can_target(target, user, silent))
+ return FALSE
+ return TRUE
diff --git a/code/modules/spells/spell_types/projectile.dm b/code/modules/spells/spell_types/projectile.dm
index be305520a2..3a8f48cf7c 100644
--- a/code/modules/spells/spell_types/projectile.dm
+++ b/code/modules/spells/spell_types/projectile.dm
@@ -37,8 +37,8 @@
var/projectile_type = text2path(proj_type)
projectile = new projectile_type(user)
if(istype(proj_type, /obj/effect/proc_holder/spell))
- projectile = new /obj/effect/proc_holder/spell/targeted/trigger(user)
- var/obj/effect/proc_holder/spell/targeted/trigger/T = projectile
+ projectile = new /obj/effect/proc_holder/spell/pointed/trigger(user)
+ var/obj/effect/proc_holder/spell/pointed/trigger/T = projectile
T.linked_spells += proj_type
projectile.icon = proj_icon
projectile.icon_state = proj_icon_state
diff --git a/code/modules/spells/spell_types/taeclowndo.dm b/code/modules/spells/spell_types/taeclowndo.dm
index 59826daf07..9d6d71a89f 100644
--- a/code/modules/spells/spell_types/taeclowndo.dm
+++ b/code/modules/spells/spell_types/taeclowndo.dm
@@ -42,6 +42,8 @@
return
. = ..()
+ if(!.)
+ return
new /obj/item/grown/bananapeel(target)
/obj/effect/proc_holder/spell/aimed/banana_peel/update_icon()
diff --git a/code/modules/spells/spell_types/trigger.dm b/code/modules/spells/spell_types/trigger.dm
index 39cff63d98..df579d9243 100644
--- a/code/modules/spells/spell_types/trigger.dm
+++ b/code/modules/spells/spell_types/trigger.dm
@@ -1,30 +1,26 @@
-/obj/effect/proc_holder/spell/targeted/trigger
+/obj/effect/proc_holder/spell/pointed/trigger
name = "Trigger"
desc = "This spell triggers another spell or a few."
-
var/list/linked_spells = list() //those are just referenced by the trigger spell and are unaffected by it directly
var/list/starting_spells = list() //those are added on New() to contents from default spells and are deleted when the trigger spell is deleted to prevent memory leaks
-/obj/effect/proc_holder/spell/targeted/trigger/Initialize()
+/obj/effect/proc_holder/spell/pointed/trigger/Initialize()
. = ..()
-
for(var/spell in starting_spells)
var/spell_to_add = text2path(spell)
new spell_to_add(src) //should result in adding to contents, needs testing
-/obj/effect/proc_holder/spell/targeted/trigger/Destroy()
+/obj/effect/proc_holder/spell/pointed/trigger/Destroy()
for(var/spell in contents)
qdel(spell)
linked_spells = null
starting_spells = null
return ..()
-/obj/effect/proc_holder/spell/targeted/trigger/cast(list/targets,mob/user = usr)
+/obj/effect/proc_holder/spell/pointed/trigger/cast(list/targets,mob/user = usr)
playMagSound()
for(var/mob/living/target in targets)
for(var/obj/effect/proc_holder/spell/spell in contents)
spell.perform(list(target),0)
for(var/obj/effect/proc_holder/spell/spell in linked_spells)
spell.perform(list(target),0)
-
- return
\ No newline at end of file
diff --git a/code/modules/spells/spell_types/wizard.dm b/code/modules/spells/spell_types/wizard.dm
index 13c47ab9ac..14f359ef81 100644
--- a/code/modules/spells/spell_types/wizard.dm
+++ b/code/modules/spells/spell_types/wizard.dm
@@ -207,40 +207,12 @@
summon_type = list(/mob/living/simple_animal/hostile/netherworld)
cast_sound = 'sound/magic/summonitems_generic.ogg'
-/obj/effect/proc_holder/spell/targeted/trigger/blind
- name = "Blind"
- desc = "This spell temporarily blinds a single person and does not require wizard garb."
-
- school = "transmutation"
- charge_max = 300
- clothes_req = NONE
- invocation = "STI KALY"
- invocation_type = "whisper"
- message = "Your eyes cry out in pain!"
- cooldown_min = 50 //12 deciseconds reduction per rank
-
- starting_spells = list("/obj/effect/proc_holder/spell/targeted/inflict_handler/blind","/obj/effect/proc_holder/spell/targeted/genetic/blind")
-
- action_icon_state = "blind"
-
/obj/effect/proc_holder/spell/aoe_turf/conjure/creature/cult
name = "Summon Creatures (DANGEROUS)"
clothes_req = SPELL_CULT_GARB
charge_max = 5000
summon_amt = 2
-
-
-/obj/effect/proc_holder/spell/targeted/inflict_handler/blind
- amt_eye_blind = 10
- amt_eye_blurry = 20
- sound = 'sound/magic/blind.ogg'
-
-/obj/effect/proc_holder/spell/targeted/genetic/blind
- mutations = list(BLINDMUT)
- duration = 300
- sound = 'sound/magic/blind.ogg'
-
/obj/effect/proc_holder/spell/aoe_turf/repulse
name = "Repulse"
desc = "This spell throws everything around the user away."
diff --git a/code/modules/station_goals/bsa.dm b/code/modules/station_goals/bsa.dm
index 4c3f30a786..472734b74b 100644
--- a/code/modules/station_goals/bsa.dm
+++ b/code/modules/station_goals/bsa.dm
@@ -180,16 +180,37 @@
reload()
/obj/machinery/bsa/full/proc/fire(mob/user, turf/bullseye)
- var/turf/point = get_front_turf()
- for(var/turf/T in getline(get_step(point,dir),get_target_turf()))
- T.ex_act(EXPLODE_DEVASTATE)
- point.Beam(get_target_turf(),icon_state="bsa_beam",time=50,maxdistance = world.maxx) //ZZZAP
-
- message_admins("[ADMIN_LOOKUPFLW(user)] has launched an artillery strike.")
- explosion(bullseye,ex_power,ex_power*2,ex_power*4)
-
reload()
+ var/turf/point = get_front_turf()
+ var/turf/target = get_target_turf()
+ var/atom/movable/blocker
+ for(var/T in getline(get_step(point, dir), target))
+ var/turf/tile = T
+ if(SEND_SIGNAL(tile, COMSIG_ATOM_BSA_BEAM) & COMSIG_ATOM_BLOCKS_BSA_BEAM)
+ blocker = tile
+ else
+ for(var/AM in tile)
+ var/atom/movable/stuff = AM
+ if(SEND_SIGNAL(stuff, COMSIG_ATOM_BSA_BEAM) & COMSIG_ATOM_BLOCKS_BSA_BEAM)
+ blocker = stuff
+ break
+ if(blocker)
+ target = tile
+ break
+ else
+ tile.ex_act(EXPLODE_DEVASTATE)
+ point.Beam(target, icon_state = "bsa_beam", time = 50, maxdistance = world.maxx) //ZZZAP
+ new /obj/effect/temp_visual/bsa_splash(point, dir)
+
+ if(!blocker)
+ message_admins("[ADMIN_LOOKUPFLW(user)] has launched an artillery strike targeting [ADMIN_VERBOSEJMP(bullseye)].")
+ log_game("[key_name(user)] has launched an artillery strike targeting [AREACOORD(bullseye)].")
+ explosion(bullseye, ex_power, ex_power*2, ex_power*4)
+ else
+ message_admins("[ADMIN_LOOKUPFLW(user)] has launched an artillery strike targeting [ADMIN_VERBOSEJMP(bullseye)] but it was blocked by [blocker] at [ADMIN_VERBOSEJMP(target)].")
+ log_game("[key_name(user)] has launched an artillery strike targeting [AREACOORD(bullseye)] but it was blocked by [blocker] at [AREACOORD(target)].")
+
/obj/machinery/bsa/full/proc/reload()
ready = FALSE
use_power(power_used_per_shot)
diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm
index 3d88282937..e90f86bf1c 100644
--- a/code/modules/surgery/bodyparts/_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/_bodyparts.dm
@@ -598,7 +598,7 @@
var/datum/species/S = H.dna.species
base_bp_icon = S?.icon_limbs || DEFAULT_BODYPART_ICON
- species_id = S.limbs_id
+ species_id = S.mutant_bodyparts["limbs_id"]
species_flags_list = H.dna.species.species_traits
//body marking memes
@@ -613,7 +613,6 @@
if(S.use_skintones)
skin_tone = H.skin_tone
- base_bp_icon = (base_bp_icon == DEFAULT_BODYPART_ICON) ? DEFAULT_BODYPART_ICON_ORGANIC : base_bp_icon
else
skin_tone = ""
@@ -626,13 +625,9 @@
species_color = S.fixed_mut_color
else
species_color = H.dna.features["mcolor"]
- base_bp_icon = (base_bp_icon == DEFAULT_BODYPART_ICON) ? DEFAULT_BODYPART_ICON_ORGANIC : base_bp_icon
else
species_color = ""
- if(base_bp_icon != DEFAULT_BODYPART_ICON)
- color_src = mut_colors ? MUTCOLORS : ((H.dna.skin_tone_override && S.use_skintones == USE_SKINTONES_GRAYSCALE_CUSTOM) ? CUSTOM_SKINTONE : SKINTONE)
-
if(S.mutant_bodyparts["legs"])
if(body_zone == BODY_ZONE_L_LEG || body_zone == BODY_ZONE_R_LEG)
if(DIGITIGRADE in S.species_traits)
@@ -652,11 +647,16 @@
body_markings = "plain"
aux_marking = "plain"
markings_color = list(colorlist)
-
else
body_markings = null
aux_marking = null
+ if(species_id in GLOB.greyscale_limb_types) //should they have greyscales?
+ base_bp_icon = DEFAULT_BODYPART_ICON_ORGANIC
+
+ if(base_bp_icon != DEFAULT_BODYPART_ICON)
+ color_src = mut_colors ? MUTCOLORS : ((H.dna.skin_tone_override && S.use_skintones == USE_SKINTONES_GRAYSCALE_CUSTOM) ? CUSTOM_SKINTONE : SKINTONE)
+
if(!dropping_limb && H.dna.check_mutation(HULK))
mutation_color = "00aa00"
else
diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm
index 049fc5b5d4..9172ce00bc 100644
--- a/code/modules/surgery/organs/eyes.dm
+++ b/code/modules/surgery/organs/eyes.dm
@@ -265,6 +265,10 @@
var/C = input(owner, "Select Color", "Select color", "#ffffff") as color|null
if(!C || QDELETED(src) || QDELETED(user) || QDELETED(owner) || owner != user)
return
+ var/list/hsv = ReadHSV(RGBtoHSV(C))
+ if(hsv[2] > 125)
+ to_chat(user, "A color that saturated? Surely not!")
+ return
var/range = input(user, "Enter range (0 - [max_light_beam_distance])", "Range Select", 0) as null|num
if(!isnum(range))
return
@@ -396,4 +400,4 @@
#undef BLURRY_VISION_ONE
#undef BLURRY_VISION_TWO
-#undef BLIND_VISION_THREE
\ No newline at end of file
+#undef BLIND_VISION_THREE
diff --git a/code/modules/vehicles/_vehicle.dm b/code/modules/vehicles/_vehicle.dm
index ac7fa879f4..12e9f365d0 100644
--- a/code/modules/vehicles/_vehicle.dm
+++ b/code/modules/vehicles/_vehicle.dm
@@ -18,6 +18,7 @@
var/canmove = TRUE
var/emulate_door_bumps = TRUE //when bumping a door try to make occupants bump them to open them.
var/default_driver_move = TRUE //handle driver movement instead of letting something else do it like riding datums.
+ var/enclosed = FALSE // is the rider protected from bullets? assume no
var/list/autogrant_actions_passenger //plain list of typepaths
var/list/autogrant_actions_controller //assoc list "[bitflag]" = list(typepaths)
var/list/mob/occupant_actions //assoc list mob = list(type = action datum assigned to mob)
@@ -166,3 +167,9 @@
if(trailer && .)
var/dir_to_move = get_dir(trailer.loc, newloc)
step(trailer, dir_to_move)
+
+/obj/vehicle/bullet_act(obj/item/projectile/Proj) //wrapper
+ if (!enclosed && length(occupants) && !Proj.force_hit && (Proj.def_zone == BODY_ZONE_HEAD || Proj.def_zone == BODY_ZONE_CHEST)) //allows bullets to hit drivers
+ occupants[1].bullet_act(Proj) // driver dinkage
+ return BULLET_ACT_HIT
+ . = ..()
diff --git a/code/modules/vehicles/sealed.dm b/code/modules/vehicles/sealed.dm
index edaab8b982..28f6b1cca8 100644
--- a/code/modules/vehicles/sealed.dm
+++ b/code/modules/vehicles/sealed.dm
@@ -1,4 +1,5 @@
/obj/vehicle/sealed
+ enclosed = TRUE // you're in a sealed vehicle dont get dinked idiot
var/enter_delay = 20
flags_1 = BLOCK_FACE_ATOM_1
diff --git a/code/modules/vending/kinkmate.dm b/code/modules/vending/kinkmate.dm
index dc4f4e9273..a78a4e6ef4 100644
--- a/code/modules/vending/kinkmate.dm
+++ b/code/modules/vending/kinkmate.dm
@@ -36,6 +36,7 @@
/obj/item/clothing/under/misc/keyholesweater = 2,
/obj/item/clothing/under/misc/stripper/mankini = 2,
/obj/item/clothing/under/costume/jabroni = 2,
+ /obj/item/clothing/gloves/evening/black = 2,
/obj/item/dildo/flared/huge = 3
)
premium = list(
diff --git a/code/modules/vending/medical.dm b/code/modules/vending/medical.dm
index 34de3b490c..795d35adc4 100644
--- a/code/modules/vending/medical.dm
+++ b/code/modules/vending/medical.dm
@@ -46,7 +46,8 @@
/obj/item/wrench/medical = 1,
/obj/item/storage/belt/medolier/full = 2,
/obj/item/gun/syringe/dart = 2,
- /obj/item/storage/briefcase/medical = 2)
+ /obj/item/storage/briefcase/medical = 2,
+ /obj/item/plunger/reinforced = 2)
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
resistance_flags = FIRE_PROOF
diff --git a/config/game_options.txt b/config/game_options.txt
index 1585d45e6d..a5b0d0b8c4 100644
--- a/config/game_options.txt
+++ b/config/game_options.txt
@@ -116,6 +116,7 @@ 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!
diff --git a/config/spaceRuinBlacklist.txt b/config/spaceRuinBlacklist.txt
index 90682f5bad..969e4135f6 100644
--- a/config/spaceRuinBlacklist.txt
+++ b/config/spaceRuinBlacklist.txt
@@ -52,3 +52,4 @@
#_maps/RandomRuins/SpaceRuins/arcade.dmm
#_maps/RandomRuins/SpaceRuins/spacehermit.dmm
#_maps/RandomRuins/SpaceRuins/advancedlab.dmm
+#_maps/RandomRuins/SpaceRuins/spacediner.dmm
diff --git a/html/changelog.html b/html/changelog.html
index 09f7352122..870578cae5 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -50,6 +50,236 @@
-->
+ 27 August 2020
+ silicons updated:
+
+ - eyebeam lighting can only have 128 maximum HSV saturation now.
+ - no more shotgun stripper clips in boxes.
+ - goliath tentacles now do 20 damage to mechs at 25% ap
+
+ timothyteakettle updated:
+
+ - changing your character's gender won't randomize its hairstyle and facial hairstyle now
+
+
+ 26 August 2020
+ ancientpower updated:
+
+ - Ghosts can read newscasters by clicking on them.
+
+ silicons updated:
+
+ - hierophant vortex blasts now have 50% armor penetration vs mecha
+ - ventcrawling now kicks off every attached/buckled mob, even for non humans.
+
+
+ 25 August 2020
+ Hatterhat updated:
+
+ - Insidious combat gloves have been replaced by insidious guerilla gloves. They're generally the same, except now you can tackle with them.
+
+ Literallynotpickles updated:
+
+ - You can now equip handheld crew monitors on all medical-related winter coats.
+
+ Putnam3145 updated:
+
+ - vore now ejects occupants on death
+
+ raspy-on-osu updated:
+
+ - Thermoelectric Generator power output
+
+ timothyteakettle updated:
+
+ - I.P.Cs now short their circuits when expressing emotion, causing sparks to appear around them.
+
+
+ 24 August 2020
+ MrJWhit updated:
+
+ - Fixes areas on expanded airlocks
+
+ silicons updated:
+
+ - wormhole jaunters work
+ - wormhole jaunters no longer get interference from bags of holding
+ - airlocks now only shock on pulse/wirecutters instead of on tgui panel open.
+
+ timothyteakettle updated:
+
+ - three new items are in the loadout for all donators
+
+ zeroisthebiggay updated:
+
+ - contraband black evening gloves in kinkvend
+
+
+ 23 August 2020
+ DeltaFire15 updated:
+
+ - silicons and clockies can now access APCs properly
+
+ EmeraldSundisk updated:
+
+ - Medbay now has a smartfridge for organ storage
+ - Slight enhancements to the station's electrical wiring layout
+ - Very small library renovation
+ - Exterior airlocks have been given proper air systems for safety's sake
+
+ Ghommie updated:
+
+ - Stops shielded hardsuits from slowly turning the wearer into a big glowing ball of stacked energy shield overlays.
+ - the shielding overlay is merely visual as result. Aim your clicks.
+
+ Ludox235 updated:
+
+ - no more 10 pop xenos (25pop now)
+
+ MrJWhit updated:
+
+ - Increases the majority of airlocks by 1 tile.
+ - Minor adjustments to the TEG engine.
+
+ Putnam3145 updated:
+
+ - Simplemobs no longer count in dynamic.
+ - "Story" storyteller no longer starts at a ludicrously low threat, always.
+ - Blob threat now scales with coverage.
+ - One person with their pref on no longer overpowers 40 people who might not even know there is one.
+ - Negative-weight rulesets are no longer put into the list.
+
+ kiwedespars updated:
+
+ - removed durathread from armwraps recipe.
+
+ lolman360 updated:
+
+ - breath mask balaclava
+
+ timothyteakettle updated:
+
+ - lizards are now a recommended species for mam snouts
+
+ zeroisthebiggay updated:
+
+ - new sprites for the temporal katana
+ - suiciding with the temporal katana omae wa mou shinderius you into the shadow realm
+ - twilight isnt earrape
+
+
+ 22 August 2020
+ Time-Green (copypasta'd by lolman360) updated:
+
+ - plumbing
+ - automatic hydro trays
+
+
+ 21 August 2020
+ LetterN updated:
+
+ - Updates and adds some of the tips
+
+ Putnam3145 updated:
+
+ - added reftracking as a compile flag
+
+ SmArtKar updated:
+
+ - RSD limitation is now 500 tiles
+ - Fixed broken RSD sprites
+ - Removed that shuttle limit
+
+ timothyteakettle updated:
+
+ - two snouts can once again be chosen in customization
+ - lizard snouts work again
+
+
+ 20 August 2020
+ DeltaFire15 updated:
+
+ - The cooking oil damage formula is no longer scuffed.
+ - Changed the clockie help-link to lead to our own wiki.
+
+ Fikou updated:
+
+ - admins can now do html in ahelps properly
+
+ Hatterhat updated:
+
+ - Pirate threats are now announced as "business propositions", and their arrivals are now also announced properly.
+
+ tiramisuapimancer updated:
+
+ - Ethereal hair is now their body color instead of accidentally white
+
+
+ 18 August 2020
+ DeltaFire15 updated:
+
+ - kindle cast time: 15ds -> 25ds
+ - Moved the Belligerent Scripture to where it should be in the code
+
+ Detective-Google updated:
+
+ - glass floors
+ - uncrowbarrable plasma floors tweak:disco inferno's plasma floors can no longer be crowbarred.
+ - ghost cafe has funky fresh art
+ - you can actually remove glass floors now
+ - get_equipped_items is hopefully less gross
+ - plasma cutters are no longer gay
+
+ Hatterhat updated:
+
+ - Slaughter demons (and laughter demons, being a subtype) are MOB_SIZE_LARGE, with one of the more immediate effects being able to mark them with a crusher and backstab them.
+ - The funny blyat men have stumbled upon another surplus of Mosin-Nagants and are starting to pack them into crates again.
+ - Vehicle riders can now, by default, get shot in the face and/or chest.
+ - Adminspawn only .357 DumDum rounds! Because sometimes the other guy just really needs to hurt.
+ - Bluespace beakers now have a chemical window through the side that shows chemical overlays.
+ - Plant DNA manipulators now let you chuck things over them. Or they WOULD, if LETPASSTHROW worked half a damn.
+
+ LetterN updated:
+
+ - uplink implant states
+ - tweaks how role assigning works
+
+ MrJWhit updated:
+
+ - Gives ashwalkers nightvision
+ - Makes tesla blast people, not the environment, to save the server.
+
+ TheObserver-sys updated:
+
+ - moves Garlic sprites from growing.dmi to growing_vegetable.dmi
+ - Removes the unused Electric Lime mutation, it just takes up space with no actual function nor sprites.
+ - Gives Catnip growing sprites
+ - Removes redundant images in growing.dmi
+
+ kiwedespars updated:
+
+ - 10 force to a fucking rubber cock.
+
+ lolman360 updated:
+
+ - shotgun stripper clip nerf. ammoboxes can now accept a load_delay that happens when they attack a magazine, internal or external.
+
+ ported from tg updated:
+
+ - bronze airlocks and windows can now be built
+ - i also tweaked bronze flooring to be cheaper.
+
+ silicons updated:
+
+ - stamina draining projectiles without stamina for their primary damage type now has their stamina damage taken into account for shield blocking, rather than the block being done for free for that.
+
+ timothyteakettle updated:
+
+ - snowflake code tidyup
+ - snowflake code for mutant bodypart selection has been rewritten to be ~14x shorter
+ - meat type and horns can now be selected by any species
+
+
17 August 2020
DeltaFire15 updated:
diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml
index 1efccd666e..fd9523fb15 100644
--- a/html/changelogs/.all_changelog.yml
+++ b/html/changelogs/.all_changelog.yml
@@ -26944,3 +26944,159 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/)
- rscadd: Added CC BY-NC-SA 3.0 license details to icon/mob/cyborg moved drakeborg.dmi
to icon/mob/cyborg
+2020-08-18:
+ DeltaFire15:
+ - balance: 'kindle cast time: 15ds -> 25ds'
+ - tweak: Moved the Belligerent Scripture to where it should be in the code
+ Detective-Google:
+ - rscadd: glass floors
+ - rscadd: uncrowbarrable plasma floors tweak:disco inferno's plasma floors can no
+ longer be crowbarred.
+ - rscadd: ghost cafe has funky fresh art
+ - bugfix: you can actually remove glass floors now
+ - code_imp: get_equipped_items is hopefully less gross
+ - balance: plasma cutters are no longer gay
+ Hatterhat:
+ - balance: Slaughter demons (and laughter demons, being a subtype) are MOB_SIZE_LARGE,
+ with one of the more immediate effects being able to mark them with a crusher
+ and backstab them.
+ - balance: The funny blyat men have stumbled upon another surplus of Mosin-Nagants
+ and are starting to pack them into crates again.
+ - balance: Vehicle riders can now, by default, get shot in the face and/or chest.
+ - rscadd: Adminspawn only .357 DumDum rounds! Because sometimes the other guy just
+ really needs to hurt.
+ - rscadd: Bluespace beakers now have a chemical window through the side that shows
+ chemical overlays.
+ - rscadd: Plant DNA manipulators now let you chuck things over them. Or they WOULD,
+ if LETPASSTHROW worked half a damn.
+ LetterN:
+ - bugfix: uplink implant states
+ - tweak: tweaks how role assigning works
+ MrJWhit:
+ - rscadd: Gives ashwalkers nightvision
+ - balance: Makes tesla blast people, not the environment, to save the server.
+ TheObserver-sys:
+ - bugfix: moves Garlic sprites from growing.dmi to growing_vegetable.dmi
+ - rscdel: Removes the unused Electric Lime mutation, it just takes up space with
+ no actual function nor sprites.
+ - imageadd: Gives Catnip growing sprites
+ - imagedel: Removes redundant images in growing.dmi
+ kiwedespars:
+ - rscadd: 10 force to a fucking rubber cock.
+ lolman360:
+ - balance: shotgun stripper clip nerf. ammoboxes can now accept a load_delay that
+ happens when they attack a magazine, internal or external.
+ ported from tg:
+ - rscadd: bronze airlocks and windows can now be built
+ - balance: i also tweaked bronze flooring to be cheaper.
+ silicons:
+ - tweak: stamina draining projectiles without stamina for their primary damage type
+ now has their stamina damage taken into account for shield blocking, rather
+ than the block being done for free for that.
+ timothyteakettle:
+ - refactor: snowflake code tidyup
+ - refactor: snowflake code for mutant bodypart selection has been rewritten to be
+ ~14x shorter
+ - tweak: meat type and horns can now be selected by any species
+2020-08-20:
+ DeltaFire15:
+ - bugfix: The cooking oil damage formula is no longer scuffed.
+ - tweak: Changed the clockie help-link to lead to our own wiki.
+ Fikou:
+ - admin: admins can now do html in ahelps properly
+ Hatterhat:
+ - balance: Pirate threats are now announced as "business propositions", and their
+ arrivals are now also announced properly.
+ tiramisuapimancer:
+ - bugfix: Ethereal hair is now their body color instead of accidentally white
+2020-08-21:
+ LetterN:
+ - rscadd: Updates and adds some of the tips
+ Putnam3145:
+ - admin: added reftracking as a compile flag
+ SmArtKar:
+ - tweak: RSD limitation is now 500 tiles
+ - bugfix: Fixed broken RSD sprites
+ - config: Removed that shuttle limit
+ timothyteakettle:
+ - bugfix: two snouts can once again be chosen in customization
+ - bugfix: lizard snouts work again
+2020-08-22:
+ Time-Green (copypasta'd by lolman360):
+ - rscadd: plumbing
+ - rscadd: automatic hydro trays
+2020-08-23:
+ DeltaFire15:
+ - bugfix: silicons and clockies can now access APCs properly
+ EmeraldSundisk:
+ - rscadd: Medbay now has a smartfridge for organ storage
+ - rscadd: Slight enhancements to the station's electrical wiring layout
+ - rscadd: Very small library renovation
+ - bugfix: Exterior airlocks have been given proper air systems for safety's sake
+ Ghommie:
+ - bugfix: Stops shielded hardsuits from slowly turning the wearer into a big glowing
+ ball of stacked energy shield overlays.
+ - tweak: the shielding overlay is merely visual as result. Aim your clicks.
+ Ludox235:
+ - tweak: no more 10 pop xenos (25pop now)
+ MrJWhit:
+ - tweak: Increases the majority of airlocks by 1 tile.
+ - tweak: Minor adjustments to the TEG engine.
+ Putnam3145:
+ - balance: Simplemobs no longer count in dynamic.
+ - balance: '"Story" storyteller no longer starts at a ludicrously low threat, always.'
+ - balance: Blob threat now scales with coverage.
+ - tweak: One person with their pref on no longer overpowers 40 people who might
+ not even know there is one.
+ - bugfix: Negative-weight rulesets are no longer put into the list.
+ kiwedespars:
+ - tweak: removed durathread from armwraps recipe.
+ lolman360:
+ - rscadd: breath mask balaclava
+ timothyteakettle:
+ - bugfix: lizards are now a recommended species for mam snouts
+ zeroisthebiggay:
+ - rscadd: new sprites for the temporal katana
+ - rscadd: suiciding with the temporal katana omae wa mou shinderius you into the
+ shadow realm
+ - soundadd: twilight isnt earrape
+2020-08-24:
+ MrJWhit:
+ - bugfix: Fixes areas on expanded airlocks
+ silicons:
+ - bugfix: wormhole jaunters work
+ - tweak: wormhole jaunters no longer get interference from bags of holding
+ - bugfix: airlocks now only shock on pulse/wirecutters instead of on tgui panel
+ open.
+ timothyteakettle:
+ - rscadd: three new items are in the loadout for all donators
+ zeroisthebiggay:
+ - rscadd: contraband black evening gloves in kinkvend
+2020-08-25:
+ Hatterhat:
+ - rscadd: Insidious combat gloves have been replaced by insidious guerilla gloves.
+ They're generally the same, except now you can tackle with them.
+ Literallynotpickles:
+ - tweak: You can now equip handheld crew monitors on all medical-related winter
+ coats.
+ Putnam3145:
+ - tweak: vore now ejects occupants on death
+ raspy-on-osu:
+ - tweak: Thermoelectric Generator power output
+ timothyteakettle:
+ - tweak: I.P.Cs now short their circuits when expressing emotion, causing sparks
+ to appear around them.
+2020-08-26:
+ ancientpower:
+ - tweak: Ghosts can read newscasters by clicking on them.
+ silicons:
+ - balance: hierophant vortex blasts now have 50% armor penetration vs mecha
+ - balance: ventcrawling now kicks off every attached/buckled mob, even for non humans.
+2020-08-27:
+ silicons:
+ - tweak: eyebeam lighting can only have 128 maximum HSV saturation now.
+ - balance: no more shotgun stripper clips in boxes.
+ - balance: goliath tentacles now do 20 damage to mechs at 25% ap
+ timothyteakettle:
+ - tweak: changing your character's gender won't randomize its hairstyle and facial
+ hairstyle now
diff --git a/html/changelogs/AutoChangeLog-pr-13232.yml b/html/changelogs/AutoChangeLog-pr-13232.yml
new file mode 100644
index 0000000000..9571dbf2b9
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13232.yml
@@ -0,0 +1,4 @@
+author: "timothyteakettle"
+delete-after: True
+changes:
+ - rscadd: "you can now choose a body sprite as an anthromorph or anthromorphic insect, and can choose from aquatic/avian and apid respectively (and obviously back to the defaults too)"
diff --git a/html/changelogs/AutoChangeLog-pr-13265.yml b/html/changelogs/AutoChangeLog-pr-13265.yml
new file mode 100644
index 0000000000..917e5786b0
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13265.yml
@@ -0,0 +1,4 @@
+author: "timothyteakettle"
+delete-after: True
+changes:
+ - rscadd: "an ancient game over a thousand years old has re-emerged among crewmembers - rock paper scissors"
diff --git a/icons/effects/160x160.dmi b/icons/effects/160x160.dmi
index 0a97573a9b..2adedb6c03 100644
Binary files a/icons/effects/160x160.dmi and b/icons/effects/160x160.dmi differ
diff --git a/icons/effects/96x96.dmi b/icons/effects/96x96.dmi
index b60ff97b2b..34f4adf6ce 100644
Binary files a/icons/effects/96x96.dmi and b/icons/effects/96x96.dmi differ
diff --git a/icons/effects/beam.dmi b/icons/effects/beam.dmi
index 0c4784553c..e5bff44ac4 100644
Binary files a/icons/effects/beam.dmi and b/icons/effects/beam.dmi differ
diff --git a/icons/effects/beam_splash.dmi b/icons/effects/beam_splash.dmi
new file mode 100644
index 0000000000..d7deb3e927
Binary files /dev/null and b/icons/effects/beam_splash.dmi differ
diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi
index a2fce4678f..52164e1d33 100644
Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ
diff --git a/icons/effects/eldritch.dmi b/icons/effects/eldritch.dmi
new file mode 100644
index 0000000000..82549dccf0
Binary files /dev/null and b/icons/effects/eldritch.dmi differ
diff --git a/icons/effects/mouse_pointers/barn_target.dmi b/icons/effects/mouse_pointers/barn_target.dmi
new file mode 100644
index 0000000000..475a2b88b1
Binary files /dev/null and b/icons/effects/mouse_pointers/barn_target.dmi differ
diff --git a/icons/effects/mouse_pointers/blind_target.dmi b/icons/effects/mouse_pointers/blind_target.dmi
new file mode 100644
index 0000000000..1d33fc7a4c
Binary files /dev/null and b/icons/effects/mouse_pointers/blind_target.dmi differ
diff --git a/icons/effects/mouse_pointers/cult_target.dmi b/icons/effects/mouse_pointers/cult_target.dmi
new file mode 100644
index 0000000000..650feb3361
Binary files /dev/null and b/icons/effects/mouse_pointers/cult_target.dmi differ
diff --git a/icons/effects/mouse_pointers/mecha_mouse-disable.dmi b/icons/effects/mouse_pointers/mecha_mouse-disable.dmi
new file mode 100644
index 0000000000..48924c58c2
Binary files /dev/null and b/icons/effects/mouse_pointers/mecha_mouse-disable.dmi differ
diff --git a/icons/effects/mouse_pointers/mecha_mouse.dmi b/icons/effects/mouse_pointers/mecha_mouse.dmi
new file mode 100644
index 0000000000..4b46a44684
Binary files /dev/null and b/icons/effects/mouse_pointers/mecha_mouse.dmi differ
diff --git a/icons/effects/mouse_pointers/mindswap_target.dmi b/icons/effects/mouse_pointers/mindswap_target.dmi
new file mode 100644
index 0000000000..32ccda154d
Binary files /dev/null and b/icons/effects/mouse_pointers/mindswap_target.dmi differ
diff --git a/icons/effects/mouse_pointers/overload_machine_target.dmi b/icons/effects/mouse_pointers/overload_machine_target.dmi
new file mode 100644
index 0000000000..8bc67cdab6
Binary files /dev/null and b/icons/effects/mouse_pointers/overload_machine_target.dmi differ
diff --git a/icons/effects/mouse_pointers/override_machine_target.dmi b/icons/effects/mouse_pointers/override_machine_target.dmi
new file mode 100644
index 0000000000..77dbb4ba32
Binary files /dev/null and b/icons/effects/mouse_pointers/override_machine_target.dmi differ
diff --git a/icons/effects/mouse_pointers/throw_target.dmi b/icons/effects/mouse_pointers/throw_target.dmi
new file mode 100644
index 0000000000..660eafbf2b
Binary files /dev/null and b/icons/effects/mouse_pointers/throw_target.dmi differ
diff --git a/icons/effects/mouse_pointers/wrap_target.dmi b/icons/effects/mouse_pointers/wrap_target.dmi
new file mode 100644
index 0000000000..2e9a338c9e
Binary files /dev/null and b/icons/effects/mouse_pointers/wrap_target.dmi differ
diff --git a/icons/mob/actions/actions_ecult.dmi b/icons/mob/actions/actions_ecult.dmi
new file mode 100644
index 0000000000..0a130f006e
Binary files /dev/null and b/icons/mob/actions/actions_ecult.dmi differ
diff --git a/icons/mob/actions/backgrounds.dmi b/icons/mob/actions/backgrounds.dmi
index 07839588ce..6b983df95a 100644
Binary files a/icons/mob/actions/backgrounds.dmi and b/icons/mob/actions/backgrounds.dmi differ
diff --git a/icons/mob/clothing/back.dmi b/icons/mob/clothing/back.dmi
index 9490595484..8594af8ec2 100644
Binary files a/icons/mob/clothing/back.dmi and b/icons/mob/clothing/back.dmi differ
diff --git a/icons/mob/clothing/belt.dmi b/icons/mob/clothing/belt.dmi
index 52ef75020c..4ac82ca299 100644
Binary files a/icons/mob/clothing/belt.dmi and b/icons/mob/clothing/belt.dmi differ
diff --git a/icons/mob/clothing/hands.dmi b/icons/mob/clothing/hands.dmi
index 755280b332..44499649f9 100644
Binary files a/icons/mob/clothing/hands.dmi and b/icons/mob/clothing/hands.dmi differ
diff --git a/icons/mob/clothing/head.dmi b/icons/mob/clothing/head.dmi
index 0ad9452994..16571a4aa1 100644
Binary files a/icons/mob/clothing/head.dmi and b/icons/mob/clothing/head.dmi differ
diff --git a/icons/mob/clothing/neck.dmi b/icons/mob/clothing/neck.dmi
index 86dec62a41..7bfecb4158 100644
Binary files a/icons/mob/clothing/neck.dmi and b/icons/mob/clothing/neck.dmi differ
diff --git a/icons/mob/clothing/suit.dmi b/icons/mob/clothing/suit.dmi
index c94e8a46d3..08d276a484 100644
Binary files a/icons/mob/clothing/suit.dmi and b/icons/mob/clothing/suit.dmi differ
diff --git a/icons/mob/eldritch_mobs.dmi b/icons/mob/eldritch_mobs.dmi
new file mode 100644
index 0000000000..8a16d53f88
Binary files /dev/null and b/icons/mob/eldritch_mobs.dmi differ
diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi
index c6dc7130c7..1d2007fd63 100644
Binary files a/icons/mob/hud.dmi and b/icons/mob/hud.dmi differ
diff --git a/icons/mob/human_parts.dmi b/icons/mob/human_parts.dmi
index 916686e63f..60978d55a2 100644
Binary files a/icons/mob/human_parts.dmi and b/icons/mob/human_parts.dmi differ
diff --git a/icons/mob/human_parts_greyscale.dmi b/icons/mob/human_parts_greyscale.dmi
index 989ec8049c..794074bfe4 100644
Binary files a/icons/mob/human_parts_greyscale.dmi and b/icons/mob/human_parts_greyscale.dmi differ
diff --git a/icons/mob/inhands/64x64_lefthand.dmi b/icons/mob/inhands/64x64_lefthand.dmi
index 6b47171066..6dc8d82753 100644
Binary files a/icons/mob/inhands/64x64_lefthand.dmi and b/icons/mob/inhands/64x64_lefthand.dmi differ
diff --git a/icons/mob/inhands/64x64_righthand.dmi b/icons/mob/inhands/64x64_righthand.dmi
index 3750e28906..ca87f74a6f 100644
Binary files a/icons/mob/inhands/64x64_righthand.dmi and b/icons/mob/inhands/64x64_righthand.dmi differ
diff --git a/icons/mob/inhands/weapons/swords_lefthand.dmi b/icons/mob/inhands/weapons/swords_lefthand.dmi
index 0ca36ad43d..23d80af9ef 100644
Binary files a/icons/mob/inhands/weapons/swords_lefthand.dmi and b/icons/mob/inhands/weapons/swords_lefthand.dmi differ
diff --git a/icons/mob/inhands/weapons/swords_righthand.dmi b/icons/mob/inhands/weapons/swords_righthand.dmi
index 59d7bbce69..702c0299b5 100644
Binary files a/icons/mob/inhands/weapons/swords_righthand.dmi and b/icons/mob/inhands/weapons/swords_righthand.dmi differ
diff --git a/icons/mob/mob.dmi b/icons/mob/mob.dmi
index de09fb1c63..23f0e2cc13 100644
Binary files a/icons/mob/mob.dmi and b/icons/mob/mob.dmi differ
diff --git a/icons/mob/wings.dmi b/icons/mob/wings.dmi
index ace37b1f17..4523403344 100644
Binary files a/icons/mob/wings.dmi and b/icons/mob/wings.dmi differ
diff --git a/icons/obj/chemical.dmi b/icons/obj/chemical.dmi
index aea15e2e39..cd12f4a457 100644
Binary files a/icons/obj/chemical.dmi and b/icons/obj/chemical.dmi differ
diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi
index 874f0d3660..c0f78ee604 100644
Binary files a/icons/obj/clothing/gloves.dmi and b/icons/obj/clothing/gloves.dmi differ
diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi
index 60304999fa..8fbb2abe1e 100644
Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ
diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi
index e8a360bc87..3476b16258 100644
Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ
diff --git a/icons/obj/decals.dmi b/icons/obj/decals.dmi
index c280ee786f..7dac61a663 100644
Binary files a/icons/obj/decals.dmi and b/icons/obj/decals.dmi differ
diff --git a/icons/obj/eldritch.dmi b/icons/obj/eldritch.dmi
new file mode 100644
index 0000000000..50c2913708
Binary files /dev/null and b/icons/obj/eldritch.dmi differ
diff --git a/icons/obj/guns/projectile.dmi b/icons/obj/guns/projectile.dmi
index 9c6df36f49..00670916db 100644
Binary files a/icons/obj/guns/projectile.dmi and b/icons/obj/guns/projectile.dmi differ
diff --git a/icons/obj/hydroponics/growing.dmi b/icons/obj/hydroponics/growing.dmi
index 5415f47528..0866791ed6 100644
Binary files a/icons/obj/hydroponics/growing.dmi and b/icons/obj/hydroponics/growing.dmi differ
diff --git a/icons/obj/hydroponics/growing_vegetables.dmi b/icons/obj/hydroponics/growing_vegetables.dmi
index e174b4fb0b..ce0beb86ce 100644
Binary files a/icons/obj/hydroponics/growing_vegetables.dmi and b/icons/obj/hydroponics/growing_vegetables.dmi differ
diff --git a/icons/obj/items_and_weapons.dmi b/icons/obj/items_and_weapons.dmi
index 57105cc089..c5aca2394f 100644
Binary files a/icons/obj/items_and_weapons.dmi and b/icons/obj/items_and_weapons.dmi differ
diff --git a/icons/obj/lavaland/terrain.dmi b/icons/obj/lavaland/terrain.dmi
new file mode 100644
index 0000000000..4db51145ee
Binary files /dev/null and b/icons/obj/lavaland/terrain.dmi differ
diff --git a/icons/obj/machines/medipen_refiller.dmi b/icons/obj/machines/medipen_refiller.dmi
new file mode 100644
index 0000000000..300d218d2d
Binary files /dev/null and b/icons/obj/machines/medipen_refiller.dmi differ
diff --git a/icons/obj/plumbing/fluid_ducts.dmi b/icons/obj/plumbing/fluid_ducts.dmi
new file mode 100644
index 0000000000..87d9d2233b
Binary files /dev/null and b/icons/obj/plumbing/fluid_ducts.dmi differ
diff --git a/icons/obj/plumbing/plumbers.dmi b/icons/obj/plumbing/plumbers.dmi
new file mode 100644
index 0000000000..242622e000
Binary files /dev/null and b/icons/obj/plumbing/plumbers.dmi differ
diff --git a/icons/obj/projectiles.dmi b/icons/obj/projectiles.dmi
index 92e76f78bb..94568b8633 100644
Binary files a/icons/obj/projectiles.dmi and b/icons/obj/projectiles.dmi differ
diff --git a/icons/obj/reagentfillings.dmi b/icons/obj/reagentfillings.dmi
index d7a9a03c41..1ac941bae3 100644
Binary files a/icons/obj/reagentfillings.dmi and b/icons/obj/reagentfillings.dmi differ
diff --git a/icons/obj/watercloset.dmi b/icons/obj/watercloset.dmi
index 4a299f29dd..2b64176878 100644
Binary files a/icons/obj/watercloset.dmi and b/icons/obj/watercloset.dmi differ
diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi
index 83dd4f5df8..f2b84bbe03 100644
Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ
diff --git a/icons/turf/floors/glass.dmi b/icons/turf/floors/glass.dmi
new file mode 100644
index 0000000000..adf6f57aaa
Binary files /dev/null and b/icons/turf/floors/glass.dmi differ
diff --git a/icons/turf/floors/reinf_glass.dmi b/icons/turf/floors/reinf_glass.dmi
new file mode 100644
index 0000000000..dda99cd07f
Binary files /dev/null and b/icons/turf/floors/reinf_glass.dmi differ
diff --git a/modular_citadel/code/modules/client/loadout/__donator.dm b/modular_citadel/code/modules/client/loadout/__donator.dm
index 378c70d187..06783df03d 100644
--- a/modular_citadel/code/modules/client/loadout/__donator.dm
+++ b/modular_citadel/code/modules/client/loadout/__donator.dm
@@ -7,6 +7,27 @@
category = LOADOUT_CATEGORY_DONATOR
ckeywhitelist = list("This entry should never appear with this variable set.") //If it does, then that means somebody fucked up the whitelist system pretty hard
+/datum/gear/donator/pet
+ name = "Pet Beacon"
+ slot = SLOT_IN_BACKPACK
+ path = /obj/item/choice_beacon/pet
+ ckeywhitelist = list()
+ donator_group_id = DONATOR_GROUP_TIER_1 // can be accessed by all donators
+
+/datum/gear/donator/carpet
+ name = "Carpet Beacon"
+ slot = SLOT_IN_BACKPACK
+ path = /obj/item/choice_beacon/box/carpet
+ ckeywhitelist = list()
+ donator_group_id = DONATOR_GROUP_TIER_1
+
+/datum/gear/donator/chameleon_bedsheet
+ name = "Chameleon Bedsheet"
+ slot = SLOT_NECK
+ path = /obj/item/bedsheet/chameleon
+ ckeywhitelist = list()
+ donator_group_id = DONATOR_GROUP_TIER_1
+
/datum/gear/donator/donortestingbikehorn
name = "Donor item testing bikehorn"
slot = SLOT_IN_BACKPACK
diff --git a/modular_citadel/code/modules/client/loadout/gloves.dm b/modular_citadel/code/modules/client/loadout/gloves.dm
index ffa4724f63..09694ddec7 100644
--- a/modular_citadel/code/modules/client/loadout/gloves.dm
+++ b/modular_citadel/code/modules/client/loadout/gloves.dm
@@ -9,6 +9,10 @@
/datum/gear/gloves/evening
name = "Evening gloves"
path = /obj/item/clothing/gloves/evening
+
+/datum/gear/gloves/midnight
+ name = "Midnight gloves"
+ path = /obj/item/clothing/gloves/evening/black
/datum/gear/gloves/goldring
name = "A gold ring"
diff --git a/modular_citadel/code/modules/projectiles/guns/ballistic/handguns.dm b/modular_citadel/code/modules/projectiles/guns/ballistic/handguns.dm
index 20917c4ba5..4829fd921c 100644
--- a/modular_citadel/code/modules/projectiles/guns/ballistic/handguns.dm
+++ b/modular_citadel/code/modules/projectiles/guns/ballistic/handguns.dm
@@ -16,13 +16,12 @@
spread = 20
actions_types = list()
-/obj/item/gun/ballistic/automatic/toy/pistol/stealth/update_icon()
- ..()
+/obj/item/gun/ballistic/automatic/toy/pistol/stealth/update_overlays()
+ . = ..()
if(magazine)
- cut_overlays()
- add_overlay("foamsp-magazine")
- else
- cut_overlays()
+ . += "foamsp-magazine"
+
+/obj/item/gun/ballistic/automatic/toy/pistol/stealth/update_icon_state()
icon_state = "[initial(icon_state)][chambered ? "" : "-e"]"
/////////RAYGUN MEMES/////////
diff --git a/modular_citadel/code/modules/projectiles/guns/ballistic/rifles.dm b/modular_citadel/code/modules/projectiles/guns/ballistic/rifles.dm
index 8a1310d2f1..c2bf251de9 100644
--- a/modular_citadel/code/modules/projectiles/guns/ballistic/rifles.dm
+++ b/modular_citadel/code/modules/projectiles/guns/ballistic/rifles.dm
@@ -155,11 +155,15 @@
casing_ejector = 0
spread = 10
recoil = 0.05
+ automatic_burst_overlay = FALSE
+ var/magtype = "flechettegun"
-/obj/item/gun/ballistic/automatic/flechette/update_icon()
- cut_overlays()
+/obj/item/gun/ballistic/automatic/flechette/update_overlays()
+ . = ..()
if(magazine)
- add_overlay("flechettegun-magazine")
+ . += "[magtype]-magazine"
+
+/obj/item/gun/ballistic/automatic/flechette/update_icon_state()
icon_state = "[initial(icon_state)][chambered ? "" : "-e"]"
///unique variant///
@@ -185,12 +189,7 @@
w_class = WEIGHT_CLASS_SMALL
spread = 15
recoil = 0.1
-
-/obj/item/gun/ballistic/automatic/flechette/shredder/update_icon()
- cut_overlays()
- if(magazine)
- add_overlay("shreddergun-magazine")
- icon_state = "[initial(icon_state)][chambered ? "" : "-e"]"
+ magtype = "shreddergun"
/*/////////////////////////////////////////////////////////////
//////////////////////// Zero's Meme //////////////////////////
@@ -218,17 +217,19 @@
burst_size = 4 //Shh.
fire_delay = 1
var/body_color = "#3333aa"
+ automatic_burst_overlay = FALSE
-/obj/item/gun/ballistic/automatic/AM4B/update_icon()
- ..()
+/obj/item/gun/ballistic/automatic/AM4B/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/update_icon_updates_onmob)
+
+/obj/item/gun/ballistic/automatic/AM4B/update_overlays()
+ . = ..()
var/mutable_appearance/body_overlay = mutable_appearance('modular_citadel/icons/obj/guns/cit_guns.dmi', "AM4-Body")
if(body_color)
body_overlay.color = body_color
- cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other
- add_overlay(body_overlay)
- if(ismob(loc))
- var/mob/M = loc
- M.update_inv_hands()
+ . += body_overlay
+
/obj/item/gun/ballistic/automatic/AM4B/AltClick(mob/living/user)
. = ..()
if(!in_range(src, user)) //Basic checks to prevent abuse
diff --git a/modular_citadel/code/modules/projectiles/guns/ballistic/spinfusor.dm b/modular_citadel/code/modules/projectiles/guns/ballistic/spinfusor.dm
index 3c0a47bfd7..c4cf8fc00f 100644
--- a/modular_citadel/code/modules/projectiles/guns/ballistic/spinfusor.dm
+++ b/modular_citadel/code/modules/projectiles/guns/ballistic/spinfusor.dm
@@ -55,8 +55,7 @@
/obj/item/gun/ballistic/automatic/spinfusor/attack_self(mob/living/user)
return //caseless rounds are too glitchy to unload properly. Best to make it so that you cannot remove disks from the spinfusor
-/obj/item/gun/ballistic/automatic/spinfusor/update_icon()
- ..()
+/obj/item/gun/ballistic/automatic/spinfusor/update_icon_state()
icon_state = "spinfusor[magazine ? "-[get_ammo(1)]" : ""]"
/obj/item/ammo_box/aspinfusor
diff --git a/modular_citadel/code/modules/projectiles/guns/energy/energy_gun.dm b/modular_citadel/code/modules/projectiles/guns/energy/energy_gun.dm
index 49d48e0000..65609f5830 100644
--- a/modular_citadel/code/modules/projectiles/guns/energy/energy_gun.dm
+++ b/modular_citadel/code/modules/projectiles/guns/energy/energy_gun.dm
@@ -14,16 +14,16 @@ obj/item/gun/energy/e_gun/cx
flight_y_offset = 10
var/body_color = "#252528"
-obj/item/gun/energy/e_gun/cx/update_icon()
- ..()
+obj/item/gun/energy/e_gun/cx/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/update_icon_updates_onmob)
+
+obj/item/gun/energy/e_gun/cx/update_overlays()
+ . = ..()
var/mutable_appearance/body_overlay = mutable_appearance('modular_citadel/icons/obj/guns/cit_guns.dmi', "cxegun_body")
if(body_color)
body_overlay.color = body_color
- add_overlay(body_overlay)
-
- if(ismob(loc))
- var/mob/M = loc
- M.update_inv_hands()
+ . += body_overlay
obj/item/gun/energy/e_gun/cx/AltClick(mob/living/user)
. = ..()
diff --git a/modular_citadel/code/modules/projectiles/guns/pumpenergy.dm b/modular_citadel/code/modules/projectiles/guns/pumpenergy.dm
index b864a9fe25..e81c7c18d3 100644
--- a/modular_citadel/code/modules/projectiles/guns/pumpenergy.dm
+++ b/modular_citadel/code/modules/projectiles/guns/pumpenergy.dm
@@ -52,13 +52,13 @@
if(has_shot)
recharge_newshot(TRUE)
-/obj/item/gun/energy/pumpaction/update_icon() //adds racked indicators
+/obj/item/gun/energy/pumpaction/update_overlays() //adds racked indicators
..()
var/obj/item/ammo_casing/energy/shot = ammo_type[current_firemode_index]
if(chambered)
- add_overlay("[icon_state]_rack_[shot.select_name]")
+ . += "[icon_state]_rack_[shot.select_name]"
else
- add_overlay("[icon_state]_rack_empty")
+ . += "[icon_state]_rack_empty"
/obj/item/gun/energy/pumpaction/proc/pump(mob/M) //pumping proc. Checks if the gun is empty and plays a different sound if it is.
var/obj/item/ammo_casing/energy/shot = ammo_type[current_firemode_index]
diff --git a/modular_citadel/icons/mob/citadel_refs/furry_parts_greyscale.dmi b/modular_citadel/icons/mob/citadel_refs/furry_parts_greyscale.dmi
deleted file mode 100644
index c8d5ceb0a6..0000000000
Binary files a/modular_citadel/icons/mob/citadel_refs/furry_parts_greyscale.dmi and /dev/null differ
diff --git a/modular_citadel/icons/mob/mutant_bodyparts.dmi b/modular_citadel/icons/mob/mutant_bodyparts.dmi
deleted file mode 100644
index 6098dd3567..0000000000
Binary files a/modular_citadel/icons/mob/mutant_bodyparts.dmi and /dev/null differ
diff --git a/sound/ambience/antag/ecult_op.ogg b/sound/ambience/antag/ecult_op.ogg
new file mode 100644
index 0000000000..9944e833a6
Binary files /dev/null and b/sound/ambience/antag/ecult_op.ogg differ
diff --git a/sound/effects/footstep/rustystep1.ogg b/sound/effects/footstep/rustystep1.ogg
new file mode 100644
index 0000000000..bf90d52779
Binary files /dev/null and b/sound/effects/footstep/rustystep1.ogg differ
diff --git a/sound/machines/sm/accent/delam/1.ogg b/sound/machines/sm/accent/delam/1.ogg
new file mode 100644
index 0000000000..75c79f89ab
Binary files /dev/null and b/sound/machines/sm/accent/delam/1.ogg differ
diff --git a/sound/machines/sm/accent/delam/10.ogg b/sound/machines/sm/accent/delam/10.ogg
new file mode 100644
index 0000000000..c87b63b526
Binary files /dev/null and b/sound/machines/sm/accent/delam/10.ogg differ
diff --git a/sound/machines/sm/accent/delam/11.ogg b/sound/machines/sm/accent/delam/11.ogg
new file mode 100644
index 0000000000..c7f678245b
Binary files /dev/null and b/sound/machines/sm/accent/delam/11.ogg differ
diff --git a/sound/machines/sm/accent/delam/12.ogg b/sound/machines/sm/accent/delam/12.ogg
new file mode 100644
index 0000000000..a395942183
Binary files /dev/null and b/sound/machines/sm/accent/delam/12.ogg differ
diff --git a/sound/machines/sm/accent/delam/13.ogg b/sound/machines/sm/accent/delam/13.ogg
new file mode 100644
index 0000000000..934f17947d
Binary files /dev/null and b/sound/machines/sm/accent/delam/13.ogg differ
diff --git a/sound/machines/sm/accent/delam/14.ogg b/sound/machines/sm/accent/delam/14.ogg
new file mode 100644
index 0000000000..4175e5b947
Binary files /dev/null and b/sound/machines/sm/accent/delam/14.ogg differ
diff --git a/sound/machines/sm/accent/delam/15.ogg b/sound/machines/sm/accent/delam/15.ogg
new file mode 100644
index 0000000000..dcf73deb84
Binary files /dev/null and b/sound/machines/sm/accent/delam/15.ogg differ
diff --git a/sound/machines/sm/accent/delam/16.ogg b/sound/machines/sm/accent/delam/16.ogg
new file mode 100644
index 0000000000..20bc19399b
Binary files /dev/null and b/sound/machines/sm/accent/delam/16.ogg differ
diff --git a/sound/machines/sm/accent/delam/17.ogg b/sound/machines/sm/accent/delam/17.ogg
new file mode 100644
index 0000000000..b517fb3d3d
Binary files /dev/null and b/sound/machines/sm/accent/delam/17.ogg differ
diff --git a/sound/machines/sm/accent/delam/18.ogg b/sound/machines/sm/accent/delam/18.ogg
new file mode 100644
index 0000000000..4ef138d27a
Binary files /dev/null and b/sound/machines/sm/accent/delam/18.ogg differ
diff --git a/sound/machines/sm/accent/delam/19.ogg b/sound/machines/sm/accent/delam/19.ogg
new file mode 100644
index 0000000000..f638a6971b
Binary files /dev/null and b/sound/machines/sm/accent/delam/19.ogg differ
diff --git a/sound/machines/sm/accent/delam/2.ogg b/sound/machines/sm/accent/delam/2.ogg
new file mode 100644
index 0000000000..5b480daa2e
Binary files /dev/null and b/sound/machines/sm/accent/delam/2.ogg differ
diff --git a/sound/machines/sm/accent/delam/20.ogg b/sound/machines/sm/accent/delam/20.ogg
new file mode 100644
index 0000000000..6072bc6227
Binary files /dev/null and b/sound/machines/sm/accent/delam/20.ogg differ
diff --git a/sound/machines/sm/accent/delam/21.ogg b/sound/machines/sm/accent/delam/21.ogg
new file mode 100644
index 0000000000..1223dd946d
Binary files /dev/null and b/sound/machines/sm/accent/delam/21.ogg differ
diff --git a/sound/machines/sm/accent/delam/22.ogg b/sound/machines/sm/accent/delam/22.ogg
new file mode 100644
index 0000000000..9ccfb9b55a
Binary files /dev/null and b/sound/machines/sm/accent/delam/22.ogg differ
diff --git a/sound/machines/sm/accent/delam/23.ogg b/sound/machines/sm/accent/delam/23.ogg
new file mode 100644
index 0000000000..6399a8376a
Binary files /dev/null and b/sound/machines/sm/accent/delam/23.ogg differ
diff --git a/sound/machines/sm/accent/delam/24.ogg b/sound/machines/sm/accent/delam/24.ogg
new file mode 100644
index 0000000000..b51d359807
Binary files /dev/null and b/sound/machines/sm/accent/delam/24.ogg differ
diff --git a/sound/machines/sm/accent/delam/25.ogg b/sound/machines/sm/accent/delam/25.ogg
new file mode 100644
index 0000000000..823f22f136
Binary files /dev/null and b/sound/machines/sm/accent/delam/25.ogg differ
diff --git a/sound/machines/sm/accent/delam/26.ogg b/sound/machines/sm/accent/delam/26.ogg
new file mode 100644
index 0000000000..24b2a2f040
Binary files /dev/null and b/sound/machines/sm/accent/delam/26.ogg differ
diff --git a/sound/machines/sm/accent/delam/27.ogg b/sound/machines/sm/accent/delam/27.ogg
new file mode 100644
index 0000000000..4b4b145b7b
Binary files /dev/null and b/sound/machines/sm/accent/delam/27.ogg differ
diff --git a/sound/machines/sm/accent/delam/28.ogg b/sound/machines/sm/accent/delam/28.ogg
new file mode 100644
index 0000000000..7bc71bf0e6
Binary files /dev/null and b/sound/machines/sm/accent/delam/28.ogg differ
diff --git a/sound/machines/sm/accent/delam/29.ogg b/sound/machines/sm/accent/delam/29.ogg
new file mode 100644
index 0000000000..7fec2f271c
Binary files /dev/null and b/sound/machines/sm/accent/delam/29.ogg differ
diff --git a/sound/machines/sm/accent/delam/3.ogg b/sound/machines/sm/accent/delam/3.ogg
new file mode 100644
index 0000000000..5b57cc2707
Binary files /dev/null and b/sound/machines/sm/accent/delam/3.ogg differ
diff --git a/sound/machines/sm/accent/delam/30.ogg b/sound/machines/sm/accent/delam/30.ogg
new file mode 100644
index 0000000000..ed1ec7d89f
Binary files /dev/null and b/sound/machines/sm/accent/delam/30.ogg differ
diff --git a/sound/machines/sm/accent/delam/31.ogg b/sound/machines/sm/accent/delam/31.ogg
new file mode 100644
index 0000000000..0baa82e246
Binary files /dev/null and b/sound/machines/sm/accent/delam/31.ogg differ
diff --git a/sound/machines/sm/accent/delam/32.ogg b/sound/machines/sm/accent/delam/32.ogg
new file mode 100644
index 0000000000..e925b32d67
Binary files /dev/null and b/sound/machines/sm/accent/delam/32.ogg differ
diff --git a/sound/machines/sm/accent/delam/33.ogg b/sound/machines/sm/accent/delam/33.ogg
new file mode 100644
index 0000000000..9ddec0e84a
Binary files /dev/null and b/sound/machines/sm/accent/delam/33.ogg differ
diff --git a/sound/machines/sm/accent/delam/4.ogg b/sound/machines/sm/accent/delam/4.ogg
new file mode 100644
index 0000000000..aa4f4da071
Binary files /dev/null and b/sound/machines/sm/accent/delam/4.ogg differ
diff --git a/sound/machines/sm/accent/delam/5.ogg b/sound/machines/sm/accent/delam/5.ogg
new file mode 100644
index 0000000000..be438f6f15
Binary files /dev/null and b/sound/machines/sm/accent/delam/5.ogg differ
diff --git a/sound/machines/sm/accent/delam/6.ogg b/sound/machines/sm/accent/delam/6.ogg
new file mode 100644
index 0000000000..b89d52a564
Binary files /dev/null and b/sound/machines/sm/accent/delam/6.ogg differ
diff --git a/sound/machines/sm/accent/delam/7.ogg b/sound/machines/sm/accent/delam/7.ogg
new file mode 100644
index 0000000000..3a9cfc62ca
Binary files /dev/null and b/sound/machines/sm/accent/delam/7.ogg differ
diff --git a/sound/machines/sm/accent/delam/8.ogg b/sound/machines/sm/accent/delam/8.ogg
new file mode 100644
index 0000000000..7bc0a727fa
Binary files /dev/null and b/sound/machines/sm/accent/delam/8.ogg differ
diff --git a/sound/machines/sm/accent/delam/9.ogg b/sound/machines/sm/accent/delam/9.ogg
new file mode 100644
index 0000000000..5c1bd37405
Binary files /dev/null and b/sound/machines/sm/accent/delam/9.ogg differ
diff --git a/sound/machines/sm/accent/normal/1.ogg b/sound/machines/sm/accent/normal/1.ogg
new file mode 100644
index 0000000000..e92beed7fe
Binary files /dev/null and b/sound/machines/sm/accent/normal/1.ogg differ
diff --git a/sound/machines/sm/accent/normal/10.ogg b/sound/machines/sm/accent/normal/10.ogg
new file mode 100644
index 0000000000..9efb616f0b
Binary files /dev/null and b/sound/machines/sm/accent/normal/10.ogg differ
diff --git a/sound/machines/sm/accent/normal/11.ogg b/sound/machines/sm/accent/normal/11.ogg
new file mode 100644
index 0000000000..2af0981ef1
Binary files /dev/null and b/sound/machines/sm/accent/normal/11.ogg differ
diff --git a/sound/machines/sm/accent/normal/12.ogg b/sound/machines/sm/accent/normal/12.ogg
new file mode 100644
index 0000000000..2fab78b02d
Binary files /dev/null and b/sound/machines/sm/accent/normal/12.ogg differ
diff --git a/sound/machines/sm/accent/normal/13.ogg b/sound/machines/sm/accent/normal/13.ogg
new file mode 100644
index 0000000000..784e84e4a8
Binary files /dev/null and b/sound/machines/sm/accent/normal/13.ogg differ
diff --git a/sound/machines/sm/accent/normal/14.ogg b/sound/machines/sm/accent/normal/14.ogg
new file mode 100644
index 0000000000..af170394dd
Binary files /dev/null and b/sound/machines/sm/accent/normal/14.ogg differ
diff --git a/sound/machines/sm/accent/normal/15.ogg b/sound/machines/sm/accent/normal/15.ogg
new file mode 100644
index 0000000000..05c88c6b29
Binary files /dev/null and b/sound/machines/sm/accent/normal/15.ogg differ
diff --git a/sound/machines/sm/accent/normal/16.ogg b/sound/machines/sm/accent/normal/16.ogg
new file mode 100644
index 0000000000..46b0e33980
Binary files /dev/null and b/sound/machines/sm/accent/normal/16.ogg differ
diff --git a/sound/machines/sm/accent/normal/17.ogg b/sound/machines/sm/accent/normal/17.ogg
new file mode 100644
index 0000000000..e432b2ee02
Binary files /dev/null and b/sound/machines/sm/accent/normal/17.ogg differ
diff --git a/sound/machines/sm/accent/normal/18.ogg b/sound/machines/sm/accent/normal/18.ogg
new file mode 100644
index 0000000000..1e0e91abc8
Binary files /dev/null and b/sound/machines/sm/accent/normal/18.ogg differ
diff --git a/sound/machines/sm/accent/normal/19.ogg b/sound/machines/sm/accent/normal/19.ogg
new file mode 100644
index 0000000000..31de063e02
Binary files /dev/null and b/sound/machines/sm/accent/normal/19.ogg differ
diff --git a/sound/machines/sm/accent/normal/2.ogg b/sound/machines/sm/accent/normal/2.ogg
new file mode 100644
index 0000000000..05e3c9ff17
Binary files /dev/null and b/sound/machines/sm/accent/normal/2.ogg differ
diff --git a/sound/machines/sm/accent/normal/20.ogg b/sound/machines/sm/accent/normal/20.ogg
new file mode 100644
index 0000000000..36810bd8f1
Binary files /dev/null and b/sound/machines/sm/accent/normal/20.ogg differ
diff --git a/sound/machines/sm/accent/normal/21.ogg b/sound/machines/sm/accent/normal/21.ogg
new file mode 100644
index 0000000000..306e8856e5
Binary files /dev/null and b/sound/machines/sm/accent/normal/21.ogg differ
diff --git a/sound/machines/sm/accent/normal/22.ogg b/sound/machines/sm/accent/normal/22.ogg
new file mode 100644
index 0000000000..38286aa98b
Binary files /dev/null and b/sound/machines/sm/accent/normal/22.ogg differ
diff --git a/sound/machines/sm/accent/normal/23.ogg b/sound/machines/sm/accent/normal/23.ogg
new file mode 100644
index 0000000000..89f85fed91
Binary files /dev/null and b/sound/machines/sm/accent/normal/23.ogg differ
diff --git a/sound/machines/sm/accent/normal/24.ogg b/sound/machines/sm/accent/normal/24.ogg
new file mode 100644
index 0000000000..7c12a3e768
Binary files /dev/null and b/sound/machines/sm/accent/normal/24.ogg differ
diff --git a/sound/machines/sm/accent/normal/25.ogg b/sound/machines/sm/accent/normal/25.ogg
new file mode 100644
index 0000000000..f89175ceb1
Binary files /dev/null and b/sound/machines/sm/accent/normal/25.ogg differ
diff --git a/sound/machines/sm/accent/normal/26.ogg b/sound/machines/sm/accent/normal/26.ogg
new file mode 100644
index 0000000000..9efd1d8ef3
Binary files /dev/null and b/sound/machines/sm/accent/normal/26.ogg differ
diff --git a/sound/machines/sm/accent/normal/27.ogg b/sound/machines/sm/accent/normal/27.ogg
new file mode 100644
index 0000000000..1fb1edbb5a
Binary files /dev/null and b/sound/machines/sm/accent/normal/27.ogg differ
diff --git a/sound/machines/sm/accent/normal/28.ogg b/sound/machines/sm/accent/normal/28.ogg
new file mode 100644
index 0000000000..890c5ea429
Binary files /dev/null and b/sound/machines/sm/accent/normal/28.ogg differ
diff --git a/sound/machines/sm/accent/normal/29.ogg b/sound/machines/sm/accent/normal/29.ogg
new file mode 100644
index 0000000000..cd2aa40714
Binary files /dev/null and b/sound/machines/sm/accent/normal/29.ogg differ
diff --git a/sound/machines/sm/accent/normal/3.ogg b/sound/machines/sm/accent/normal/3.ogg
new file mode 100644
index 0000000000..38de5571a4
Binary files /dev/null and b/sound/machines/sm/accent/normal/3.ogg differ
diff --git a/sound/machines/sm/accent/normal/30.ogg b/sound/machines/sm/accent/normal/30.ogg
new file mode 100644
index 0000000000..87d1782768
Binary files /dev/null and b/sound/machines/sm/accent/normal/30.ogg differ
diff --git a/sound/machines/sm/accent/normal/31.ogg b/sound/machines/sm/accent/normal/31.ogg
new file mode 100644
index 0000000000..9ce3eeb72e
Binary files /dev/null and b/sound/machines/sm/accent/normal/31.ogg differ
diff --git a/sound/machines/sm/accent/normal/32.ogg b/sound/machines/sm/accent/normal/32.ogg
new file mode 100644
index 0000000000..26ca056142
Binary files /dev/null and b/sound/machines/sm/accent/normal/32.ogg differ
diff --git a/sound/machines/sm/accent/normal/33.ogg b/sound/machines/sm/accent/normal/33.ogg
new file mode 100644
index 0000000000..24964c1ce9
Binary files /dev/null and b/sound/machines/sm/accent/normal/33.ogg differ
diff --git a/sound/machines/sm/accent/normal/4.ogg b/sound/machines/sm/accent/normal/4.ogg
new file mode 100644
index 0000000000..2e71e976e8
Binary files /dev/null and b/sound/machines/sm/accent/normal/4.ogg differ
diff --git a/sound/machines/sm/accent/normal/5.ogg b/sound/machines/sm/accent/normal/5.ogg
new file mode 100644
index 0000000000..04852e10f2
Binary files /dev/null and b/sound/machines/sm/accent/normal/5.ogg differ
diff --git a/sound/machines/sm/accent/normal/6.ogg b/sound/machines/sm/accent/normal/6.ogg
new file mode 100644
index 0000000000..bf06c06bbe
Binary files /dev/null and b/sound/machines/sm/accent/normal/6.ogg differ
diff --git a/sound/machines/sm/accent/normal/7.ogg b/sound/machines/sm/accent/normal/7.ogg
new file mode 100644
index 0000000000..d29821701f
Binary files /dev/null and b/sound/machines/sm/accent/normal/7.ogg differ
diff --git a/sound/machines/sm/accent/normal/8.ogg b/sound/machines/sm/accent/normal/8.ogg
new file mode 100644
index 0000000000..0b94b9dbe0
Binary files /dev/null and b/sound/machines/sm/accent/normal/8.ogg differ
diff --git a/sound/machines/sm/accent/normal/9.ogg b/sound/machines/sm/accent/normal/9.ogg
new file mode 100644
index 0000000000..545b038be1
Binary files /dev/null and b/sound/machines/sm/accent/normal/9.ogg differ
diff --git a/sound/machines/sm/loops/calm.ogg b/sound/machines/sm/loops/calm.ogg
new file mode 100644
index 0000000000..cee14fcd13
Binary files /dev/null and b/sound/machines/sm/loops/calm.ogg differ
diff --git a/sound/machines/sm/loops/delamming.ogg b/sound/machines/sm/loops/delamming.ogg
new file mode 100644
index 0000000000..7d79f0e3c4
Binary files /dev/null and b/sound/machines/sm/loops/delamming.ogg differ
diff --git a/sound/machines/sm/supermatter1.ogg b/sound/machines/sm/supermatter1.ogg
index 1860e78800..be5185009e 100644
Binary files a/sound/machines/sm/supermatter1.ogg and b/sound/machines/sm/supermatter1.ogg differ
diff --git a/sound/machines/sm/supermatter2.ogg b/sound/machines/sm/supermatter2.ogg
index fb2d39fe26..5c98d28ed1 100644
Binary files a/sound/machines/sm/supermatter2.ogg and b/sound/machines/sm/supermatter2.ogg differ
diff --git a/sound/machines/sm/supermatter3.ogg b/sound/machines/sm/supermatter3.ogg
index 93ac3d505b..fb8e09166c 100644
Binary files a/sound/machines/sm/supermatter3.ogg and b/sound/machines/sm/supermatter3.ogg differ
diff --git a/sound/music/twilight.ogg b/sound/music/twilight.ogg
new file mode 100644
index 0000000000..635663314d
Binary files /dev/null and b/sound/music/twilight.ogg differ
diff --git a/strings/round_start_sounds.txt b/strings/round_start_sounds.txt
index c67bf6b4a6..177a3ea0a8 100644
--- a/strings/round_start_sounds.txt
+++ b/strings/round_start_sounds.txt
@@ -25,3 +25,4 @@ sound/music/rocketridersprayer.ogg
sound/music/theend.ogg
sound/music/flyinghigh.ogg
sound/music/samsara.ogg
+sound/music/twilight.ogg
\ No newline at end of file
diff --git a/strings/tips.txt b/strings/tips.txt
index a1d2befab3..5dc4e1b985 100644
--- a/strings/tips.txt
+++ b/strings/tips.txt
@@ -25,7 +25,7 @@ As the Captain, you have absolute access and control over the station, but this
As the Captain, you have a fancy pen that can be used as a holdout dagger or even as a scalpel in surgery!
As the Captain, you can purchase a new emergency shuttle using a communications console. Some require credits, while others give you credits in exchange. Keep in mind that purchasing dangerous shuttles will incur the ire of your crew.
As the Chief Medical Officer, your hypospray is like the ones that your Medical Doctors can buy, except it comes in a fancy box that can hold several more hypovials than the standard, and already comes preloaded with specially-made high-capacity hypovials that hold double the reagents the standard ones do.
-As the Chief Medical Officer, coordinate and communicate with your doctors, chemists, and geneticists during a nuclear emergency, blob infestation, or some other crisis to keep people alive and fighting.
+As the Chief Medical Officer, coordinate and communicate with your doctors, chemists, and paramedics during a nuclear emergency, blob infestation, or some other crisis to keep people alive and fighting.
As a Medical Doctor, pester Research for improved surgical tools. They work faster, combine the purposes of several tools in one (scalpel/saw, retractor/hemostat, drill/cautery), and don't cost many materials to boot!
As a Medical Doctor, the surgical saw and drill are both powerful weapons, the saw is sharp and can slice and dice, while the drill can quickly blind someone if aimed for the eyes. The laser scalpel is an upgraded version producible with Research's aid, and it has the highest force of most common place weapons, while still remaining sharp.
As a Medical Doctor, your belt can hold a full set of surgical tools. Using sterilizine before each attempt during surgery will reduce your failure chance on tricky steps or when using less-than-optimal equipment.
@@ -34,11 +34,14 @@ As a Medical Doctor, while both heal toxin damage, the difference between charco
As a Medical Doctor, you can surgically implant or extract things from people's chests by performing a cavity implant. This could range from inserting a suicide bomb to embedding the nuke disk into the Captain's chest.
As a Medical Doctor, it's of utmost urgency that you tend to anyone who's been hugged by a facehugger. You only have a couple of minutes from the initial attachment to perform organ manipulation to their chest and remove the rapidly developing alien embryo before it bursts out and immediately kills your patient.
As a Medical Doctor, you must target the correct limb and be on help intent when trying to perform surgery on someone. Using disarm attempt will intentionally fail the surgery step.
-As a Medical Doctor, corpses with the "...and their soul has departed" description no longer have a ghost attached to them and aren't usually revivable or cloneable. However it may prove useful to be creative in your revivification techniques with these bodies.
+As a Medical Doctor, corpses with the "...and their soul has departed" description no longer have a ghost attached to them and can't be revived. However it may prove useful to be creative in your revivification techniques with these bodies.
As a Medical Doctor, treating plasmamen is not impossible! Salbutamol and epinephrine stops them from suffocating due to lack of internals and showers stop them from burning alive. You can even perform surgery on them by doing the procedure on a roller bed under a shower.
As a Medical Doctor, you can point your penlight at people to create a medical hologram. This lets them know that you're coming to treat them.
As a Medical Doctor, you can extract implants by holding an empty implant case in your offhand while performing the extraction step.
As a Medical Doctor, clone scanning people will implant them with a health tracker that displays their vitals in the clone records. Useful to check on crew members that didn't activate suit sensors!
+As a Medical Doctor, you can deal with patients who have absurd amounts of wounds by putting them in cryo. This will slowly treat all of their wounds simultaneously, but is much slower than direct treatment.
+As a Medical Doctor, Critical Slash wounds are one of the most dangerous conditions someone can have. Apply gauze, epipens, sutures, cauteries, whatever you can, as soon as possible!
+As a Medical Doctor, Saline-Glucose not only acts as a temporary boost to a patient's blood level, it also speeds regeneration! Perfect for drained patients!
As a Medical Doctor, medical gauze is an incredibly underrated tool. It can be used to entirely halt a limb from bleeding or sling one that's been shattered until it can be given proper attention. This even works on the dead, too! Be sure to stop someone's bleeding whether they're in critical condition or a corpse, as dragging someone whom is bleeding will rapidly deplete them of all their blood.
As a Chemist, there are dozens of chemicals that can heal, and even more that can cause harm. See which chemicals have the best synergy, both in healing, and in harming. Experiment!
As a Chemist, some chemicals can only be synthesized by heating up the contents in the chemical heater.
@@ -135,10 +138,10 @@ As a Security Officer, examining someone while wearing your security HUDglasses
As a Security Officer, you can take out the power cell on your baton to replace it with a better or fully charged one. Just use a screwdriver on your baton to remove the old cell.
As a Security Officer, you can just about any firearm on your vest, this even works with other non-standard armor-substitutes like security winter coats!
As the Detective, people leave fingerprints everywhere and on everything. With the exception of white latex, gloves will hide them. All is not lost, however, as gloves leave fibers specific to their kind such as black or nitrile, pointing to a general department.
-As the Detective, you can use your forensics scanner from a distance.
+As the Detective, you can use your forensics scanner from a distance. Use this to scan boxes or other storage containers.
As the Detective, your revolver can be loaded with .357 ammunition. Use a screwdriver to permanently modify your revolver into using this type of ammunition, be warned however, firing it has a decent chance to cause the revolver to misfire and shoot you in the foot.
As the Lawyer, try to negotiate with the Warden if sentences seem too high for the crime.
-As the Lawyer, you can try to convince the captain and Head of Security to hold trials for prisoners in the courtroom.
+As the Lawyer, you can try to convince the Captain and Head of Security to hold trials for prisoners in the courtroom.
As the Head of Personnel, you are not higher ranking than other heads of staff, even though you are expected to take the Captain's place first should he go missing. If the situation seems too rough for you, consider allowing another head to become temporary Captain.
As the Head of Personnel, you are just as large a target as the Captain because of the potential power your ID and computer can hand out and your comparative vulnerability.
As the Mime, your invisible wall power blocks people as well as projectiles. You can use it in a pinch to delay your pursuer.
@@ -187,7 +190,7 @@ As a Shaft Miner, every monster on Lavaland has a pattern you can exploit to min
As a Shaft Miner, you can harvest goliath plates from goliaths and upgrade your explorer's suit, mining hardsuits as well as Firefighter APLUs with them, greatly reducing incoming melee damage.
As a Shaft Miner, always have a GPS on you, so a fellow miner or cyborg can come to save you if you die.
As a Shaft Miner, you can craft a variety of equipment from the local fauna. Bone axes, lava boats and ash drake armour are just a few of them!
-As a Traitor, the cryptographic sequencer (emag) can not only open doors, but also lockers, crates, APCs and more. It can hack cyborgs, and even cause bots to go berserk. Use it on the right machines, and you may just be able to create some difficult to obtain substances, or contact your employers to request special objectives! Experiment!
+As a Traitor, the cryptographic sequencer (emag) can not only open lockers, crates, APCs and more. It can also do things like hack cyborgs, and even cause bots to go berserk. Use it on the right machines, and you can even contact the Syndicate. Experiment!
As a Traitor, subverting the AI to serve you can make it an extremely powerful ally. However, be careful of the wording in the laws you give it, as it may use your poorly written laws against you!
As a Traitor, the Captain and the Head of Security are two of the most difficult to kill targets on the station. If either one is your target, plan carefully.
As a Traitor, you can manufacture and recycle revolver bullets at a hacked autolathe, making the revolver an extremely powerful tool if you manage to nab an autolathe for yourself.
@@ -235,6 +238,7 @@ As a Changeling, absorbing someone will give you their full memory. This can inc
As a Changeling, absorbing another Changeling will permanently boost your chemical reserve, allow you to pick more abilities, and make the victim unable to revive. Be careful when exposing your identity to other Changelings, as they may be out of those wonderful benefits.
As a Changeling, BZ gas will dramatically slow down or even halt your natural chemical regeneration, be sure to avoid it at all costs as some lunatics may try and flood portions of the station to deal with you.
As a Changeling, death is not the end for you! You can revive after two minutes from being dead by triggering your stasis ability, and then waiting for the prompt to resurrect yourself to show up.
+As a Changeling, your Regenerate Limbs power will quickly heal all of your wounds, but they'll still leave scars. Changelings can use Fleshmend to get rid of scars, or you can ingest Carpotoxin to get rid of them like a normal person.
As a Cultist, do not cause too much chaos before your objective is completed. If the shuttle gets called too soon, you may not have enough time to win.
As a Cultist, your team starts off very weak, but if necessary can quickly convert everything they have into raw power. Make sure you have the numbers and equipment to support going loud, or the cult will fall flat on its face.
As a Cultist, the Blood Boil rune will deal massive amounts of brute damage to non-cultists, stamina damage to Ratvarian scum, and some damage to fellow cultists of Nar-Sie nearby, but will create a fire where the rune stands on use.
@@ -281,12 +285,17 @@ As a Devil, you gain power for every three souls you control, however you also b
As a Devil, as long as you control at least one other soul, you will automatically resurrect, as long as a banishment ritual is not performed.
At which time a Devil's nameth is spake on the tongue of man, the Devil may appeareth.
You can swap floor tiles by holding a crowbar in one hand and a stack of tiles in the other.
-When hacking doors, cutting and mending the "test light wire" will restore power to the door.
-When hacking, remote singulars pulse when attached to a wire and pinged. This can allow you to hack things or set traps from far away.
+When hacking doors, cutting and mending a "test light wire" will restore power to the door.
When crafting most items, you can either manually combine parts or use the crafting menu.
Suit storage units not only remove blood and dirt from clothing, but also radiation!
-Suit storage units entirely purge radiation from any carbon mob put inside of them when cycling, at the cost of some horrific burns, this is a very effective strategy to clean someone up after they bathed in the engine.
Remote devices will work when used through cameras. For example: Bluespace RPEDs and door remotes.
+You can light a cigar on a supermatter crystal.
+Using sticky tape on items can make them stick to people and walls! Be careful, grenades might stick to your hand during the moment of truth!
+In a pinch, stripping yourself naked will give you a sizeable resistance to being tackled. What do you value more, your freedom or your dignity?
+Wearing riot armor makes you significantly more effective at performing tackle takedowns, but will use extra stamina with each leap! It will also significantly protect you from other tackles!
+Epipens contain a powerful coagulant that drastically reduces bleeding on all bleeding wounds. If you don't have time to properly treat someone with lots of slashes or piercings, stick them with a pen to buy some time!
+Anything you can light a cigarette with, you can use to cauterize a bleeding wound. Technically, that includes the supermatter.
+Suit storage units entirely purge radiation from any carbon mob put inside of them when cycling, at the cost of some horrific burns, this is a very effective strategy to clean someone up after they bathed in the engine.
Laser pointers can be upgraded by replacing its micro laser with a better one from RnD! Use a screwdriver on it to remove the old laser. Upgrading the laser pointer gives you better odds of stunning a cyborg, and even blinding people with sunglasses.
Being out of combat mode makes makes you deal less damage to people and objects when attacking. This stacks with the penalty incurred by resting.
Resting makes you deal less damage to people and objects when attacking. This stacks with the penalty incurred by being out of combat mode.
diff --git a/tgstation.dme b/tgstation.dme
index 4784fb3d32..de6ee1a6bf 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -81,6 +81,7 @@
#include "code\__DEFINES\networks.dm"
#include "code\__DEFINES\pinpointers.dm"
#include "code\__DEFINES\pipe_construction.dm"
+#include "code\__DEFINES\plumbing.dm"
#include "code\__DEFINES\pool.dm"
#include "code\__DEFINES\power.dm"
#include "code\__DEFINES\preferences.dm"
@@ -95,6 +96,7 @@
#include "code\__DEFINES\reagents_specific_heat.dm"
#include "code\__DEFINES\research.dm"
#include "code\__DEFINES\robots.dm"
+#include "code\__DEFINES\rockpaperscissors.dm"
#include "code\__DEFINES\role_preferences.dm"
#include "code\__DEFINES\rust_g.dm"
#include "code\__DEFINES\say.dm"
@@ -301,6 +303,7 @@
#include "code\controllers\subsystem\events.dm"
#include "code\controllers\subsystem\fail2topic.dm"
#include "code\controllers\subsystem\fire_burning.dm"
+#include "code\controllers\subsystem\fluid.dm"
#include "code\controllers\subsystem\garbage.dm"
#include "code\controllers\subsystem\holodeck.dm"
#include "code\controllers\subsystem\icon_smooth.dm"
@@ -376,6 +379,7 @@
#include "code\datums\datumvars.dm"
#include "code\datums\dna.dm"
#include "code\datums\dog_fashion.dm"
+#include "code\datums\ductnet.dm"
#include "code\datums\emotes.dm"
#include "code\datums\ert.dm"
#include "code\datums\explosion.dm"
@@ -489,6 +493,11 @@
#include "code\datums\components\fantasy\affix.dm"
#include "code\datums\components\fantasy\prefixes.dm"
#include "code\datums\components\fantasy\suffixes.dm"
+#include "code\datums\components\plumbing\_plumbing.dm"
+#include "code\datums\components\plumbing\chemical_acclimator.dm"
+#include "code\datums\components\plumbing\filter.dm"
+#include "code\datums\components\plumbing\reaction_chamber.dm"
+#include "code\datums\components\plumbing\splitter.dm"
#include "code\datums\components\storage\storage.dm"
#include "code\datums\components\storage\ui.dm"
#include "code\datums\components\storage\concrete\_concrete.dm"
@@ -558,6 +567,7 @@
#include "code\datums\elements\_element.dm"
#include "code\datums\elements\art.dm"
#include "code\datums\elements\beauty.dm"
+#include "code\datums\elements\bsa_blocker.dm"
#include "code\datums\elements\cleaning.dm"
#include "code\datums\elements\decal.dm"
#include "code\datums\elements\dusts_on_catatonia.dm"
@@ -727,6 +737,7 @@
#include "code\game\gamemodes\dynamic\dynamic_rulesets_midround.dm"
#include "code\game\gamemodes\dynamic\dynamic_rulesets_roundstart.dm"
#include "code\game\gamemodes\dynamic\dynamic_storytellers.dm"
+#include "code\game\gamemodes\eldritch_cult\eldritch_cult.dm"
#include "code\game\gamemodes\extended\extended.dm"
#include "code\game\gamemodes\gangs\dominator.dm"
#include "code\game\gamemodes\gangs\dominator_countdown.dm"
@@ -1280,6 +1291,7 @@
#include "code\game\objects\structures\crates_lockers\crates\secure.dm"
#include "code\game\objects\structures\crates_lockers\crates\wooden.dm"
#include "code\game\objects\structures\icemoon\cave_entrance.dm"
+#include "code\game\objects\structures\lavaland\geyser.dm"
#include "code\game\objects\structures\lavaland\necropolis_tendril.dm"
#include "code\game\objects\structures\signs\_signs.dm"
#include "code\game\objects\structures\signs\signs_departments.dm"
@@ -1296,6 +1308,7 @@
#include "code\game\turfs\open.dm"
#include "code\game\turfs\turf.dm"
#include "code\game\turfs\openspace\openspace.dm"
+#include "code\game\turfs\openspace\transparent.dm"
#include "code\game\turfs\simulated\chasm.dm"
#include "code\game\turfs\simulated\dirtystation.dm"
#include "code\game\turfs\simulated\floor.dm"
@@ -1391,6 +1404,7 @@
#include "code\modules\admin\view_variables\mark_datum.dm"
#include "code\modules\admin\view_variables\mass_edit_variables.dm"
#include "code\modules\admin\view_variables\modify_variables.dm"
+#include "code\modules\admin\view_variables\reference_tracking.dm"
#include "code\modules\admin\view_variables\topic.dm"
#include "code\modules\admin\view_variables\topic_basic.dm"
#include "code\modules\admin\view_variables\topic_list.dm"
@@ -1598,6 +1612,16 @@
#include "code\modules\antagonists\disease\disease_disease.dm"
#include "code\modules\antagonists\disease\disease_event.dm"
#include "code\modules\antagonists\disease\disease_mob.dm"
+#include "code\modules\antagonists\eldritch_cult\eldritch_antag.dm"
+#include "code\modules\antagonists\eldritch_cult\eldritch_book.dm"
+#include "code\modules\antagonists\eldritch_cult\eldritch_effects.dm"
+#include "code\modules\antagonists\eldritch_cult\eldritch_items.dm"
+#include "code\modules\antagonists\eldritch_cult\eldritch_knowledge.dm"
+#include "code\modules\antagonists\eldritch_cult\eldritch_magic.dm"
+#include "code\modules\antagonists\eldritch_cult\eldritch_monster_antag.dm"
+#include "code\modules\antagonists\eldritch_cult\knowledge\ash_lore.dm"
+#include "code\modules\antagonists\eldritch_cult\knowledge\flesh_lore.dm"
+#include "code\modules\antagonists\eldritch_cult\knowledge\rust_lore.dm"
#include "code\modules\antagonists\ert\ert.dm"
#include "code\modules\antagonists\fugitive\fugitive.dm"
#include "code\modules\antagonists\fugitive\fugitive_outfits.dm"
@@ -2589,6 +2613,7 @@
#include "code\modules\mob\living\simple_animal\constructs.dm"
#include "code\modules\mob\living\simple_animal\corpse.dm"
#include "code\modules\mob\living\simple_animal\damage_procs.dm"
+#include "code\modules\mob\living\simple_animal\eldritch_demons.dm"
#include "code\modules\mob\living\simple_animal\parrot.dm"
#include "code\modules\mob\living\simple_animal\pickle.dm"
#include "code\modules\mob\living\simple_animal\shade.dm"
@@ -2844,6 +2869,21 @@
#include "code\modules\photography\photos\album.dm"
#include "code\modules\photography\photos\frame.dm"
#include "code\modules\photography\photos\photo.dm"
+#include "code\modules\plumbing\ducts.dm"
+#include "code\modules\plumbing\plumbers\_plumb_machinery.dm"
+#include "code\modules\plumbing\plumbers\acclimator.dm"
+#include "code\modules\plumbing\plumbers\autohydro.dm"
+#include "code\modules\plumbing\plumbers\bottler.dm"
+#include "code\modules\plumbing\plumbers\destroyer.dm"
+#include "code\modules\plumbing\plumbers\fermenter.dm"
+#include "code\modules\plumbing\plumbers\filter.dm"
+#include "code\modules\plumbing\plumbers\grinder_chemical.dm"
+#include "code\modules\plumbing\plumbers\medipenrefill.dm"
+#include "code\modules\plumbing\plumbers\pill_press.dm"
+#include "code\modules\plumbing\plumbers\pumps.dm"
+#include "code\modules\plumbing\plumbers\reaction_chamber.dm"
+#include "code\modules\plumbing\plumbers\splitters.dm"
+#include "code\modules\plumbing\plumbers\synthesizer.dm"
#include "code\modules\pool\pool_controller.dm"
#include "code\modules\pool\pool_drain.dm"
#include "code\modules\pool\pool_effects.dm"
@@ -3263,9 +3303,9 @@
#include "code\modules\spells\spell.dm"
#include "code\modules\spells\spell_types\aimed.dm"
#include "code\modules\spells\spell_types\area_teleport.dm"
-#include "code\modules\spells\spell_types\barnyard.dm"
#include "code\modules\spells\spell_types\bloodcrawl.dm"
#include "code\modules\spells\spell_types\charge.dm"
+#include "code\modules\spells\spell_types\cone_spells.dm"
#include "code\modules\spells\spell_types\conjure.dm"
#include "code\modules\spells\spell_types\construct_spells.dm"
#include "code\modules\spells\spell_types\curse.dm"
@@ -3284,7 +3324,6 @@
#include "code\modules\spells\spell_types\lichdom.dm"
#include "code\modules\spells\spell_types\lightning.dm"
#include "code\modules\spells\spell_types\mime.dm"
-#include "code\modules\spells\spell_types\mind_transfer.dm"
#include "code\modules\spells\spell_types\projectile.dm"
#include "code\modules\spells\spell_types\rightandwrong.dm"
#include "code\modules\spells\spell_types\rod_form.dm"
@@ -3301,6 +3340,10 @@
#include "code\modules\spells\spell_types\turf_teleport.dm"
#include "code\modules\spells\spell_types\voice_of_god.dm"
#include "code\modules\spells\spell_types\wizard.dm"
+#include "code\modules\spells\spell_types\pointed\barnyard.dm"
+#include "code\modules\spells\spell_types\pointed\blind.dm"
+#include "code\modules\spells\spell_types\pointed\mind_transfer.dm"
+#include "code\modules\spells\spell_types\pointed\pointed.dm"
#include "code\modules\station_goals\bsa.dm"
#include "code\modules\station_goals\dna_vault.dm"
#include "code\modules\station_goals\shield.dm"
|