diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_alien_nest.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_alien_nest.dmm
index c2bdea157e..ed882850cf 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_surface_alien_nest.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_alien_nest.dmm
@@ -499,10 +499,6 @@
/mob/living/simple_animal/hostile/alien,
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/ruin/unpowered/xenonest)
-"bD" = (
-/obj/structure/alien/weeds,
-/turf/template_noop,
-/area/ruin/unpowered/xenonest)
"dE" = (
/obj/structure/alien/weeds,
/obj/structure/bed/nest,
@@ -1573,8 +1569,8 @@ aa
aa
aa
ac
-bD
-bD
+ag
+ag
aa
"}
(20,1,1) = {"
@@ -1625,7 +1621,7 @@ aa
aa
aa
ac
-bD
+ag
aa
"}
(21,1,1) = {"
@@ -1676,8 +1672,8 @@ ac
aa
aa
ac
-bD
-bD
+ag
+ag
"}
(22,1,1) = {"
ab
@@ -1727,8 +1723,8 @@ ac
ac
ac
aW
-bD
-bD
+ag
+ag
"}
(23,1,1) = {"
ab
@@ -1778,8 +1774,8 @@ ag
aw
ar
ag
-bD
-bD
+ag
+ag
"}
(24,1,1) = {"
ab
@@ -1829,8 +1825,8 @@ ag
aw
ar
ag
-bD
-bD
+ag
+ag
"}
(25,1,1) = {"
ab
@@ -1880,8 +1876,8 @@ ac
ac
ac
ac
-bD
-bD
+ag
+ag
"}
(26,1,1) = {"
ab
diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm
index 8731eaa256..1109031a2e 100644
--- a/_maps/map_files/BoxStation/BoxStation.dmm
+++ b/_maps/map_files/BoxStation/BoxStation.dmm
@@ -23919,11 +23919,11 @@
dir = 4
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/structure/reagent_dispensers/fueltank,
/turf/open/floor/plating,
/area/maintenance/port)
"bfe" = (
/obj/machinery/atmospherics/pipe/manifold/supply/hidden,
-/obj/structure/reagent_dispensers/watertank,
/turf/open/floor/plating,
/area/maintenance/port)
"bff" = (
@@ -27606,13 +27606,13 @@
/obj/structure/sign/warning/radiation/rad_area{
pixel_x = 32
},
-/obj/structure/cable{
- icon_state = "0-2"
- },
/obj/structure/cable{
icon_state = "0-8"
},
/obj/effect/spawner/structure/window/reinforced,
+/obj/structure/cable{
+ icon_state = "1-8"
+ },
/turf/open/floor/plating,
/area/engineering/gravity_generator)
"bnX" = (
@@ -40890,8 +40890,8 @@
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bTT" = (
-/obj/machinery/atmospherics/pipe/manifold/yellow/visible{
- dir = 8
+/obj/machinery/atmospherics/pipe/manifold/general/visible{
+ dir = 1
},
/obj/machinery/meter,
/turf/open/floor/plasteel,
@@ -56045,7 +56045,7 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
-/obj/structure/reagent_dispensers/fueltank,
+/obj/structure/reagent_dispensers/watertank,
/turf/open/floor/plating,
/area/maintenance/port)
"jyO" = (
@@ -56262,6 +56262,7 @@
/obj/structure/cable{
icon_state = "1-2"
},
+/obj/effect/mapping_helpers/airlock/cyclelink_helper,
/turf/open/floor/plasteel,
/area/engineering/engine_smes)
"jLv" = (
@@ -56574,7 +56575,7 @@
dir = 6
},
/obj/structure/cable{
- icon_state = "0-8"
+ icon_state = "0-2"
},
/turf/open/floor/plasteel,
/area/engineering/gravity_generator)
@@ -57372,6 +57373,7 @@
/area/service/bar)
"moS" = (
/obj/machinery/atmospherics/pipe/manifold4w/yellow/visible,
+/obj/machinery/meter,
/turf/open/floor/plasteel,
/area/engineering/atmos)
"mps" = (
@@ -57535,6 +57537,19 @@
/obj/structure/falsewall,
/turf/open/floor/plating,
/area/security/prison)
+"mJf" = (
+/obj/structure/cable{
+ icon_state = "0-8"
+ },
+/obj/structure/cable{
+ icon_state = "0-4"
+ },
+/obj/effect/spawner/structure/window/reinforced,
+/obj/structure/cable{
+ icon_state = "1-4"
+ },
+/turf/open/floor/plating,
+/area/engineering/gravity_generator)
"mJo" = (
/obj/structure/door_assembly/door_assembly_mai,
/obj/item/electronics/airlock,
@@ -57576,9 +57591,6 @@
name = "Gravity Generator";
req_access_txt = "11"
},
-/obj/structure/cable{
- icon_state = "1-8"
- },
/turf/open/floor/plasteel/dark,
/area/engineering/gravity_generator)
"mOG" = (
@@ -58245,9 +58257,6 @@
/obj/effect/turf_decal/stripes/line{
dir = 4
},
-/obj/structure/cable{
- icon_state = "4-8"
- },
/obj/machinery/light{
dir = 4;
light_color = "#c1caff"
@@ -60541,6 +60550,9 @@
/obj/structure/cable{
icon_state = "1-2"
},
+/obj/effect/mapping_helpers/airlock/cyclelink_helper{
+ dir = 1
+ },
/turf/open/floor/plasteel,
/area/engineering/gravity_generator)
"tJS" = (
@@ -60771,10 +60783,10 @@
/turf/open/floor/plating,
/area/maintenance/port/fore)
"ugu" = (
-/obj/structure/cable{
- icon_state = "1-4"
- },
/obj/effect/turf_decal/stripes/line,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/plasteel,
/area/engineering/gravity_generator)
"uhm" = (
@@ -61143,10 +61155,6 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 5
},
-/obj/structure/cable{
- icon_state = "0-8"
- },
-/obj/machinery/power/terminal,
/turf/closed/wall/r_wall,
/area/engineering/gravity_generator)
"uRn" = (
@@ -61353,11 +61361,10 @@
/turf/open/floor/plating,
/area/maintenance/port)
"vob" = (
-/obj/structure/cable{
- icon_state = "1-4"
- },
+/obj/machinery/atmospherics/pipe/simple/yellow/visible,
+/obj/machinery/meter,
/turf/open/floor/plasteel,
-/area/engineering/gravity_generator)
+/area/engineering/atmos)
"voW" = (
/obj/structure/pool/Lboard,
/turf/open/pool,
@@ -61563,10 +61570,13 @@
/turf/open/floor/plating,
/area/maintenance/starboard/fore)
"vFr" = (
-/obj/structure/cable{
- icon_state = "4-8"
- },
/obj/effect/turf_decal/stripes/line,
+/obj/machinery/power/terminal{
+ dir = 4
+ },
+/obj/structure/cable{
+ icon_state = "0-8"
+ },
/turf/open/floor/plasteel,
/area/engineering/gravity_generator)
"vGn" = (
@@ -62192,9 +62202,6 @@
/turf/open/floor/carpet/royalblue,
/area/maintenance/starboard/aft)
"xgC" = (
-/obj/structure/cable{
- icon_state = "0-4"
- },
/obj/machinery/power/apc{
areastring = "/area/engineering/gravity_generator";
dir = 8;
@@ -62208,13 +62215,13 @@
/obj/effect/turf_decal/stripes/line{
dir = 8
},
-/obj/structure/cable{
- icon_state = "0-2"
- },
/obj/machinery/light{
dir = 8;
light_color = "#e8eaff"
},
+/obj/structure/cable{
+ icon_state = "0-2"
+ },
/turf/open/floor/plasteel,
/area/engineering/gravity_generator)
"xgF" = (
@@ -62224,13 +62231,10 @@
},
/area/maintenance/bar)
"xhS" = (
-/obj/structure/cable{
- icon_state = "2-4"
- },
-/obj/structure/cable{
- icon_state = "4-8"
- },
/obj/effect/turf_decal/stripes/line,
+/obj/structure/cable{
+ icon_state = "1-4"
+ },
/turf/open/floor/plasteel,
/area/engineering/gravity_generator)
"xhV" = (
@@ -81880,7 +81884,7 @@ aQN
aQN
aZA
aPA
-aWv
+jxF
aYb
aZE
aZE
@@ -82651,7 +82655,7 @@ aQW
aQW
xDM
aPA
-jxF
+aWv
aYb
aZE
bjp
@@ -85028,7 +85032,7 @@ btG
rXl
xgC
ugu
-bnV
+mJf
bph
bih
big
@@ -85283,7 +85287,7 @@ xTy
xTy
tJK
xTy
-vob
+xTy
xhS
mOB
bph
@@ -86189,7 +86193,7 @@ aaa
aaa
gXs
gXs
-aaH
+gXs
abc
abu
abu
@@ -87072,11 +87076,11 @@ bCq
bSs
ceY
ccw
-ccw
+cjJ
cnR
cgT
cjJ
-ccw
+cjJ
ccw
ccw
ccw
@@ -96303,7 +96307,7 @@ bPc
bQs
cez
ceA
-daq
+bTT
bUN
bOd
bOd
@@ -97335,9 +97339,9 @@ moS
kGv
bUS
cCE
-bTT
-bUS
+bXU
bUS
+vob
bUS
bXU
bUS
diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index 87aa425f4d..a00b502fc5 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -72141,24 +72141,6 @@
/obj/machinery/atmospherics/pipe/simple/general/visible,
/turf/open/floor/plasteel,
/area/engineering/atmos)
-"exg" = (
-/obj/structure/chair/office/light{
- dir = 8
- },
-/obj/structure/cable/white{
- icon_state = "4-8"
- },
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/obj/effect/turf_decal/tile/neutral{
- dir = 1
- },
-/obj/effect/turf_decal/tile/neutral{
- dir = 8
- },
-/turf/open/floor/plasteel{
- heat_capacity = 1e+006
- },
-/area/command/heads_quarters/ce)
"exo" = (
/obj/effect/turf_decal/stripes/line{
dir = 1
@@ -79857,20 +79839,6 @@
},
/turf/open/floor/plasteel/dark,
/area/service/library)
-"hkJ" = (
-/obj/structure/cable/white{
- icon_state = "1-2"
- },
-/obj/effect/turf_decal/tile/neutral{
- dir = 1
- },
-/obj/effect/turf_decal/tile/neutral{
- dir = 4
- },
-/turf/open/floor/plasteel{
- heat_capacity = 1e+006
- },
-/area/command/heads_quarters/ce)
"hkK" = (
/obj/structure/table/reinforced,
/obj/item/electronics/firelock,
@@ -86455,6 +86423,9 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
+/obj/structure/cable/white{
+ icon_state = "4-8"
+ },
/turf/open/floor/plasteel{
heat_capacity = 1e+006
},
@@ -91661,6 +91632,9 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
+/obj/structure/cable/white{
+ icon_state = "4-8"
+ },
/turf/open/floor/plasteel/dark,
/area/command/heads_quarters/ce)
"laA" = (
@@ -92991,9 +92965,6 @@
/area/engineering/break_room)
"lCx" = (
/obj/structure/table/reinforced,
-/obj/structure/cable/white{
- icon_state = "1-2"
- },
/obj/item/clipboard,
/obj/item/toy/figure/ce,
/obj/effect/turf_decal/tile/neutral{
@@ -93526,9 +93497,6 @@
/area/service/abandoned_gambling_den)
"lLv" = (
/obj/structure/table/reinforced,
-/obj/structure/cable/white{
- icon_state = "2-4"
- },
/obj/item/folder/blue{
pixel_x = 3;
pixel_y = 3
@@ -94394,9 +94362,6 @@
/obj/item/gps/engineering{
gpstag = "CE0"
},
-/obj/machinery/newscaster{
- pixel_y = 32
- },
/obj/structure/disposalpipe/segment{
dir = 4
},
@@ -94410,6 +94375,15 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
+/obj/machinery/power/apc{
+ areastring = "/area/command/heads_quarters/ce";
+ dir = 1;
+ name = "Chief Engineer's APC";
+ pixel_y = 30
+ },
+/obj/structure/cable/white{
+ icon_state = "0-2"
+ },
/turf/open/floor/plasteel/dark,
/area/command/heads_quarters/ce)
"mcu" = (
@@ -109351,25 +109325,6 @@
/obj/effect/turf_decal/bot,
/turf/open/floor/plasteel,
/area/service/hydroponics)
-"rts" = (
-/obj/structure/cable/white,
-/obj/machinery/power/apc{
- areastring = "/area/command/heads_quarters/ce";
- name = "Chief Engineer's APC";
- 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,
-/area/command/heads_quarters/ce)
"rtx" = (
/obj/structure/table/wood,
/obj/item/storage/briefcase{
@@ -116201,6 +116156,19 @@
/obj/effect/turf_decal/delivery,
/turf/open/floor/plasteel,
/area/engineering/storage/tech)
+"tGF" = (
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/neutral,
+/obj/effect/turf_decal/tile/neutral{
+ dir = 8
+ },
+/obj/structure/cable/white{
+ icon_state = "1-4"
+ },
+/turf/open/floor/plasteel,
+/area/command/heads_quarters/ce)
"tGL" = (
/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
dir = 4
@@ -117812,9 +117780,6 @@
/obj/structure/cable/white{
icon_state = "1-2"
},
-/obj/structure/cable/white{
- icon_state = "1-8"
- },
/obj/machinery/light{
dir = 4
},
@@ -117829,6 +117794,10 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
+/obj/machinery/airalarm{
+ dir = 8;
+ pixel_x = 24
+ },
/turf/open/floor/plasteel/dark,
/area/command/heads_quarters/ce)
"uiv" = (
@@ -121250,9 +121219,6 @@
/area/service/chapel/office)
"vBq" = (
/obj/structure/table/reinforced,
-/obj/structure/cable/white{
- icon_state = "1-2"
- },
/obj/item/cartridge/engineering{
pixel_x = 6
},
@@ -122264,6 +122230,22 @@
/obj/effect/spawner/lootdrop/keg,
/turf/open/floor/plating,
/area/service/abandoned_gambling_den)
+"vXq" = (
+/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/firealarm{
+ pixel_y = -28
+ },
+/turf/open/floor/plasteel/dark,
+/area/command/heads_quarters/ce)
"vXw" = (
/obj/effect/spawner/structure/window/reinforced,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
@@ -124083,10 +124065,6 @@
/obj/item/cartridge/atmos,
/obj/item/cartridge/atmos,
/obj/item/cartridge/atmos,
-/obj/machinery/airalarm{
- dir = 1;
- pixel_y = -22
- },
/obj/item/stamp/ce,
/obj/effect/turf_decal/tile/neutral{
dir = 1
@@ -151712,13 +151690,13 @@ mMB
pRP
kkO
mcs
-mHG
+tGF
xKr
lLv
lCx
vBq
-hkJ
-rts
+ikP
+vXq
qjg
ine
vJe
@@ -151971,7 +151949,7 @@ kkO
nZq
jpC
ivQ
-exg
+tbI
tbI
ilG
hbc
@@ -152485,7 +152463,7 @@ kkO
jKf
prr
qPW
-xSN
+kkO
sSa
jry
pTd
diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm
index 93c625b238..0570a6d480 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -53189,7 +53189,10 @@
/turf/open/floor/plasteel,
/area/engineering/atmos)
"fVD" = (
-/obj/machinery/pool/drain,
+/obj/machinery/pool/drain{
+ drain_suck_range = 2;
+ item_suction_range = 1
+ },
/turf/open/pool,
/area/commons/fitness/pool)
"fVX" = (
@@ -67711,6 +67714,9 @@
pixel_y = 24
},
/obj/machinery/computer/atmos_control,
+/obj/machinery/atmospherics/pipe/simple/orange/hidden{
+ dir = 4
+ },
/turf/open/floor/plasteel/checker,
/area/engineering/atmos)
"oOi" = (
@@ -74460,9 +74466,6 @@
},
/turf/open/floor/plasteel/dark,
/area/command/bridge)
-"sKV" = (
-/turf/open/space/basic,
-/area/command/heads_quarters/captain)
"sLs" = (
/obj/effect/decal/cleanable/cobweb,
/obj/machinery/field/generator,
@@ -122066,7 +122069,7 @@ oRp
oRp
aaa
aai
-sKV
+aaa
aaa
aaa
aaa
@@ -130637,7 +130640,7 @@ aaf
aaf
aaa
aaa
-sKV
+aaa
aaa
aaa
aaa
diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm
index eacbc74508..27a4cb8491 100644
--- a/_maps/map_files/PubbyStation/PubbyStation.dmm
+++ b/_maps/map_files/PubbyStation/PubbyStation.dmm
@@ -10755,6 +10755,11 @@
name = "Port Solar APC";
pixel_y = 23
},
+/obj/machinery/camera{
+ c_tag = "Port Bow Solar";
+ dir = 9;
+ name = "solar camera"
+ },
/turf/open/floor/plating,
/area/maintenance/solars/port)
"ayD" = (
@@ -24647,6 +24652,12 @@
},
/turf/open/space,
/area/solars/starboard)
+"beW" = (
+/obj/machinery/atmospherics/pipe/simple/general/visible{
+ dir = 5
+ },
+/turf/open/floor/plasteel,
+/area/engineering/atmos)
"beY" = (
/obj/machinery/camera{
c_tag = "Arrivals Central";
@@ -37817,6 +37828,10 @@
/obj/effect/turf_decal/tile/purple{
dir = 8
},
+/obj/item/radio/intercom{
+ pixel_x = 30;
+ pixel_y = -2
+ },
/turf/open/floor/plasteel,
/area/science/mixing)
"bHI" = (
@@ -40355,15 +40370,9 @@
/obj/structure/cable{
icon_state = "1-2"
},
-/obj/machinery/atmospherics/components/binary/pump{
+/obj/machinery/atmospherics/components/binary/pump/on{
dir = 8;
- name = "Mix to Ports"
- },
-/turf/open/floor/plasteel,
-/area/engineering/atmos)
-"bNk" = (
-/obj/machinery/atmospherics/pipe/manifold/green/visible{
- dir = 1
+ name = "Unfiltered to Mix"
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
@@ -40372,8 +40381,9 @@
/obj/effect/turf_decal/tile/yellow{
dir = 4
},
-/obj/machinery/atmospherics/pipe/manifold/green/visible{
- dir = 1
+/obj/machinery/atmospherics/components/binary/pump/on{
+ dir = 4;
+ name = "Unfiltered & Air to Mix"
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
@@ -40809,23 +40819,19 @@
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
-"bOo" = (
-/obj/machinery/atmospherics/pipe/manifold/general/visible,
-/turf/open/floor/plasteel,
-/area/engineering/atmos)
"bOp" = (
/obj/structure/cable{
icon_state = "1-2"
},
-/obj/machinery/atmospherics/pipe/simple/general/visible{
- dir = 10
+/obj/machinery/atmospherics/components/binary/pump{
+ dir = 8;
+ name = "Pure to Mix"
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bOq" = (
-/obj/machinery/atmospherics/components/binary/pump{
- dir = 1;
- name = "Pure to Mix"
+/obj/machinery/atmospherics/pipe/manifold/green/visible{
+ dir = 1
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
@@ -40844,7 +40850,7 @@
/turf/open/floor/engine/vacuum,
/area/science/mixing)
"bOu" = (
-/obj/machinery/atmospherics/components/unary/outlet_injector/on{
+/obj/machinery/atmospherics/components/unary/outlet_injector/atmos/toxins_mixing_input{
dir = 4
},
/turf/open/floor/plating/airless,
@@ -41089,13 +41095,6 @@
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
-"bPa" = (
-/obj/machinery/portable_atmospherics/canister,
-/obj/machinery/atmospherics/components/unary/portables_connector/visible{
- dir = 1
- },
-/turf/open/floor/plasteel,
-/area/engineering/atmos)
"bPd" = (
/obj/machinery/atmospherics/pipe/manifold/yellow/visible{
dir = 8
@@ -41407,7 +41406,6 @@
/obj/structure/cable{
icon_state = "1-2"
},
-/obj/machinery/atmospherics/pipe/simple/general/visible,
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bPW" = (
@@ -41785,14 +41783,16 @@
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bQK" = (
+/obj/machinery/atmospherics/pipe/simple/cyan/visible,
/obj/machinery/atmospherics/pipe/simple/general/visible{
dir = 4
},
-/obj/machinery/atmospherics/pipe/simple/cyan/visible,
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bQL" = (
-/obj/machinery/atmospherics/pipe/manifold4w/general/visible,
+/obj/machinery/atmospherics/pipe/manifold/green/visible{
+ dir = 8
+ },
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bQM" = (
@@ -41800,9 +41800,8 @@
/obj/effect/turf_decal/tile/yellow{
dir = 4
},
-/obj/machinery/atmospherics/components/binary/pump/on{
- dir = 1;
- name = "Unfiltered to Mix"
+/obj/machinery/atmospherics/pipe/simple/green/visible{
+ dir = 10
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
@@ -42109,8 +42108,7 @@
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bRw" = (
-/obj/machinery/atmospherics/pipe/manifold4w/general/visible,
-/obj/machinery/meter,
+/obj/machinery/atmospherics/pipe/simple/general/visible,
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bRx" = (
@@ -52332,7 +52330,6 @@
/area/service/library)
"czp" = (
/obj/structure/table/wood,
-/obj/item/disk/nuclear/fake,
/obj/item/barcodescanner,
/turf/open/floor/plasteel/dark,
/area/service/library)
@@ -53829,6 +53826,12 @@
},
/turf/open/floor/plasteel,
/area/construction/mining/aux_base)
+"eEd" = (
+/obj/machinery/atmospherics/pipe/simple/green/visible{
+ dir = 6
+ },
+/turf/open/floor/plasteel,
+/area/engineering/atmos)
"eEp" = (
/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
dir = 4
@@ -55198,6 +55201,15 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel,
/area/construction/mining/aux_base)
+"hEi" = (
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/obj/machinery/atmospherics/pipe/simple/general/visible{
+ dir = 10
+ },
+/turf/open/floor/plasteel,
+/area/engineering/atmos)
"hEX" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 6
@@ -56739,6 +56751,12 @@
/obj/effect/turf_decal/delivery,
/turf/open/floor/plasteel/dark,
/area/engineering/main)
+"kWG" = (
+/obj/machinery/atmospherics/pipe/manifold/general/visible{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/engineering/atmos)
"kWQ" = (
/obj/machinery/atmospherics/pipe/simple/orange/visible,
/obj/structure/cable/yellow{
@@ -57369,6 +57387,11 @@
name = "Starboard Solar APC";
pixel_x = -25
},
+/obj/machinery/camera{
+ c_tag = "Starboard Solar";
+ dir = 10;
+ name = "solar camera"
+ },
/turf/open/floor/plating,
/area/maintenance/solars/starboard)
"mwg" = (
@@ -57443,6 +57466,15 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/closed/wall,
/area/maintenance/department/engine)
+"mAR" = (
+/obj/machinery/atmospherics/pipe/simple/green/visible{
+ dir = 5
+ },
+/obj/machinery/atmospherics/pipe/simple/yellow/visible{
+ dir = 10
+ },
+/turf/open/floor/plasteel,
+/area/engineering/atmos)
"mCe" = (
/obj/effect/spawner/structure/window/reinforced,
/obj/machinery/door/poddoor/preopen{
@@ -58849,6 +58881,10 @@
},
/turf/open/floor/wood,
/area/service/lawoffice)
+"pEM" = (
+/obj/machinery/atmospherics/pipe/manifold/general/visible,
+/turf/open/floor/plasteel,
+/area/engineering/atmos)
"pFe" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/effect/turf_decal/tile/red{
@@ -59370,6 +59406,13 @@
},
/turf/open/floor/plasteel/dark,
/area/maintenance/department/crew_quarters/dorms)
+"qQu" = (
+/obj/machinery/portable_atmospherics/canister,
+/obj/machinery/atmospherics/components/unary/portables_connector/visible{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/engineering/atmos)
"qRl" = (
/obj/item/radio/intercom{
name = "Station Intercom (General)";
@@ -60110,6 +60153,13 @@
},
/turf/open/floor/plating,
/area/maintenance/department/security/brig)
+"sGJ" = (
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/obj/machinery/atmospherics/pipe/simple/general/visible,
+/turf/open/floor/plasteel,
+/area/engineering/atmos)
"sIK" = (
/obj/effect/turf_decal/stripes/line{
dir = 8
@@ -61031,6 +61081,12 @@
},
/turf/open/floor/engine,
/area/engineering/main)
+"uST" = (
+/obj/machinery/atmospherics/components/binary/pump{
+ name = "Mix to Ports"
+ },
+/turf/open/floor/plasteel,
+/area/engineering/atmos)
"uUQ" = (
/obj/machinery/door/airlock/maintenance{
name = "Engineering Maintenance";
@@ -99648,7 +99704,7 @@ bJN
bKS
bMe
bNh
-bOo
+pEM
bOX
bMf
bMf
@@ -100162,9 +100218,9 @@ bHw
bKU
bOr
bPU
+kWG
bRw
-bPa
-bMf
+beW
bMf
bMf
bMf
@@ -100418,13 +100474,13 @@ bIF
bHw
bKV
bOX
-bUv
+eEd
bQL
-bPa
-bMf
-bMf
-bMf
+uST
+pEM
bMf
+qQu
+qQu
bSU
bTT
bUv
@@ -100678,10 +100734,10 @@ bMg
bNj
bOp
bPV
-bPV
-bPV
-bPV
-bPV
+hEi
+sGJ
+bUw
+bUw
bUw
bUw
bUw
@@ -100932,8 +100988,8 @@ bIH
bHw
cqG
bOX
-bNk
bOq
+mAR
bPd
bPW
bPW
diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm
index a5f2c5d0f6..cf98755a36 100644
--- a/code/__DEFINES/DNA.dm
+++ b/code/__DEFINES/DNA.dm
@@ -53,6 +53,7 @@
#define GELADIKINESIS /datum/mutation/human/geladikinesis
#define CRYOKINESIS /datum/mutation/human/cryokinesis
#define SPIDER_WEB /datum/mutation/human/webbing
+#define CLUWNEMUT /datum/mutation/human/cluwne
#define UI_CHANGED "ui changed"
#define UE_CHANGED "ue changed"
diff --git a/code/__DEFINES/_flags/_flags.dm b/code/__DEFINES/_flags/_flags.dm
index 0d97634a66..bd6ae98594 100644
--- a/code/__DEFINES/_flags/_flags.dm
+++ b/code/__DEFINES/_flags/_flags.dm
@@ -56,8 +56,6 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define UNUSED_RESERVATION_TURF_1 (1<<1)
/// If a turf can be made dirty at roundstart. This is also used in areas.
#define CAN_BE_DIRTY_1 (1<<2)
-/// If blood cultists can draw runes or build structures on this turf
-#define CULT_PERMITTED_1 (1<<3)
/// Blocks lava rivers being generated on the turf
#define NO_LAVA_GEN_1 (1<<6)
/// Blocks ruins spawning on the turf
@@ -92,6 +90,8 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define ABDUCTOR_PROOF (1<<11)
/// If an area should be hidden from power consoles, power/atmosphere alerts, etc.
#define NO_ALERTS (1<<12)
+/// If blood cultists can draw runes or build structures on this AREA.
+#define CULT_PERMITTED (1<<13)
/*
These defines are used specifically with the atom/pass_flags bitmask
diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm
index f6293454ee..bd6e549d15 100644
--- a/code/__DEFINES/admin.dm
+++ b/code/__DEFINES/admin.dm
@@ -82,6 +82,7 @@
#define ADMIN_PUNISHMENT_PICKLE "Pickle-ify"
#define ADMIN_PUNISHMENT_FRY "Fry"
#define ADMIN_PUNISHMENT_PERFORATE ":B:erforate"
+#define ADMIN_PUNISHMENT_CLUWNE "Cluwne"
#define AHELP_ACTIVE 1
#define AHELP_CLOSED 2
diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm
index b2566278a6..74470d248f 100644
--- a/code/__DEFINES/atmospherics.dm
+++ b/code/__DEFINES/atmospherics.dm
@@ -151,7 +151,7 @@
#define ATMOS_TANK_PLASMA "plasma=70000;TEMP=293.15"
#define ATMOS_TANK_O2 "o2=100000;TEMP=293.15"
#define ATMOS_TANK_N2 "n2=100000;TEMP=293.15"
-#define ATMOS_TANK_AIRMIX "o2=2644;n2=10580;TEMP=293.15"
+#define ATMOS_TANK_AIRMIX "o2=2811;n2=10583;TEMP=293.15"
//LAVALAND
#define LAVALAND_EQUIPMENT_EFFECT_PRESSURE 50 //what pressure you have to be under to increase the effect of equipment meant for lavaland
diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm
index d219736abe..a6d411a8dd 100644
--- a/code/__DEFINES/combat.dm
+++ b/code/__DEFINES/combat.dm
@@ -158,7 +158,7 @@
/// how long they're staggered for
#define SHOVE_STAGGER_DURATION 35
/// how long they're off balance for
-#define SHOVE_OFFBALANCE_DURATION 30
+#define SHOVE_OFFBALANCE_DURATION 3 SECONDS
//Embedded objects
diff --git a/code/__DEFINES/construction.dm b/code/__DEFINES/construction.dm
index 683681a9a6..d3caedac22 100644
--- a/code/__DEFINES/construction.dm
+++ b/code/__DEFINES/construction.dm
@@ -23,6 +23,14 @@
#define WINDOW_IN_FRAME 1
#define WINDOW_SCREWED_TO_FRAME 2
+//reinforced plasma window construction states
+#define PRWINDOW_FRAME_BOLTED 3
+#define PRWINDOW_BARS_CUT 4
+#define PRWINDOW_POPPED 5
+#define PRWINDOW_BOLTS_OUT 6
+#define PRWINDOW_BOLTS_HEATED 7
+#define PRWINDOW_SECURE 8
+
//airlock assembly construction states
#define AIRLOCK_ASSEMBLY_NEEDS_WIRES 0
#define AIRLOCK_ASSEMBLY_NEEDS_ELECTRONICS 1
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index ded183ba0b..3807b66b06 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -165,6 +165,7 @@
#define TRAIT_EXEMPT_HEALTH_EVENTS "exempt-health-events"
#define TRAIT_NO_MIDROUND_ANTAG "no-midround-antag" //can't be turned into an antag by random events
#define TRAIT_PUGILIST "pugilist" //This guy punches people for a living
+#define TRAIT_NOPUGILIST "nopugilist" // for preventing ((((((((((extreme)))))))))) punch stacking
#define TRAIT_KI_VAMPIRE "ki-vampire" //when someone with this trait rolls maximum damage on a punch and stuns the target, they regain some stamina and do clone damage
#define TRAIT_MAULER "mauler" // this guy punches the shit out of people to hurt them, not to drain their stamina
#define TRAIT_PASSTABLE "passtable"
diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm
index 9c6f16e724..781fa38b94 100644
--- a/code/_globalvars/bitfields.dm
+++ b/code/_globalvars/bitfields.dm
@@ -15,7 +15,7 @@ GLOBAL_LIST_INIT(bitfields, list(
"ABDUCTOR_PROOF" = ABDUCTOR_PROOF,
"BLOBS_ALLOWED" = BLOBS_ALLOWED,
"BLOCK_SUICIDE" = BLOCK_SUICIDE,
- // "CULT_PERMITTED" = CULT_PERMITTED,
+ "CULT_PERMITTED" = CULT_PERMITTED,
"FLORA_ALLOWED" = FLORA_ALLOWED,
"HIDDEN_AREA" = HIDDEN_AREA,
"MEGAFAUNA_SPAWN_ALLOWED" = MEGAFAUNA_SPAWN_ALLOWED,
diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm
index a1b7a74384..d1fff25dae 100644
--- a/code/_onclick/hud/_defines.dm
+++ b/code/_onclick/hud/_defines.dm
@@ -89,6 +89,7 @@
//Generic living
#define ui_living_pull "EAST-1:28,CENTER-2:15"
#define ui_living_health "EAST-1:28,CENTER:15"
+#define ui_living_healthdoll "EAST-1:28,CENTER-1:15"
//Monkeys
#define ui_monkey_head "CENTER-5:13,SOUTH:5"
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index 34fd90f4f0..b27abad841 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -637,6 +637,11 @@
name = "health doll"
screen_loc = ui_healthdoll
+/obj/screen/healthdoll/living
+ icon_state = "fullhealth0"
+ screen_loc = ui_living_healthdoll
+ var/filtered = FALSE //so we don't repeatedly create the mask of the mob every update
+
/obj/screen/mood
name = "mood"
icon_state = "mood5"
diff --git a/code/_onclick/hud/simple_animal.dm b/code/_onclick/hud/simple_animal.dm
new file mode 100644
index 0000000000..ef46c0d66e
--- /dev/null
+++ b/code/_onclick/hud/simple_animal.dm
@@ -0,0 +1,15 @@
+/datum/hud/living/simple_animal
+ ui_style = 'icons/mob/screen_gen.dmi'
+/datum/hud/living/simple_animal/New(mob/living/owner)
+ ..()
+ pull_icon = new /obj/screen/pull()
+ pull_icon.icon = ui_style
+ pull_icon.update_icon()
+ pull_icon.screen_loc = ui_living_pull
+ pull_icon.hud = src
+ static_inventory += pull_icon
+
+ //mob health doll! assumes whatever sprite the mob is
+ healthdoll = new /obj/screen/healthdoll/living()
+ healthdoll.hud = src
+ infodisplay += healthdoll
diff --git a/code/datums/chatmessage.dm b/code/datums/chatmessage.dm
index 669e3ddd77..03c23e11f6 100644
--- a/code/datums/chatmessage.dm
+++ b/code/datums/chatmessage.dm
@@ -176,6 +176,11 @@
scheduled_destruction = world.time + (lifespan - CHAT_MESSAGE_EOL_FADE)
enter_subsystem()
+ var/mob/living/silicon/robot/R = target
+ if(iscyborg(R))
+ if(R.module.dogborg == TRUE || R.dogborg == TRUE) //I hate whoever that thought that putting two types of dogborg that don't even sync up properly was good
+ message.pixel_x = 16
+
/**
* Applies final animations to overlay CHAT_MESSAGE_EOL_FADE deciseconds prior to message deletion
* Arguments:
diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm
index 5881c76827..9b9ea3c86e 100644
--- a/code/datums/martial/sleeping_carp.dm
+++ b/code/datums/martial/sleeping_carp.dm
@@ -165,6 +165,7 @@
ADD_TRAIT(H, TRAIT_PIERCEIMMUNE, SLEEPING_CARP_TRAIT)
ADD_TRAIT(H, TRAIT_NODISMEMBER, SLEEPING_CARP_TRAIT)
ADD_TRAIT(H, TRAIT_TASED_RESISTANCE, SLEEPING_CARP_TRAIT)
+ ADD_TRAIT(H, TRAIT_NOPUGILIST, SLEEPING_CARP_TRAIT) // cqc doesn't get this as it's intended to be able to stack with northstar gloves
H.physiology.brute_mod *= 0.4 //brute is really not gonna cut it
H.physiology.burn_mod *= 0.7 //burn is distinctly more useful against them than brute but they're still resistant
H.physiology.stamina_mod *= 0.4 //You take less stamina damage overall, but you do not reduce the damage from stun batons as much
@@ -181,6 +182,7 @@
REMOVE_TRAIT(H, TRAIT_PIERCEIMMUNE, SLEEPING_CARP_TRAIT)
REMOVE_TRAIT(H, TRAIT_NODISMEMBER, SLEEPING_CARP_TRAIT)
REMOVE_TRAIT(H, TRAIT_TASED_RESISTANCE, SLEEPING_CARP_TRAIT)
+ REMOVE_TRAIT(H, TRAIT_NOPUGILIST, SLEEPING_CARP_TRAIT)
H.physiology.brute_mod = initial(H.physiology.brute_mod)
H.physiology.burn_mod = initial(H.physiology.burn_mod)
H.physiology.stamina_mod = initial(H.physiology.stamina_mod)
diff --git a/code/datums/mutations/cluwne.dm b/code/datums/mutations/cluwne.dm
new file mode 100644
index 0000000000..59b7752372
--- /dev/null
+++ b/code/datums/mutations/cluwne.dm
@@ -0,0 +1,57 @@
+/datum/mutation/human/cluwne
+
+ name = "Cluwne"
+ quality = NEGATIVE
+ locked = TRUE
+ text_gain_indication = "You feel like your brain is tearing itself apart."
+
+/datum/mutation/human/cluwne/on_acquiring(mob/living/carbon/human/owner)
+ if(..())
+ return
+ owner.dna.add_mutation(CLOWNMUT)
+ owner.dna.add_mutation(EPILEPSY)
+ owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, 199, 199)
+
+ var/mob/living/carbon/human/H = owner
+
+ if(!istype(H.wear_mask, /obj/item/clothing/mask/gas/cluwne))
+ if(!H.dropItemToGround(H.wear_mask))
+ qdel(H.wear_mask)
+ H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/cluwne(H), SLOT_WEAR_MASK)
+ if(!istype(H.w_uniform, /obj/item/clothing/under/cluwne))
+ if(!H.dropItemToGround(H.w_uniform))
+ qdel(H.w_uniform)
+ H.equip_to_slot_or_del(new /obj/item/clothing/under/cluwne(H), SLOT_W_UNIFORM)
+ if(!istype(H.shoes, /obj/item/clothing/shoes/clown_shoes/cluwne))
+ if(!H.dropItemToGround(H.shoes))
+ qdel(H.shoes)
+ H.equip_to_slot_or_del(new /obj/item/clothing/shoes/clown_shoes/cluwne(H), SLOT_SHOES)
+
+ owner.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/white(owner), SLOT_GLOVES) // this is purely for cosmetic purposes incase they aren't wearing anything in that slot
+ owner.equip_to_slot_or_del(new /obj/item/storage/backpack/clown(owner), SLOT_BACK) // ditto
+
+/datum/mutation/human/cluwne/on_life(mob/living/carbon/human/owner)
+ if((prob(15) && owner.IsUnconscious()))
+ owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, 199, 199) // there I changed it to setBrainLoss
+ switch(rand(1, 6))
+ if(1)
+ owner.say("HONK")
+ if(2 to 5)
+ owner.emote("scream")
+ if(6)
+ owner.Stun(1)
+ owner.Knockdown(20)
+ owner.Jitter(500)
+
+/datum/mutation/human/cluwne/on_losing(mob/living/carbon/human/owner)
+ owner.adjust_fire_stacks(1)
+ owner.IgniteMob()
+ owner.dna.add_mutation(CLUWNEMUT)
+
+/mob/living/carbon/human/proc/cluwneify()
+ dna.add_mutation(CLUWNEMUT)
+ emote("scream")
+ regenerate_icons()
+ visible_message("[src]'s body glows green, the glow dissipating only to leave behind a cluwne formerly known as [src]!", \
+ "Your brain feels like it's being torn apart, there is only the honkmother now.")
+ flash_act()
diff --git a/code/game/area/Space_Station_13_areas.dm b/code/game/area/Space_Station_13_areas.dm
index a27f4b291e..57f4fdb8de 100644
--- a/code/game/area/Space_Station_13_areas.dm
+++ b/code/game/area/Space_Station_13_areas.dm
@@ -209,7 +209,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Generic Maintenance"
// ambience_index = AMBIENCE_MAINT
ambientsounds = MAINTENANCE
- area_flags = BLOBS_ALLOWED | UNIQUE_AREA
+ area_flags = BLOBS_ALLOWED | UNIQUE_AREA | CULT_PERMITTED
// airlock_wires = /datum/wires/airlock/maint
sound_environment = SOUND_AREA_TUNNEL_ENCLOSED
@@ -294,7 +294,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/maintenance/department/science/xenobiology
name = "Xenobiology Maintenance"
icon_state = "xenomaint"
- area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA | XENOBIOLOGY_COMPATIBLE
+ area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA | XENOBIOLOGY_COMPATIBLE | CULT_PERMITTED
//Maintenance - Generic
@@ -598,11 +598,11 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/commons
name = "Crew Quarters"
sound_environment = SOUND_AREA_STANDARD_STATION
+ area_flags = BLOBS_ALLOWED | UNIQUE_AREA | CULT_PERMITTED
/area/commons/dorms
name = "Dormitories"
icon_state = "dorms"
- area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
/area/commons/dorms/barracks
name = "Sleep Barracks"
@@ -899,7 +899,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
// mood_bonus = 5
// mood_message = "I love being in the library!\n"
// mood_trait = TRAIT_INTROVERT
- flags_1 = CULT_PERMITTED_1
+ area_flags = BLOBS_ALLOWED | UNIQUE_AREA | CULT_PERMITTED
sound_environment = SOUND_AREA_LARGE_SOFTFLOOR
/area/service/library/lounge
@@ -926,7 +926,6 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/service/library/abandoned
name = "Abandoned Library"
icon_state = "abandoned_library"
- flags_1 = CULT_PERMITTED_1
nightshift_public_area = NIGHTSHIFT_AREA_NONE
/area/service/chapel
@@ -973,8 +972,8 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/service/janitor
name = "Custodial Closet"
icon_state = "janitor"
- flags_1 = CULT_PERMITTED_1
sound_environment = SOUND_AREA_SMALL_ENCLOSED
+ area_flags = BLOBS_ALLOWED | UNIQUE_AREA | CULT_PERMITTED
/area/service/janitor/aux
name = "Auxiliary Custodial Closet"
@@ -1027,7 +1026,6 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/engineering/atmos
name = "Atmospherics"
icon_state = "atmos"
- flags_1 = CULT_PERMITTED_1
/area/engineering/atmos/upper
name = "Upper Atmospherics"
@@ -1035,7 +1033,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/engineering/atmospherics_engine
name = "Atmospherics Engine"
icon_state = "atmos_engine"
- area_flags = BLOBS_ALLOWED | UNIQUE_AREA
+ area_flags = BLOBS_ALLOWED | UNIQUE_AREA | CULT_PERMITTED
/area/engineering/lobby
name = "Engineering Lobby"
@@ -1044,7 +1042,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/engineering/supermatter
name = "Supermatter Engine"
icon_state = "engine_sm"
- area_flags = BLOBS_ALLOWED | UNIQUE_AREA
+ area_flags = BLOBS_ALLOWED | UNIQUE_AREA | CULT_PERMITTED
sound_environment = SOUND_AREA_SMALL_ENCLOSED
/area/engineering/break_room
@@ -1084,7 +1082,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/engineering/storage/tcomms
name = "Telecomms Storage"
icon_state = "tcom"
- area_flags = BLOBS_ALLOWED | UNIQUE_AREA
+ area_flags = BLOBS_ALLOWED | UNIQUE_AREA | CULT_PERMITTED
clockwork_warp_allowed = FALSE
//Engineering - Construction
@@ -1314,7 +1312,6 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/medical/virology
name = "Virology"
icon_state = "virology"
- flags_1 = CULT_PERMITTED_1
/area/medical/morgue
name = "Morgue"
@@ -1608,7 +1605,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/science/test_area
name = "Toxins Test Area"
icon_state = "tox_test"
- area_flags = BLOBS_ALLOWED | UNIQUE_AREA
+ area_flags = BLOBS_ALLOWED | UNIQUE_AREA | CULT_PERMITTED
/area/science/mixing
name = "Toxins Mixing Lab"
@@ -1617,7 +1614,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/science/mixing/chamber
name = "Toxins Mixing Chamber"
icon_state = "tox_mix_chamber"
- area_flags = BLOBS_ALLOWED | UNIQUE_AREA
+ area_flags = BLOBS_ALLOWED | UNIQUE_AREA | CULT_PERMITTED
/area/science/misc_lab
name = "Testing Lab"
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index bc7a802df5..2a21d72119 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -13,7 +13,7 @@
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
invisibility = INVISIBILITY_LIGHTING
- var/area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
+ var/area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA | CULT_PERMITTED
var/fire = null
///Whether there is an atmos alarm in this area
diff --git a/code/game/area/areas/centcom.dm b/code/game/area/areas/centcom.dm
index 09adaf72f9..0befe0bd86 100644
--- a/code/game/area/areas/centcom.dm
+++ b/code/game/area/areas/centcom.dm
@@ -11,7 +11,7 @@
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
requires_power = FALSE
has_gravity = STANDARD_GRAVITY
- area_flags = VALID_TERRITORY | UNIQUE_AREA | NOTELEPORT
+ area_flags = UNIQUE_AREA | NOTELEPORT
flags_1 = NONE
/area/centcom/control
diff --git a/code/game/area/areas/holodeck.dm b/code/game/area/areas/holodeck.dm
index c639080775..3bc73a945f 100644
--- a/code/game/area/areas/holodeck.dm
+++ b/code/game/area/areas/holodeck.dm
@@ -3,7 +3,6 @@
icon_state = "Holodeck"
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
flags_1 = NONE
- area_flags = VALID_TERRITORY | UNIQUE_AREA
sound_environment = SOUND_ENVIRONMENT_PADDED_CELL
var/obj/machinery/computer/holodeck/linked
@@ -87,9 +86,6 @@
/area/holodeck/rec_center/lounge
name = "Holodeck - Lounge"
-/area/holodeck/rec_center/medical
- name = "Holodeck - Emergency Medical"
-
/area/holodeck/rec_center/pet_lounge
name = "Holodeck - Pet Park"
@@ -128,6 +124,10 @@
name = "Holodeck - Holdout Bunker"
restricted = 1
+/area/holodeck/rec_center/medical
+ name = "Holodeck - Emergency Medical"
+ restricted = 1
+
/area/holodeck/rec_center/anthophila
name = "Holodeck - Anthophila"
restricted = 1
diff --git a/code/game/area/areas/shuttles.dm b/code/game/area/areas/shuttles.dm
index 78bf7a1311..c8ee2973c4 100644
--- a/code/game/area/areas/shuttles.dm
+++ b/code/game/area/areas/shuttles.dm
@@ -157,10 +157,10 @@
/area/shuttle/escape
name = "Emergency Shuttle"
- area_flags = BLOBS_ALLOWED
+ area_flags = BLOBS_ALLOWED | CULT_PERMITTED
// area_limited_icon_smoothing = /area/shuttle/escape
canSmoothWithAreas = /area/shuttle/escape
- flags_1 = CAN_BE_DIRTY_1 // | CULT_PERMITTED_1
+ flags_1 = CAN_BE_DIRTY_1
/area/shuttle/escape/backup
name = "Backup Emergency Shuttle"
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index aafa77b878..098f1a2ea0 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -579,7 +579,7 @@
//TODO: Better floating
/atom/movable/proc/float(on, throw_override)
- if(throwing || !throw_override)
+ if(throwing && !throw_override)
return
if(on && !(movement_type & FLOATING))
animate(src, pixel_y = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm
index 9953b593d9..64b950a417 100644
--- a/code/game/gamemodes/meteor/meteors.dm
+++ b/code/game/gamemodes/meteor/meteors.dm
@@ -18,6 +18,8 @@ GLOBAL_LIST_INIT(meteorsB, list(/obj/effect/meteor/meaty=5, /obj/effect/meteor/m
GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
+GLOBAL_LIST_INIT(meteorsCat, list(/obj/effect/meteor/cat)) //for cat meteors
+
///////////////////////////////
//Meteor spawning global procs
@@ -345,6 +347,17 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
..()
if(prob(20))
explosion(src.loc,2,4,6,8)
+
+/obj/effect/meteor/cat
+ name = "space cat"
+ icon_state = "catmeteor"
+ desc = "Meow."
+ hits = 1
+ heavy = FALSE
+ meteorsound = 'sound/effects/meow1.ogg'
+ meteordrop = list(/mob/living/simple_animal/pet/cat/space)
+ threat = 0
+ dropamt = 1
//////////////////////////
//Spookoween meteors
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 4eed168ad6..477f72ee3b 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -688,7 +688,7 @@
else
. += "It looks very robust."
- if(hasSiliconAccessInArea(user) && (!stat & BROKEN))
+ if(hasSiliconAccessInArea(user) && !(stat & BROKEN))
. += "Shift-click [src] to [ density ? "open" : "close"] it."
. += "Ctrl-click [src] to [ locked ? "raise" : "drop"] its bolts."
. += "Alt-click [src] to [ secondsElectrified ? "un-electrify" : "permanently electrify"] it."
diff --git a/code/game/objects/effects/effect_system/effects_foam.dm b/code/game/objects/effects/effect_system/effects_foam.dm
index 53fbd55b70..6eb21118ff 100644
--- a/code/game/objects/effects/effect_system/effects_foam.dm
+++ b/code/game/objects/effects/effect_system/effects_foam.dm
@@ -341,6 +341,9 @@
return TRUE
. = ..()
+/obj/structure/foamedmetal/resin/BlockSuperconductivity()
+ return TRUE
+
#undef ALUMINUM_FOAM
#undef IRON_FOAM
#undef RESIN_FOAM
diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
index 069e72b318..d7eeb2789b 100644
--- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm
+++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
@@ -378,6 +378,12 @@
icon_state = "shieldsparkles"
duration = 6
+/obj/effect/temp_visual/impact_effect/judgement_cut
+ name = "judgement cut impact"
+ icon = 'icons/effects/effects.dmi'
+ icon_state = "impact_judgement"
+ duration = 6
+
/obj/effect/temp_visual/heart
name = "heart"
icon = 'icons/mob/animal.dmi'
@@ -535,3 +541,7 @@
/obj/effect/temp_visual/slime_puddle/reverse
icon_state = "from_puddle"
duration = 7
+
+/obj/effect/temp_visual/gib_animation
+ icon = 'icons/mob/mob.dmi'
+ duration = 15
diff --git a/code/game/objects/items/devices/dogborg_sleeper.dm b/code/game/objects/items/devices/dogborg_sleeper.dm
index 4d57d05be4..01970ccdbd 100644
--- a/code/game/objects/items/devices/dogborg_sleeper.dm
+++ b/code/game/objects/items/devices/dogborg_sleeper.dm
@@ -77,8 +77,11 @@
return
if(!iscarbon(target))
return
+ if(!(target?.client?.prefs?.cit_toggles & MEDIHOUND_SLEEPER))
+ to_chat(user, "The user has opted out of the use of your [src].")
+ return
var/voracious = TRUE
- if(!target.client || !(target.client.prefs.cit_toggles & MEDIHOUND_SLEEPER) || !hound.client || !(hound.client.prefs.cit_toggles & MEDIHOUND_SLEEPER))
+ if(!hound.client || !(hound.client.prefs.cit_toggles & MEDIHOUND_SLEEPER))
voracious = FALSE
if(target.buckled)
to_chat(user, "The user is buckled and can not be put into your [src].")
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 34fe90e797..8a941283b7 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -381,8 +381,8 @@ GENETICS SCANNER
else if (S.mutantstomach != initial(S.mutantstomach))
mutant = TRUE
- msg += "\tReported Species: [H.dna.custom_species ? H.dna.custom_species : S.name]\n"
- msg += "\tBase Species: [S.name]\n"
+ msg += "\tReported Species: [H.spec_trait_examine_font()][H.dna.custom_species ? H.dna.custom_species : S.name]\n"
+ msg += "\tBase Species: [H.spec_trait_examine_font()][S.name]\n"
if(mutant)
msg += "\tSubject has mutations present.\n"
msg += "\tBody temperature: [round(M.bodytemperature-T0C,0.1)] °C ([round(M.bodytemperature*1.8-459.67,0.1)] °F)\n"
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index 6e66f833c2..f888927411 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -383,7 +383,7 @@
. = ..()
/obj/item/stack/medical/mesh/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
- if(!is_open & user.get_inactive_held_item() == src)
+ if(!is_open && (user.get_inactive_held_item() == src))
to_chat(user, "You need to open [src] first.")
return
. = ..()
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index ffcd15c39e..592b2e42cc 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -593,7 +593,7 @@ GLOBAL_LIST_INIT(runed_metal_recipes, list ( \
return
var/turf/T = get_turf(user) //we may have moved. adjust as needed...
var/area/A = get_area(user)
- if((!is_station_level(T.z) && !is_mining_level(T.z)) || (A && !(A.flags_1 & CULT_PERMITTED_1)))
+ if((!is_station_level(T.z) && !is_mining_level(T.z)) || !(A?.area_flags & CULT_PERMITTED))
to_chat(user, "The veil is not weak enough here.")
return FALSE
return ..()
diff --git a/code/game/objects/structures/spawner.dm b/code/game/objects/structures/spawner.dm
index 9032a80d91..7d13af1e3e 100644
--- a/code/game/objects/structures/spawner.dm
+++ b/code/game/objects/structures/spawner.dm
@@ -73,3 +73,15 @@
name = "wumborian fugu den"
desc = "A den housing a nest of wumborian fugus, how do they all even fit in there?"
mob_types = list(/mob/living/simple_animal/hostile/asteroid/fugu)
+
+/obj/structure/spawner/clown
+ name = "Laughing Larry"
+ desc = "A laughing, jovial figure. Something seems stuck in his throat."
+ icon_state = "clownbeacon"
+ icon = 'icons/obj/device.dmi'
+ max_integrity = 200
+ max_mobs = 15
+ spawn_time = 150
+ mob_types = list(/mob/living/simple_animal/hostile/retaliate/clown, /mob/living/simple_animal/hostile/retaliate/clown/fleshclown, /mob/living/simple_animal/hostile/retaliate/clown/clownhulk, /mob/living/simple_animal/hostile/retaliate/clown/longface, /mob/living/simple_animal/hostile/retaliate/clown/clownhulk/chlown, /mob/living/simple_animal/hostile/retaliate/clown/clownhulk/honcmunculus, /mob/living/simple_animal/hostile/retaliate/clown/mutant/blob)
+ spawn_text = "climbs out of"
+ faction = list("clown")
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index fba79ac2b0..6356424aaf 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -127,7 +127,7 @@
to_chat(user, "Throwing [pushed_mob] onto the table might hurt them!")
return
var/added_passtable = FALSE
- if(!pushed_mob.pass_flags & PASSTABLE)
+ if(!(pushed_mob.pass_flags & PASSTABLE))
added_passtable = TRUE
pushed_mob.pass_flags |= PASSTABLE
pushed_mob.Move(src.loc)
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 6452e71e4e..5f84094477 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -21,6 +21,7 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
var/ini_dir = null
var/state = WINDOW_OUT_OF_FRAME
var/reinf = FALSE
+ var/extra_reinforced = FALSE
var/heat_resistance = 800
var/decon_speed = 30
var/wtype = "glass"
@@ -65,6 +66,20 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
. += "The window is out of the frame, but could be pried in. It is screwed to the floor."
else if(!anchored)
. += "The window is unscrewed from the floor, and could be deconstructed by wrenching."
+ switch(state)
+ if(PRWINDOW_SECURE)
+ if(extra_reinforced)
+ . += "It's been screwed in with one way screws, you'd need to heat their solder cover to have any chance of backing them out."
+ else
+ . += "It's been screwed in with solid screws, you'd need to screw them out to unsecure the window."
+ if(PRWINDOW_BOLTS_HEATED)
+ . += "The solder cover melts away, and you'll likely be able to unscrew them now."
+ if(PRWINDOW_BOLTS_OUT)
+ . += "The screws have been removed, revealing a small gap you could fit a prying tool in."
+ if(PRWINDOW_POPPED)
+ . += "The main plate of the window has popped out of the frame, exposing some bars that look like they can be cut."
+ if(PRWINDOW_BARS_CUT)
+ . += "The main pane can be easily moved out of the way to reveal some bolts holding the frame in."
else
if(anchored)
. += "The window is screwed to the floor."
@@ -75,8 +90,13 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
. = ..()
if(direct)
setDir(direct)
- if(reinf && anchored)
+
+ if(extra_reinforced && anchored)
+ state = PRWINDOW_SECURE
+
+ else if(reinf && anchored)
state = WINDOW_SCREWED_TO_FRAME
+
if(mapload && electrochromatic_id && electrochromatic_id[1] == "!")
electrochromatic_id = SSmapping.get_obfuscated_id(electrochromatic_id)
@@ -230,29 +250,26 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
make_electrochromatic(K.id)
qdel(K)
- if(!(flags_1&NODECONSTRUCT_1))
+ if(!(flags_1 & NODECONSTRUCT_1) && !(state >= PRWINDOW_FRAME_BOLTED))
if(I.tool_behaviour == TOOL_SCREWDRIVER)
I.play_tool_sound(src, 75)
- if(reinf)
- if(state == WINDOW_SCREWED_TO_FRAME || state == WINDOW_IN_FRAME)
- to_chat(user, "You begin to [state == WINDOW_SCREWED_TO_FRAME ? "unscrew the window from":"screw the window to"] the frame...")
- if(I.use_tool(src, user, decon_speed, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored)))
+ if(state == WINDOW_SCREWED_TO_FRAME || state == WINDOW_IN_FRAME && anchored)
+ to_chat(user, "You begin to [state == WINDOW_SCREWED_TO_FRAME ? "unscrew the window from":"screw the window to"] the frame...")
+ if(I.use_tool(src, user, decon_speed, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored)))
+ if(extra_reinforced && state == WINDOW_IN_FRAME)
+ state = PRWINDOW_SECURE
+ else
state = (state == WINDOW_IN_FRAME ? WINDOW_SCREWED_TO_FRAME : WINDOW_IN_FRAME)
- to_chat(user, "You [state == WINDOW_IN_FRAME ? "unfasten the window from":"fasten the window to"] the frame.")
- else if(state == WINDOW_OUT_OF_FRAME)
- to_chat(user, "You begin to [anchored ? "unscrew the frame from":"screw the frame to"] the floor...")
- if(I.use_tool(src, user, decon_speed, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored)))
- setAnchored(!anchored)
- to_chat(user, "You [anchored ? "fasten the frame to":"unfasten the frame from"] the floor.")
- else //if we're not reinforced, we don't need to check or update state
- to_chat(user, "You begin to [anchored ? "unscrew the window from":"screw the window to"] the floor...")
- if(I.use_tool(src, user, decon_speed, extra_checks = CALLBACK(src, .proc/check_anchored, anchored)))
+ to_chat(user, "You [state == WINDOW_IN_FRAME ? "unfasten the window from":"fasten the window to"] the frame.")
+ else if(state == WINDOW_OUT_OF_FRAME)
+ to_chat(user, "You begin to [anchored ? "unscrew the frame from":"screw the frame to"] the floor...")
+ if(I.use_tool(src, user, decon_speed, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored)))
setAnchored(!anchored)
- to_chat(user, "You [anchored ? "fasten the window to":"unfasten the window from"] the floor.")
+ to_chat(user, "You [anchored ? "fasten the frame to":"unfasten the frame from"] the floor.")
return
- else if(I.tool_behaviour == TOOL_CROWBAR && reinf && (state == WINDOW_OUT_OF_FRAME || state == WINDOW_IN_FRAME))
+ else if(I.tool_behaviour == TOOL_CROWBAR && reinf && (state == WINDOW_OUT_OF_FRAME || state == WINDOW_IN_FRAME) && anchored)
to_chat(user, "You begin to lever the window [state == WINDOW_OUT_OF_FRAME ? "into":"out of"] the frame...")
I.play_tool_sound(src, 75)
if(I.use_tool(src, user, decon_speed, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored)))
@@ -270,8 +287,67 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
to_chat(user, "You successfully disassemble [src].")
qdel(src)
return
+ if(!reinf || !anchored)
+ return ..()
+ switch(state)
+ if(PRWINDOW_SECURE)
+ if(extra_reinforced)
+ if(I.tool_behaviour == TOOL_WELDER && user.a_intent == INTENT_HARM)
+ user.visible_message("[user] holds \the [I] to the security screws on \the [src]...",
+ "You begin heating the security screws on \the [src]...")
+ if(I.use_tool(src, user, 180, volume = 100))
+ to_chat(user, "The security bolts are glowing white hot and look ready to be removed.")
+ state = PRWINDOW_BOLTS_HEATED
+ addtimer(CALLBACK(src, .proc/cool_bolts), 300)
+ return
+ else
+ if(I.tool_behaviour == TOOL_SCREWDRIVER)
+ user.visible_message("[user] digs into the screws and starts removing them...",
+ "You dig into the screws hard and they start turning...")
+ if(I.use_tool(src, user, 80, volume = 50))
+ state = PRWINDOW_BOLTS_OUT
+ to_chat(user, "The screws come out, and a gap forms around the edge of the pane.")
+ return
+ if(PRWINDOW_BOLTS_HEATED)
+ if(I.tool_behaviour == TOOL_SCREWDRIVER)
+ user.visible_message("[user] digs into the security screws and starts removing them...",
+ "You dig into the screws hard and they start turning...")
+ if(I.use_tool(src, user, 80, volume = 50))
+ state = PRWINDOW_BOLTS_OUT
+ to_chat(user, "The screws come out, and a gap forms around the edge of the pane.")
+ return
+ if(PRWINDOW_BOLTS_OUT)
+ if(I.tool_behaviour == TOOL_CROWBAR)
+ user.visible_message("[user] wedges \the [I] into the gap in the frame and starts prying...",
+ "You wedge \the [I] into the gap in the frame and start prying...")
+ if(I.use_tool(src, user, 50, volume = 50))
+ state = PRWINDOW_POPPED
+ to_chat(user, "The panel pops out of the frame, exposing some thin metal bars that looks like they can be cut.")
+ return
+ if(PRWINDOW_POPPED)
+ if(I.tool_behaviour == TOOL_WIRECUTTER)
+ user.visible_message("[user] starts cutting the exposed bars on \the [src]...",
+ "You start cutting the exposed bars on \the [src]")
+ if(I.use_tool(src, user, 30, volume = 50))
+ state = PRWINDOW_BARS_CUT
+ to_chat(user, "The panels falls out of the way exposing the frame bolts.")
+ return
+ if(PRWINDOW_BARS_CUT)
+ if(I.tool_behaviour == TOOL_WRENCH)
+ user.visible_message("[user] starts unfastening \the [src] from the frame...",
+ "You start unfastening the bolts from the frame...")
+ if(I.use_tool(src, user, 50, volume = 50))
+ to_chat(user, "You unscrew the bolts from the frame and the window pops loose.")
+ state = WINDOW_OUT_OF_FRAME
+ setAnchored(FALSE)
+ return
return ..()
+/obj/structure/window/proc/cool_bolts()
+ if(state == PRWINDOW_BOLTS_HEATED)
+ state = PRWINDOW_SECURE
+ visible_message("The bolts on \the [src] look like they've cooled off...")
+
/obj/structure/window/setAnchored(anchorvalue)
..()
air_update_turf(TRUE)
@@ -577,6 +653,7 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
desc = "A window made out of a plasma-silicate alloy and a rod matrix. It looks hopelessly tough to break and is most likely nigh fireproof."
icon_state = "plasmarwindow"
reinf = TRUE
+ extra_reinforced = TRUE
heat_resistance = 50000
armor = list("melee" = 85, "bullet" = 20, "laser" = 0, "energy" = 0, "bomb" = 60, "bio" = 100, "rad" = 100, "fire" = 99, "acid" = 100)
max_integrity = 500
@@ -642,6 +719,7 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
icon = 'icons/obj/smooth_structures/rplasma_window.dmi'
icon_state = "rplasmawindow"
dir = FULLTILE_WINDOW_DIR
+ state = PRWINDOW_SECURE
max_integrity = 1000
fulltile = TRUE
flags_1 = PREVENT_CLICK_UNDER_1
@@ -726,6 +804,7 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
fulltile = TRUE
flags_1 = PREVENT_CLICK_UNDER_1
reinf = TRUE
+ extra_reinforced = TRUE
heat_resistance = 1600
armor = list("melee" = 50, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 100)
smooth = SMOOTH_TRUE
@@ -758,6 +837,7 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
wave_explosion_block = EXPLOSION_BLOCK_BOROSILICATE_WINDOW
wave_explosion_multiply = EXPLOSION_DAMPEN_BOROSILICATE_WINDOW
decon_speed = 40
+ extra_reinforced = TRUE
glass_type = /obj/item/stack/tile/brass
glass_amount = 1
reinf = FALSE
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 0727149b9b..22bbf03014 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -116,6 +116,7 @@ GLOBAL_LIST_INIT(admin_verbs_fun, list(
/client/proc/show_tip,
/client/proc/smite,
/client/proc/admin_away,
+ /client/proc/spawn_floor_cluwne,
/client/proc/cmd_admin_toggle_fov, //CIT CHANGE - FOV
/client/proc/roll_dices //CIT CHANGE - Adds dice verb
))
diff --git a/code/modules/admin/antag_panel.dm b/code/modules/admin/antag_panel.dm
index 84071d76f4..2d1aa63a91 100644
--- a/code/modules/admin/antag_panel.dm
+++ b/code/modules/admin/antag_panel.dm
@@ -104,7 +104,7 @@ GLOBAL_VAR(antag_prototypes)
var/datum/component/activity/activity = current.GetComponent(/datum/component/activity)
if(activity)
out += "Activity level: [activity.activity_level]
"
- out += "Hasn't changed areas in approximately [activity.not_moved_counter] seconds"
+ out += "Hasn't changed areas in approximately [activity.not_moved_counter] seconds
"
var/special_statuses = get_special_statuses()
if(length(special_statuses))
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 59eee83b35..72ec804d28 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -1333,9 +1333,10 @@ Traitors and the like can also be revived with the previous role mostly intact.
ADMIN_PUNISHMENT_SHOES,
ADMIN_PUNISHMENT_PICKLE,
ADMIN_PUNISHMENT_FRY,
- ADMIN_PUNISHMENT_CRACK,
- ADMIN_PUNISHMENT_BLEED,
- ADMIN_PUNISHMENT_SCARIFY)
+ ADMIN_PUNISHMENT_CRACK,
+ ADMIN_PUNISHMENT_BLEED,
+ ADMIN_PUNISHMENT_SCARIFY,
+ ADMIN_PUNISHMENT_CLUWNE)
var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in punishment_list
@@ -1501,6 +1502,11 @@ Traitors and the like can also be revived with the previous role mostly intact.
to_chat(usr,"[C] does not have knottable shoes!")
return
sick_kicks.adjust_laces(SHOES_KNOTTED)
+ if(ADMIN_PUNISHMENT_CLUWNE)
+ if(!iscarbon(target))
+ to_chat(usr,"This must be used on a carbon mob.")
+ return
+ target.cluwneify()
punish_log(target, punishment)
@@ -1691,3 +1697,23 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(!source)
return
REMOVE_TRAIT(D,chosen_trait,source)
+
+/client/proc/spawn_floor_cluwne()
+ set category = "Admin.Fun"
+ set name = "Unleash Floor Cluwne"
+ set desc = "Pick a specific target or just let it select randomly and spawn the floor cluwne mob on the station. Be warned: spawning more than one may cause issues!"
+ var/target
+
+ if(!check_rights(R_FUN))
+ return
+
+ var/turf/T = get_turf(usr)
+ target = input("Any specific target in mind? Please note only live, non cluwned, human targets are valid.", "Target", target) as null|anything in GLOB.player_list
+ if(target && ishuman(target))
+ var/mob/living/carbon/human/H = target
+ var/mob/living/simple_animal/hostile/floor_cluwne/FC = new /mob/living/simple_animal/hostile/floor_cluwne(T)
+ FC.Acquire_Victim(H)
+ else
+ new /mob/living/simple_animal/hostile/floor_cluwne(T)
+ log_admin("[key_name(usr)] spawned floor cluwne.")
+ message_admins("[key_name(usr)] spawned floor cluwne.")
diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm
index ba3d8106ef..b92b659183 100644
--- a/code/modules/antagonists/_common/antag_datum.dm
+++ b/code/modules/antagonists/_common/antag_datum.dm
@@ -164,14 +164,12 @@ GLOBAL_LIST_EMPTY(antagonists)
/datum/antagonist/proc/remove_blacklisted_quirks()
var/mob/living/L = owner.current
if(istype(L))
- var/list/my_quirks = L.client?.prefs.all_quirks.Copy()
- SSquirks.filter_quirks(my_quirks,blacklisted_quirks)
for(var/q in L.roundstart_quirks)
var/datum/quirk/Q = q
- if(!(SSquirks.quirk_name_by_path(Q.type) in my_quirks))
+ if(Q.type in blacklisted_quirks)
if(initial(Q.antag_removal_text))
to_chat(L, "[initial(Q.antag_removal_text)]")
- L.remove_quirk(Q.type)
+ qdel(Q)
//Returns the team antagonist belongs to if any.
/datum/antagonist/proc/get_team()
diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm
index 5b6a7648c8..b7aeb23e6f 100644
--- a/code/modules/antagonists/changeling/powers/mutations.dm
+++ b/code/modules/antagonists/changeling/powers/mutations.dm
@@ -680,6 +680,11 @@
glove_type = /obj/item/clothing/gloves/fingerless/pugilist/cling // just punch his head off dude
glove_name_simple = "bone gauntlets"
+/obj/effect/proc_holder/changeling/gloves/gauntlets/sting_action(mob/living/user)
+ if(HAS_TRAIT(user, TRAIT_NOPUGILIST))
+ to_chat(user, "We would gain nothing by forming our fists into brute-force weapons when we are trained in precision martial arts!")
+ return
+
/obj/item/clothing/gloves/fingerless/pugilist/cling // switches between lesser GotNS and Big Punchy Rib Breaky Hands
name = "hewn bone gauntlets"
icon_state = "ling_gauntlets"
diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm
index 6b6dd64f72..41c82bb45e 100644
--- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm
+++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm
@@ -25,7 +25,7 @@
/datum/clockwork_scripture/create_object/stargazer/check_special_requirements()
var/area/A = get_area(invoker)
var/turf/T = get_turf(invoker)
- if(!is_station_level(invoker.z) || isspaceturf(T) || !(A.area_flags & VALID_TERRITORY))
+ if(!is_station_level(invoker.z) || isspaceturf(T) || !(A?.area_flags & CULT_PERMITTED))
to_chat(invoker, "Stargazers can't be built off-station.")
return
return ..()
diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_judgement.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_judgement.dm
index 6802576bd6..caa45d55d2 100644
--- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_judgement.dm
+++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_judgement.dm
@@ -34,7 +34,7 @@
return FALSE
var/area/A = get_area(invoker)
var/turf/T = get_turf(invoker)
- if(!is_station_level(T.z) || isspaceturf(T) || !(A.area_flags & VALID_TERRITORY) || isshuttleturf(T))
+ if(!is_station_level(T.z) || isspaceturf(T) || !(A?.area_flags & CULT_PERMITTED) || isshuttleturf(T))
to_chat(invoker, "You must be on the station to activate the Ark!")
return FALSE
if(GLOB.clockwork_gateway_activated)
diff --git a/code/modules/antagonists/clockcult/clock_structures/stargazer.dm b/code/modules/antagonists/clockcult/clock_structures/stargazer.dm
index 88a29f14f1..dea8f428ba 100644
--- a/code/modules/antagonists/clockcult/clock_structures/stargazer.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/stargazer.dm
@@ -52,7 +52,7 @@
break
if(has_starlight && anchored)
var/area/A = get_area(src)
- if(A.outdoors || A.map_name == "Space" || !(A.area_flags & VALID_TERRITORY))
+ if(A.outdoors || A.map_name == "Space" || !(A?.area_flags & CULT_PERMITTED))
has_starlight = FALSE
if(old_status != has_starlight)
if(has_starlight)
diff --git a/code/modules/antagonists/cult/cult.dm b/code/modules/antagonists/cult/cult.dm
index 30ccb731c3..0cc0ed133e 100644
--- a/code/modules/antagonists/cult/cult.dm
+++ b/code/modules/antagonists/cult/cult.dm
@@ -419,7 +419,7 @@
var/sanity = 0
while(summon_spots.len < SUMMON_POSSIBILITIES && sanity < 100)
var/area/summon = pick(GLOB.sortedAreas - summon_spots)
- if(summon && is_station_level(summon.z) && !(summon.area_flags & VALID_TERRITORY))
+ if(summon && is_station_level(summon.z) && (summon.area_flags & VALID_TERRITORY))
summon_spots += summon
sanity++
update_explanation_text()
diff --git a/code/modules/antagonists/cult/ritual.dm b/code/modules/antagonists/cult/ritual.dm
index 1aef9654e3..98889169c6 100644
--- a/code/modules/antagonists/cult/ritual.dm
+++ b/code/modules/antagonists/cult/ritual.dm
@@ -148,7 +148,7 @@ This file contains the cult dagger and rune list code
to_chat(user, "There is already a rune here.")
return FALSE
var/area/A = get_area(T)
- if((!is_station_level(T.z) && !is_mining_level(T.z)) || !(A?.area_flags & VALID_TERRITORY))
+ if((!is_station_level(T.z) && !is_mining_level(T.z)) || !(A?.area_flags & CULT_PERMITTED))
to_chat(user, "The veil is not weak enough here.")
return FALSE
return TRUE
diff --git a/code/modules/antagonists/eldritch_cult/eldritch_book.dm b/code/modules/antagonists/eldritch_cult/eldritch_book.dm
index 265f4db095..808932443f 100644
--- a/code/modules/antagonists/eldritch_cult/eldritch_book.dm
+++ b/code/modules/antagonists/eldritch_cult/eldritch_book.dm
@@ -89,6 +89,7 @@
var/list/lore = list()
data["charges"] = charge
+ data["total_sacs"] = cultie.total_sacrifices
for(var/X in to_know)
lore = list()
@@ -96,7 +97,11 @@
lore["type"] = EK.type
lore["name"] = EK.name
lore["cost"] = EK.cost
- lore["disabled"] = EK.cost <= charge ? FALSE : TRUE
+ lore["sacs"] = EK.sacs_needed
+ if(EK.cost <= charge && cultie.total_sacrifices >= EK.sacs_needed)
+ lore["disabled"] = FALSE
+ else
+ lore["disabled"] = TRUE
lore["path"] = EK.route
lore["state"] = "Research"
lore["flavour"] = EK.gain_text
@@ -108,6 +113,7 @@
var/datum/eldritch_knowledge/EK = known[X]
lore["name"] = EK.name
lore["cost"] = EK.cost
+ lore["sacs"] = EK.sacs_needed
lore["disabled"] = TRUE
lore["path"] = EK.route
lore["state"] = "Researched"
diff --git a/code/modules/antagonists/eldritch_cult/eldritch_effects.dm b/code/modules/antagonists/eldritch_cult/eldritch_effects.dm
index a390c04a1c..3d6059dfe3 100644
--- a/code/modules/antagonists/eldritch_cult/eldritch_effects.dm
+++ b/code/modules/antagonists/eldritch_cult/eldritch_effects.dm
@@ -165,6 +165,25 @@
new /obj/effect/reality_smash(chosen_location)
ReworkNetwork()
+/**
+*CIT CHANGE
+*
+*Creates a singular reality smash
+*Credit to slimelust
+*/
+
+/datum/reality_smash_tracker/proc/RandomSpawnSmash(var/deferred = FALSE)
+ var/turf/chosen_location = get_safe_random_station_turf()
+ //we also dont want them close to each other, at least 1 tile of separation
+ 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)
+ var/tries = 10
+ while((what_if_i_have_one || what_if_i_had_one_but_got_used) && tries-- > 0)
+ chosen_location = get_safe_random_station_turf()
+ new /obj/effect/reality_smash(chosen_location)
+ if(!deferred)
+ ReworkNetwork()
+
/**
* Adds a mind to the list of people that can see the reality smashes
*
@@ -200,15 +219,23 @@
/obj/effect/broken_illusion/Initialize()
. = ..()
addtimer(CALLBACK(src,.proc/show_presence),15 SECONDS)
+ addtimer(CALLBACK(src,.proc/remove_presence),195 SECONDS)
var/image/I = image('icons/effects/eldritch.dmi',src,null,OBJ_LAYER)
I.override = TRUE
add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/silicons, "pierced_reality", I)
+/obj/effect/broken_illusion/Destroy()
+ GLOB.reality_smash_track.RandomSpawnSmash()
+ return ..()
+
///Makes this obj appear out of nothing
/obj/effect/broken_illusion/proc/show_presence()
animate(src,alpha = 255,time = 15 SECONDS)
+/obj/effect/broken_illusion/proc/remove_presence()
+ qdel(src)
+
/obj/effect/broken_illusion/attack_hand(mob/living/user, list/modifiers)
if(!ishuman(user))
return ..()
diff --git a/code/modules/antagonists/eldritch_cult/eldritch_items.dm b/code/modules/antagonists/eldritch_cult/eldritch_items.dm
index 86ef2afacb..87a4ddf7eb 100644
--- a/code/modules/antagonists/eldritch_cult/eldritch_items.dm
+++ b/code/modules/antagonists/eldritch_cult/eldritch_items.dm
@@ -44,46 +44,6 @@
if(target.stat == DEAD)
to_chat(user,"[target.real_name] is dead. Bring them onto a transmutation rune!")
-/datum/action/innate/heretic_shatter
- name = "Shattering Offer"
- desc = "After a brief delay, you will be granted salvation from a dire situation at the cost of your blade. (Teleports you to a random safe turf on your current z level after a windup, but destroys your blade.)"
- background_icon_state = "bg_ecult"
- button_icon_state = "shatter"
- icon_icon = 'icons/mob/actions/actions_ecult.dmi'
- check_flags = MOBILITY_HOLD|MOBILITY_MOVE|MOBILITY_USE
- var/mob/living/carbon/human/holder
- var/obj/item/melee/sickly_blade/sword
-
-/datum/action/innate/heretic_shatter/Grant(mob/user, obj/object)
- sword = object
- holder = user
- //i know what im doing
- return ..()
-
-/datum/action/innate/heretic_shatter/IsAvailable()
- if(IS_HERETIC(holder) || IS_HERETIC_MONSTER(holder))
- return ..()
- else
- return FALSE
-
-/datum/action/innate/heretic_shatter/Activate()
- if(do_after(holder,10, target = holder))
- if(!sword || QDELETED(sword))
- return
- if(!IsAvailable()) //Never trust the user.
- return
- var/swordz = (get_turf(sword))?.z //SHOULD usually have a turf but if it doesn't better be prepared.
- if(!swordz)
- to_chat(holder, "[sword] flickers but remains in place, as do you...")
- return
- var/turf/safe_turf = find_safe_turf(zlevels = swordz, extended_safety_checks = TRUE)
- if(!safe_turf)
- to_chat(holder, "[sword] flickers but remains in place, as do you...")
- return
- do_teleport(holder,safe_turf,forceMove = TRUE,channel=TELEPORT_CHANNEL_MAGIC)
- to_chat(holder,"You feel a gust of energy flow through your body... the Rusted Hills heard your call...")
- qdel(sword)
-
/obj/item/melee/sickly_blade
name = "sickly blade"
desc = "A sickly green crescent blade, decorated with an ornamental eye. You feel like you're being watched..."
@@ -101,11 +61,6 @@
throwforce = 10
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "tore", "lacerated", "ripped", "diced", "rended")
- var/datum/action/innate/heretic_shatter/linked_action
-
-/obj/item/melee/sickly_blade/Initialize()
- . = ..()
- linked_action = new(src)
/obj/item/melee/sickly_blade/attack(mob/living/target, mob/living/user)
if(!(IS_HERETIC(user) || IS_HERETIC_MONSTER(user)))
@@ -120,13 +75,17 @@
return
return ..()
-/obj/item/melee/sickly_blade/pickup(mob/user)
- . = ..()
- linked_action.Grant(user, src)
-
-/obj/item/melee/sickly_blade/dropped(mob/user, silent)
- . = ..()
- linked_action.Remove(user, src)
+/obj/item/melee/sickly_blade/attack_self(mob/user)
+ var/turf/safe_turf = find_safe_turf(zlevels = z, extended_safety_checks = TRUE)
+ if(IS_HERETIC(user) || IS_HERETIC_MONSTER(user))
+ if(do_teleport(user, safe_turf, forceMove = TRUE, channel = TELEPORT_CHANNEL_MAGIC))
+ to_chat(user,"As you shatter [src], you feel a gust of energy flow through your body. The Rusted Hills heard your call...")
+ else
+ to_chat(user,"You shatter [src], but your plea goes unanswered.")
+ else
+ to_chat(user,"You shatter [src].")
+ playsound(src, "shatter", 70, TRUE) //copied from the code for smashing a glass sheet onto the ground to turn it into a shard
+ qdel(src)
/obj/item/melee/sickly_blade/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
. = ..()
@@ -141,6 +100,11 @@
else
eldritch_knowledge_datum.on_ranged_attack_eldritch_blade(target,user,click_parameters)
+/obj/item/melee/sickly_blade/examine(mob/user)
+ . = ..()
+ if(IS_HERETIC(user) || IS_HERETIC_MONSTER(user))
+ . += "A heretic (or a servant of one) can shatter this blade to teleport to a random, mostly safe location by activating it in-hand."
+
/obj/item/melee/sickly_blade/rust
name = "rusted blade"
desc = "This crescent blade is decrepit, wasting to rust. Yet still it bites, ripping flesh and bone with jagged, rotten teeth."
@@ -243,6 +207,7 @@
// slightly worse than normal cult robes
armor = list("melee" = 30, "bullet" = 30, "laser" = 30,"energy" = 30, "bomb" = 15, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
pocket_storage_component_path = /datum/component/storage/concrete/pockets/void_cloak
+ mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
/obj/item/clothing/suit/hooded/cultrobes/void/ToggleHood()
if(!iscarbon(loc))
diff --git a/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm b/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm
index d2132be4bc..33a17c3278 100644
--- a/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm
+++ b/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm
@@ -15,6 +15,8 @@
var/gain_text = ""
///Cost of knowledge in souls
var/cost = 0
+ ///Required sacrifices to unlock
+ var/sacs_needed = 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.
@@ -230,7 +232,6 @@
atoms -= H
H.gib()
-
///////////////
///Base lore///
///////////////
diff --git a/code/modules/antagonists/eldritch_cult/eldritch_magic.dm b/code/modules/antagonists/eldritch_cult/eldritch_magic.dm
index 4aeb2e1b73..4d6576ee92 100644
--- a/code/modules/antagonists/eldritch_cult/eldritch_magic.dm
+++ b/code/modules/antagonists/eldritch_cult/eldritch_magic.dm
@@ -50,7 +50,7 @@
/obj/item/melee/touch_attack/mansus_fist/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
- if(!proximity_flag | target == user)
+ if(!proximity_flag || (target == user))
return
playsound(user, 'sound/items/welder.ogg', 75, TRUE)
if(ishuman(target))
diff --git a/code/modules/antagonists/eldritch_cult/knowledge/ash_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/ash_lore.dm
index 0256382723..e453f5456d 100644
--- a/code/modules/antagonists/eldritch_cult/knowledge/ash_lore.dm
+++ b/code/modules/antagonists/eldritch_cult/knowledge/ash_lore.dm
@@ -109,10 +109,15 @@
gain_text = "When the Glory of the Lantern scorches and sears their skin, nothing will protect them from the ashes."
desc = "Fire off five streams of fire from your hand, each setting ablaze targets hit and scorching them upon contact."
cost = 2
+ sacs_needed = 3
spell_to_add = /obj/effect/proc_holder/spell/pointed/nightwatchers_rite
next_knowledge = list(/datum/eldritch_knowledge/final/ash_final)
route = PATH_ASH
+/datum/eldritch_knowledge/spell/nightwatchers_rite/on_gain(mob/user)
+ . = ..()
+ priority_announce("Large heat signatures discovered! A swelling fiery horror is coming..", sound = 'sound/misc/notice1.ogg')
+
/datum/eldritch_knowledge/ash_blade_upgrade
name = "Fiery Blade"
gain_text = "Blade in hand, he swung and swung as the ash fell from the skies. His city, his people... all burnt to cinders, and yet life still remained in his charred body."
@@ -181,6 +186,7 @@
desc = "Bring 3 corpses onto a transmutation rune, you will become immune to fire, the vacuum of space, cold and other enviromental hazards and become overall sturdier to all other damages. You will gain a spell that passively creates ring of fire around you as well ,as you will gain a powerful ability that lets you create a wave of flames all around you."
required_atoms = list(/mob/living/carbon/human)
cost = 5
+ sacs_needed = 8
route = PATH_ASH
var/list/trait_list = list(TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE)
diff --git a/code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm
index 9e71f34735..023be4b3e7 100644
--- a/code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm
+++ b/code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm
@@ -170,7 +170,7 @@
gain_text = "The Uncanny Man, who walks alone in the valley between the worlds... I was able to summon his aid."
desc = "You can now summon a Raw Prophet by transmutating a pair of eyes, a left arm and a pool of blood. Raw prophets have increased seeing range, as well as X-Ray vision, but they are very 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)
+ required_atoms = list(/obj/item/organ/eyes,/obj/item/bodypart/l_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/rune_carver,/datum/eldritch_knowledge/curse/paralysis)
route = PATH_FLESH
@@ -217,6 +217,7 @@
desc = "Bring 3 bodies onto a transmutation rune to shed your human form and ascend to untold power."
required_atoms = list(/mob/living/carbon/human)
cost = 5
+ sacs_needed = 8
route = PATH_FLESH
/datum/eldritch_knowledge/final/flesh_final/on_finished_recipe(mob/living/user, list/atoms, loc)
@@ -257,6 +258,11 @@
gain_text = "The ignorant mind that inhabits their feeble bodies will crumble when they acknowledge - willingly or not, the truth."
desc = "By forcing the knowledge of the Mansus upon my foes, I can show them things that would drive any normal man insane."
cost = 2
+ sacs_needed = 3
spell_to_add = /obj/effect/proc_holder/spell/targeted/touch/mad_touch
next_knowledge = list(/datum/eldritch_knowledge/final/flesh_final)
route = PATH_FLESH
+
+/datum/eldritch_knowledge/spell/touch_of_madness/on_gain(mob/user)
+ . = ..()
+ priority_announce("The stench of rotting flesh fills the air... An approaching abomination has been detected!", sound = 'sound/misc/notice1.ogg')
diff --git a/code/modules/antagonists/eldritch_cult/knowledge/rust_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/rust_lore.dm
index 8184beb3aa..509c35261e 100644
--- a/code/modules/antagonists/eldritch_cult/knowledge/rust_lore.dm
+++ b/code/modules/antagonists/eldritch_cult/knowledge/rust_lore.dm
@@ -24,7 +24,7 @@
var/check = FALSE
if(ismob(target))
var/mob/living/mobster = target
- if(!mobster.mob_biotypes & MOB_ROBOTIC)
+ if(!(mobster.mob_biotypes & MOB_ROBOTIC))
return FALSE
else
check = TRUE
@@ -159,15 +159,21 @@
desc = "Applying your knowledge of rust to the human body, a knowledge that could decay your foes from the inside out, resulting in organ failure, vomiting, or eventual death through the peeling of rotting flesh."
gain_text = "Rust, decay, it's all the same. All that remains is application."
cost = 2
+ sacs_needed = 3
spell_to_add = /obj/effect/proc_holder/spell/targeted/touch/grasp_of_decay
next_knowledge = list(/datum/eldritch_knowledge/final/rust_final)
route = PATH_RUST
+/datum/eldritch_knowledge/spell/grasp_of_decay/on_gain(mob/user)
+ . = ..()
+ priority_announce("A foul wind is blowing... The floor creaks with rust as something sinister approaches!", sound = 'sound/misc/notice1.ogg')
+
/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 the Rustbringer has come! Rusted Hills, CALL MY NAME!"
cost = 5
+ sacs_needed = 8
required_atoms = list(/mob/living/carbon/human)
route = PATH_RUST
diff --git a/code/modules/antagonists/eldritch_cult/knowledge/void_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/void_lore.dm
index 6046bfbdf5..97b5af0f4d 100644
--- a/code/modules/antagonists/eldritch_cult/knowledge/void_lore.dm
+++ b/code/modules/antagonists/eldritch_cult/knowledge/void_lore.dm
@@ -160,15 +160,21 @@
gain_text = "This world will be my stage, and nothing will be out of my reach."
desc = "Gain the ability to mark a 7x7 area as your domain after a short delay. Creatures in your domain are slowed and branded with a void mark, allowing you to quickly teleport to them and slash them, further inhibiting their ability to move."
cost = 2
+ sacs_needed = 3
spell_to_add = /obj/effect/proc_holder/spell/aoe_turf/domain_expansion
next_knowledge = list(/datum/eldritch_knowledge/final/void_final)
route = PATH_VOID
+/datum/eldritch_knowledge/spell/domain_expansion/on_gain(mob/user)
+ . = ..()
+ priority_announce("Echos of the lost in space are heard... An ominous presence is being detected! ", sound = 'sound/misc/notice1.ogg')
+
/datum/eldritch_knowledge/final/void_final
name = "Waltz at the End of Time"
desc = "Bring 3 corpses onto the transmutation rune. After you finish the ritual you will automatically silence people around you and will summon a snow storm around you."
gain_text = "The world falls into darkness. I stand in an empty plane, small flakes of ice fall from the sky. The Aristocrat stands before me, he motions to me. We will play a waltz to the whispers of dying reality, as the world is destroyed before our eyes."
cost = 5
+ sacs_needed = 8
required_atoms = list(/mob/living/carbon/human)
route = PATH_VOID
///soundloop for the void theme
diff --git a/code/modules/antagonists/revenant/revenant.dm b/code/modules/antagonists/revenant/revenant.dm
index 31989fe241..537c714966 100644
--- a/code/modules/antagonists/revenant/revenant.dm
+++ b/code/modules/antagonists/revenant/revenant.dm
@@ -492,7 +492,7 @@
var/targetAmount = 100
/datum/objective/revenant/New()
- targetAmount = rand(350,600)
+ targetAmount = rand(150,300)
explanation_text = "Absorb [targetAmount] points of essence from humans."
..()
diff --git a/code/modules/antagonists/slaughter/slaughter.dm b/code/modules/antagonists/slaughter/slaughter.dm
index a26d081f08..f616f2c848 100644
--- a/code/modules/antagonists/slaughter/slaughter.dm
+++ b/code/modules/antagonists/slaughter/slaughter.dm
@@ -84,6 +84,9 @@
if(slam_cooldown + slam_cooldown_time > world.time)
to_chat(src, "Your slam ability is still on cooldown!")
return
+ if(!isopenturf(loc))
+ to_chat(src, "You need to be on open flooring to do that!")
+ return
face_atom(A)
var/mob/living/victim = A
diff --git a/code/modules/antagonists/wizard/equipment/soulstone.dm b/code/modules/antagonists/wizard/equipment/soulstone.dm
index 8303de60cc..c328fa232d 100644
--- a/code/modules/antagonists/wizard/equipment/soulstone.dm
+++ b/code/modules/antagonists/wizard/equipment/soulstone.dm
@@ -145,7 +145,7 @@
if("VICTIM")
var/mob/living/carbon/human/T = target
var/datum/antagonist/cult/C = user.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
- if(C?.cult_team.is_sacrifice_target(T.mind))
+ if(C && C.cult_team.is_sacrifice_target(T.mind))
if(iscultist(user))
to_chat(user, "\"This soul is mine. SACRIFICE THEM!\"")
else
diff --git a/code/modules/antagonists/wizard/equipment/spellbook.dm b/code/modules/antagonists/wizard/equipment/spellbook.dm
index 9b2def48d7..21de660edb 100644
--- a/code/modules/antagonists/wizard/equipment/spellbook.dm
+++ b/code/modules/antagonists/wizard/equipment/spellbook.dm
@@ -252,6 +252,10 @@
name = "Barnyard Curse"
spell_type = /obj/effect/proc_holder/spell/pointed/barnyardcurse
+/datum/spellbook_entry/cluwne
+ name = "Cluwne Curse"
+ spell_type = /obj/effect/proc_holder/spell/targeted/cluwnecurse
+
/datum/spellbook_entry/charge
name = "Charge"
spell_type = /obj/effect/proc_holder/spell/targeted/charge
diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm
index a558abbfe8..a337439931 100644
--- a/code/modules/clothing/gloves/miscellaneous.dm
+++ b/code/modules/clothing/gloves/miscellaneous.dm
@@ -37,14 +37,19 @@
/obj/item/clothing/gloves/fingerless/pugilist/equipped(mob/user, slot)
. = ..()
if(slot == SLOT_GLOVES)
- use_buffs(user, TRUE)
wornonce = TRUE
+ if((HAS_TRAIT(user, TRAIT_NOPUGILIST)))
+ to_chat(user, "What purpose is there to don the weapons of pugilism if you're already well-practiced in martial arts? Mixing arts is blasphemous!")
+ return
+ use_buffs(user, TRUE)
/obj/item/clothing/gloves/fingerless/pugilist/dropped(mob/user)
. = ..()
if(wornonce)
- use_buffs(user, FALSE)
wornonce = FALSE
+ if((HAS_TRAIT(user, TRAIT_NOPUGILIST)))
+ return
+ use_buffs(user, FALSE)
/obj/item/clothing/gloves/fingerless/pugilist/proc/use_buffs(mob/user, buff)
if(buff) // tarukaja
@@ -67,6 +72,7 @@
H.dna.species.punchdamagehigh -= enhancement
H.dna.species.punchdamagelow -= enhancement
H.dna.species.punchwoundbonus -= wound_enhancement
+ H.dna?.species?.attack_sound_override = null
if(!silent)
to_chat(user, "With [src] off of your arms, you feel less ready to punch things.")
@@ -223,6 +229,50 @@
parry_cooldown = 0
parry_failed_clickcd_duration = 0
+/obj/item/clothing/gloves/fingerless/pugilist/mauler
+ name = "mauler gauntlets"
+ desc = "Plastitanium gauntlets coated in a thick nano-weave carbon material and implanted with nanite injectors that boost the wielder's strength six-fold."
+ icon_state = "mauler_gauntlets"
+ item_state = "mauler_gauntlets"
+ transfer_prints = FALSE
+ body_parts_covered = ARMS|HANDS
+ cold_protection = ARMS|HANDS
+ min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT
+ max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
+ armor = list("melee" = 30, "bullet" = 30, "laser" = 10, "energy" = 10, "bomb" = 55, "bio" = 15, "rad" = 15, "fire" = 80, "acid" = 50)
+ siemens_coefficient = 0
+ permeability_coefficient = 0.05
+ strip_delay = 80
+ enhancement = 12 // same as the changeling gauntlets but without changeling utility
+ wound_enhancement = 12
+ silent = TRUE
+ inherited_trait = TRAIT_CHUNKYFINGERS // your fingers are fat because the gloves are
+ secondary_trait = TRAIT_MAULER // commit table slam
+
+/obj/item/clothing/gloves/fingerless/pugilist/mauler/equipped(mob/user, slot)
+ . = ..()
+ if(slot == SLOT_GLOVES)
+ wornonce = TRUE
+ if((HAS_TRAIT(user, TRAIT_NOPUGILIST)))
+ return
+ use_mauls(user, TRUE)
+
+/obj/item/clothing/gloves/fingerless/pugilist/mauler/dropped(mob/user)
+ . = ..()
+ if(wornonce)
+ wornonce = FALSE
+ if((HAS_TRAIT(user, TRAIT_NOPUGILIST)))
+ return
+ use_mauls(user, FALSE)
+
+/obj/item/clothing/gloves/fingerless/pugilist/mauler/proc/use_mauls(mob/user, maul)
+ if(maul)
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ H.dna?.species?.attack_sound_override = 'sound/weapons/mauler_punch.ogg'
+ if(silent)
+ to_chat(H, "You feel prickles around your wrists as [src] cling to them - strength courses through your veins!")
+
/obj/item/clothing/gloves/botanic_leather
name = "botanist's leather gloves"
desc = "These leather gloves protect against thorns, barbs, prickles, spikes and other harmful objects of floral origin. They're also quite warm."
@@ -253,7 +303,6 @@
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 50)
strip_mod = 1.5
-
/obj/item/clothing/gloves/bracer
name = "bone bracers"
desc = "For when you're expecting to get slapped on the wrist. Offers modest protection to your arms."
diff --git a/code/modules/clothing/masks/cluwne.dm b/code/modules/clothing/masks/cluwne.dm
new file mode 100644
index 0000000000..a1177e2b47
--- /dev/null
+++ b/code/modules/clothing/masks/cluwne.dm
@@ -0,0 +1,106 @@
+/obj/item/clothing/mask/gas/cluwne
+ name = "clown wig and mask"
+ desc = "A true prankster's facial attire. A clown is incomplete without his wig and mask."
+ flags_cover = MASKCOVERSEYES
+ icon_state = "cluwne"
+ item_state = "cluwne"
+ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
+ clothing_flags = ALLOWINTERNALS
+ item_flags = ABSTRACT | DROPDEL
+ flags_inv = HIDEEARS|HIDEEYES
+ var/voicechange = TRUE
+ var/last_sound = 0
+ var/delay = 15
+
+/obj/item/clothing/mask/gas/cluwne/Initialize()
+ .=..()
+ ADD_TRAIT(src, TRAIT_NODROP, CLOTHING_TRAIT)
+ ADD_TRAIT(src, CURSED_ITEM_TRAIT, CLOTHING_TRAIT)
+
+/obj/item/clothing/mask/gas/cluwne/proc/play_laugh1()
+ if(world.time - delay > last_sound)
+ playsound (src, 'sound/voice/cluwnelaugh1.ogg', 30, 1)
+ last_sound = world.time
+
+/obj/item/clothing/mask/gas/cluwne/proc/play_laugh2()
+ if(world.time - delay > last_sound)
+ playsound (src, 'sound/voice/cluwnelaugh2.ogg', 30, 1)
+ last_sound = world.time
+
+/obj/item/clothing/mask/gas/cluwne/proc/play_laugh3()
+ if(world.time - delay > last_sound)
+ playsound (src, 'sound/voice/cluwnelaugh3.ogg', 30, 1)
+ last_sound = world.time
+
+/obj/item/clothing/mask/gas/cluwne/equipped(mob/user, slot) //when you put it on
+ var/mob/living/carbon/C = user
+ if((C.wear_mask == src) && (voicechange))
+ play_laugh1()
+ return ..()
+
+/obj/item/clothing/mask/gas/cluwne/handle_speech(datum/source, list/speech_args)
+ if(voicechange)
+ if(prob(5)) //the brain isn't fully gone yet...
+ speech_args[SPEECH_MESSAGE] = pick("HELP ME!!","PLEASE KILL ME!!","I WANT TO DIE!!", "END MY SUFFERING", "I CANT TAKE THIS ANYMORE!!" ,"SOMEBODY STOP ME!!")
+ play_laugh2()
+ if(prob(3))
+ speech_args[SPEECH_MESSAGE] = pick("HOOOOINKKKKKKK!!", "HOINK HOINK HOINK HOINK!!","HOINK HOINK!!","HOOOOOOIIINKKKK!!") //but most of the time they cant speak,
+ play_laugh3()
+ else
+ speech_args[SPEECH_MESSAGE] = pick("HEEEENKKKKKK!!", "HONK HONK HONK HONK!!","HONK HONK!!","HOOOOOONKKKK!!") //More sounds,
+ play_laugh1()
+ return SPEECH_MESSAGE
+
+/obj/item/clothing/mask/gas/cluwne/equipped(mob/user, slot)
+ . = ..()
+ if(!ishuman(user))
+ return
+ if(slot == SLOT_WEAR_MASK)
+ var/mob/living/carbon/human/H = user
+ H.dna.add_mutation(CLUWNEMUT)
+ return
+
+/obj/item/clothing/mask/gas/cluwne/happy_cluwne
+ name = "Happy Cluwne Mask"
+ desc = "The mask of a poor cluwne that has been scrubbed of its curse by the Nanotrasen supernatural machinations division. Guaranteed to be %99 curse free and %99.9 not haunted. "
+ item_flags = ABSTRACT
+ var/can_cluwne = FALSE
+ var/is_cursed = FALSE //i don't care that this is *slightly* memory wasteful, it's just one more byte and it's not like some madman is going to spawn thousands of these
+ var/is_very_cursed = FALSE
+
+/obj/item/clothing/mask/gas/cluwne/happy_cluwne/Initialize()
+ .=..()
+ if(prob(1)) //this function pre-determines the logic of the cluwne mask. applying and reapplying the mask does not alter or change anything
+ is_cursed = TRUE
+ is_very_cursed = FALSE
+ else if(prob(0.1))
+ is_cursed = FALSE
+ is_very_cursed = TRUE
+
+/obj/item/clothing/mask/gas/cluwne/happy_cluwne/attack_self(mob/user)
+ voicechange = !voicechange
+ to_chat(user, "You turn the voice box [voicechange ? "on" : "off"]!")
+ if(voicechange)
+ play_laugh1()
+
+/obj/item/clothing/mask/gas/cluwne/happy_cluwne/equipped(mob/user, slot)
+ . = ..()
+ if(!ishuman(user))
+ return
+ var/mob/living/carbon/human/H = user
+ if(slot == SLOT_WEAR_MASK)
+ if(is_cursed && can_cluwne) //logic predetermined
+ log_admin("[key_name(H)] was made into a cluwne by [src]")
+ message_admins("[key_name(H)] got cluwned by [src]")
+ to_chat(H, "The masks straps suddenly tighten to your face and your thoughts are erased by a horrible green light!")
+ H.dropItemToGround(src)
+ H.cluwneify()
+ qdel(src)
+ else if(is_very_cursed && can_cluwne)
+ var/turf/T = get_turf(src)
+ var/mob/living/simple_animal/hostile/floor_cluwne/S = new(T)
+ S.Acquire_Victim(user)
+ log_admin("[key_name(user)] summoned a floor cluwne using the [src]")
+ message_admins("[key_name(user)] summoned a floor cluwne using the [src]")
+ to_chat(H, "The mask suddenly slips off your face and... slides under the floor?")
+ to_chat(H, "...dneirf uoy ot gnoleb ton seod tahT")
diff --git a/code/modules/clothing/shoes/cluwne.dm b/code/modules/clothing/shoes/cluwne.dm
new file mode 100644
index 0000000000..fbe1ba624b
--- /dev/null
+++ b/code/modules/clothing/shoes/cluwne.dm
@@ -0,0 +1,29 @@
+/obj/item/clothing/shoes/clown_shoes/cluwne
+ desc = "The prankster's standard-issue clowning shoes. Damn, they're huge!"
+ name = "clown shoes"
+ icon_state = "cluwne"
+ item_state = "cluwne"
+ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
+ item_flags = DROPDEL
+ var/footstep = 1
+
+/obj/item/clothing/shoes/clown_shoes/cluwne/Initialize()
+ .=..()
+ ADD_TRAIT(src, TRAIT_NODROP, CLOTHING_TRAIT)
+ ADD_TRAIT(src, CURSED_ITEM_TRAIT, CLOTHING_TRAIT)
+
+/obj/item/clothing/shoes/clown_shoes/cluwne/step_action()
+ if(footstep > 1)
+ playsound(src, "clownstep", 50, 1)
+ footstep = 0
+ else
+ footstep++
+
+/obj/item/clothing/shoes/clown_shoes/cluwne/equipped(mob/user, slot)
+ . = ..()
+ if(!ishuman(user))
+ return
+ if(slot == SLOT_SHOES)
+ var/mob/living/carbon/human/H = user
+ H.dna.add_mutation(CLUWNEMUT)
+ return
diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm
index cc14424980..6858de59df 100644
--- a/code/modules/clothing/shoes/miscellaneous.dm
+++ b/code/modules/clothing/shoes/miscellaneous.dm
@@ -535,3 +535,9 @@
to_chat(user, "You insert [I] into [src].")
B.use(10)
icon_state = initial(icon_state)
+
+/obj/item/clothing/shoes/swagshoes
+ name = "swag shoes"
+ desc = "They got me for my foams!"
+ icon_state = "SwagShoes"
+ item_state = "SwagShoes"
diff --git a/code/modules/clothing/under/cluwne.dm b/code/modules/clothing/under/cluwne.dm
new file mode 100644
index 0000000000..5a908c5663
--- /dev/null
+++ b/code/modules/clothing/under/cluwne.dm
@@ -0,0 +1,22 @@
+/obj/item/clothing/under/cluwne
+ name = "clown suit"
+ desc = "'HONK!'"
+ icon_state = "greenclown"
+ item_state = "greenclown"
+ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
+ item_flags = DROPDEL
+ can_adjust = 0
+ mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
+
+/obj/item/clothing/under/cluwne/Initialize()
+ .=..()
+ ADD_TRAIT(src, TRAIT_NODROP, CLOTHING_TRAIT)
+ ADD_TRAIT(src, CURSED_ITEM_TRAIT, CLOTHING_TRAIT)
+
+/obj/item/clothing/under/cluwne/equipped(mob/living/carbon/user, slot)
+ if(!ishuman(user))
+ return
+ if(slot == SLOT_W_UNIFORM)
+ var/mob/living/carbon/human/H = user
+ H.dna.add_mutation(CLUWNEMUT)
+ return ..()
diff --git a/code/modules/clothing/under/costume.dm b/code/modules/clothing/under/costume.dm
index f8292738ee..60d82292ef 100644
--- a/code/modules/clothing/under/costume.dm
+++ b/code/modules/clothing/under/costume.dm
@@ -355,3 +355,10 @@
name = "Sakura Kimono'"
icon_state = "sakura_kimono"
item_state = "sakura_kimono"
+
+/obj/item/clothing/under/costume/swagoutfit
+ name = "Swag outfit"
+ desc = "Why don't you go secure some bitches?"
+ icon_state = "SwagOutfit"
+ item_state = "SwagOutfit"
+ can_adjust = FALSE
diff --git a/code/modules/clothing/under/trek.dm b/code/modules/clothing/under/trek.dm
index 8b6b8055bd..89e42d2566 100644
--- a/code/modules/clothing/under/trek.dm
+++ b/code/modules/clothing/under/trek.dm
@@ -102,9 +102,14 @@
desc = "An uniform worn by command officers since 2420s."
icon_state = "orv_com"
-/obj/item/clothing/under/trek/engsec/orv
+/obj/item/clothing/under/trek/eng/orv
desc = "An uniform worn by operations officers since 2420s."
- icon_state = "orv_ops"
+ icon_state = "orv_eng"
+
+/obj/item/clothing/under/trek/sec/orv
+ desc = "An uniform worn by security officers since 2420s."
+ armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 30, "acid" = 30, "wound" = 10)
+ icon_state = "orv_sec"
/obj/item/clothing/under/trek/medsci/orv
desc = "An uniform worn by medsci officers since 2420s."
@@ -114,13 +119,20 @@
//honestly no idea why i added specified comm. uniforms but w/e
/obj/item/clothing/under/trek/command/orv/captain
name = "captain uniform"
- desc = "An uniform worn by captains since 2550s."
+ desc = "An uniform worn by captains and commanders since 2550s."
icon_state = "orv_com_capt"
-/obj/item/clothing/under/trek/command/orv/engsec
- name = "operations command uniform"
- desc = "An uniform worn by operations command officers since 2550s."
- icon_state = "orv_com_ops"
+/obj/item/clothing/under/trek/command/orv/eng
+ name = "engineering command uniform"
+ desc = "An uniform worn by Chief Engineers since 2550s."
+ icon_state = "orv_com_eng"
+
+/obj/item/clothing/under/trek/command/orv/sec
+ name = "security command uniform"
+ armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50, "wound" = 10)
+ desc = "An uniform worn by Heads of Security since 2550s."
+ icon_state = "orv_com_sec"
+
/obj/item/clothing/under/trek/command/orv/medsci
name = "medsci command uniform"
@@ -131,13 +143,11 @@
name = "adjutant uniform"
desc = "An uniform worn by adjutants (assistants) since 2550s."
icon_state = "orv_ass"
- item_state = "gy_suit"
/obj/item/clothing/under/trek/orv/service
name = "service uniform"
desc = "An uniform worn by service officers since 2550s."
icon_state = "orv_srv"
- item_state = "g_suit"
//The Motion Picture
/obj/item/clothing/under/trek/fedutil
diff --git a/code/modules/events/brand_intelligence.dm b/code/modules/events/brand_intelligence.dm
index 7d4ea66d30..b9480a646c 100644
--- a/code/modules/events/brand_intelligence.dm
+++ b/code/modules/events/brand_intelligence.dm
@@ -61,7 +61,7 @@
originMachine.visible_message("[originMachine] beeps and seems lifeless.")
kill()
return
- vendingMachines = listclearnulls(vendingMachines)
+ listclearnulls(vendingMachines)
if(!vendingMachines.len) //if every machine is infected
for(var/obj/machinery/vending/upriser in infectedMachines)
if(prob(70) && !QDELETED(upriser))
diff --git a/code/modules/events/cat_surgeon.dm b/code/modules/events/cat_surgeon.dm
new file mode 100644
index 0000000000..d968e5e1f8
--- /dev/null
+++ b/code/modules/events/cat_surgeon.dm
@@ -0,0 +1,22 @@
+/datum/round_event_control/cat_surgeon
+ name = "Cat Surgeon"
+ typepath = /datum/round_event/cat_surgeon
+ max_occurrences = 1
+ weight = 10
+
+
+/datum/round_event/cat_surgeon/start()
+ var/list/spawn_locs = list()
+ for(var/X in GLOB.xeno_spawn)
+ spawn_locs += X
+
+ if(!spawn_locs.len)
+ message_admins("No valid spawn locations found, aborting...")
+ return MAP_ERROR
+
+ var/turf/T = get_turf(pick(spawn_locs))
+ var/mob/living/simple_animal/hostile/cat_butcherer/S = new(T)
+ playsound(S, 'sound/misc/catscream.ogg', 50, 1, -1)
+ message_admins("A cat surgeon has been spawned at [COORD(T)][ADMIN_JMP(T)]")
+ log_game("A cat surgeon has been spawned at [COORD(T)]")
+ return SUCCESSFUL_SPAWN
diff --git a/code/modules/events/cat_wave.dm b/code/modules/events/cat_wave.dm
new file mode 100644
index 0000000000..155da8ca08
--- /dev/null
+++ b/code/modules/events/cat_wave.dm
@@ -0,0 +1,11 @@
+/datum/round_event_control/meteor_wave/cat
+ name = "Meteor Wave: CATastrophic"
+ typepath = /datum/round_event/meteor_wave/cat
+ weight = 10
+ max_occurrences = 1
+
+/datum/round_event/meteor_wave/cat
+ wave_name = "cat"
+
+/datum/round_event/meteor_wave/cat/announce(fake)
+ priority_announce("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert", "meteors")
diff --git a/code/modules/events/floorcluwne.dm b/code/modules/events/floorcluwne.dm
new file mode 100644
index 0000000000..3df636809a
--- /dev/null
+++ b/code/modules/events/floorcluwne.dm
@@ -0,0 +1,23 @@
+/datum/round_event_control/floor_cluwne
+ name = "Floor Cluwne"
+ typepath = /datum/round_event/floor_cluwne
+ max_occurrences = 1
+ min_players = 20
+ weight = 10
+
+
+/datum/round_event/floor_cluwne/start()
+ var/list/spawn_locs = list()
+ for(var/X in GLOB.xeno_spawn)
+ spawn_locs += X
+
+ if(!spawn_locs.len)
+ message_admins("No valid spawn locations found, aborting...")
+ return MAP_ERROR
+
+ var/turf/T = get_turf(pick(spawn_locs))
+ var/mob/living/simple_animal/hostile/floor_cluwne/S = new(T)
+ playsound(S, 'sound/misc/bikehorn_creepy.ogg', 50, 1, -1)
+ message_admins("A floor cluwne has been spawned at [COORD(T)][ADMIN_JMP(T)]")
+ log_game("A floor cluwne has been spawned at [COORD(T)]")
+ return SUCCESSFUL_SPAWN
diff --git a/code/modules/events/meteor_wave.dm b/code/modules/events/meteor_wave.dm
index e69af1df13..9aa9cac258 100644
--- a/code/modules/events/meteor_wave.dm
+++ b/code/modules/events/meteor_wave.dm
@@ -56,6 +56,8 @@
wave_type = GLOB.meteorsC
if("halloween")
wave_type = GLOB.meteorsSPOOKY
+ if("cat")
+ wave_type = GLOB.meteorsCat
else
WARNING("Wave name of [wave_name] not recognised.")
kill()
diff --git a/code/modules/food_and_drinks/food.dmi b/code/modules/food_and_drinks/food.dmi
new file mode 100644
index 0000000000..3f38a8068e
Binary files /dev/null and b/code/modules/food_and_drinks/food.dmi differ
diff --git a/code/modules/food_and_drinks/food/snacks_meat.dm b/code/modules/food_and_drinks/food/snacks_meat.dm
index 152740f932..402192e034 100644
--- a/code/modules/food_and_drinks/food/snacks_meat.dm
+++ b/code/modules/food_and_drinks/food/snacks_meat.dm
@@ -391,6 +391,15 @@
bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 1)
tastes = list("meat" = 3, "smokey sauce" = 1)
foodtype = MEAT
+
+/obj/item/reagent_containers/food/snacks/goliathcalamari
+ name = "goliath calamari"
+ desc = "ACKCHYUALLY, this isn't calamari, guys!"
+ icon_state = "goliathcalamari"
+ bonus_reagents = list(/datum/reagent/consumable/nutriment/vitamin = 3, /datum/reagent/consumable/capsaicin = 1)
+ list_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/consumable/nutriment/vitamin = 5, /datum/reagent/consumable/capsaicin = 2)
+ tastes = list("rock" = 1, "meat" = 1)
+ foodtype = MEAT
////////////// Cubes //////////
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_meat.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_meat.dm
index 2409032760..edd30ab1a9 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_meat.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_meat.dm
@@ -213,3 +213,12 @@
)
result = /obj/item/reagent_containers/food/snacks/salad/gumbo
subcategory = CAT_MEAT
+
+/datum/crafting_recipe/food/goliathcalamari
+ name = "Goliath Calamari"
+ reqs = list(
+ /obj/item/reagent_containers/food/snacks/meat/slab/goliath = 2,
+ /datum/reagent/consumable/cooking_oil = 10
+ )
+ result = /obj/item/reagent_containers/food/snacks/goliathcalamari
+ subcategory = CAT_MEAT
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 8fb735e10a..628a5e53ac 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/ears.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/ears.dm
@@ -101,6 +101,13 @@
matrixed_sections = MATRIX_RED
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
+/datum/sprite_accessory/ears/lablight
+ name = "Dog, Floppy (Light)"
+ icon_state = "lablight"
+ color_src = MATRIXED
+ matrixed_sections = MATRIX_RED
+ icon = 'modular_citadel/icons/mob/mam_ears.dmi'
+
/datum/sprite_accessory/ears/human/eevee
name = "Eevee"
icon_state = "eevee"
@@ -162,12 +169,19 @@
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
/datum/sprite_accessory/ears/human/rabbit
- name = "Rabbit"
+ name = "Rabbit (Lop-eared)"
icon_state = "rabbit"
color_src = MATRIXED
matrixed_sections = MATRIX_RED_GREEN
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
+/datum/sprite_accessory/ears/human/rabbitalt
+ name = "Rabbit (Straight-eared)"
+ icon_state = "rabbitalt"
+ color_src = MATRIXED
+ matrixed_sections = MATRIX_ALL
+ icon = 'modular_citadel/icons/mob/mam_ears.dmi'
+
/datum/sprite_accessory/ears/human/pede
name = "Scolipede"
icon_state = "pede"
@@ -296,7 +310,7 @@
/datum/sprite_accessory/ears/mam_ears/deer
name = "Deer"
icon_state = "deer"
- color_src = MUTCOLORS3
+ matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/ears/mam_ears/eevee
name = "Eevee"
@@ -344,10 +358,15 @@
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/ears/mam_ears/lab
- name = "Dog, Long"
+ name = "Dog, Floppy"
icon_state = "lab"
matrixed_sections = MATRIX_RED
+/datum/sprite_accessory/ears/mam_ears/lablight
+ name = "Dog, Floppy (Light)"
+ icon_state = "lablight"
+ matrixed_sections = MATRIX_RED
+
/datum/sprite_accessory/ears/mam_ears/murid
name = "Murid"
icon_state = "murid"
@@ -359,10 +378,15 @@
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/ears/mam_ears/rabbit
- name = "Rabbit"
+ name = "Rabbit (Lop-eared)"
icon_state = "rabbit"
matrixed_sections = MATRIX_RED_GREEN
+/datum/sprite_accessory/ears/mam_ears/rabbitalt
+ name = "Rabbit (Straight-eared)"
+ icon_state = "rabbitalt"
+ matrixed_sections = MATRIX_ALL
+
/datum/sprite_accessory/ears/mam_ears/pede
name = "Scolipede"
icon_state = "pede"
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm b/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm
index a4bd0afdcb..88dda923a0 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm
@@ -17,6 +17,10 @@
name = "Adhara"
icon_state = "hair_adhara"
+/datum/sprite_accessory/hair/africanpigtails
+ name = "African Pig Tails"
+ icon_state = "hair_africanpigtails"
+
/datum/sprite_accessory/hair/afro
name = "Afro"
icon_state = "hair_afro"
@@ -25,10 +29,26 @@
name = "Afro 2"
icon_state = "hair_afro2"
+/datum/sprite_accessory/hair/afro2alt
+ name = "Afro 2 (Alt)"
+ icon_state = "hair_afro2alt"
+
/datum/sprite_accessory/hair/afro_large
name = "Afro (Large)"
icon_state = "hair_bigafro"
+/datum/sprite_accessory/hair/afropuffdouble
+ name = "Afropuff (Double)"
+ icon_state = "hair_afropuffdouble"
+
+/datum/sprite_accessory/hair/afropuffleft
+ name = "Afropuff (Left)"
+ icon_state = "hair_afropuffleft"
+
+/datum/sprite_accessory/hair/afropuffright
+ name = "Afropuff (Right)"
+ icon_state = "hair_afropuffright"
+
/datum/sprite_accessory/hair/antenna
name = "Ahoge"
icon_state = "hair_antenna"
@@ -41,10 +61,18 @@
name = "Anita"
icon_state = "hair_anita"
+/datum/sprite_accessory/hair/astolfo
+ name = "Astolfo"
+ icon_state = "hair_astolfo"
+
/datum/sprite_accessory/hair/balding
name = "Balding Hair"
icon_state = "hair_e"
+/datum/sprite_accessory/hair/baum
+ name = "Baum"
+ icon_state = "hair_baum"
+
/datum/sprite_accessory/hair/bedhead
name = "Bedhead"
icon_state = "hair_bedhead"
@@ -85,6 +113,14 @@
name = "Belle"
icon_state = "hair_belle"
+/datum/sprite_accessory/hair/bluntbangs
+ name = "Bluntbangs"
+ icon_state = "hair_bluntbangs"
+
+/datum/sprite_accessory/hair/bluntbangsalt
+ name = "Bluntbangs (Alt)"
+ icon_state = "hair_bluntbangsalt"
+
/datum/sprite_accessory/hair/bob
name = "Bob Hair"
icon_state = "hair_bob"
@@ -109,6 +145,10 @@
name = "Bobcut (Alt)"
icon_state = "hair_bobcutalt"
+/datum/sprite_accessory/hair/bobcutalt2
+ name = "Bobcut (Alt) 2"
+ icon_state = "hair_bobcutalt2"
+
/datum/sprite_accessory/hair/boddicker
name = "Boddicker"
icon_state = "hair_boddicker"
@@ -205,6 +245,14 @@
name = "CIA"
icon_state = "hair_cia"
+/datum/sprite_accessory/hair/combedback
+ name = "Combed Back"
+ icon_state = "hair_combedback"
+
+/datum/sprite_accessory/hair/combedbob
+ name = "Combed Bob"
+ icon_state = "hair_combedbob"
+
/datum/sprite_accessory/hair/combover
name = "Combover"
icon_state = "hair_combover"
@@ -233,6 +281,14 @@
name = "Cornrow Tail"
icon_state = "hair_cornrowtail"
+/datum/sprite_accessory/hair/cotton
+ name = "Cotton"
+ icon_state = "hair_cotton"
+
+/datum/sprite_accessory/hair/cottonalt
+ name = "Cotton (Alt)"
+ icon_state = "hair_cottonalt"
+
/datum/sprite_accessory/hair/country
name = "Country"
icon_state = "hair_country"
@@ -261,6 +317,10 @@
name = "Devil Lock"
icon_state = "hair_devillock"
+/datum/sprite_accessory/hair/diagonalbangs
+ name = "Diagonal Bangs"
+ icon_state = "hair_diagonalbangs"
+
/datum/sprite_accessory/hair/dreadlocks
name = "Dreadlocks"
icon_state = "hair_dreads"
@@ -337,10 +397,22 @@
name = "Fluffy"
icon_state = "hair_fluffy"
+/datum/sprite_accessory/hair/fortuneteller
+ name = "Fortune Teller"
+ icon_state = "hair_fortuneteller"
+
/datum/sprite_accessory/hair/fringetail
name = "Fringe Tail"
icon_state = "hair_fringetail"
+/datum/sprite_accessory/hair/froofy
+ name = "Froofy"
+ icon_state = "hair_froofy"
+
+/datum/sprite_accessory/hair/geisha
+ name = "Geisha"
+ icon_state = "hair_geisha"
+
/datum/sprite_accessory/hair/gelled
name = "Gelled Back"
icon_state = "hair_gelled"
@@ -349,6 +421,26 @@
name = "Gentle"
icon_state = "hair_gentle"
+/datum/sprite_accessory/hair/glammetal
+ name = "Glam Metal"
+ icon_state = "hair_glammetal"
+
+/datum/sprite_accessory/hair/gloomy
+ name = "Gloomy"
+ icon_state = "hair_gloomy"
+
+/datum/sprite_accessory/hair/gloomylong
+ name = "Gloomy (Long)"
+ icon_state = "hair_gloomylong"
+
+/datum/sprite_accessory/hair/hajime
+ name = "Hajime"
+ icon_state = "hair_hajime"
+
+/datum/sprite_accessory/hair/hajimealt
+ name = "Hajime (Alt)"
+ icon_state = "hair_hajimealt"
+
/datum/sprite_accessory/hair/halfbang
name = "Half-banged Hair"
icon_state = "hair_halfbang"
@@ -365,6 +457,10 @@
name = "Half-shaved Hair"
icon_state = "hair_halfshaved"
+/datum/sprite_accessory/hair/harold
+ name = "Harold"
+ icon_state = "hair_harold"
+
/datum/sprite_accessory/hair/hedgehog
name = "Hedgehog Hair"
icon_state = "hair_hedgehog"
@@ -393,6 +489,10 @@
name = "Hitop"
icon_state = "hair_hitop"
+/datum/sprite_accessory/hair/inari
+ name = "Inari"
+ icon_state = "hair_inari"
+
/datum/sprite_accessory/hair/inkling
name = "Inkling"
icon_state = "hair_inkling"
@@ -421,14 +521,18 @@
name = "Keanu"
icon_state = "hair_keanu"
-/datum/sprite_accessory/hair/kusangi
- name = "Kusanagi"
- icon_state = "hair_kusanagi"
+/datum/sprite_accessory/hair/kisaragi
+ name = "Kisaragi"
+ icon_state = "hair_kisaragi"
/datum/sprite_accessory/hair/kleeia
name = "Kleeia"
icon_state = "hair_kleeia"
+/datum/sprite_accessory/hair/kusangi
+ name = "Kusanagi"
+ icon_state = "hair_kusanagi"
+
/datum/sprite_accessory/hair/long
name = "Long Hair 1"
icon_state = "hair_long"
@@ -449,6 +553,10 @@
name = "Long Over Eye"
icon_state = "hair_longovereye"
+/datum/sprite_accessory/hair/long_over_eyealt
+ name = "Long Over Eye (Alt)"
+ icon_state = "hair_longovereyealt"
+
/datum/sprite_accessory/hair/longbangs
name = "Long Bangs"
icon_state = "hair_lbangs"
@@ -489,10 +597,6 @@
name = "Mohawk"
icon_state = "hair_d"
-/datum/sprite_accessory/hair/newyou
- name = "New You"
- icon_state = "hair_newyou"
-
/datum/sprite_accessory/hair/reversemohawk
name = "Mohawk (Reverse)"
icon_state = "hair_reversemohawk"
@@ -509,6 +613,10 @@
name = "Mulder"
icon_state = "hair_mulder"
+/datum/sprite_accessory/hair/newyou
+ name = "New You"
+ icon_state = "hair_newyou"
+
/datum/sprite_accessory/hair/nia
name = "Nia"
icon_state = "hair_nia"
@@ -579,10 +687,18 @@
name = "Pompadour (Big)"
icon_state = "hair_bigpompadour"
+/datum/sprite_accessory/hair/bigpompadouralt
+ name = "Pompadour (Big) (Alt)"
+ icon_state = "hair_bigpompadouralt"
+
/datum/sprite_accessory/hair/ponytail1
name = "Ponytail"
icon_state = "hair_ponytail"
+/datum/sprite_accessory/hair/ponytail1alt
+ name = "Ponytail (Alt)"
+ icon_state = "hair_ponytailalt"
+
/datum/sprite_accessory/hair/ponytail2
name = "Ponytail 2"
icon_state = "hair_ponytail2"
@@ -591,14 +707,26 @@
name = "Ponytail 3"
icon_state = "hair_ponytail3"
+/datum/sprite_accessory/hair/ponytail3alt
+ name = "Ponytail 3 (Alt)"
+ icon_state = "hair_ponytail3alt"
+
/datum/sprite_accessory/hair/ponytail4
name = "Ponytail 4"
icon_state = "hair_ponytail4"
+/datum/sprite_accessory/hair/ponytail4alt
+ name = "Ponytail 4 (Alt)"
+ icon_state = "hair_ponytail4alt"
+
/datum/sprite_accessory/hair/ponytail5
name = "Ponytail 5"
icon_state = "hair_ponytail5"
+/datum/sprite_accessory/hair/ponytail6
+ name = "Ponytail 6"
+ icon_state = "hair_ponytail6"
+
/datum/sprite_accessory/hair/highponytail
name = "Ponytail (High)"
icon_state = "hair_highponytail"
@@ -623,6 +751,10 @@
name = "Ponytail (Side) 4"
icon_state = "hair_sidetail4"
+/datum/sprite_accessory/hair/sidetail5
+ name = "Ponytail (Side) 5"
+ icon_state = "hair_sidetail5"
+
/datum/sprite_accessory/hair/sharptail
name = "Ponytail (Sharp)"
icon_state = "hair_sharptail"
@@ -639,10 +771,18 @@
name = "Poofy 2"
icon_state = "hair_poofy2"
+/datum/sprite_accessory/hair/quadcurls
+ name = "Quad Curls"
+ icon_state = "hair_quadcurls"
+
/datum/sprite_accessory/hair/quiff
name = "Quiff"
icon_state = "hair_quiff"
+/datum/sprite_accessory/hair/rockstar
+ name = "Rockstar"
+ icon_state = "hair_rockstar"
+
/datum/sprite_accessory/hair/ronin
name = "Ronin"
icon_state = "hair_ronin"
@@ -759,6 +899,10 @@
name = "Slightly Long Hair"
icon_state = "hair_protagonist"
+/datum/sprite_accessory/hair/slightlymessy
+ name = "Slightly Messy Hair"
+ icon_state = "hair_slightlymessy"
+
/datum/sprite_accessory/hair/spiky
name = "Spiky"
icon_state = "hair_spikey"
@@ -771,6 +915,26 @@
name = "Spiky 3"
icon_state = "hair_spiky2"
+/datum/sprite_accessory/hair/slimedroplet
+ name = "Slime Droplet"
+ icon_state = "hair_slimedroplet"
+
+/datum/sprite_accessory/hair/slimedropletalt
+ name = "Slime Droplet (Alt)"
+ icon_state = "hair_slimedropletalt"
+
+/datum/sprite_accessory/hair/slimespikes
+ name = "Slime Spikes"
+ icon_state = "hair_slimespikes"
+
+/datum/sprite_accessory/hair/slimetendrils
+ name = "Slime Tendrils"
+ icon_state = "hair_slimetendrils"
+
+/datum/sprite_accessory/hair/slimetendrilsalt
+ name = "Slime Tendrils (Alt)"
+ icon_state = "hair_slimetendrilsalt"
+
/datum/sprite_accessory/hair/supernova
name = "Supernova"
icon_state = "hair_supernova"
@@ -851,6 +1015,10 @@
name = "Very Long Hair 2"
icon_state = "hair_longest"
+/datum/sprite_accessory/hair/longestalt
+ name = "Very Long Hair 2 (Alt)"
+ icon_state = "hair_longestalt"
+
/datum/sprite_accessory/hair/longest2
name = "Very Long Over Eye"
icon_state = "hair_longest2"
@@ -886,3 +1054,7 @@
/datum/sprite_accessory/hair/ziegler
name = "Ziegler"
icon_state = "hair_ziegler"
+
+/datum/sprite_accessory/hair/zone
+ name = "Zone"
+ icon_state = "hair_zone"
diff --git a/code/modules/mob/dead/observer/orbit.dm b/code/modules/mob/dead/observer/orbit.dm
index 26494dcb34..b799c5e592 100644
--- a/code/modules/mob/dead/observer/orbit.dm
+++ b/code/modules/mob/dead/observer/orbit.dm
@@ -83,7 +83,8 @@
for (var/_A in mind.antag_datums)
var/datum/antagonist/A = _A
- if (A.show_to_ghosts)
+ var/mob/dead/observer/O = user
+ if (A?.show_to_ghosts || !O?.can_reenter_corpse)
was_antagonist = TRUE
serialized["antag"] = A.name
antagonists += list(serialized)
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index aa14fe6013..f363aecf84 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -28,7 +28,7 @@
if(skipface || get_visible_name() == "Unknown")
. += "You can't make out what species they are."
else
- . += "[t_He] [t_is] a [dna.custom_species ? dna.custom_species : dna.species.name]!"
+ . += "[t_He] [t_is] a [spec_trait_examine_font()][dna.custom_species ? dna.custom_species : dna.species.name]!"
//uniform
if(w_uniform && !(SLOT_W_UNIFORM in obscured))
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index f636ae76ab..41ac05b8e2 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -1083,6 +1083,30 @@
. = ..()
set_species(race)
+/**
+ * # `spec_trait_examine_font()`
+ *
+ * This gets a humanoid's special examine font, which is used to color their species name during examine / health analyzing.
+ * The first of these that applies is returned.
+ * Returns:
+ * * Metallic font if robotic
+ * * Cyan if a toxinlover
+ * * Purple if plasmaperson
+ * * Rock / Brownish if a golem
+ * * Green if none of the others apply (aka, generic organic)
+*/
+/mob/living/carbon/human/proc/spec_trait_examine_font()
+ if(HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM))
+ return ""
+ if(HAS_TRAIT(src, TRAIT_TOXINLOVER))
+ return ""
+ if(isplasmaman(src))
+ return ""
+
+
/mob/living/carbon/human/get_tooltip_data()
var/t_He = p_they(TRUE)
var/t_is = p_are()
@@ -1091,7 +1115,7 @@
if(skipface || get_visible_name() == "Unknown")
. += "You can't make out what species they are."
else
- . += "[t_He] [t_is] a [dna.custom_species ? dna.custom_species : dna.species.name]"
+ . += "[t_He] [t_is] a [spec_trait_examine_font()][dna.custom_species ? dna.custom_species : dna.species.name]"
SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, usr, .)
/mob/living/carbon/human/species/abductor
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 1aa3749589..96a44792a8 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -149,6 +149,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
///
var/sound/attack_sound = 'sound/weapons/punch1.ogg'
var/sound/miss_sound = 'sound/weapons/punchmiss.ogg'
+ var/attack_sound_override = null
var/list/mob/living/ignored_by = list() // list of mobs that will ignore this species
//Breathing!
@@ -569,12 +570,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
/datum/species/proc/remove_blacklisted_quirks(mob/living/carbon/C)
var/mob/living/L = C.mind?.current
if(istype(L))
- var/list/my_quirks = L.client?.prefs.all_quirks.Copy()
- SSquirks.filter_quirks(my_quirks, blacklisted_quirks)
for(var/q in L.roundstart_quirks)
var/datum/quirk/Q = q
- if(!(SSquirks.quirk_name_by_path(Q.type) in my_quirks))
- L.remove_quirk(Q.type)
+ if(Q.type in blacklisted_quirks)
+ qdel(Q)
removed_quirks += Q.type
// restore any quirks that we removed
@@ -1615,7 +1614,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/armor_block = target.run_armor_check(affecting, "melee")
- playsound(target.loc, user.dna.species.attack_sound, 25, 1, -1)
+ playsound(target.loc, user.dna.species.attack_sound_override || attack_sound, 25, 1, -1)
target.visible_message("[user] [atk_verb]ed [target]!", \
"[user] [atk_verb]ed you!", null, COMBAT_MESSAGE_RANGE, null, \
user, "You [atk_verb]ed [target]!")
@@ -2003,6 +2002,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/turf/target_shove_turf = get_step(target.loc, shove_dir)
var/mob/living/carbon/human/target_collateral_human
var/shove_blocked = FALSE //Used to check if a shove is blocked so that if it is knockdown logic can be applied
+ var/targetatrest = !CHECK_MOBILITY(target, MOBILITY_STAND)
//Thank you based whoneedsspace
target_collateral_human = locate(/mob/living/carbon/human) in target_shove_turf.contents
@@ -2017,7 +2017,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/append_message = ""
if(shove_blocked && !target.buckled)
var/directional_blocked = !target.Adjacent(target_shove_turf)
- var/targetatrest = !CHECK_MOBILITY(target, MOBILITY_STAND)
if((directional_blocked || !(target_collateral_human || target_shove_turf.shove_act(target, user))) && !targetatrest)
target.DefaultCombatKnockdown(SHOVE_KNOCKDOWN_SOLID)
target.visible_message("[user.name] shoves [target.name], knocking them down!",
@@ -2046,11 +2045,15 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
append_message += ", loosening their grip on [target_held_item]"
else
append_message += ", but couldn't loose their grip on [target_held_item]"
- else if(target_held_item)
- if(target.dropItemToGround(target_held_item))
- target.visible_message("[target.name] drops \the [target_held_item]!!",
- "You drop \the [target_held_item]!!", null, COMBAT_MESSAGE_RANGE)
- append_message += ", causing them to drop [target_held_item]"
+ else if(target.has_status_effect(STATUS_EFFECT_OFF_BALANCE))
+ if(target_held_item)
+ if(shove_blocked)
+ if (target.buckled)
+ return
+ else if(target.dropItemToGround(target_held_item))
+ target.visible_message("[target.name] drops \the [target_held_item]!!",
+ "You drop \the [target_held_item]!!", null, COMBAT_MESSAGE_RANGE)
+ append_message += ", causing them to drop [target_held_item]"
target.ShoveOffBalance(SHOVE_OFFBALANCE_DURATION)
log_combat(user, target, "shoved", append_message)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index b3b539e3cd..b0d340eed0 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -542,8 +542,48 @@
update_stat()
med_hud_set_health()
med_hud_set_status()
+ update_health_hud()
-//proc used to ressuscitate a mob
+/mob/living/update_health_hud()
+ var/severity = 0
+ var/healthpercent = (health/maxHealth) * 100
+ if(hud_used?.healthdoll) //to really put you in the boots of a simplemob
+ var/obj/screen/healthdoll/living/livingdoll = hud_used.healthdoll
+ switch(healthpercent)
+ if(100 to INFINITY)
+ livingdoll.icon_state = "living0"
+ if(80 to 100)
+ livingdoll.icon_state = "living1"
+ severity = 1
+ if(60 to 80)
+ livingdoll.icon_state = "living2"
+ severity = 2
+ if(40 to 60)
+ livingdoll.icon_state = "living3"
+ severity = 3
+ if(20 to 40)
+ livingdoll.icon_state = "living4"
+ severity = 4
+ if(1 to 20)
+ livingdoll.icon_state = "living5"
+ severity = 5
+ else
+ livingdoll.icon_state = "living6"
+ severity = 6
+ if(!livingdoll.filtered)
+ livingdoll.filtered = TRUE
+ var/icon/mob_mask = icon(icon, icon_state)
+ if(mob_mask.Height() > world.icon_size || mob_mask.Width() > world.icon_size)
+ var/health_doll_icon_state = health_doll_icon ? health_doll_icon : "megasprite"
+ mob_mask = icon('icons/mob/screen_gen.dmi', health_doll_icon_state) //swap to something generic if they have no special doll
+ UNLINT(livingdoll.filters += filter(type="alpha", icon = mob_mask))
+ livingdoll.filters += filter(type="drop_shadow", size = -1)
+ if(severity > 0)
+ overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity)
+ else
+ clear_fullscreen("brute")
+
+//Proc used to resuscitate a mob, for full_heal see fully_heal()
/mob/living/proc/revive(full_heal = FALSE, admin_revive = FALSE)
SEND_SIGNAL(src, COMSIG_LIVING_REVIVE, full_heal, admin_revive)
if(full_heal)
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index 386f1174e1..f5919f389c 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -94,6 +94,7 @@
var/smoke_delay = 0 //used to prevent spam with smoke reagent reaction on mob.
var/bubble_icon = "default" //what icon the mob uses for speechbubbles
+ var/health_doll_icon //if this exists AND the normal sprite is bigger than 32x32, this is the replacement icon state (because health doll size limitations). the icon will always be screen_gen.dmi
var/last_bumped = 0
var/unique_name = 0 //if a mob's name should be appended with an id when created e.g. Mob (666)
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index 0c3ba87f5f..d0c53508fa 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -231,8 +231,11 @@
R.update_module_innate()
RM.rebuild_modules()
INVOKE_ASYNC(RM, .proc/do_transform_animation)
- if(RM.dogborg)
+ if(RM.dogborg || R.dogborg)
RM.dogborg_equip()
+ R.typing_indicator_state = /obj/effect/overlay/typing_indicator/machine/dogborg
+ else
+ R.typing_indicator_state = /obj/effect/overlay/typing_indicator/machine
R.maxHealth = borghealth
R.health = min(borghealth, R.health)
qdel(src)
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 8af55370bb..77d1be2bcd 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -48,6 +48,8 @@
var/hack_software = FALSE //Will be able to use hacking actions
var/interaction_range = 7 //wireless control range
+ typing_indicator_state = /obj/effect/overlay/typing_indicator/machine
+
/mob/living/silicon/Initialize()
. = ..()
GLOB.silicon_mobs += src
diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm
index c0a4822b6d..57ddbe6290 100644
--- a/code/modules/mob/living/simple_animal/hostile/alien.dm
+++ b/code/modules/mob/living/simple_animal/hostile/alien.dm
@@ -149,6 +149,7 @@
icon_state = "alienq"
icon_living = "alienq"
icon_dead = "alienq_dead"
+ health_doll_icon = "alienq"
bubble_icon = "alienroyal"
move_to_delay = 4
maxHealth = 400
diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm
index 51a646f668..8388d6501a 100644
--- a/code/modules/mob/living/simple_animal/hostile/carp.dm
+++ b/code/modules/mob/living/simple_animal/hostile/carp.dm
@@ -73,6 +73,7 @@
icon_living = "megacarp"
icon_dead = "megacarp_dead"
icon_gib = "megacarp_gib"
+ health_doll_icon = "megacarp"
regen_amount = 6
maxHealth = 30
diff --git a/code/modules/mob/living/simple_animal/hostile/cat_butcher.dm b/code/modules/mob/living/simple_animal/hostile/cat_butcher.dm
index d85f75cbbd..6950c6409f 100644
--- a/code/modules/mob/living/simple_animal/hostile/cat_butcher.dm
+++ b/code/modules/mob/living/simple_animal/hostile/cat_butcher.dm
@@ -6,37 +6,108 @@
icon_living = "cat_butcher"
icon_dead = "syndicate_dead"
icon_gib = "syndicate_gib"
+ projectiletype = /obj/item/projectile/bullet/dart/catranq
+ projectilesound = 'sound/items/syringeproj.ogg'
+ ranged = 1
+ ranged_message = "fires the syringe gun at"
+ ranged_cooldown_time = 30
speak_chance = 0
turns_per_move = 5
+ response_help_continuous = "pokes"
+ response_harm_continuous = "hits"
speed = 0
stat_attack = UNCONSCIOUS
robust_searching = 1
maxHealth = 100
health = 100
- harm_intent_damage = 5
melee_damage_lower = 15
melee_damage_upper = 15
attack_verb_continuous = "slashes at"
- attack_verb_simple = "slash at"
attack_sound = 'sound/weapons/circsawhit.ogg'
a_intent = INTENT_HARM
- mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
- loot = list(/obj/effect/mob_spawn/human/corpse/cat_butcher, /obj/item/circular_saw)
+ mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID)
+ loot = list(/obj/effect/mob_spawn/human/corpse/cat_butcher, /obj/item/circular_saw, /obj/item/gun/syringe)
atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0)
unsuitable_atmos_damage = 15
faction = list("hostile")
check_friendly_fire = 1
status_flags = CANPUSH
- del_on_death = 1
+ del_on_death = TRUE
+ var/impatience = 0
+ rapid_melee = 2 //this lets him attack nearly as fast as a normal player, instead of half as fast as one. Without this, due to mood differences, a greytider in melee can actually facetank and beat him to death with only fists
+ dodging = TRUE
+
+/mob/living/simple_animal/hostile/cat_butcherer/Life()
+ . = ..()
+ if(prob(10) && health <= maxHealth && !target) //heal himself when not in combat
+ var/healamount = min(maxHealth-health, 20)
+ visible_message("[src] medicates themself.", "You medicate yourself.")
+ health += healamount
+
+/mob/living/simple_animal/hostile/cat_butcherer/CanAttack(atom/the_target)
+ if(iscarbon(target))
+ var/mob/living/carbon/human/C = target
+ if(C.getorgan(/obj/item/organ/ears/cat) && C.getorgan(/obj/item/organ/tail/cat) && C.has_trauma_type(/datum/brain_trauma/severe/pacifism))//he wont attack his creations
+ if(C.stat && !istype(C.dna.species, /datum/species/ipc))//unless they need healing
+ return ..()
+ else
+ return FALSE
+ return ..()
/mob/living/simple_animal/hostile/cat_butcherer/AttackingTarget()
- . = ..()
- if(. && prob(35) && iscarbon(target))
+ if(iscarbon(target))
var/mob/living/carbon/human/L = target
- var/obj/item/organ/tail/cat/tail = L.getorgan(/obj/item/organ/tail/cat)
- if(!QDELETED(tail))
- visible_message("[src] severs [L]'s tail in one swift swipe!", "You sever [L]'s tail in one swift swipe.")
- tail.Remove()
- var/obj/item/organ/tail/cat/dropped_tail = new(target.drop_location())
- dropped_tail.color = L.hair_color
- return 1
+ if(!L.getorgan(/obj/item/organ/ears/cat) && L.stat) //target doesnt have cat ears
+ if(L.getorgan(/obj/item/organ/ears)) //slice off the old ears
+ var/obj/item/organ/ears/ears = L.getorgan(/obj/item/organ/ears)
+ visible_message("[src] slices off [L]'s ears!", "You slice [L]'s ears off.")
+ ears.Remove(L)
+ ears.forceMove(get_turf(L))
+ else //implant new ears
+ visible_message("[src] attaches a pair of cat ears to [L]!", "You attach a pair of cat ears to [L].")
+ var/obj/item/organ/ears/cat/newears = new
+ newears.Insert(L, drop_if_replaced = FALSE)
+ return
+ else if(!L.getorgan(/obj/item/organ/tail/cat) && L.stat)
+ if(L.getorgan(/obj/item/organ/tail)) //cut off the tail if they have one already
+ var/obj/item/organ/tail/tail = L.getorgan(/obj/item/organ/tail)
+ visible_message("[src] severs [L]'s tail in one swift swipe!", "You sever [L]'s tail in one swift swipe.")
+ tail.Remove(L)
+ tail.forceMove(get_turf(L))
+ else //put a cat tail on
+ visible_message("[src] attaches a cat tail to [L]!", "You attach a tail to [L].")
+ var/obj/item/organ/tail/cat/newtail = new
+ newtail.Insert(L, drop_if_replaced = FALSE)
+ return
+ else if(!L.has_trauma_type(/datum/brain_trauma/severe/pacifism) && L.getorgan(/obj/item/organ/ears/cat) && L.getorgan(/obj/item/organ/tail/cat)) //still does damage. This also lacks a Stat check- felinids beware.
+ visible_message("[src] drills a hole in [L]'s skull!", "You pacify [L]. Another successful creation.")
+ if(L.stat == CONSCIOUS)
+ L.emote("scream")
+ L.gain_trauma(/datum/brain_trauma/severe/pacifism, TRAUMA_RESILIENCE_BASIC)
+ say("Such a GOOD KITTY!!")
+ if(L.mind && maxHealth <= 300) //if he robusts a tider, he becomes stronger
+ maxHealth += 20
+ adjustHealth(-(maxHealth)) //he heals whenever he finishes
+ else if(L.stat) //quickly heal them up and move on to our next target!
+ visible_message("[src] injects [L] with an unknown medicine!", "You inject [L] with medicine.")
+ L.SetSleeping(0, FALSE)
+ L.SetUnconscious(0, FALSE)
+ L.adjustOxyLoss(-50)// do CPR first
+ if(L.blood_volume <= 500) //bandage them up and give em some blood if they're bleeding
+ L.blood_volume += 30
+ L.bleedsuppress = 0
+ if(L.getBruteLoss() >= 50)// first, did we beat them into crit? if so, heal that
+ var/healing = min(L.getBruteLoss(), 120)
+ L.adjustBruteLoss(-healing)
+ L.bleedsuppress = 0 //bandage their ass
+ return
+ else if(L.getFireLoss() >= 50) // are they still down from other damage? fix it, but not as fast as the burns
+ var/healing = min(L.getFireLoss(), 50)
+ L.adjustFireLoss(-healing)
+ impatience += 50
+ if(prob(impatience))
+ FindTarget()//so we don't focus on some unconscious dude when we could get our eyes on the prize
+ impatience = 0
+ say("Bah!!")
+ return
+ return ..()
diff --git a/code/modules/mob/living/simple_animal/hostile/floor_cluwne.dm b/code/modules/mob/living/simple_animal/hostile/floor_cluwne.dm
new file mode 100644
index 0000000000..b6d5db7d6d
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/hostile/floor_cluwne.dm
@@ -0,0 +1,457 @@
+GLOBAL_VAR_INIT(floor_cluwnes, 0)
+
+#define STAGE_HAUNT 1
+#define STAGE_SPOOK 2
+#define STAGE_TORMENT 3
+#define STAGE_ATTACK 4
+#define MANIFEST_DELAY 9
+
+/mob/living/simple_animal/hostile/floor_cluwne
+ name = "???"
+ desc = "...."
+ icon = 'icons/obj/clothing/masks.dmi'
+ icon_state = "cluwne"
+ icon_living = "cluwne"
+ icon_gib = "clown_gib"
+ maxHealth = 250
+ health = 250
+ speed = -1
+ attack_verb_continuous = "attacks"
+ attack_verb_simple = "attack"
+ attack_sound = 'sound/items/bikehorn.ogg'
+ del_on_death = TRUE
+ pass_flags = PASSTABLE | PASSGRILLE | PASSMOB | LETPASSTHROW | PASSGLASS | PASSBLOB//it's practically a ghost when unmanifested (under the floor)
+ loot = list(/obj/item/clothing/mask/gas/cluwne)
+ wander = FALSE
+ minimum_distance = 2
+ move_to_delay = 1
+ movement_type = FLYING
+ environment_smash = FALSE
+ lose_patience_timeout = FALSE
+ pixel_y = 8
+ pressure_resistance = 200
+ minbodytemp = 0
+ maxbodytemp = 1500
+ 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)
+ var/mob/living/carbon/human/current_victim
+ var/manifested = FALSE
+ var/switch_stage = 60
+ var/stage = STAGE_HAUNT
+ var/interest = 0
+ var/target_area
+ var/invalid_area_typecache = list(/area/space, /area/lavaland, /area/centcom, /area/reebe, /area/shuttle/syndicate)
+ var/eating = FALSE
+ var/dontkill = FALSE //for if we just wanna curse a fucker
+ var/obj/effect/dummy/floorcluwne_orbit/poi
+ var/obj/effect/temp_visual/fcluwne_manifest/cluwnehole
+ move_resist = INFINITY
+ hud_type = /datum/hud/ghost
+ hud_possible = list(ANTAG_HUD)
+
+
+/mob/living/simple_animal/hostile/floor_cluwne/Initialize()
+ . = ..()
+ access_card = new /obj/item/card/id(src)
+ var/datum/job/captain/C = new /datum/job/captain
+ access_card.access = C.get_access()
+ invalid_area_typecache = typecacheof(invalid_area_typecache)
+ Manifest()
+ if(!current_victim)
+ Acquire_Victim()
+ poi = new(src)
+
+/mob/living/simple_animal/hostile/floor_cluwne/med_hud_set_health()
+ return //we use a different hud
+
+/mob/living/simple_animal/hostile/floor_cluwne/med_hud_set_status()
+ return //we use a different hud
+
+/mob/living/simple_animal/hostile/floor_cluwne/Destroy()
+ QDEL_NULL(poi)
+ return ..()
+
+
+/mob/living/simple_animal/hostile/floor_cluwne/attack_hand(mob/living/carbon/human/M)
+ ..()
+ playsound(src.loc, 'sound/items/bikehorn.ogg', 50, 1)
+
+
+/mob/living/simple_animal/hostile/floor_cluwne/CanPass(atom/A, turf/target)
+ return TRUE
+
+
+/mob/living/simple_animal/hostile/floor_cluwne/Life()
+ do_jitter_animation(1000)
+ pixel_y = 8
+
+ var/area/A = get_area(src.loc)
+ if(is_type_in_typecache(A, invalid_area_typecache) || !is_station_level(z))
+ var/area = pick(GLOB.teleportlocs)
+ var/area/tp = GLOB.teleportlocs[area]
+ forceMove(pick(get_area_turfs(tp.type)))
+
+ if(!current_victim)
+ Acquire_Victim()
+
+ if(stage && !manifested)
+ INVOKE_ASYNC(src, .proc/On_Stage)
+
+ if(stage == STAGE_ATTACK)
+ playsound(src, 'sound/misc/cluwne_breathing.ogg', 75, 1)
+
+ if(eating)
+ return
+
+ var/turf/T = get_turf(current_victim)
+ A = get_area(T)
+ if(prob(5))//checks roughly every 20 ticks
+ if(current_victim.stat == DEAD || current_victim.dna.check_mutation(CLUWNEMUT) || is_type_in_typecache(A, invalid_area_typecache) || !is_station_level(current_victim.z))
+ if(!Found_You())
+ Acquire_Victim()
+
+ if(get_dist(src, current_victim) > 9 && !manifested && !is_type_in_typecache(A, invalid_area_typecache))//if cluwne gets stuck he just teleports
+ do_teleport(src, T)
+
+ interest++
+ if(interest >= switch_stage * 4 && !dontkill)
+ stage = STAGE_ATTACK
+
+ else if(interest >= switch_stage * 2)
+ stage = STAGE_TORMENT
+
+ else if(interest >= switch_stage)
+ stage = STAGE_SPOOK
+
+ else if(interest < switch_stage)
+ stage = STAGE_HAUNT
+
+ ..()
+
+/mob/living/simple_animal/hostile/floor_cluwne/Goto(target, delay, minimum_distance)
+ var/area/A = get_area(current_victim.loc)
+ if(!manifested && !is_type_in_typecache(A, invalid_area_typecache) && is_station_level(current_victim.z))
+ walk_to(src, target, minimum_distance, delay)
+ else
+ walk_to(src,0)
+
+
+/mob/living/simple_animal/hostile/floor_cluwne/FindTarget()
+ return current_victim
+
+
+/mob/living/simple_animal/hostile/floor_cluwne/CanAttack(atom/the_target)//you will not escape
+ return TRUE
+
+
+/mob/living/simple_animal/hostile/floor_cluwne/AttackingTarget()
+ return
+
+
+/mob/living/simple_animal/hostile/floor_cluwne/LoseTarget()
+ return
+
+
+/mob/living/simple_animal/hostile/floor_cluwne/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE)//prevents runtimes with machine fuckery
+ return FALSE
+
+/mob/living/simple_animal/hostile/floor_cluwne/proc/Found_You()
+ for(var/obj/structure/closet/hiding_spot in orange(7,src))
+ if(current_victim.loc == hiding_spot)
+ hiding_spot.bust_open()
+ current_victim.Paralyze(40)
+ to_chat(current_victim, "...edih t'nac uoY")
+ return TRUE
+ return FALSE
+
+/mob/living/simple_animal/hostile/floor_cluwne/proc/Acquire_Victim(specific)
+ for(var/I in GLOB.player_list)//better than a potential recursive loop
+ var/mob/living/carbon/human/H = pick(GLOB.player_list)//so the check is fair
+ var/area/A
+
+ if(specific)
+ H = specific
+ A = get_area(H.loc)
+ if(H.stat != DEAD && H.has_dna() && !H.dna.check_mutation(CLUWNEMUT) && !is_type_in_typecache(A, invalid_area_typecache) && is_station_level(H.z))
+ return target = current_victim
+
+ A = get_area(H.loc)
+ if(H && ishuman(H) && H.stat != DEAD && H != current_victim && H.has_dna() && !H.dna.check_mutation(CLUWNEMUT) && !is_type_in_typecache(A, invalid_area_typecache) && is_station_level(H.z))
+ current_victim = H
+ interest = 0
+ stage = STAGE_HAUNT
+ return target = current_victim
+
+ message_admins("Floor Cluwne was deleted due to a lack of valid targets, if this was a manually targeted instance please re-evaluate your choice.")
+ qdel(src)
+
+
+/mob/living/simple_animal/hostile/floor_cluwne/proc/Manifest()//handles disappearing and appearance anim
+ if(manifested)
+ mobility_flags &= ~MOBILITY_MOVE
+ update_mobility()
+ cluwnehole = new(src.loc)
+ addtimer(CALLBACK(src, /mob/living/simple_animal/hostile/floor_cluwne/.proc/Appear), MANIFEST_DELAY)
+ else
+ layer = GAME_PLANE
+ invisibility = INVISIBILITY_OBSERVER
+ density = FALSE
+ mobility_flags |= MOBILITY_MOVE
+ update_mobility()
+ if(cluwnehole)
+ qdel(cluwnehole)
+
+
+/mob/living/simple_animal/hostile/floor_cluwne/proc/Appear()//handled in a seperate proc so floor cluwne doesn't appear before the animation finishes
+ layer = LYING_MOB_LAYER
+ invisibility = FALSE
+ density = TRUE
+
+/mob/living/simple_animal/hostile/floor_cluwne/proc/Reset_View(screens, colour, mob/living/carbon/human/H)
+ if(screens)
+ for(var/whole_screen in screens)
+ animate(whole_screen, transform = matrix(), time = 5, easing = QUAD_EASING)
+ if(colour && H)
+ H.client.color = colour
+
+
+/mob/living/simple_animal/hostile/floor_cluwne/proc/On_Stage()
+ var/mob/living/carbon/human/H = current_victim
+ switch(stage)
+
+ if(STAGE_HAUNT)
+
+ if(prob(5))
+ H.blur_eyes(1)
+
+ if(prob(5))
+ H.playsound_local(src,'sound/voice/cluwnelaugh2_reversed.ogg', 1)
+
+ if(prob(5))
+ H.playsound_local(src,'sound/misc/bikehorn_creepy.ogg', 5)
+
+ if(prob(3))
+ var/obj/item/I = locate() in orange(H, 8)
+ if(I && !I.anchored)
+ I.throw_at(H, 4, 3)
+ to_chat(H, "What threw that?")
+
+ if(STAGE_SPOOK)
+
+ if(prob(4))
+ var/turf/T = get_turf(H)
+ T.handle_slip(H, 20)
+ to_chat(H, "The floor shifts underneath you!")
+
+ if(prob(5))
+ H.playsound_local(src,'sound/voice/cluwnelaugh2.ogg', 2)
+
+ if(prob(5))
+ H.playsound_local(src,'sound/voice/cluwnelaugh2_reversed.ogg', 2)
+
+ if(prob(5))
+ H.playsound_local(src,'sound/misc/bikehorn_creepy.ogg', 10)
+ to_chat(H, "knoh")
+
+ if(prob(5))
+ var/obj/item/I = locate() in orange(H, 8)
+ if(I && !I.anchored)
+ I.throw_at(H, 4, 3)
+ to_chat(H, "What threw that?")
+
+ if(prob(2))
+ to_chat(H, "yalp ot tnaw I")
+ Appear()
+ manifested = FALSE
+ addtimer(CALLBACK(src, /mob/living/simple_animal/hostile/floor_cluwne/.proc/Manifest), 1)
+
+ if(STAGE_TORMENT)
+
+ if(prob(5))
+ var/turf/T = get_turf(H)
+ T.handle_slip(H, 20)
+ to_chat(H, "The floor shifts underneath you!")
+
+ if(prob(3))
+ playsound(src,pick('sound/spookoween/scary_horn.ogg', 'sound/spookoween/scary_horn2.ogg', 'sound/spookoween/scary_horn3.ogg'), 30, 1)
+
+ if(prob(3))
+ playsound(src,'sound/voice/cluwnelaugh1.ogg', 30, 1)
+
+ if(prob(3))
+ playsound(src,'sound/voice/cluwnelaugh2_reversed.ogg', 30, 1)
+
+ if(prob(5))
+ playsound(src,'sound/misc/bikehorn_creepy.ogg', 30, 1)
+
+ if(prob(4))
+ for(var/obj/item/I in orange(8, H))
+ if(!I.anchored)
+ I.throw_at(H, 4, 3)
+ to_chat(H, "What the hell?!")
+
+ if(prob(2))
+ to_chat(H, "Something feels very wrong...")
+ H.playsound_local(src,'sound/hallucinations/behind_you1.ogg', 25)
+ H.flash_act()
+
+ if(prob(2))
+ to_chat(H, "!?REHTOMKNOH eht esiarp uoy oD")
+ to_chat(H, "Something grabs your foot!")
+ H.playsound_local(src,'sound/hallucinations/i_see_you1.ogg', 25)
+ H.Stun(20)
+
+ if(prob(3))
+ to_chat(H, "KNOH ?od nottub siht seod tahW")
+ for(var/turf/open/O in RANGE_TURFS(6, src))
+ O.MakeSlippery(TURF_WET_WATER, 10)
+ playsound(src, 'sound/effects/meteorimpact.ogg', 30, 1)
+
+ if(prob(1))
+ to_chat(H, "WHAT THE FUCK IS THAT?!")
+ to_chat(H, ".KNOH !nuf hcum os si uoy htiw gniyalP .KNOH KNOH KNOH")
+ H.playsound_local(src,'sound/hallucinations/im_here1.ogg', 25)
+ H.reagents.add_reagent(/datum/reagent/toxin/mindbreaker, 3)
+ H.reagents.add_reagent(/datum/reagent/consumable/laughter, 5)
+ H.reagents.add_reagent(/datum/reagent/mercury, 3)
+ Appear()
+ manifested = FALSE
+ addtimer(CALLBACK(src, /mob/living/simple_animal/hostile/floor_cluwne/.proc/Manifest), 2)
+ for(var/obj/machinery/light/L in range(8, H))
+ L.flicker()
+
+
+ if(STAGE_ATTACK)
+ if(dontkill)
+ stage = STAGE_TORMENT
+ return
+ if(!eating)
+ Found_You()
+ for(var/I in getline(src,H))
+ var/turf/T = I
+ if(T.density)
+ forceMove(H.loc)
+ for(var/obj/structure/O in T)
+ if(O.density || istype(O, /obj/machinery/door/airlock))
+ forceMove(H.loc)
+ to_chat(H, "You feel the floor closing in on your feet!")
+ H.Paralyze(300)
+ INVOKE_ASYNC(H, /mob.proc/emote, "scream")
+ H.adjustBruteLoss(10)
+ manifested = TRUE
+ Manifest()
+ if(!eating)
+ addtimer(CALLBACK(src, /mob/living/simple_animal/hostile/floor_cluwne/.proc/Grab, H), 50, TIMER_OVERRIDE|TIMER_UNIQUE)
+ for(var/turf/open/O in RANGE_TURFS(6, src))
+ O.MakeSlippery(TURF_WET_LUBE, 20)
+ playsound(src, 'sound/effects/meteorimpact.ogg', 30, 1)
+ eating = TRUE
+
+
+/mob/living/simple_animal/hostile/floor_cluwne/proc/Grab(mob/living/carbon/human/H)
+ if (H != current_victim)
+ message_admins("Cluwne tried to grab someone who's not the target. Returning to life stage.")
+ return
+ to_chat(H, "You feel a cold, gloved hand clamp down on your ankle!")
+ for(var/I in 1 to get_dist(src, H))
+ if(do_after(src, 5, target = H))
+ step_towards(H, src)
+ playsound(H, pick('sound/effects/bodyscrape-01.ogg', 'sound/effects/bodyscrape-02.ogg'), 20, 1, -4)
+ if(prob(40))
+ H.emote("scream")
+ else if(prob(25))
+ H.say(pick("HELP ME!!","IT'S GOT ME!!","DON'T LET IT TAKE ME!!",";SOMETHING'S KILLING ME!!","HOLY FUCK!!"))
+ playsound(src, pick('sound/voice/cluwnelaugh1.ogg', 'sound/voice/cluwnelaugh2.ogg', 'sound/voice/cluwnelaugh3.ogg'), 50, 1)
+
+ if(get_dist(src,H) <= 1)
+ visible_message("[src] begins dragging [H] under the floor!")
+ if(do_after(src, 50, target = H) && eating)
+ H.become_blind()
+ H.layer = GAME_PLANE
+ H.invisibility = INVISIBILITY_OBSERVER
+ H.density = FALSE
+ H.anchored = TRUE
+ addtimer(CALLBACK(src, /mob/living/simple_animal/hostile/floor_cluwne/.proc/Kill, H), 100, TIMER_OVERRIDE|TIMER_UNIQUE)
+ visible_message("[src] pulls [H] under!")
+ to_chat(H, "[src] drags you underneath the floor!")
+ else
+ eating = FALSE
+ else
+ eating = FALSE
+ manifested = FALSE
+ Manifest()
+
+
+/mob/living/simple_animal/hostile/floor_cluwne/proc/Kill(mob/living/carbon/human/H)
+ if (H != current_victim)
+ message_admins("Cluwne tried to kill someone who's not the target. Returning to life stage.")
+ H.invisibility = initial(H.invisibility)
+ return
+ if(!istype(H) || !H.client)
+ H.invisibility = initial(H.invisibility)
+ Acquire_Victim()
+ return
+ playsound(H, 'sound/effects/cluwne_feast.ogg', 100, 0, -4)
+ var/old_color = H.client.color
+ var/red_splash = list(1,0,0,0.8,0.2,0, 0.8,0,0.2,0.1,0,0)
+ var/pure_red = list(0,0,0,0,0,0,0,0,0,1,0,0)
+ H.client.color = pure_red
+ animate(H.client,color = red_splash, time = 10, easing = SINE_EASING|EASE_OUT)
+ for(var/turf/T in orange(H, 4))
+ H.add_splatter_floor(T)
+ if(do_after(src, 50, target = H))
+ H.unequip_everything()//more runtime prevention
+ if(prob(75))
+ H.gib(FALSE)
+ else
+ H.cluwneify()
+ H.adjustBruteLoss(30)
+ H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 100, 100)
+ H.cure_blind()
+ H.layer = initial(H.layer)
+ H.invisibility = initial(H.invisibility)
+ H.density = initial(H.density)
+ H.anchored = initial(H.anchored)
+ H.blur_eyes(10)
+ animate(H.client,color = old_color, time = 20)
+
+ eating = FALSE
+ switch_stage = switch_stage * 0.75 //he gets faster after each feast
+ for(var/mob/M in GLOB.player_list)
+ M.playsound_local(get_turf(M), 'sound/misc/honk_echo_distant.ogg', 50, 1, pressure_affected = FALSE)
+
+ interest = 0
+ stage = STAGE_HAUNT
+ Acquire_Victim()
+
+//manifestation animation
+/obj/effect/temp_visual/fcluwne_manifest
+ icon = 'icons/turf/floors.dmi'
+ icon_state = "fcluwne_open"
+ layer = TURF_LAYER
+ duration = 600
+ randomdir = FALSE
+
+/obj/effect/temp_visual/fcluwne_manifest/Initialize()
+ . = ..()
+ playsound(src, 'sound/misc/floor_cluwne_emerge.ogg', 100, 1)
+ flick("fcluwne_manifest",src)
+
+/obj/effect/dummy/floorcluwne_orbit
+ name = "floor cluwne"
+ desc = "If you have this, tell a coder or admin!"
+
+/obj/effect/dummy/floorcluwne_orbit/Initialize()
+ . = ..()
+ GLOB.floor_cluwnes++
+ name += " ([GLOB.floor_cluwnes])"
+ GLOB.poi_list += src
+
+/obj/effect/dummy/floorcluwne_orbit/Destroy()
+ . = ..()
+ GLOB.poi_list -= src
+
+#undef STAGE_HAUNT
+#undef STAGE_SPOOK
+#undef STAGE_TORMENT
+#undef STAGE_ATTACK
+#undef MANIFEST_DELAY
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 ec0b7acd07..67cecd3832 100644
--- a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm
+++ b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm
@@ -9,6 +9,7 @@
icon_state = "crawling"
icon_living = "crawling"
icon_dead = "dead"
+ health_doll_icon = "crawling"
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
speak_chance = 80
maxHealth = 220
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 61f1fe0c9d..a60c5504e6 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
@@ -28,6 +28,7 @@ Difficulty: Medium
icon_state = "miner"
icon_living = "miner"
icon = 'icons/mob/broadMobs.dmi'
+ health_doll_icon = "miner"
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
light_color = "#E4C7C5"
movement_type = GROUND
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 5305813ebf..b80e6cc72f 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
@@ -33,6 +33,7 @@ Difficulty: Hard
icon_state = "bubblegum"
icon_living = "bubblegum"
icon_dead = ""
+ health_doll_icon = "bubblegum"
friendly_verb_continuous = "stares down"
friendly_verb_simple = "stare down"
icon = 'icons/mob/lavaland/96x96megafauna.dmi'
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 787c15a5b4..5751512b19 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -32,6 +32,7 @@ Difficulty: Very Hard
icon_state = "eva"
icon_living = "eva"
icon_dead = "dragon_dead"
+ health_doll_icon = "eva"
friendly_verb_continuous = "stares down"
friendly_verb_simple = "stare down"
icon = 'icons/mob/lavaland/96x96megafauna.dmi'
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 6c1e9eef6e..a3d51744b9 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
@@ -48,6 +48,7 @@ Difficulty: Medium
icon_state = "dragon"
icon_living = "dragon"
icon_dead = "dragon_dead"
+ health_doll_icon = "dragon"
friendly_verb_continuous = "stares down"
friendly_verb_simple = "stare down"
speak_emote = list("roars")
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 32300dea18..14b71b3bac 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
@@ -44,6 +44,7 @@ Difficulty: Normal
attack_sound = 'sound/weapons/sonic_jackhammer.ogg'
icon_state = "hierophant"
icon_living = "hierophant"
+ health_doll_icon = "hierophant"
friendly_verb_continuous = "stares down"
friendly_verb_simple = "stare down"
icon = 'icons/mob/lavaland/hierophant_new.dmi'
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 07c1957da2..15bfe2b7f7 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
@@ -26,6 +26,7 @@ SHITCODE AHEAD. BE ADVISED. Also comment extravaganza
spacewalk = TRUE
icon_state = "mega_legion"
icon_living = "mega_legion"
+ health_doll_icon = "mega_legion"
desc = "One of many."
icon = 'icons/mob/lavaland/96x96megafauna.dmi'
attack_verb_continuous = "chomps"
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 bda898ef17..f2ece50af2 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
@@ -75,6 +75,7 @@
icon_living = "watcher"
icon_aggro = "watcher"
icon_dead = "watcher_dead"
+ health_doll_icon = "watcher"
pixel_x = -10
throw_message = "bounces harmlessly off of"
melee_damage_lower = 15
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 ef51dc572f..5ee249c767 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,6 +25,7 @@
icon_aggro = "broodmother"
icon_dead = "egg_sac"
icon_gib = "syndicate_gib"
+ health_doll_icon = "broodmother"
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 032bc2d60d..4425bce532 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,6 +24,7 @@
icon_aggro = "herald"
icon_dead = "herald_dying"
icon_gib = "syndicate_gib"
+ health_doll_icon = "herald"
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 6c13bb903e..dca508cfeb 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,6 +24,7 @@
icon_aggro = "legionnaire"
icon_dead = "legionnaire_dead"
icon_gib = "syndicate_gib"
+ health_doll_icon = "legionnaire"
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 e3a5d5f762..50b15933a9 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,6 +24,7 @@
icon_aggro = "pandora"
icon_dead = "pandora_dead"
icon_gib = "syndicate_gib"
+ health_doll_icon = "pandora"
maxHealth = 800
health = 800
melee_damage_lower = 15
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 446fe80c7d..7db91b50ad 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
@@ -253,6 +253,7 @@
icon_state = "legion"
icon_living = "legion"
icon_dead = "legion"
+ health_doll_icon = "legion"
health = 450
maxHealth = 450
melee_damage_lower = 20
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
index 96418686d3..5750d1ecb9 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
@@ -6,6 +6,7 @@
icon_living = "clown"
icon_dead = "clown_dead"
icon_gib = "clown_gib"
+ health_doll_icon = "clown" //if >32x32, it will use this generic. for all the huge clown mobs that subtype from this
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
turns_per_move = 5
response_disarm_continuous = "gently pushes aside"
diff --git a/code/modules/mob/living/simple_animal/hostile/tree.dm b/code/modules/mob/living/simple_animal/hostile/tree.dm
index 89afdf0c0d..978d58339d 100644
--- a/code/modules/mob/living/simple_animal/hostile/tree.dm
+++ b/code/modules/mob/living/simple_animal/hostile/tree.dm
@@ -6,6 +6,7 @@
icon_living = "pine_1"
icon_dead = "pine_1"
icon_gib = "pine_1"
+ health_doll_icon = "pine_1"
gender = NEUTER
speak_chance = 0
turns_per_move = 5
@@ -72,5 +73,6 @@
icon_living = "festivus_pole"
icon_dead = "festivus_pole"
icon_gib = "festivus_pole"
+ health_doll_icon = "festivus_pole"
loot = list(/obj/item/stack/rods)
speak_emote = list("polls")
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 bce1a01c8a..f10b184a45 100644
--- a/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm
+++ b/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm
@@ -8,6 +8,7 @@
icon_aggro = "Fugu0"
icon_dead = "Fugu_dead"
icon_gib = "syndicate_gib"
+ health_doll_icon = "Fugu0"
mob_biotypes = MOB_ORGANIC|MOB_BEAST
mouse_opacity = MOUSE_OPACITY_ICON
move_to_delay = 5
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 51f06e9f16..58e0483f20 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -7,6 +7,7 @@
///How much blud it has for bloodsucking
blood_volume = 550
rad_flags = RAD_NO_CONTAMINATE
+ hud_type = /datum/hud/living/simple_animal
status_flags = CANPUSH
diff --git a/code/modules/mob/living/simple_animal/slime/life.dm b/code/modules/mob/living/simple_animal/slime/life.dm
index c8d5c95733..2ce355a0ef 100644
--- a/code/modules/mob/living/simple_animal/slime/life.dm
+++ b/code/modules/mob/living/simple_animal/slime/life.dm
@@ -6,6 +6,7 @@
var/Discipline = 0 // if a slime has been hit with a freeze gun, or wrestled/attacked off a human, they become disciplined and don't attack anymore for a while
var/SStun = 0 // stun variable
+ typing_indicator_state = /obj/effect/overlay/typing_indicator/slime
/mob/living/simple_animal/slime/BiologicalLife(seconds, times_fired)
if(!(. = ..()))
diff --git a/code/modules/mob/typing_indicator.dm b/code/modules/mob/typing_indicator.dm
index 159d370b92..570f01f5d9 100644
--- a/code/modules/mob/typing_indicator.dm
+++ b/code/modules/mob/typing_indicator.dm
@@ -55,3 +55,12 @@ GLOBAL_LIST_EMPTY(typing_indicator_overlays)
icon_state = "normal_typing"
appearance_flags = RESET_COLOR | TILE_BOUND | PIXEL_SCALE
layer = ABOVE_FLY_LAYER
+
+/obj/effect/overlay/typing_indicator/machine
+ icon_state = "machine_typing"
+
+/obj/effect/overlay/typing_indicator/machine/dogborg
+ icon = 'icons/mob/talk_64x64.dmi'
+
+/obj/effect/overlay/typing_indicator/slime
+ icon_state = "slime_typing"
diff --git a/code/modules/photography/camera/camera.dm b/code/modules/photography/camera/camera.dm
index b925c67940..49821e55e0 100644
--- a/code/modules/photography/camera/camera.dm
+++ b/code/modules/photography/camera/camera.dm
@@ -158,12 +158,12 @@
return FALSE
size_x = clamp(size_x, 0, CAMERA_PICTURE_SIZE_HARD_LIMIT)
size_y = clamp(size_y, 0, CAMERA_PICTURE_SIZE_HARD_LIMIT)
- var/list/desc = list("This is a photo of an area of [size_x+1] meters by [size_y+1] meters.")
+ var/list/desc = list("This is a photo of an area of [size_x*2 + 1] meters by [size_y*2 + 1] meters.")
var/ai_user = isAI(user)
var/list/seen
- var/list/viewlist = (user && user.client)? getviewsize(user.client.view) : getviewsize(world.view)
+ var/list/viewlist = user?.client? getviewsize(user.client.view) : getviewsize(world.view)
var/viewr = max(viewlist[1], viewlist[2]) + max(size_x, size_y)
- var/viewc = user.client? user.client.eye : target
+ var/viewc = user?.client? user.client.eye : target
seen = get_hear(viewr, viewc)
var/list/turfs = list()
var/list/mobs = list()
@@ -184,7 +184,7 @@
var/psize_y = (size_y * 2 + 1) * world.icon_size
var/get_icon = camera_get_icon(turfs, target_turf, psize_x, psize_y, clone_area, size_x, size_y, (size_x * 2 + 1), (size_y * 2 + 1))
qdel(clone_area)
- var/icon/temp = icon('icons/effects/96x96.dmi',"")
+ var/icon/temp = icon('icons/effects/camera_image_base.dmi',"")
temp.Blend("#000", ICON_OVERLAY)
temp.Scale(psize_x, psize_y)
temp.Blend(get_icon, ICON_OVERLAY)
diff --git a/code/modules/photography/camera/camera_image_capturing.dm b/code/modules/photography/camera/camera_image_capturing.dm
index 5bd9c108d1..a5a1cbeedc 100644
--- a/code/modules/photography/camera/camera_image_capturing.dm
+++ b/code/modules/photography/camera/camera_image_capturing.dm
@@ -47,7 +47,7 @@
atoms += A
CHECK_TICK
- var/icon/res = icon('icons/effects/96x96.dmi', "")
+ var/icon/res = icon('icons/effects/camera_image_base.dmi', "")
res.Scale(psize_x, psize_y)
var/list/sorted = list()
@@ -64,7 +64,6 @@
var/xcomp = FLOOR(psize_x / 2, 1) - 15
var/ycomp = FLOOR(psize_y / 2, 1) - 15
-
for(var/atom/A in sorted)
var/xo = (A.x - center.x) * world.icon_size + A.pixel_x + xcomp
var/yo = (A.y - center.y) * world.icon_size + A.pixel_y + ycomp
diff --git a/code/modules/pool/pool_controller.dm b/code/modules/pool/pool_controller.dm
index 9f670de282..142690566b 100644
--- a/code/modules/pool/pool_controller.dm
+++ b/code/modules/pool/pool_controller.dm
@@ -235,10 +235,10 @@
if(POOL_SCALDING) //Scalding
M.adjust_bodytemperature(50,0,500)
if(POOL_WARM) //Warm
- M.adjust_bodytemperature(20,0,360) //Heats up mobs till the termometer shows up
+ M.adjust_bodytemperature(20,0,360) //Heats up mobs till the thermometer shows up
//Normal temp does nothing, because it's just room temperature water.
if(POOL_COOL)
- M.adjust_bodytemperature(-20,250) //Cools mobs till the termometer shows up
+ M.adjust_bodytemperature(-20,250) //Cools mobs till the thermometer shows up
if(POOL_FRIGID) //Freezing
M.adjust_bodytemperature(-60) //cool mob at -35k per cycle, less would not affect the mob enough.
if(M.bodytemperature <= 50 && !M.stat)
@@ -290,10 +290,10 @@
/obj/machinery/pool/controller/proc/update_temp()
if(mist_state)
- if(temperature < POOL_SCALDING)
+ if(temperature < POOL_WARM)
mist_off()
else
- if(temperature == POOL_SCALDING)
+ if(temperature >= POOL_WARM)
mist_on()
update_icon()
diff --git a/code/modules/projectiles/ammunition/special/magic.dm b/code/modules/projectiles/ammunition/special/magic.dm
index 8380bf82e9..821f6d002f 100644
--- a/code/modules/projectiles/ammunition/special/magic.dm
+++ b/code/modules/projectiles/ammunition/special/magic.dm
@@ -35,6 +35,9 @@
/obj/item/ammo_casing/magic/spellblade
projectile_type = /obj/item/projectile/magic/spellblade
+/obj/item/ammo_casing/magic/judgement_cut
+ projectile_type = /obj/item/projectile/judgement_cut
+
/obj/item/ammo_casing/magic/arcane_barrage
projectile_type = /obj/item/projectile/magic/arcane_barrage
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 63d019f97f..06bf298454 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -568,12 +568,18 @@
/datum/action/item_action/toggle_scope_zoom/IsAvailable(silent = FALSE)
. = ..()
if(!.)
+ var/obj/item/gun/G = target
+ G.zoom(owner, owner.dir, FALSE)
+
+/datum/action/item_action/toggle_scope_zoom/Trigger()
+ . = ..()
+ if(.)
var/obj/item/gun/G = target
G.zoom(owner, owner.dir)
/datum/action/item_action/toggle_scope_zoom/Remove(mob/living/L)
var/obj/item/gun/G = target
- G.zoom(L, L.dir)
+ G.zoom(L, L.dir, FALSE)
return ..()
/obj/item/gun/proc/rotate(atom/thing, old_dir, new_dir)
diff --git a/code/modules/projectiles/guns/magic/motivation.dm b/code/modules/projectiles/guns/magic/motivation.dm
new file mode 100644
index 0000000000..0eaeea4418
--- /dev/null
+++ b/code/modules/projectiles/guns/magic/motivation.dm
@@ -0,0 +1,91 @@
+/obj/item/gun/magic/staff/motivation
+ name = "Motivation"
+ desc = "Rumored to have the ability to open up a portal the depths of Lavaland."
+ icon = 'icons/obj/items_and_weapons.dmi'
+ icon_state = "motivation"
+ item_state = "motivation"
+ lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
+ fire_sound = 'sound/weapons/judgementhit.ogg'
+ ammo_type = /obj/item/ammo_casing/magic/judgement_cut
+ force = 20 //so it's worth that 20 tc
+ armour_penetration = 50
+ w_class = WEIGHT_CLASS_NORMAL
+ slot_flags = ITEM_SLOT_BELT
+ hitsound = 'sound/weapons/bladeslice.ogg'
+ attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
+ sharpness = SHARP_EDGED
+ max_integrity = 200
+ resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
+ max_charges = 3
+ recharge_rate = 5
+ var/datum/action/judgement_cut/judgementcut = new/datum/action/judgement_cut()
+ block_parry_data = /datum/block_parry_data/motivation
+
+//to get this to toggle correctly
+/obj/item/gun/magic/staff/motivation/Initialize()
+ . = ..()
+ judgementcut = new(src)
+
+//lets the user know that their judgment cuts are recharging
+/obj/item/gun/magic/staff/motivation/shoot_with_empty_chamber(mob/living/user as mob|obj)
+ to_chat(user, "Judgment Cut is recharging.")
+
+//action button to toggle judgement cuts on/off
+/datum/action/judgement_cut
+ name = "Judgement Cut - Allows Motivation to slash at a longer distance."
+ icon_icon = 'icons/obj/projectiles.dmi'
+ button_icon_state = "judgement_fire"
+ var/judgement_toggled = TRUE
+
+//lets the user know that you toggled them on/off
+/datum/action/judgement_cut/Trigger()
+ judgement_toggled = !judgement_toggled
+ to_chat(owner, "You [judgement_toggled ? "enable" : "disable"] Judgement Cuts with Motivation.")
+
+//Prevents "firing" the judgement cuts if toggled off and lets the user know
+/obj/item/gun/magic/staff/motivation/can_trigger_gun(mob/living/user)
+ . = ..()
+ if(!judgementcut.judgement_toggled)
+ to_chat(user, " Judgment Cut is disabled.")
+ return FALSE
+
+//adds/removes judgement cut and judgement cut end upon pickup/drop
+/obj/item/gun/magic/staff/motivation/pickup(mob/living/user)
+ . = ..()
+ judgementcut.Grant(user, src)
+ user.update_icons()
+ playsound(src, 'sound/items/unsheath.ogg', 25, 1)
+
+/obj/item/gun/magic/staff/motivation/dropped(mob/user)
+ . = ..()
+ judgementcut.Remove(user)
+ user.update_icons()
+
+//A parry tight enough to stagger, but not to counter attack
+/datum/block_parry_data/motivation
+ parry_time_windup = 0.5
+ parry_time_active = 5
+ parry_time_spindown = 0
+ parry_attack_types = ALL
+ parry_time_active_visual_override = 3
+ parry_time_spindown_visual_override = 2
+ parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK | PARRY_LOCK_ATTACKING
+ parry_time_perfect = 0
+ parry_time_perfect_leeway = 3
+ parry_time_perfect_leeway_override = list(
+ TEXT_ATTACK_TYPE_PROJECTILE = 1
+ )
+ parry_imperfect_falloff_percent_override = list(
+ TEXT_ATTACK_TYPE_PROJECTILE = 50 // useless after 3rd decisecond
+ )
+ parry_imperfect_falloff_percent = 30
+ parry_efficiency_to_counterattack = 100
+ parry_efficiency_considered_successful = 1
+ parry_efficiency_perfect = 100
+ parry_data = list(
+ PARRY_STAGGER_ATTACKER = 10
+ )
+ parry_failed_stagger_duration = 2 SECONDS
+ parry_failed_clickcd_duration = CLICK_CD_RANGE
+ parry_cooldown = 0
diff --git a/code/modules/projectiles/projectile/bullets/dart_syringe.dm b/code/modules/projectiles/projectile/bullets/dart_syringe.dm
index 25809cc7ca..bc2a7c40fb 100644
--- a/code/modules/projectiles/projectile/bullets/dart_syringe.dm
+++ b/code/modules/projectiles/projectile/bullets/dart_syringe.dm
@@ -38,6 +38,10 @@
reagents.add_reagent(/datum/reagent/foaming_agent, 5)
reagents.add_reagent(/datum/reagent/toxin/acid, 5)
+/obj/item/projectile/bullet/dart/catranq/Initialize()
+ . = ..()
+ reagents.add_reagent(/datum/reagent/fermi/furranium, 5) // Turns out I don't even need to give this guy actual tranquilizer chems.
+
/obj/item/projectile/bullet/dart/syringe
name = "syringe"
icon_state = "syringeproj"
diff --git a/code/modules/projectiles/projectile/special/judgement_cut.dm b/code/modules/projectiles/projectile/special/judgement_cut.dm
new file mode 100644
index 0000000000..275bd54a80
--- /dev/null
+++ b/code/modules/projectiles/projectile/special/judgement_cut.dm
@@ -0,0 +1,15 @@
+/obj/item/projectile/judgement_cut
+ name = "judgement cut"
+ icon_state = "judgement_fire"
+ hitsound = 'sound/weapons/judgementfire.ogg'
+ damage = 10
+ damage_type = BRUTE
+ range = 30
+ is_reflectable = FALSE
+ sharpness = SHARP_EDGED
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/judgement_cut
+
+/obj/item/projectile/judgement_cut/on_hit(atom/target, blocked = FALSE)
+ . = ..()
+ if(ishuman(target))
+ new /obj/effect/temp_visual/impact_effect/judgement_cut(src)
diff --git a/code/modules/reagents/chemistry/recipes/others.dm b/code/modules/reagents/chemistry/recipes/others.dm
index 6eb0d5825c..1e9e1aa679 100644
--- a/code/modules/reagents/chemistry/recipes/others.dm
+++ b/code/modules/reagents/chemistry/recipes/others.dm
@@ -741,6 +741,13 @@
required_reagents = list(/datum/reagent/liquid_dark_matter = 5, /datum/reagent/medicine/synaptizine = 10, /datum/reagent/medicine/oculine = 10, /datum/reagent/mutationtoxin = 1)
required_temp = 600
+/datum/chemical_reaction/slimejelly
+ name = "slimejelly"
+ results = list(/datum/reagent/toxin/slimejelly = 5)
+ required_reagents = list(/datum/reagent/oil = 3, /datum/reagent/radium = 2, /datum/reagent/consumable/tinlux = 1)
+ required_container = /obj/item/reagent_containers/food/snacks/grown/mushroom/glowshroom
+ mix_message = "The mushroom's insides bubble and pop and it becomes very limp."
+
/datum/chemical_reaction/slime_extractification
required_reagents = list(/datum/reagent/toxin/slimejelly = 30, /datum/reagent/consumable/frostoil = 5, /datum/reagent/toxin/plasma = 5)
mix_message = "The mixture condenses into a ball."
diff --git a/code/modules/research/nanites/nanite_programs.dm b/code/modules/research/nanites/nanite_programs.dm
index d3cf755de2..946dec3f49 100644
--- a/code/modules/research/nanites/nanite_programs.dm
+++ b/code/modules/research/nanites/nanite_programs.dm
@@ -254,14 +254,14 @@
software_error()
/datum/nanite_program/proc/on_shock(shock_damage)
- if(!program_flags & NANITE_SHOCK_IMMUNE)
+ if(!(program_flags & NANITE_SHOCK_IMMUNE))
if(prob(10))
software_error()
else if(prob(33))
self_destruct()
/datum/nanite_program/proc/on_minor_shock()
- if(!program_flags & NANITE_SHOCK_IMMUNE)
+ if(!(program_flags & NANITE_SHOCK_IMMUNE))
if(prob(10))
software_error()
diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm
index 74ac0fc166..6044e8131d 100644
--- a/code/modules/shuttle/supply.dm
+++ b/code/modules/shuttle/supply.dm
@@ -27,8 +27,6 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
/obj/machinery/syndicatebomb,
/obj/item/hilbertshotel,
/obj/machinery/launchpad,
- /obj/machinery/disposal,
- /obj/structure/disposalpipe,
/obj/item/hilbertshotel,
/obj/machinery/camera,
/obj/item/gps,
diff --git a/code/modules/spells/spell_types/cluwnecurse.dm b/code/modules/spells/spell_types/cluwnecurse.dm
new file mode 100644
index 0000000000..2da87b9e50
--- /dev/null
+++ b/code/modules/spells/spell_types/cluwnecurse.dm
@@ -0,0 +1,36 @@
+/obj/effect/proc_holder/spell/targeted/cluwnecurse
+ name = "Curse of the Cluwne"
+ desc = "This spell dooms the fate of any unlucky soul to the live of a pitiful cluwne, a terrible creature that is hunted for fun."
+ school = "transmutation"
+ charge_type = "recharge"
+ charge_max = 600
+ charge_counter = 0
+ clothes_req = SPELL_WIZARD_GARB
+ stat_allowed = 0
+ invocation = "CLU WO'NIS CA'TE'BEST'IS MAXIMUS!"
+ invocation_type = "shout"
+ range = 3
+ cooldown_min = 75
+ selection_type = "range"
+ var/list/compatible_mobs = list(/mob/living/carbon/human)
+ action_icon = 'icons/mob/actions/actions_spells.dmi'
+ action_icon_state = "cluwne"
+
+/obj/effect/proc_holder/spell/targeted/cluwnecurse/cast(list/targets, mob/user = usr)
+ if(!targets.len)
+ to_chat(user, "No target found in range.")
+ return
+ var/mob/living/carbon/target = targets[1]
+ if(!(target.type in compatible_mobs))
+ to_chat(user, "You are unable to curse [target]!")
+ return
+ if(!(target in oview(range)))
+ to_chat(user, "They are too far away!")
+ return
+ var/mob/living/carbon/human/H = target
+ H.cluwneify()
+
+/datum/action/spell_action/New(Target)
+ ..()
+ var/obj/effect/proc_holder/spell/S = Target
+ icon_icon = S.action_icon
diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm
index 168a12a2ef..d595c494b5 100644
--- a/code/modules/surgery/bodyparts/_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/_bodyparts.dm
@@ -214,6 +214,7 @@
switch(animal_origin)
if(ALIEN_BODYPART,LARVA_BODYPART) //aliens take some additional burn //nothing can burn with so much snowflake code around
burn *= 1.2
+ stamina = 0
/*
// START WOUND HANDLING
diff --git a/code/modules/unit_tests/crafting_recipes.dm b/code/modules/unit_tests/crafting_recipes.dm
new file mode 100644
index 0000000000..33803bd111
--- /dev/null
+++ b/code/modules/unit_tests/crafting_recipes.dm
@@ -0,0 +1,7 @@
+/datum/unit_test/crafting_recipes/Run()
+ for(var/i in GLOB.crafting_recipes)
+ var/datum/crafting_recipe/R = i
+ if(!R.subcategory)
+ Fail("Invalid subcategory on [R] ([R.type]).")
+ if(!R.category && (R.cateogry != CAT_NONE))
+ Fail("Invalid category on [R] ([R.type])")
diff --git a/code/modules/uplink/uplink_items/uplink_bundles.dm b/code/modules/uplink/uplink_items/uplink_bundles.dm
index 9b17162532..cf33c893ad 100644
--- a/code/modules/uplink/uplink_items/uplink_bundles.dm
+++ b/code/modules/uplink/uplink_items/uplink_bundles.dm
@@ -38,7 +38,7 @@
specialised contractor baton, and three randomly selected low cost items. Can include otherwise unobtainable items."
item = /obj/item/storage/box/syndie_kit/contract_kit
cost = 20
- player_minimum = 30
+ player_minimum = 25
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
restricted = TRUE
diff --git a/code/modules/uplink/uplink_items/uplink_clothing.dm b/code/modules/uplink/uplink_items/uplink_clothing.dm
index 5471eb9f31..a9a9050903 100644
--- a/code/modules/uplink/uplink_items/uplink_clothing.dm
+++ b/code/modules/uplink/uplink_items/uplink_clothing.dm
@@ -104,7 +104,7 @@
name = "Mechanical Eyepatch"
desc = "An eyepatch that connects itself to your eye socket, enhancing your shooting to an impossible degree, allowing your bullets to ricochet far more often than usual."
item = /obj/item/clothing/glasses/eyepatch/syndicate
- cost = 8
+ cost = 4
/datum/uplink_item/device_tools/ablative_armwraps
name = "Ablative Armwraps"
diff --git a/code/modules/uplink/uplink_items/uplink_dangerous.dm b/code/modules/uplink/uplink_items/uplink_dangerous.dm
index a8ca068ad2..f13d11736f 100644
--- a/code/modules/uplink/uplink_items/uplink_dangerous.dm
+++ b/code/modules/uplink/uplink_items/uplink_dangerous.dm
@@ -189,7 +189,7 @@
desc = "Though capable of near sorcerous feats via use of hardlight holograms and nanomachines, they require an \
organic host as a home base and source of fuel. Holoparasites come in various types and share damage with their host."
item = /obj/item/storage/box/syndie_kit/guardian
- cost = 15
+ cost = 12
limited_stock = 1 // you can only have one holopara apparently?
refundable = TRUE
cant_discount = TRUE
@@ -204,7 +204,7 @@
desc = "Though capable of near sorcerous feats via use of hardlight holograms and nanomachines, they require an \
organic host as a home base and source of fuel. Holoparasites come in various types and share damage with their host."
item = /obj/item/storage/box/syndie_kit/nukieguardian
- cost = 15
+ cost = 8
refundable = TRUE
surplus = 50
refund_path = /obj/item/guardiancreator/tech/choose/nukie
@@ -228,6 +228,15 @@
surplus = 50
include_modes = list(/datum/game_mode/nuclear)
+/datum/uplink_item/dangerous/maulergauntlets
+ name = "Mauler Gauntlets"
+ desc = "Mauler gauntlets are a pair of high-tech plastitanium gauntlets fused with illegal nanite auto-injectors designed \
+ to grant the wearer sextuple the strength of an average human being. Wearing these, you will punch harder, inflict more injuries \
+ with your fists, and be able to slam people through tables with immense force. \
+ Unfortunately, due to the size of the gloves you will be unable to wield firearms with them equipped."
+ item = /obj/item/clothing/gloves/fingerless/pugilist/mauler
+ cost = 8
+
/datum/uplink_item/dangerous/powerfist
name = "Power Fist"
desc = "The power-fist is a metal gauntlet with a built-in piston-ram powered by an external gas supply.\
@@ -277,3 +286,13 @@
item = /obj/item/gun/ballistic/automatic/toy/pistol/riot
cost = 3
surplus = 10
+
+/datum/uplink_item/dangerous/motivation
+ name = "Motivation"
+ desc = "An ancient blade said to have ties with Lavaland's most inner demons. \
+ Allows you to cut from a far distance!"
+ item = /obj/item/gun/magic/staff/motivation
+ cost = 20
+ player_minimum = 20
+ exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs)
+ cant_discount = TRUE
diff --git a/code/modules/vehicles/cars/car.dm b/code/modules/vehicles/cars/car.dm
index 4545fab2a7..08a7986fa3 100644
--- a/code/modules/vehicles/cars/car.dm
+++ b/code/modules/vehicles/cars/car.dm
@@ -76,11 +76,15 @@
return FALSE
if(occupant_amount() >= max_occupants)
return FALSE
- if(do_mob(forcer, get_enter_delay(M), target = src))
+ var/atom/old_loc = loc
+ if(do_mob(forcer, M, get_enter_delay(M), extra_checks=CALLBACK(src, /obj/vehicle/sealed/car/proc/is_car_stationary, old_loc)))
mob_forced_enter(M, silent)
return TRUE
return FALSE
+/obj/vehicle/sealed/car/proc/is_car_stationary(atom/old_loc)
+ return (old_loc == loc)
+
/obj/vehicle/sealed/car/proc/mob_forced_enter(mob/M, silent = FALSE)
if(!silent)
M.visible_message("[M] is forced into \the [src]!")
diff --git a/code/modules/vending/clothesmate.dm b/code/modules/vending/clothesmate.dm
index fedaeff98c..da3c740a1b 100644
--- a/code/modules/vending/clothesmate.dm
+++ b/code/modules/vending/clothesmate.dm
@@ -212,6 +212,8 @@
/obj/item/clothing/suit/jacket/leather/overcoat = 4,
/obj/item/clothing/under/pants/mustangjeans = 3,
/obj/item/clothing/neck/necklace/dope = 5,
+ /obj/item/clothing/under/costume/swagoutfit = 5,
+ /obj/item/clothing/shoes/swagshoes = 5,
/obj/item/clothing/suit/jacket/letterman_nanotrasen = 5,
/obj/item/clothing/under/misc/corporateuniform = 5,
/obj/item/clothing/suit/hooded/wintercoat/polychromic = 5,
diff --git a/html/changelog.html b/html/changelog.html
index e2d94f4eb5..fe3a0fe1b5 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -50,6 +50,162 @@
-->
+
10 June 2021
+
Arturlang updated:
+
+ - Holoparasites for traitors now cost 12 crystals, for operatives 8, the ricochet eyepath traitor item now 4.
+
+
DrPainis updated:
+
+ - goliath calamari
+ - cat meteors
+
+
Linzolle updated:
+
+ - cults can build in maintenance (and other small areas) again.
+ - centcom can no longer be selected as the target area for narsie to be summoned??????
+
+
MrJWhit updated:
+
+ - Moves medical holodeck to the restricted category
+
+
SandPoot updated:
+
+ - Uses some of the existing images for the typing indicators.
+ - Fixes soulstone shard not working for non-cultists.
+
+
WanderingFox95 updated:
+
+ - A random event for the cat surgeon to invade the station. Listen for scary noises!
+ - Screaming Cat SFX, you know, for the mood.
+
+
bunny232 updated:
+
+ - Atmos resin now properly prevents all atmos from moving
+ - Air tanks now properly have a 21/79 o2/n2 mix
+ - Hydroponics can now make 5u of slimejelly by injecting 3 oil, 2 radium and 1 tinea luxor into a glowshroom
+
+
keronshb updated:
+
+ - Made it so Off Balance only disarms if they're shoved into a wall or person.
+ - Reduced Off Balance time to 2 seconds.
+ - Pierced Realities despawn after 3 minutes and 15 seconds, new unresearched realities spawn in after that time elsewhere to help other heretics get back into the game.
+ - A required sacrifice amount for heretic's second to last and last powers are added to discourage only rushing for holes.
+ - An announcement automatically plays to everyone that there's a heretic gunning for ascension upon learning the 2nd to last power
+ - Blade Shatters are now used in hand other than with a HUD icon tweak: Adjusted some TGUI menus for the book to reflect how many sacrifices a heretic has and how many are required for certain powers
+ - Fixes sprite issue for Void Cloak for people who have digigrade legs.
+ - Fixes the Raw Prophet recipe to match the description
+ - Lets the Cargo Shuttle use Disposal Pipes again
+ - Adds motivation and adds it to the uplink
+ - Adds Judgement Cut projectiles
+ - Adds Judgement Cut hit effects and firing effects.
+ - added sounds for the firing and hit sounds of Judgement Cuts, created by @dzahlus
+ - Adds Floor Cluwnes and event for midround
+ - Adds Cluwne mutation
+ - Adds Cluwne spell
+ - Adds Cluwnes
+ - Adds Cluwne Mask + shoes
+ - Adds Floor Cluwne spawn button
+ - Adds Cluwne smite button
+
+
zeroisthebiggay updated:
+
+ - Fixed an exploit allowing you to grab people from anywhere with a clowncar.
+ - revenant essence objective reduced
+
+
+
06 June 2021
+
bunny232 updated:
+
+ - Pools are capable of mist at lower temperatures
+
+
+
05 June 2021
+
Arturlang updated:
+
+ - float sanity now makes it not actually run if it's actively being thrown
+
+
coderbus13 updated:
+
+ - Pubby's toxins injector now starts at 200L, like it does on other maps
+
+
zeroisthebiggay updated:
+
+ - light floppy dog ears
+
+
+
04 June 2021
+
MrJWhit updated:
+
+
Putnam3145 updated:
+
+ - sniper rifle doesn't ruin your round instantly now
+
+
+
03 June 2021
+
MrJWhit updated:
+
+ - Removed some debug tiles on the xenoruin.
+
+
TripleShades updated:
+
+ - Added a camera to both solar entryways
+ - Added an intercom to toxin's launch for the doppler
+ - The fake nuke auth disk in the library
+
+
+
29 May 2021
+
Kraseo updated:
+
+ - No more slamming into people while bloodcrawled.
+
+
Linzolle updated:
+
+ - brand intelligence event works again
+
+
keronshb updated:
+
+ - swag outfit available in clothesmate
+ - swag shoes availble in clothesmate resprite: changed swag shoes icon to the one twaticus made.
+ - Adds the clown mob spawner for admins
+
+
zeroisthebiggay updated:
+
+ - puglism damage can no longer stack with scarp
+
+
+
26 May 2021
+
bunny232 updated:
+
+ - Removed two random 'captain's office' tiles from space on meta station
+
+
+
24 May 2021
+
zeroisthebiggay updated:
+
+ - New traitor item: the Mauler Gauntlets! Punch hard, punch good! Eight telecrystals, buy today!
+ - hairs from Airborne Snitch
+
+
+
23 May 2021
+
Putnam3145 updated:
+
+ - Antag and species no longer remove all traits if one has a blacklisted trait
+
+
WanderingFox95 updated:
+
+ - Replaced the antlers showing up when you select deer ears with actual deer ears. Literally why was that even a thing before?
+ - Straight rabbit ears are now a thing.
+
+
keronshb updated:
+
+ - 30 > 25 pop req for contractor kit
+ - adds a special hud for simple mobs.
+ - a lot of >32x32 mobs now have icons for their health dolls
+
+
21 May 2021
Putnam3145 updated:
@@ -446,290 +602,6 @@
- makes AGE_VERIFICATION option off by default
-
- 09 April 2021
- BlueWildrose updated:
-
- - The genetics mutation Autotomy has been buffed to be 20 instability instead of 30, and harmless in delimbing.
- - There are now three more pills in each breast or penis enlargement pill bottle. tweak: There are now 10 pill bottles of breast and penis enlargement pill bottles in a Kinkmate instead of 5.
- - Because of such changes that increases their amount in the kinkmate, succubus milk and incubus draft values are reduced to RARE from VERY_RARE.
- - Grammar correction on titty pill bottle.
- - The pandemic machine can now let you swap containers.
- - Slime puddles will now show mutation visual indicators & cult indicators after exiting slime puddle form
- - Slime puddle transformation animations are now resized to fit the slimeperson's current size, making it visually more consistent
- - Typo correction in some mutation descriptions and other things
- - Cult/clockcult layers moved from LAYER_MUTATION to LAYER_ANTAG, new update section for them specifically now
- - Sylvan and Mushroom languages are now tongueless, and Encoded Audio Language is now learnable.
-
- SandPoot updated:
-
- - The dragons_blood "lizard with the appearance of a drake" no longer wipes important stuff.
- - Fixes Ashlizard legs not being digitigrade and makes them have the "Sharp" snout.
- - Machines that open no longer drop their stock parts.
-
- brokenOculus updated:
-
- - Added Telescopic Baseball Bat
- - Added Telescopic Baseball Bat to Stealthy uplink items
- - Added sprites for Telescopic Baseball Bat
- - Added Telescopic Baseball Bat to Baseball kit under uplink bundles
-
-
- 07 April 2021
- LetterN updated:
-
- - Perln generation & biomes from lavaland
- - Cleans up the area, update it's icon and updates the openspace to use the modules.
-
-
- 06 April 2021
- ArcaneMusic updated:
-
- - Prevents people from lagging the server by growing HUMANS FROM CABBAGE!
-
- BlueWildrose updated:
-
- - Admins get to hear the prayer ding again unless they have prayer sounds turned off.
-
- DeltaFire15 updated:
-
- - The wood plank cargo pack no longer is named incorrectly.
-
- Putnam3145 updated:
-
- - forced climax doesn't do a climax-with
-
- SandPoot updated:
-
- - Reverts locker/crate behavior for attacking it with an item while closed (use any intent other than help to bash it).
- - Laptop interactions are no longer weird and now you can drag it to yourself to pick it up. tweak: Ctrl+Shift-Click to toggle laptops open/closed. tweak: More examine info for laptops.
- - Lockers/Crates can now be deconstructed the right way respecting the cutting_tool (even if it's not one of the default interactions).
- - Dragging the laptop into itself shouldn't do anything anymore (kind of pointless and hard to do).
-
-
- 04 April 2021
- Hatterhat updated:
-
- - After a sudden crash in the tower-cap log slash wooden plank economy, NanoTrasen has decided to stop selling tower-cap logs to Cargo.
-
-
- 03 April 2021
- BlueWildrose updated:
-
- - The hydroponics pet bee, Bumbles no longer has a number besides their name.
-
- Putnam3145 updated:
-
- - "Destroy all nanotrasen cloning machines" objective is gone
- - Removed all the commented-out sabotage objectives (we can just get them from history)
- - Observe verb logging
-
-
- 02 April 2021
- LetterN updated:
-
-
- 29 March 2021
- BlueWildrose updated:
-
- - Fixed being unable to fix suit sensors if damaged at all unless destroyed completely
-
- YakumoChen updated:
-
- - A less-than-new Syndicate bundle that reminds you of the good old days when we didn't need all those newfangled traitor items the young-uns get. We had 6 items in the uplink and we had Monkey in rotation and by god we made do.
-
- qweq12yt updated:
-
- - Added Earmuffs
- - Added Random Drink
- - Added Clear PDA
- - Added Internals Box
- - Added Meson Goggles
- - Added Smoke Grenade
-
- silicons updated:
-
- - automated hydroponics system design now works properly
-
-
- 28 March 2021
- CuteMoff updated:
-
- - Changed Strength Modifier from the default (1.0) too .7
-
- Hatterhat updated:
-
- - As a heretic, shattering your blade no longer interferes with bluespace.
-
- Putnam3145 updated:
-
- - Threat tracking is now universal, rather than dynamic-only
- - Slaughter demon event now increases weight based on how much blood there is.
-
- R3dtail updated:
-
- - Removed ichor creates
- - Removed ichor crates and adjusted crate rolling appropriately
- - Removed the bonespear from the blackmarket uplink, and made EMP grenades harder to get from the same item.
- - Added a description to the black market uplink
-
- Shadow-Quill updated:
-
- - Added small versions of the walk icon for all hud styles, except Retro.
-
- dzahlus updated:
-
- - Added radial menu to joy mask for alt reskins
- - added pensive, angry and flushed sprites to joy mask
-
- keronshb updated:
-
- - Radioactive microlasers can no longer knock out creatures who are immune to the effects of radiation.
- - The radioactive microlaser now calculates the strength of its delay effect using the intensity setting it had when you initially used it on your victim, not the intensity setting it currently has. This prevents people from "cheating out" its intensity 20 effect with only a 2 second delay and a 1 second cooldown.
- - Radioactive microlasers no longer contain twice as much metal as normal health analyzers do.
-
- necromanceranne updated:
-
- - Replaces the useless bullet and laser shields with new Kinetic and Ablative shields, which do as they advertise.
- - Replaces the shield implants shield with a hardlight shield that can take large amounts of brute damage, but disintegrates when shot with disablers.
- - Fixes Fake Roman Shields being able to be used as normal riot shields.
- - Fixes nonlethal/non-physical damage types destroying shields. (stamina, toxins, oxygen, clone, brain)
- - Fixes tower shields not doing anything, while also giving them intergrity to match their advertised durability.
- - Uses additional flags to determine what kind effects work well and what works poorly against various shields.
-
- timothyteakettle updated:
-
- - ghost cafe residents can now disguise themselves as any mob or object
- - fixes character preview not updating when selecting the loadout tab
-
- zeroisthebiggay updated:
-
-
- 26 March 2021
- BlueWildrose updated:
-
- - Clothing no longer drops when shredded. It just becomes useless.
- - Suit sensors are guaranteed to short out when the clothes become shredded, not damaged now.
- - Uniform limb integrity increased from 30 to 120.
- - Suit sensor damage has been added. The more damaged your suit sensors get, the less features that will be available from these suit sensors. It takes two e-sword hits to ruin your tracking beacon for instance. tweak: Examine text on uniforms is now more clear about needing cable coil to repair your suit sensors.
- - Fixed prisoner uniform sprite paths
-
- CuteMoff updated:
-
- - Diamond's forcemod was changed from 1.1x to 1.2x
-
- Hatterhat updated:
-
- - Lever-action rifles, chambered in .38, are now sitting in the code. They might be buyable from Cargo or the Black Market soon. Watch this space.
- - Sawed-off shotguns now look like shotguns, but short, when inhand, instead of "generic gun".
-
- timothyteakettle updated:
-
- - slimes can be delimbed
- - the loadout now colours pet collars correctly
-
-
- 25 March 2021
- zeroisthebiggay updated:
-
- - strained muscles isn't free
-
-
- 24 March 2021
- BlueWildrose updated:
-
- - The nightmare's light eater can now destroy messes that emit light, like glowing goo or ectoplasmic puddles.
-
- Hatterhat updated:
-
- - The NOGUNS trait now takes precedence over the triggerguard checks.
- - Medicated sutures and advanced regenerative mesh are now easier to make. Reagent-quantity wise, anyway.
-
- ItzGabby updated:
-
- - Fluff Items with polychromic support
- - A new vendor called Bark box
- - A new form of snack with it's own box
- - Two harness, one of them being lewd
- - One new collar, with a ribbon. Classy.
- - More locked forms of collars
- - Purged old balls
- - Removed the funny buffs each colored tennis ball had, down with the powergame!
- - Added polychromic fluff icons, vendor icons, suit icons, snack icons, fancy box icons, and a polychromic version of Izzy's ball.
- - Deleted old balls, Izzy's Ball, except the rainbow one since it's special and as I did not go out of my way to get permission to touch.
- - Walked into vending.dm and glared for a moment at hydroponics' grammar.
-
- LetterN updated:
-
- - fixed laptops pickability
- - fixed closets being unweldable
-
- YakumoChen updated:
-
- - Genetics - Thermal vision is a recipe instead of a natural gene now. Nearsighted+Stimmed. Other minor nerfs, Thermal is 40 instability.
- - Research - X-ray eyes are now an illegal tech.
-
- qweq12yt updated:
-
- - added the black market uplink
- - added blackmarket.dmi
- - increased the black market interface's width, now the delivery options will show properly when the LTSRBT is built
-
- zeroisthebiggay updated:
-
- - biodegrade works on legcuffs
-
-
- 23 March 2021
- LetterN updated:
-
- - NIRM departamental purchases now work. Have fun spending the entire R&D Budget!
-
-
- 21 March 2021
- Arturlang updated:
-
- - Vampire statpanel no longer shows spans unnecesary
-
- GrayRachnid updated:
-
- - fixed the holopad autocall bug
- - properly incorporated the secure holopad that was commented out in the code.
- - the in_character_filter.txt is now usable
- - headmins should edit the in_character_filter.txt
- - someone with box access should delete racism with the in_character_filter.txt
- - buffed particle defender disabler shots from 13->15 stamina (15*6=90)
- - buffed particle defender laser ammo to 4 shots
-
- Hatterhat updated:
-
- - removes pacifism from ghost cafe. have fun beating up your coworkers
-
- LetterN updated:
-
- - Art gallery (meta)
- - Laptop vendor (meta, delta, box)
-
- Putnam3145 updated:
-
- - Buffed supermatter surge massively.
-
- The-Sun-In-Splendour updated:
-
- - You cannot revive yourself (as a changeling) if you've been absorbed anymore
-
- dzahlus updated:
-
- - rebalanced hierophant STAFF to do 15 damage on all attacks
-
- timothyteakettle updated:
-
- - using the puddle ability when stunned wont break it
-
GoonStation 13 Development Team
diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml
index 135e6db518..cb669eb064 100644
--- a/html/changelogs/.all_changelog.yml
+++ b/html/changelogs/.all_changelog.yml
@@ -29332,3 +29332,114 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
2021-05-21:
Putnam3145:
- bugfix: Fixed activity being attached to minds instead of mobs on antag attach.
+2021-05-23:
+ Putnam3145:
+ - bugfix: Antag and species no longer remove all traits if one has a blacklisted
+ trait
+ WanderingFox95:
+ - imageadd: Replaced the antlers showing up when you select deer ears with actual
+ deer ears. Literally why was that even a thing before?
+ - imageadd: Straight rabbit ears are now a thing.
+ keronshb:
+ - balance: 30 > 25 pop req for contractor kit
+ - code_imp: adds a special hud for simple mobs.
+ - imageadd: a lot of >32x32 mobs now have icons for their health dolls
+2021-05-24:
+ zeroisthebiggay:
+ - rscadd: 'New traitor item: the Mauler Gauntlets! Punch hard, punch good! Eight
+ telecrystals, buy today!'
+ - rscadd: hairs from Airborne Snitch
+2021-05-26:
+ bunny232:
+ - bugfix: Removed two random 'captain's office' tiles from space on meta station
+2021-05-29:
+ Kraseo:
+ - bugfix: No more slamming into people while bloodcrawled.
+ Linzolle:
+ - bugfix: brand intelligence event works again
+ keronshb:
+ - rscadd: swag outfit available in clothesmate
+ - rscadd: 'swag shoes availble in clothesmate resprite: changed swag shoes icon
+ to the one twaticus made.'
+ - rscadd: Adds the clown mob spawner for admins
+ zeroisthebiggay:
+ - balance: puglism damage can no longer stack with scarp
+2021-06-03:
+ MrJWhit:
+ - balance: Removed some debug tiles on the xenoruin.
+ TripleShades:
+ - rscadd: Added a camera to both solar entryways
+ - rscadd: Added an intercom to toxin's launch for the doppler
+ - rscdel: The fake nuke auth disk in the library
+2021-06-04:
+ MrJWhit:
+ - rscadd: Adds a missing pipe
+ Putnam3145:
+ - bugfix: sniper rifle doesn't ruin your round instantly now
+2021-06-05:
+ Arturlang:
+ - code_imp: float sanity now makes it not actually run if it's actively being thrown
+ coderbus13:
+ - bugfix: Pubby's toxins injector now starts at 200L, like it does on other maps
+ zeroisthebiggay:
+ - rscadd: light floppy dog ears
+2021-06-06:
+ bunny232:
+ - rscadd: Pools are capable of mist at lower temperatures
+2021-06-10:
+ Arturlang:
+ - balance: Holoparasites for traitors now cost 12 crystals, for operatives 8, the
+ ricochet eyepath traitor item now 4.
+ DrPainis:
+ - rscadd: goliath calamari
+ - rscadd: cat meteors
+ Linzolle:
+ - bugfix: cults can build in maintenance (and other small areas) again.
+ - bugfix: centcom can no longer be selected as the target area for narsie to be
+ summoned??????
+ MrJWhit:
+ - balance: Moves medical holodeck to the restricted category
+ SandPoot:
+ - code_imp: Uses some of the existing images for the typing indicators.
+ - bugfix: Fixes soulstone shard not working for non-cultists.
+ WanderingFox95:
+ - rscadd: A random event for the cat surgeon to invade the station. Listen for scary
+ noises!
+ - soundadd: Screaming Cat SFX, you know, for the mood.
+ bunny232:
+ - bugfix: Atmos resin now properly prevents all atmos from moving
+ - bugfix: Air tanks now properly have a 21/79 o2/n2 mix
+ - rscadd: Hydroponics can now make 5u of slimejelly by injecting 3 oil, 2 radium
+ and 1 tinea luxor into a glowshroom
+ keronshb:
+ - balance: Made it so Off Balance only disarms if they're shoved into a wall or
+ person.
+ - balance: Reduced Off Balance time to 2 seconds.
+ - balance: Pierced Realities despawn after 3 minutes and 15 seconds, new unresearched
+ realities spawn in after that time elsewhere to help other heretics get back
+ into the game.
+ - balance: A required sacrifice amount for heretic's second to last and last powers
+ are added to discourage only rushing for holes.
+ - balance: An announcement automatically plays to everyone that there's a heretic
+ gunning for ascension upon learning the 2nd to last power
+ - balance: 'Blade Shatters are now used in hand other than with a HUD icon tweak:
+ Adjusted some TGUI menus for the book to reflect how many sacrifices a heretic
+ has and how many are required for certain powers'
+ - bugfix: Fixes sprite issue for Void Cloak for people who have digigrade legs.
+ - bugfix: Fixes the Raw Prophet recipe to match the description
+ - balance: Lets the Cargo Shuttle use Disposal Pipes again
+ - rscadd: Adds motivation and adds it to the uplink
+ - rscadd: Adds Judgement Cut projectiles
+ - rscadd: Adds Judgement Cut hit effects and firing effects.
+ - soundadd: added sounds for the firing and hit sounds of Judgement Cuts, created
+ by @dzahlus
+ - rscadd: Adds Floor Cluwnes and event for midround
+ - rscadd: Adds Cluwne mutation
+ - rscadd: Adds Cluwne spell
+ - rscadd: Adds Cluwnes
+ - imageadd: Adds Cluwne Mask + shoes
+ - admin: Adds Floor Cluwne spawn button
+ - admin: Adds Cluwne smite button
+ zeroisthebiggay:
+ - bugfix: Fixed an exploit allowing you to grab people from anywhere with a clowncar.
+ - balance: revenant essence objective reduced
diff --git a/html/changelogs/AutoChangeLog-pr-14768.yml b/html/changelogs/AutoChangeLog-pr-14768.yml
new file mode 100644
index 0000000000..007ecd6f58
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-14768.yml
@@ -0,0 +1,4 @@
+author: "silicons"
+delete-after: True
+changes:
+ - bugfix: "xenos are now truly immune to stamina damage."
diff --git a/icons/effects/camera_image_base.dmi b/icons/effects/camera_image_base.dmi
new file mode 100644
index 0000000000..4f5867e07e
Binary files /dev/null and b/icons/effects/camera_image_base.dmi differ
diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi
index 4038a384fd..2614e35211 100644
Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ
diff --git a/icons/mob/actions/actions_spells.dmi b/icons/mob/actions/actions_spells.dmi
index 72e72ad6f3..9c2a30031e 100644
Binary files a/icons/mob/actions/actions_spells.dmi and b/icons/mob/actions/actions_spells.dmi differ
diff --git a/icons/mob/clothing/feet.dmi b/icons/mob/clothing/feet.dmi
index d93543805b..df40636049 100644
Binary files a/icons/mob/clothing/feet.dmi and b/icons/mob/clothing/feet.dmi differ
diff --git a/icons/mob/clothing/feet_digi.dmi b/icons/mob/clothing/feet_digi.dmi
index 43244e99b9..7215875f2c 100644
Binary files a/icons/mob/clothing/feet_digi.dmi and b/icons/mob/clothing/feet_digi.dmi differ
diff --git a/icons/mob/clothing/hands.dmi b/icons/mob/clothing/hands.dmi
index 406b0fe62a..5155f06134 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 c237feed29..f3f2eaa90b 100644
Binary files a/icons/mob/clothing/head.dmi and b/icons/mob/clothing/head.dmi differ
diff --git a/icons/mob/clothing/mask.dmi b/icons/mob/clothing/mask.dmi
index d06f9cf899..60c2e34b39 100644
Binary files a/icons/mob/clothing/mask.dmi and b/icons/mob/clothing/mask.dmi differ
diff --git a/icons/mob/clothing/mask_muzzled.dmi b/icons/mob/clothing/mask_muzzled.dmi
index 807d944172..9da3545c65 100644
Binary files a/icons/mob/clothing/mask_muzzled.dmi and b/icons/mob/clothing/mask_muzzled.dmi differ
diff --git a/icons/mob/clothing/uniform.dmi b/icons/mob/clothing/uniform.dmi
index f2611b3ab7..fd4ded6ad8 100644
Binary files a/icons/mob/clothing/uniform.dmi and b/icons/mob/clothing/uniform.dmi differ
diff --git a/icons/mob/clothing/uniform_digi.dmi b/icons/mob/clothing/uniform_digi.dmi
index 98ec436b86..cbda1ab616 100644
Binary files a/icons/mob/clothing/uniform_digi.dmi and b/icons/mob/clothing/uniform_digi.dmi differ
diff --git a/icons/mob/hair.dmi b/icons/mob/hair.dmi
index 7322b2cfaf..55c79b9740 100644
Binary files a/icons/mob/hair.dmi and b/icons/mob/hair.dmi differ
diff --git a/icons/mob/screen_gen.dmi b/icons/mob/screen_gen.dmi
index 95aaf330ce..4377a0d7c6 100644
Binary files a/icons/mob/screen_gen.dmi and b/icons/mob/screen_gen.dmi differ
diff --git a/icons/mob/talk_64x64.dmi b/icons/mob/talk_64x64.dmi
new file mode 100644
index 0000000000..a9c759985d
Binary files /dev/null and b/icons/mob/talk_64x64.dmi differ
diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi
index 629b989520..25cde38df9 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 6b0dc9e63e..f20dc86be5 100644
Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ
diff --git a/icons/obj/clothing/masks.dmi b/icons/obj/clothing/masks.dmi
index 9f1c0cbd2a..532d4f5df7 100644
Binary files a/icons/obj/clothing/masks.dmi and b/icons/obj/clothing/masks.dmi differ
diff --git a/icons/obj/clothing/shoes.dmi b/icons/obj/clothing/shoes.dmi
index aee67da199..bde07bd54d 100644
Binary files a/icons/obj/clothing/shoes.dmi and b/icons/obj/clothing/shoes.dmi differ
diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi
index 6171e032dd..2bbe93a410 100644
Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ
diff --git a/icons/obj/items_and_weapons.dmi b/icons/obj/items_and_weapons.dmi
index 239a95ce5e..112d6f78ca 100644
Binary files a/icons/obj/items_and_weapons.dmi and b/icons/obj/items_and_weapons.dmi differ
diff --git a/icons/obj/meteor.dmi b/icons/obj/meteor.dmi
index 84faabcc18..7c91a74004 100644
Binary files a/icons/obj/meteor.dmi and b/icons/obj/meteor.dmi differ
diff --git a/icons/obj/projectiles.dmi b/icons/obj/projectiles.dmi
index 740c64b1dc..59f0362203 100644
Binary files a/icons/obj/projectiles.dmi and b/icons/obj/projectiles.dmi differ
diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi
index 19d4dca13d..e1b128e10b 100644
Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ
diff --git a/modular_citadel/code/modules/client/loadout/__donator.dm b/modular_citadel/code/modules/client/loadout/__donator.dm
index 0c59c3e711..39ed9d6ec8 100644
--- a/modular_citadel/code/modules/client/loadout/__donator.dm
+++ b/modular_citadel/code/modules/client/loadout/__donator.dm
@@ -550,7 +550,7 @@
ckeywhitelist = list("sneka")
/datum/gear/donator/smaiden
- name = "Shrine Maiden"
- slot = SLOT_WEAR_SUIT
- path = /obj/item/clothing/suit/smaiden
+ name = "shrine maiden outfit"
+ slot = SLOT_W_UNIFORM
+ path = /obj/item/clothing/under/smaiden
ckeywhitelist = list("ultimarifox")
diff --git a/modular_citadel/code/modules/client/loadout/head.dm b/modular_citadel/code/modules/client/loadout/head.dm
index d1c2c69b99..6d6c803ef1 100644
--- a/modular_citadel/code/modules/client/loadout/head.dm
+++ b/modular_citadel/code/modules/client/loadout/head.dm
@@ -114,13 +114,21 @@
restricted_desc = "Heads of Staff"
restricted_roles = list("Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Research Director", "Chief Medical Officer", "Quartermaster")
-/datum/gear/head/orvkepiops
- name = "Federation Kepi, ops/sec"
+/datum/gear/head/orvkepieng
+ name = "Federation Kepi, eng"
description = "A visored cap. Intended to be used with ORV uniform."
- path = /obj/item/clothing/head/kepi/orvi/engsec
+ path = /obj/item/clothing/head/kepi/orvi/eng
subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS
- restricted_desc = "Engineering, Security and Cargo"
- restricted_roles = list("Chief Engineer", "Atmospheric Technician", "Station Engineer", "Warden", "Detective", "Security Officer", "Head of Security", "Cargo Technician", "Shaft Miner", "Quartermaster")
+ restricted_desc = "Engineering"
+ restricted_roles = list("Chief Engineer", "Atmospheric Technician", "Station Engineer")
+
+/datum/gear/head/orvkepisec
+ name = "Federation Kepi, sec"
+ description = "A visored cap. Intended to be used with ORV uniform."
+ path = /obj/item/clothing/head/kepi/orvi/sec
+ subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS
+ restricted_desc = "Security"
+ restricted_roles = list("Warden", "Detective", "Security Officer", "Head of Security")
/datum/gear/head/orvkepimedsci
name = "Federation Kepi, medsci"
@@ -135,8 +143,8 @@
description = "A visored cap. Intended to be used with ORV uniform."
path = /obj/item/clothing/head/kepi/orvi/service
subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS
- restricted_desc = "Service and Civilian, barring Clown, Mime and Lawyer"
- restricted_roles = list("Assistant", "Bartender", "Botanist", "Cook", "Curator", "Janitor", "Chaplain")
+ restricted_desc = "Service, Cargo and Civilian, barring Clown, Mime and Lawyer"
+ restricted_roles = list("Bartender", "Botanist", "Cook", "Curator", "Janitor", "Chaplain", "Cargo Technician", "Shaft Miner")
/datum/gear/head/orvkepiass
name = "Federation Kepi, assistant"
diff --git a/modular_citadel/code/modules/client/loadout/uniform.dm b/modular_citadel/code/modules/client/loadout/uniform.dm
index 945e0dfe12..86fcc867a3 100644
--- a/modular_citadel/code/modules/client/loadout/uniform.dm
+++ b/modular_citadel/code/modules/client/loadout/uniform.dm
@@ -588,18 +588,31 @@
subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_roles = list("Chief Medical Officer", "Research Director")
-/datum/gear/uniform/orvops
- name = "ORV uniform, ops/sec"
- path = /obj/item/clothing/under/trek/engsec/orv
+/datum/gear/uniform/orvsec
+ name = "ORV uniform, sec"
+ path = /obj/item/clothing/under/trek/sec/orv
subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
- restricted_desc = "Engineering, Security and Cargo"
- restricted_roles = list("Chief Engineer", "Atmospheric Technician", "Station Engineer", "Warden", "Detective", "Security Officer", "Head of Security", "Cargo Technician", "Shaft Miner", "Quartermaster")
+ restricted_desc = "Security"
+ restricted_roles = list("Warden", "Detective", "Security Officer", "Head of Security")
-/datum/gear/uniform/orvcmd_ops
- name = "ORV uniform, ops/sec, cmd"
- path = /obj/item/clothing/under/trek/command/orv/engsec
+/datum/gear/uniform/orveng
+ name = "ORV uniform, eng"
+ path = /obj/item/clothing/under/trek/eng/orv
subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
- restricted_roles = list("Chief Engineer", "Head of Security")
+ restricted_desc = "Engineering"
+ restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer")
+
+/datum/gear/uniform/orvcmd_sec
+ name = "ORV uniform, sec, cmd"
+ path = /obj/item/clothing/under/trek/command/orv/sec
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
+ restricted_roles = list("Head of Security")
+
+/datum/gear/uniform/orvcmd_eng
+ name = "ORV uniform, eng, cmd"
+ path = /obj/item/clothing/under/trek/command/orv/eng
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
+ restricted_roles = list("Chief Engineer")
/datum/gear/uniform/orvass
name = "ORV uniform, assistant"
@@ -608,11 +621,11 @@
restricted_roles = list("Assistant")
/datum/gear/uniform/orvsrv
- name = "ORV uniform, service"
+ name = "ORV uniform, other"
path = /obj/item/clothing/under/trek/orv/service
subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
- restricted_roles = list("Assistant", "Bartender", "Botanist", "Cook", "Curator", "Janitor", "Chaplain")
- restricted_desc = "Service and Civilian, barring Clown, Mime and Lawyer"
+ restricted_roles = list("Bartender", "Botanist", "Cook", "Curator", "Janitor", "Chaplain", "Cargo Technician", "Shaft Miner")
+ restricted_desc = "Service, Cargo and Civilian, barring Clown, Mime and Lawyer"
//Memes
/datum/gear/uniform/gear_harnesses
diff --git a/modular_citadel/code/modules/clothing/trek.dm b/modular_citadel/code/modules/clothing/trek.dm
index dd02a6d0f8..cf422053c7 100644
--- a/modular_citadel/code/modules/clothing/trek.dm
+++ b/modular_citadel/code/modules/clothing/trek.dm
@@ -172,8 +172,11 @@
/obj/item/clothing/head/kepi/orvi/command
icon_state = "kepi_com"
-/obj/item/clothing/head/kepi/orvi/engsec
- icon_state = "kepi_ops"
+/obj/item/clothing/head/kepi/orvi/sec
+ icon_state = "kepi_sec"
+
+/obj/item/clothing/head/kepi/orvi/eng
+ icon_state = "kepi_eng"
/obj/item/clothing/head/kepi/orvi/medsci
icon_state = "kepi_medsci"
diff --git a/modular_citadel/code/modules/custom_loadout/custom_items.dm b/modular_citadel/code/modules/custom_loadout/custom_items.dm
index 89734106cf..b7d04e0780 100644
--- a/modular_citadel/code/modules/custom_loadout/custom_items.dm
+++ b/modular_citadel/code/modules/custom_loadout/custom_items.dm
@@ -602,8 +602,8 @@
mob_overlay_icon = 'icons/mob/clothing/custom_w.dmi'
icon_state = "mmask"
-/obj/item/clothing/suit/smaiden
- name = "shrine maiden"
+/obj/item/clothing/under/smaiden
+ name = "shrine maiden outfit"
desc = "Seems questionably tight for religious purposes."
icon_state = "smaiden"
item_state = "smaiden"
diff --git a/modular_citadel/icons/mob/mam_ears.dmi b/modular_citadel/icons/mob/mam_ears.dmi
index a8209f25c5..51541619d4 100644
Binary files a/modular_citadel/icons/mob/mam_ears.dmi and b/modular_citadel/icons/mob/mam_ears.dmi differ
diff --git a/sound/effects/bodyscrape-01.ogg b/sound/effects/bodyscrape-01.ogg
new file mode 100644
index 0000000000..48c7563412
Binary files /dev/null and b/sound/effects/bodyscrape-01.ogg differ
diff --git a/sound/effects/bodyscrape-02.ogg b/sound/effects/bodyscrape-02.ogg
new file mode 100644
index 0000000000..b870b5d7b0
Binary files /dev/null and b/sound/effects/bodyscrape-02.ogg differ
diff --git a/sound/effects/cluwne_feast.ogg b/sound/effects/cluwne_feast.ogg
new file mode 100644
index 0000000000..47c23e6445
Binary files /dev/null and b/sound/effects/cluwne_feast.ogg differ
diff --git a/sound/misc/bikehorn_creepy.ogg b/sound/misc/bikehorn_creepy.ogg
new file mode 100644
index 0000000000..7fb3290f5c
Binary files /dev/null and b/sound/misc/bikehorn_creepy.ogg differ
diff --git a/sound/misc/catscream.ogg b/sound/misc/catscream.ogg
new file mode 100644
index 0000000000..831767730e
Binary files /dev/null and b/sound/misc/catscream.ogg differ
diff --git a/sound/misc/cluwne_breathing.ogg b/sound/misc/cluwne_breathing.ogg
new file mode 100644
index 0000000000..30de4d7931
Binary files /dev/null and b/sound/misc/cluwne_breathing.ogg differ
diff --git a/sound/misc/floor_cluwne_emerge.ogg b/sound/misc/floor_cluwne_emerge.ogg
new file mode 100644
index 0000000000..cf8254fc21
Binary files /dev/null and b/sound/misc/floor_cluwne_emerge.ogg differ
diff --git a/sound/misc/honk_echo_distant.ogg b/sound/misc/honk_echo_distant.ogg
new file mode 100644
index 0000000000..32e95884bc
Binary files /dev/null and b/sound/misc/honk_echo_distant.ogg differ
diff --git a/sound/voice/cluwnelaugh1.ogg b/sound/voice/cluwnelaugh1.ogg
new file mode 100644
index 0000000000..6a128cf3a3
Binary files /dev/null and b/sound/voice/cluwnelaugh1.ogg differ
diff --git a/sound/voice/cluwnelaugh2.ogg b/sound/voice/cluwnelaugh2.ogg
new file mode 100644
index 0000000000..e118709ce2
Binary files /dev/null and b/sound/voice/cluwnelaugh2.ogg differ
diff --git a/sound/voice/cluwnelaugh2_reversed.ogg b/sound/voice/cluwnelaugh2_reversed.ogg
new file mode 100644
index 0000000000..5dc7e9b7c3
Binary files /dev/null and b/sound/voice/cluwnelaugh2_reversed.ogg differ
diff --git a/sound/voice/cluwnelaugh3.ogg b/sound/voice/cluwnelaugh3.ogg
new file mode 100644
index 0000000000..5ff795c94c
Binary files /dev/null and b/sound/voice/cluwnelaugh3.ogg differ
diff --git a/sound/weapons/judgementfire.ogg b/sound/weapons/judgementfire.ogg
new file mode 100644
index 0000000000..f356a094de
Binary files /dev/null and b/sound/weapons/judgementfire.ogg differ
diff --git a/sound/weapons/judgementhit.ogg b/sound/weapons/judgementhit.ogg
new file mode 100644
index 0000000000..23816a537f
Binary files /dev/null and b/sound/weapons/judgementhit.ogg differ
diff --git a/sound/weapons/mauler_punch.ogg b/sound/weapons/mauler_punch.ogg
new file mode 100644
index 0000000000..3e610ea238
Binary files /dev/null and b/sound/weapons/mauler_punch.ogg differ
diff --git a/tgstation.dme b/tgstation.dme
index df3bb258c7..50e7e52b76 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -273,6 +273,7 @@
#include "code\_onclick\hud\revenanthud.dm"
#include "code\_onclick\hud\robot.dm"
#include "code\_onclick\hud\screen_objects.dm"
+#include "code\_onclick\hud\simple_animal.dm"
#include "code\_onclick\hud\swarmer.dm"
#include "code\_onclick\hud\screen_objects\clickdelay.dm"
#include "code\_onclick\hud\screen_objects\sprint.dm"
@@ -682,6 +683,7 @@
#include "code\datums\mutations\antenna.dm"
#include "code\datums\mutations\body.dm"
#include "code\datums\mutations\chameleon.dm"
+#include "code\datums\mutations\cluwne.dm"
#include "code\datums\mutations\cold.dm"
#include "code\datums\mutations\combined.dm"
#include "code\datums\mutations\hulk.dm"
@@ -1988,6 +1990,7 @@
#include "code\modules\clothing\masks\_masks.dm"
#include "code\modules\clothing\masks\boxing.dm"
#include "code\modules\clothing\masks\breath.dm"
+#include "code\modules\clothing\masks\cluwne.dm"
#include "code\modules\clothing\masks\gasmask.dm"
#include "code\modules\clothing\masks\hailer.dm"
#include "code\modules\clothing\masks\miscellaneous.dm"
@@ -2000,6 +2003,7 @@
#include "code\modules\clothing\outfits\vv_outfit.dm"
#include "code\modules\clothing\shoes\_shoes.dm"
#include "code\modules\clothing\shoes\bananashoes.dm"
+#include "code\modules\clothing\shoes\cluwne.dm"
#include "code\modules\clothing\shoes\colour.dm"
#include "code\modules\clothing\shoes\magboots.dm"
#include "code\modules\clothing\shoes\miscellaneous.dm"
@@ -2023,6 +2027,7 @@
#include "code\modules\clothing\suits\wiz_robe.dm"
#include "code\modules\clothing\under\_under.dm"
#include "code\modules\clothing\under\accessories.dm"
+#include "code\modules\clothing\under\cluwne.dm"
#include "code\modules\clothing\under\color.dm"
#include "code\modules\clothing\under\costume.dm"
#include "code\modules\clothing\under\miscellaneous.dm"
@@ -2072,6 +2077,7 @@
#include "code\modules\events\bureaucratic_error.dm"
#include "code\modules\events\camerafailure.dm"
#include "code\modules\events\carp_migration.dm"
+#include "code\modules\events\cat_surgeon.dm"
#include "code\modules\events\communications_blackout.dm"
#include "code\modules\events\devil.dm"
#include "code\modules\events\disease_outbreak.dm"
@@ -2079,6 +2085,7 @@
#include "code\modules\events\electrical_storm.dm"
#include "code\modules\events\fake_virus.dm"
#include "code\modules\events\false_alarm.dm"
+#include "code\modules\events\floorcluwne.dm"
#include "code\modules\events\fugitive_spawning.dm"
#include "code\modules\events\ghost_role.dm"
#include "code\modules\events\grid_check.dm"
@@ -2785,6 +2792,7 @@
#include "code\modules\mob\living\simple_animal\hostile\dark_wizard.dm"
#include "code\modules\mob\living\simple_animal\hostile\eyeballs.dm"
#include "code\modules\mob\living\simple_animal\hostile\faithless.dm"
+#include "code\modules\mob\living\simple_animal\hostile\floor_cluwne.dm"
#include "code\modules\mob\living\simple_animal\hostile\giant_spider.dm"
#include "code\modules\mob\living\simple_animal\hostile\goose.dm"
#include "code\modules\mob\living\simple_animal\hostile\headcrab.dm"
@@ -3133,6 +3141,7 @@
#include "code\modules\projectiles\guns\energy\pulse.dm"
#include "code\modules\projectiles\guns\energy\special.dm"
#include "code\modules\projectiles\guns\energy\stun.dm"
+#include "code\modules\projectiles\guns\magic\motivation.dm"
#include "code\modules\projectiles\guns\magic\spell_book.dm"
#include "code\modules\projectiles\guns\magic\staff.dm"
#include "code\modules\projectiles\guns\magic\wand.dm"
@@ -3178,6 +3187,7 @@
#include "code\modules\projectiles\projectile\special\gravity.dm"
#include "code\modules\projectiles\projectile\special\hallucination.dm"
#include "code\modules\projectiles\projectile\special\ion.dm"
+#include "code\modules\projectiles\projectile\special\judgement_cut.dm"
#include "code\modules\projectiles\projectile\special\meteor.dm"
#include "code\modules\projectiles\projectile\special\mindflayer.dm"
#include "code\modules\projectiles\projectile\special\neurotoxin.dm"
@@ -3432,6 +3442,7 @@
#include "code\modules\spells\spell_types\area_teleport.dm"
#include "code\modules\spells\spell_types\bloodcrawl.dm"
#include "code\modules\spells\spell_types\charge.dm"
+#include "code\modules\spells\spell_types\cluwnecurse.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"
diff --git a/tgui/packages/tgui-dev-server/package.json b/tgui/packages/tgui-dev-server/package.json
index 5a04f61d75..78d84354a3 100644
--- a/tgui/packages/tgui-dev-server/package.json
+++ b/tgui/packages/tgui-dev-server/package.json
@@ -9,6 +9,6 @@
"glob": "^7.1.6",
"source-map": "^0.7.3",
"stacktrace-parser": "^0.1.10",
- "ws": "^7.4.3"
+ "ws": "^7.4.6"
}
}
diff --git a/tgui/packages/tgui/interfaces/ForbiddenLore.js b/tgui/packages/tgui/interfaces/ForbiddenLore.js
index 1225132810..cecbacdc27 100644
--- a/tgui/packages/tgui/interfaces/ForbiddenLore.js
+++ b/tgui/packages/tgui/interfaces/ForbiddenLore.js
@@ -7,7 +7,7 @@ import { Window } from '../layouts';
export const ForbiddenLore = (props, context) => {
const { act, data } = useBackend(context);
const {
- charges,
+ charges, total_sacs,
} = data;
const to_know = flow([
sortBy(to_know => to_know.state !== "Research",
@@ -21,6 +21,8 @@ export const ForbiddenLore = (props, context) => {
Charges left : {charges}
+
+ Completed Sacrifices : {total_sacs}
{to_know!== null ? (
to_know.map(knowledge => (
{
cost: knowledge.cost,
})} />
{' '}
- Cost : {knowledge.cost}
+ Cost : {knowledge.cost}
+ | Sacrifices Required : {knowledge.sacs}
{knowledge.flavour}
diff --git a/tgui/packages/tgui/interfaces/Orbit.js b/tgui/packages/tgui/interfaces/Orbit.js
index d71348c412..f8f1351c06 100644
--- a/tgui/packages/tgui/interfaces/Orbit.js
+++ b/tgui/packages/tgui/interfaces/Orbit.js
@@ -165,7 +165,7 @@ export const Orbit = (props, context) => {
{antagonists.length > 0 && (
-
+
{sortedAntagonists.map(([name, antags]) => (
{antags
diff --git a/tgui/public/tgui-common.bundle.js b/tgui/public/tgui-common.bundle.js
new file mode 100644
index 0000000000..6b0a626a7b
--- /dev/null
+++ b/tgui/public/tgui-common.bundle.js
@@ -0,0 +1 @@
+(self.webpackChunktgui_workspace=self.webpackChunktgui_workspace||[]).push([[962],{15453:function(e){"use strict";e.exports=function(e){if("function"!=typeof e)throw TypeError(String(e)+" is not a function");return e}},25401:function(e,t,n){"use strict";var r=n(99766);e.exports=function(e){if(!r(e)&&null!==e)throw TypeError("Can't set "+String(e)+" as a prototype");return e}},63142:function(e,t,n){"use strict";var r=n(55090),o=n(73072),i=n(19965),u=r("unscopables"),a=Array.prototype;a[u]==undefined&&i.f(a,u,{configurable:!0,value:o(null)}),e.exports=function(e){a[u][e]=!0}},78838:function(e,t,n){"use strict";var r=n(93294).charAt;e.exports=function(e,t,n){return t+(n?r(e,t).length:1)}},48246:function(e){"use strict";e.exports=function(e,t,n){if(!(e instanceof t))throw TypeError("Incorrect "+(n?n+" ":"")+"invocation");return e}},34699:function(e,t,n){"use strict";var r=n(99766);e.exports=function(e){if(!r(e))throw TypeError(String(e)+" is not an object");return e}},56097:function(e){"use strict";e.exports="undefined"!=typeof ArrayBuffer&&"undefined"!=typeof DataView},77066:function(e,t,n){"use strict";var r,o=n(56097),i=n(15289),u=n(93156),a=n(99766),c=n(13375),s=n(45423),l=n(57068),f=n(55103),d=n(19965).f,p=n(11993),h=n(62743),g=n(55090),v=n(94633),m=u.Int8Array,y=m&&m.prototype,b=u.Uint8ClampedArray,E=b&&b.prototype,D=m&&p(m),x=y&&p(y),w=Object.prototype,C=w.isPrototypeOf,_=g("toStringTag"),k=v("TYPED_ARRAY_TAG"),S=o&&!!h&&"Opera"!==s(u.opera),A=!1,N={Int8Array:1,Uint8Array:1,Uint8ClampedArray:1,Int16Array:2,Uint16Array:2,Int32Array:4,Uint32Array:4,Float32Array:4,Float64Array:8},F={BigInt64Array:8,BigUint64Array:8},B=function(e){if(!a(e))return!1;var t=s(e);return"DataView"===t||c(N,t)||c(F,t)},O=function(e){if(!a(e))return!1;var t=s(e);return c(N,t)||c(F,t)};for(r in N)u[r]||(S=!1);if((!S||"function"!=typeof D||D===Function.prototype)&&(D=function(){throw TypeError("Incorrect invocation")},S))for(r in N)u[r]&&h(u[r],D);if((!S||!x||x===w)&&(x=D.prototype,S))for(r in N)u[r]&&h(u[r].prototype,x);if(S&&p(E)!==x&&h(E,x),i&&!c(x,_))for(r in A=!0,d(x,_,{get:function(){return a(this)?this[k]:undefined}}),N)u[r]&&l(u[r],k,r);e.exports={NATIVE_ARRAY_BUFFER_VIEWS:S,TYPED_ARRAY_TAG:A&&k,aTypedArray:function(e){if(O(e))return e;throw TypeError("Target is not a typed array")},aTypedArrayConstructor:function(e){if(h){if(C.call(D,e))return e}else for(var t in N)if(c(N,r)){var n=u[t];if(n&&(e===n||C.call(n,e)))return e}throw TypeError("Target is not a typed array constructor")},exportTypedArrayMethod:function(e,t,n){if(i){if(n)for(var r in N){var o=u[r];o&&c(o.prototype,e)&&delete o.prototype[e]}x[e]&&!n||f(x,e,n?t:S&&y[e]||t)}},exportTypedArrayStaticMethod:function(e,t,n){var r,o;if(i){if(h){if(n)for(r in N)(o=u[r])&&c(o,e)&&delete o[e];if(D[e]&&!n)return;try{return f(D,e,n?t:S&&m[e]||t)}catch(a){}}for(r in N)!(o=u[r])||o[e]&&!n||f(o,e,t)}},isView:B,isTypedArray:O,TypedArray:D,TypedArrayPrototype:x}},3011:function(e,t,n){"use strict";var r=n(93156),o=n(15289),i=n(56097),u=n(57068),a=n(1165),c=n(62213),s=n(48246),l=n(30150),f=n(19047),d=n(20306),p=n(58383),h=n(11993),g=n(62743),v=n(68715).f,m=n(19965).f,y=n(83759),b=n(33698),E=n(90206),D=E.get,x=E.set,w="ArrayBuffer",C="DataView",_="Wrong index",k=r.ArrayBuffer,S=k,A=r.DataView,N=A&&A.prototype,F=Object.prototype,B=r.RangeError,O=p.pack,T=p.unpack,I=function(e){return[255&e]},M=function(e){return[255&e,e>>8&255]},V=function(e){return[255&e,e>>8&255,e>>16&255,e>>24&255]},R=function(e){return e[3]<<24|e[2]<<16|e[1]<<8|e[0]},L=function(e){return O(e,23,4)},P=function(e){return O(e,52,8)},j=function(e,t){m(e.prototype,t,{get:function(){return D(this)[t]}})},z=function(e,t,n,r){var o=d(n),i=D(e);if(o+t>i.byteLength)throw B(_);var u=D(i.buffer).bytes,a=o+i.byteOffset,c=u.slice(a,a+t);return r?c:c.reverse()},K=function(e,t,n,r,o,i){var u=d(n),a=D(e);if(u+t>a.byteLength)throw B(_);for(var c=D(a.buffer).bytes,s=u+a.byteOffset,l=r(+o),f=0;fH;)(U=$[H++])in S||u(S,U,k[U]);Y.constructor=S}g&&h(N)!==F&&g(N,F);var W=new A(new S(2)),G=N.setInt8;W.setInt8(0,2147483648),W.setInt8(1,2147483649),!W.getInt8(0)&&W.getInt8(1)||a(N,{setInt8:function(e,t){G.call(this,e,t<<24>>24)},setUint8:function(e,t){G.call(this,e,t<<24>>24)}},{unsafe:!0})}else S=function(e){s(this,S,w);var t=d(e);x(this,{bytes:y.call(new Array(t),0),byteLength:t}),o||(this.byteLength=t)},A=function(e,t,n){s(this,A,C),s(e,S,C);var r=D(e).byteLength,i=l(t);if(i<0||i>r)throw B("Wrong offset");if(i+(n=n===undefined?r-i:f(n))>r)throw B("Wrong length");x(this,{buffer:e,byteLength:n,byteOffset:i}),o||(this.buffer=e,this.byteLength=n,this.byteOffset=i)},o&&(j(S,"byteLength"),j(A,"buffer"),j(A,"byteLength"),j(A,"byteOffset")),a(A.prototype,{getInt8:function(e){return z(this,1,e)[0]<<24>>24},getUint8:function(e){return z(this,1,e)[0]},getInt16:function(e){var t=z(this,2,e,arguments.length>1?arguments[1]:undefined);return(t[1]<<8|t[0])<<16>>16},getUint16:function(e){var t=z(this,2,e,arguments.length>1?arguments[1]:undefined);return t[1]<<8|t[0]},getInt32:function(e){return R(z(this,4,e,arguments.length>1?arguments[1]:undefined))},getUint32:function(e){return R(z(this,4,e,arguments.length>1?arguments[1]:undefined))>>>0},getFloat32:function(e){return T(z(this,4,e,arguments.length>1?arguments[1]:undefined),23)},getFloat64:function(e){return T(z(this,8,e,arguments.length>1?arguments[1]:undefined),52)},setInt8:function(e,t){K(this,1,e,I,t)},setUint8:function(e,t){K(this,1,e,I,t)},setInt16:function(e,t){K(this,2,e,M,t,arguments.length>2?arguments[2]:undefined)},setUint16:function(e,t){K(this,2,e,M,t,arguments.length>2?arguments[2]:undefined)},setInt32:function(e,t){K(this,4,e,V,t,arguments.length>2?arguments[2]:undefined)},setUint32:function(e,t){K(this,4,e,V,t,arguments.length>2?arguments[2]:undefined)},setFloat32:function(e,t){K(this,4,e,L,t,arguments.length>2?arguments[2]:undefined)},setFloat64:function(e,t){K(this,8,e,P,t,arguments.length>2?arguments[2]:undefined)}});b(S,w),b(A,C),e.exports={ArrayBuffer:S,DataView:A}},90838:function(e,t,n){"use strict";var r=n(62314),o=n(60248),i=n(19047),u=Math.min;e.exports=[].copyWithin||function(e,t){var n=r(this),a=i(n.length),c=o(e,a),s=o(t,a),l=arguments.length>2?arguments[2]:undefined,f=u((l===undefined?a:o(l,a))-s,a-c),d=1;for(s0;)s in n?n[c]=n[s]:delete n[c],c+=d,s+=d;return n}},83759:function(e,t,n){"use strict";var r=n(62314),o=n(60248),i=n(19047);e.exports=function(e){for(var t=r(this),n=i(t.length),u=arguments.length,a=o(u>1?arguments[1]:undefined,n),c=u>2?arguments[2]:undefined,s=c===undefined?n:o(c,n);s>a;)t[a++]=e;return t}},83679:function(e,t,n){"use strict";var r=n(73846).forEach,o=n(67481)("forEach");e.exports=o?[].forEach:function(e){return r(this,e,arguments.length>1?arguments[1]:undefined)}},18703:function(e,t,n){"use strict";var r=n(6738),o=n(62314),i=n(83180),u=n(71713),a=n(19047),c=n(92996),s=n(3933);e.exports=function(e){var t,n,l,f,d,p,h=o(e),g="function"==typeof this?this:Array,v=arguments.length,m=v>1?arguments[1]:undefined,y=m!==undefined,b=s(h),E=0;if(y&&(m=r(m,v>2?arguments[2]:undefined,2)),b==undefined||g==Array&&u(b))for(n=new g(t=a(h.length));t>E;E++)p=y?m(h[E],E):h[E],c(n,E,p);else for(d=(f=b.call(h)).next,n=new g;!(l=d.call(f)).done;E++)p=y?i(f,m,[l.value,E],!0):l.value,c(n,E,p);return n.length=E,n}},38682:function(e,t,n){"use strict";var r=n(75018),o=n(19047),i=n(60248),u=function(e){return function(t,n,u){var a,c=r(t),s=o(c.length),l=i(u,s);if(e&&n!=n){for(;s>l;)if((a=c[l++])!=a)return!0}else for(;s>l;l++)if((e||l in c)&&c[l]===n)return e||l||0;return!e&&-1}};e.exports={includes:u(!0),indexOf:u(!1)}},73846:function(e,t,n){"use strict";var r=n(6738),o=n(98475),i=n(62314),u=n(19047),a=n(89130),c=[].push,s=function(e){var t=1==e,n=2==e,s=3==e,l=4==e,f=6==e,d=7==e,p=5==e||f;return function(h,g,v,m){for(var y,b,E=i(h),D=o(E),x=r(g,v,3),w=u(D.length),C=0,_=m||a,k=t?_(h,w):n||d?_(h,0):undefined;w>C;C++)if((p||C in D)&&(b=x(y=D[C],C,E),e))if(t)k[C]=b;else if(b)switch(e){case 3:return!0;case 5:return y;case 6:return C;case 2:c.call(k,y)}else switch(e){case 4:return!1;case 7:c.call(k,y)}return f?-1:s||l?l:k}};e.exports={forEach:s(0),map:s(1),filter:s(2),some:s(3),every:s(4),find:s(5),findIndex:s(6),filterOut:s(7)}},95180:function(e,t,n){"use strict";var r=n(75018),o=n(30150),i=n(19047),u=n(67481),a=Math.min,c=[].lastIndexOf,s=!!c&&1/[1].lastIndexOf(1,-0)<0,l=u("lastIndexOf"),f=s||!l;e.exports=f?function(e){if(s)return c.apply(this,arguments)||0;var t=r(this),n=i(t.length),u=n-1;for(arguments.length>1&&(u=a(u,o(arguments[1]))),u<0&&(u=n+u);u>=0;u--)if(u in t&&t[u]===e)return u||0;return-1}:c},35876:function(e,t,n){"use strict";var r=n(62213),o=n(55090),i=n(51976),u=o("species");e.exports=function(e){return i>=51||!r((function(){var t=[];return(t.constructor={})[u]=function(){return{foo:1}},1!==t[e](Boolean).foo}))}},67481:function(e,t,n){"use strict";var r=n(62213);e.exports=function(e,t){var n=[][e];return!!n&&r((function(){n.call(null,t||function(){throw 1},1)}))}},90047:function(e,t,n){"use strict";var r=n(15453),o=n(62314),i=n(98475),u=n(19047),a=function(e){return function(t,n,a,c){r(n);var s=o(t),l=i(s),f=u(s.length),d=e?f-1:0,p=e?-1:1;if(a<2)for(;;){if(d in l){c=l[d],d+=p;break}if(d+=p,e?d<0:f<=d)throw TypeError("Reduce of empty array with no initial value")}for(;e?d>=0:f>d;d+=p)d in l&&(c=n(c,l[d],d,s));return c}};e.exports={left:a(!1),right:a(!0)}},89130:function(e,t,n){"use strict";var r=n(99766),o=n(73707),i=n(55090)("species");e.exports=function(e,t){var n;return o(e)&&("function"!=typeof(n=e.constructor)||n!==Array&&!o(n.prototype)?r(n)&&null===(n=n[i])&&(n=undefined):n=undefined),new(n===undefined?Array:n)(0===t?0:t)}},83180:function(e,t,n){"use strict";var r=n(34699),o=n(6816);e.exports=function(e,t,n,i){try{return i?t(r(n)[0],n[1]):t(n)}catch(u){throw o(e),u}}},84673:function(e,t,n){"use strict";var r=n(55090)("iterator"),o=!1;try{var i=0,u={next:function(){return{done:!!i++}},"return":function(){o=!0}};u[r]=function(){return this},Array.from(u,(function(){throw 2}))}catch(a){}e.exports=function(e,t){if(!t&&!o)return!1;var n=!1;try{var i={};i[r]=function(){return{next:function(){return{done:n=!0}}}},e(i)}catch(a){}return n}},74803:function(e){"use strict";var t={}.toString;e.exports=function(e){return t.call(e).slice(8,-1)}},45423:function(e,t,n){"use strict";var r=n(94274),o=n(74803),i=n(55090)("toStringTag"),u="Arguments"==o(function(){return arguments}());e.exports=r?o:function(e){var t,n,r;return e===undefined?"Undefined":null===e?"Null":"string"==typeof(n=function(e,t){try{return e[t]}catch(n){}}(t=Object(e),i))?n:u?o(t):"Object"==(r=o(t))&&"function"==typeof t.callee?"Arguments":r}},36579:function(e,t,n){"use strict";var r=n(19965).f,o=n(73072),i=n(1165),u=n(6738),a=n(48246),c=n(32732),s=n(490),l=n(83360),f=n(15289),d=n(33214).fastKey,p=n(90206),h=p.set,g=p.getterFor;e.exports={getConstructor:function(e,t,n,s){var l=e((function(e,r){a(e,l,t),h(e,{type:t,index:o(null),first:undefined,last:undefined,size:0}),f||(e.size=0),r!=undefined&&c(r,e[s],{that:e,AS_ENTRIES:n})})),p=g(t),v=function(e,t,n){var r,o,i=p(e),u=m(e,t);return u?u.value=n:(i.last=u={index:o=d(t,!0),key:t,value:n,previous:r=i.last,next:undefined,removed:!1},i.first||(i.first=u),r&&(r.next=u),f?i.size++:e.size++,"F"!==o&&(i.index[o]=u)),e},m=function(e,t){var n,r=p(e),o=d(t);if("F"!==o)return r.index[o];for(n=r.first;n;n=n.next)if(n.key==t)return n};return i(l.prototype,{clear:function(){for(var e=p(this),t=e.index,n=e.first;n;)n.removed=!0,n.previous&&(n.previous=n.previous.next=undefined),delete t[n.index],n=n.next;e.first=e.last=undefined,f?e.size=0:this.size=0},"delete":function(e){var t=this,n=p(t),r=m(t,e);if(r){var o=r.next,i=r.previous;delete n.index[r.index],r.removed=!0,i&&(i.next=o),o&&(o.previous=i),n.first==r&&(n.first=o),n.last==r&&(n.last=i),f?n.size--:t.size--}return!!r},forEach:function(e){for(var t,n=p(this),r=u(e,arguments.length>1?arguments[1]:undefined,3);t=t?t.next:n.first;)for(r(t.value,t.key,this);t&&t.removed;)t=t.previous},has:function(e){return!!m(this,e)}}),i(l.prototype,n?{get:function(e){var t=m(this,e);return t&&t.value},set:function(e,t){return v(this,0===e?0:e,t)}}:{add:function(e){return v(this,e=0===e?0:e,e)}}),f&&r(l.prototype,"size",{get:function(){return p(this).size}}),l},setStrong:function(e,t,n){var r=t+" Iterator",o=g(t),i=g(r);s(e,t,(function(e,t){h(this,{type:r,target:e,state:o(e),kind:t,last:undefined})}),(function(){for(var e=i(this),t=e.kind,n=e.last;n&&n.removed;)n=n.previous;return e.target&&(e.last=n=n?n.next:e.state.first)?"keys"==t?{value:n.key,done:!1}:"values"==t?{value:n.value,done:!1}:{value:[n.key,n.value],done:!1}:(e.target=undefined,{value:undefined,done:!0})}),n?"entries":"values",!n,!0),l(t)}}},60079:function(e,t,n){"use strict";var r=n(1165),o=n(33214).getWeakData,i=n(34699),u=n(99766),a=n(48246),c=n(32732),s=n(73846),l=n(13375),f=n(90206),d=f.set,p=f.getterFor,h=s.find,g=s.findIndex,v=0,m=function(e){return e.frozen||(e.frozen=new y)},y=function(){this.entries=[]},b=function(e,t){return h(e.entries,(function(e){return e[0]===t}))};y.prototype={get:function(e){var t=b(this,e);if(t)return t[1]},has:function(e){return!!b(this,e)},set:function(e,t){var n=b(this,e);n?n[1]=t:this.entries.push([e,t])},"delete":function(e){var t=g(this.entries,(function(t){return t[0]===e}));return~t&&this.entries.splice(t,1),!!~t}},e.exports={getConstructor:function(e,t,n,s){var f=e((function(e,r){a(e,f,t),d(e,{type:t,id:v++,frozen:undefined}),r!=undefined&&c(r,e[s],{that:e,AS_ENTRIES:n})})),h=p(t),g=function(e,t,n){var r=h(e),u=o(i(t),!0);return!0===u?m(r).set(t,n):u[r.id]=n,e};return r(f.prototype,{"delete":function(e){var t=h(this);if(!u(e))return!1;var n=o(e);return!0===n?m(t)["delete"](e):n&&l(n,t.id)&&delete n[t.id]},has:function(e){var t=h(this);if(!u(e))return!1;var n=o(e);return!0===n?m(t).has(e):n&&l(n,t.id)}}),r(f.prototype,n?{get:function(e){var t=h(this);if(u(e)){var n=o(e);return!0===n?m(t).get(e):n?n[t.id]:undefined}},set:function(e,t){return g(this,e,t)}}:{add:function(e){return g(this,e,!0)}}),f}}},31912:function(e,t,n){"use strict";var r=n(10629),o=n(93156),i=n(76799),u=n(55103),a=n(33214),c=n(32732),s=n(48246),l=n(99766),f=n(62213),d=n(84673),p=n(33698),h=n(65136);e.exports=function(e,t,n){var g=-1!==e.indexOf("Map"),v=-1!==e.indexOf("Weak"),m=g?"set":"add",y=o[e],b=y&&y.prototype,E=y,D={},x=function(e){var t=b[e];u(b,e,"add"==e?function(e){return t.call(this,0===e?0:e),this}:"delete"==e?function(e){return!(v&&!l(e))&&t.call(this,0===e?0:e)}:"get"==e?function(e){return v&&!l(e)?undefined:t.call(this,0===e?0:e)}:"has"==e?function(e){return!(v&&!l(e))&&t.call(this,0===e?0:e)}:function(e,n){return t.call(this,0===e?0:e,n),this})};if(i(e,"function"!=typeof y||!(v||b.forEach&&!f((function(){(new y).entries().next()})))))E=n.getConstructor(t,e,g,m),a.REQUIRED=!0;else if(i(e,!0)){var w=new E,C=w[m](v?{}:-0,1)!=w,_=f((function(){w.has(1)})),k=d((function(e){new y(e)})),S=!v&&f((function(){for(var e=new y,t=5;t--;)e[m](t,t);return!e.has(-0)}));k||((E=t((function(t,n){s(t,E,e);var r=h(new y,t,E);return n!=undefined&&c(n,r[m],{that:r,AS_ENTRIES:g}),r}))).prototype=b,b.constructor=E),(_||S)&&(x("delete"),x("has"),g&&x("get")),(S||C)&&x(m),v&&b.clear&&delete b.clear}return D[e]=E,r({global:!0,forced:E!=y},D),p(E,e),v||n.setStrong(E,e,g),E}},7924:function(e,t,n){"use strict";var r=n(13375),o=n(92506),i=n(48378),u=n(19965);e.exports=function(e,t){for(var n=o(t),a=u.f,c=i.f,s=0;s"+u+""+t+">"}},47155:function(e,t,n){"use strict";var r=n(37916).IteratorPrototype,o=n(73072),i=n(42831),u=n(33698),a=n(17080),c=function(){return this};e.exports=function(e,t,n){var s=t+" Iterator";return e.prototype=o(r,{next:i(1,n)}),u(e,s,!1,!0),a[s]=c,e}},57068:function(e,t,n){"use strict";var r=n(15289),o=n(19965),i=n(42831);e.exports=r?function(e,t,n){return o.f(e,t,i(1,n))}:function(e,t,n){return e[t]=n,e}},42831:function(e){"use strict";e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},92996:function(e,t,n){"use strict";var r=n(57391),o=n(19965),i=n(42831);e.exports=function(e,t,n){var u=r(t);u in e?o.f(e,u,i(0,n)):e[u]=n}},33743:function(e,t,n){"use strict";var r=n(62213),o=n(52274).start,i=Math.abs,u=Date.prototype,a=u.getTime,c=u.toISOString;e.exports=r((function(){return"0385-07-25T07:06:39.999Z"!=c.call(new Date(-50000000000001))}))||!r((function(){c.call(new Date(NaN))}))?function(){if(!isFinite(a.call(this)))throw RangeError("Invalid time value");var e=this,t=e.getUTCFullYear(),n=e.getUTCMilliseconds(),r=t<0?"-":t>9999?"+":"";return r+o(i(t),r?6:4,0)+"-"+o(e.getUTCMonth()+1,2,0)+"-"+o(e.getUTCDate(),2,0)+"T"+o(e.getUTCHours(),2,0)+":"+o(e.getUTCMinutes(),2,0)+":"+o(e.getUTCSeconds(),2,0)+"."+o(n,3,0)+"Z"}:c},57029:function(e,t,n){"use strict";var r=n(34699),o=n(57391);e.exports=function(e){if("string"!==e&&"number"!==e&&"default"!==e)throw TypeError("Incorrect hint");return o(r(this),"number"!==e)}},490:function(e,t,n){"use strict";var r=n(10629),o=n(47155),i=n(11993),u=n(62743),a=n(33698),c=n(57068),s=n(55103),l=n(55090),f=n(27689),d=n(17080),p=n(37916),h=p.IteratorPrototype,g=p.BUGGY_SAFARI_ITERATORS,v=l("iterator"),m="keys",y="values",b="entries",E=function(){return this};e.exports=function(e,t,n,l,p,D,x){o(n,t,l);var w,C,_,k=function(e){if(e===p&&B)return B;if(!g&&e in N)return N[e];switch(e){case m:case y:case b:return function(){return new n(this,e)}}return function(){return new n(this)}},S=t+" Iterator",A=!1,N=e.prototype,F=N[v]||N["@@iterator"]||p&&N[p],B=!g&&F||k(p),O="Array"==t&&N.entries||F;if(O&&(w=i(O.call(new e)),h!==Object.prototype&&w.next&&(f||i(w)===h||(u?u(w,h):"function"!=typeof w[v]&&c(w,v,E)),a(w,S,!0,!0),f&&(d[S]=E))),p==y&&F&&F.name!==y&&(A=!0,B=function(){return F.call(this)}),f&&!x||N[v]===B||c(N,v,B),d[t]=B,p)if(C={values:k(y),keys:D?B:k(m),entries:k(b)},x)for(_ in C)(g||A||!(_ in N))&&s(N,_,C[_]);else r({target:t,proto:!0,forced:g||A},C);return C}},49712:function(e,t,n){"use strict";var r=n(10483),o=n(13375),i=n(43384),u=n(19965).f;e.exports=function(e){var t=r.Symbol||(r.Symbol={});o(t,e)||u(t,e,{value:i.f(e)})}},15289:function(e,t,n){"use strict";var r=n(62213);e.exports=!r((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},17765:function(e,t,n){"use strict";var r=n(93156),o=n(99766),i=r.document,u=o(i)&&o(i.createElement);e.exports=function(e){return u?i.createElement(e):{}}},88621:function(e,t,n){"use strict";var r=n(22909);e.exports=/(iphone|ipod|ipad).*applewebkit/i.test(r)},80597:function(e,t,n){"use strict";var r=n(74803),o=n(93156);e.exports="process"==r(o.process)},68486:function(e,t,n){"use strict";var r=n(22909);e.exports=/web0s(?!.*chrome)/i.test(r)},22909:function(e,t,n){"use strict";var r=n(1555);e.exports=r("navigator","userAgent")||""},51976:function(e,t,n){"use strict";var r,o,i=n(93156),u=n(22909),a=i.process,c=a&&a.versions,s=c&&c.v8;s?o=(r=s.split("."))[0]+r[1]:u&&(!(r=u.match(/Edge\/(\d+)/))||r[1]>=74)&&(r=u.match(/Chrome\/(\d+)/))&&(o=r[1]),e.exports=o&&+o},92002:function(e){"use strict";e.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},10629:function(e,t,n){"use strict";var r=n(93156),o=n(48378).f,i=n(57068),u=n(55103),a=n(16731),c=n(7924),s=n(76799);e.exports=function(e,t){var n,l,f,d,p,h=e.target,g=e.global,v=e.stat;if(n=g?r:v?r[h]||a(h,{}):(r[h]||{}).prototype)for(l in t){if(d=t[l],f=e.noTargetGet?(p=o(n,l))&&p.value:n[l],!s(g?l:h+(v?".":"#")+l,e.forced)&&f!==undefined){if(typeof d==typeof f)continue;c(d,f)}(e.sham||f&&f.sham)&&i(d,"sham",!0),u(n,l,d,e)}}},62213:function(e){"use strict";e.exports=function(e){try{return!!e()}catch(t){return!0}}},63905:function(e,t,n){"use strict";n(16431);var r=n(55103),o=n(62213),i=n(55090),u=n(69107),a=n(57068),c=i("species"),s=!o((function(){var e=/./;return e.exec=function(){var e=[];return e.groups={a:"7"},e},"7"!=="".replace(e,"$")})),l="$0"==="a".replace(/./,"$0"),f=i("replace"),d=!!/./[f]&&""===/./[f]("a","$0"),p=!o((function(){var e=/(?:)/,t=e.exec;e.exec=function(){return t.apply(this,arguments)};var n="ab".split(e);return 2!==n.length||"a"!==n[0]||"b"!==n[1]}));e.exports=function(e,t,n,f){var h=i(e),g=!o((function(){var t={};return t[h]=function(){return 7},7!=""[e](t)})),v=g&&!o((function(){var t=!1,n=/a/;return"split"===e&&((n={}).constructor={},n.constructor[c]=function(){return n},n.flags="",n[h]=/./[h]),n.exec=function(){return t=!0,null},n[h](""),!t}));if(!g||!v||"replace"===e&&(!s||!l||d)||"split"===e&&!p){var m=/./[h],y=n(h,""[e],(function(e,t,n,r,o){return t.exec===u?g&&!o?{done:!0,value:m.call(t,n,r)}:{done:!0,value:e.call(n,t,r)}:{done:!1}}),{REPLACE_KEEPS_$0:l,REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE:d}),b=y[0],E=y[1];r(String.prototype,e,b),r(RegExp.prototype,h,2==t?function(e,t){return E.call(e,this,t)}:function(e){return E.call(e,this)})}f&&a(RegExp.prototype[h],"sham",!0)}},67767:function(e,t,n){"use strict";var r=n(73707),o=n(19047),i=n(6738);e.exports=function u(e,t,n,a,c,s,l,f){for(var d,p=c,h=0,g=!!l&&i(l,f,3);h0&&r(d))p=u(e,t,d,o(d.length),p,s-1)-1;else{if(p>=9007199254740991)throw TypeError("Exceed the acceptable array length");e[p]=d}p++}h++}return p}},41830:function(e,t,n){"use strict";var r=n(62213);e.exports=!r((function(){return Object.isExtensible(Object.preventExtensions({}))}))},6738:function(e,t,n){"use strict";var r=n(15453);e.exports=function(e,t,n){if(r(e),t===undefined)return e;switch(n){case 0:return function(){return e.call(t)};case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,o){return e.call(t,n,r,o)}}return function(){return e.apply(t,arguments)}}},67043:function(e,t,n){"use strict";var r=n(15453),o=n(99766),i=[].slice,u={},a=function(e,t,n){if(!(t in u)){for(var r=[],o=0;o]*>)/g,a=/\$([$&'`]|\d\d?)/g;e.exports=function(e,t,n,c,s,l){var f=n+e.length,d=c.length,p=a;return s!==undefined&&(s=r(s),p=u),i.call(l,p,(function(r,i){var u;switch(i.charAt(0)){case"$":return"$";case"&":return e;case"`":return t.slice(0,n);case"'":return t.slice(f);case"<":u=s[i.slice(1,-1)];break;default:var a=+i;if(0===a)return r;if(a>d){var l=o(a/10);return 0===l?r:l<=d?c[l-1]===undefined?i.charAt(1):c[l-1]+i.charAt(1):r}u=c[a-1]}return u===undefined?"":u}))}},93156:function(e,t,n){"use strict";var r=function(e){return e&&e.Math==Math&&e};e.exports=r("object"==typeof globalThis&&globalThis)||r("object"==typeof window&&window)||r("object"==typeof self&&self)||r("object"==typeof n.g&&n.g)||function(){return this}()||Function("return this")()},13375:function(e){"use strict";var t={}.hasOwnProperty;e.exports=function(e,n){return t.call(e,n)}},97204:function(e){"use strict";e.exports={}},31538:function(e,t,n){"use strict";var r=n(93156);e.exports=function(e,t){var n=r.console;n&&n.error&&(1===arguments.length?n.error(e):n.error(e,t))}},73214:function(e,t,n){"use strict";var r=n(1555);e.exports=r("document","documentElement")},76689:function(e,t,n){"use strict";var r=n(15289),o=n(62213),i=n(17765);e.exports=!r&&!o((function(){return 7!=Object.defineProperty(i("div"),"a",{get:function(){return 7}}).a}))},58383:function(e){"use strict";var t=Math.abs,n=Math.pow,r=Math.floor,o=Math.log,i=Math.LN2;e.exports={pack:function(e,u,a){var c,s,l,f=new Array(a),d=8*a-u-1,p=(1<>1,g=23===u?n(2,-24)-n(2,-77):0,v=e<0||0===e&&1/e<0?1:0,m=0;for((e=t(e))!=e||e===Infinity?(s=e!=e?1:0,c=p):(c=r(o(e)/i),e*(l=n(2,-c))<1&&(c--,l*=2),(e+=c+h>=1?g/l:g*n(2,1-h))*l>=2&&(c++,l/=2),c+h>=p?(s=0,c=p):c+h>=1?(s=(e*l-1)*n(2,u),c+=h):(s=e*n(2,h-1)*n(2,u),c=0));u>=8;f[m++]=255&s,s/=256,u-=8);for(c=c<0;f[m++]=255&c,c/=256,d-=8);return f[--m]|=128*v,f},unpack:function(e,t){var r,o=e.length,i=8*o-t-1,u=(1<>1,c=i-7,s=o-1,l=e[s--],f=127&l;for(l>>=7;c>0;f=256*f+e[s],s--,c-=8);for(r=f&(1<<-c)-1,f>>=-c,c+=t;c>0;r=256*r+e[s],s--,c-=8);if(0===f)f=1-a;else{if(f===u)return r?NaN:l?-Infinity:Infinity;r+=n(2,t),f-=a}return(l?-1:1)*r*n(2,f-t)}}},98475:function(e,t,n){"use strict";var r=n(62213),o=n(74803),i="".split;e.exports=r((function(){return!Object("z").propertyIsEnumerable(0)}))?function(e){return"String"==o(e)?i.call(e,""):Object(e)}:Object},65136:function(e,t,n){"use strict";var r=n(99766),o=n(62743);e.exports=function(e,t,n){var i,u;return o&&"function"==typeof(i=t.constructor)&&i!==n&&r(u=i.prototype)&&u!==n.prototype&&o(e,u),e}},59601:function(e,t,n){"use strict";var r=n(41030),o=Function.toString;"function"!=typeof r.inspectSource&&(r.inspectSource=function(e){return o.call(e)}),e.exports=r.inspectSource},33214:function(e,t,n){"use strict";var r=n(97204),o=n(99766),i=n(13375),u=n(19965).f,a=n(94633),c=n(41830),s=a("meta"),l=0,f=Object.isExtensible||function(){return!0},d=function(e){u(e,s,{value:{objectID:"O"+ ++l,weakData:{}}})},p=e.exports={REQUIRED:!1,fastKey:function(e,t){if(!o(e))return"symbol"==typeof e?e:("string"==typeof e?"S":"P")+e;if(!i(e,s)){if(!f(e))return"F";if(!t)return"E";d(e)}return e[s].objectID},getWeakData:function(e,t){if(!i(e,s)){if(!f(e))return!0;if(!t)return!1;d(e)}return e[s].weakData},onFreeze:function(e){return c&&p.REQUIRED&&f(e)&&!i(e,s)&&d(e),e}};r[s]=!0},90206:function(e,t,n){"use strict";var r,o,i,u=n(60768),a=n(93156),c=n(99766),s=n(57068),l=n(13375),f=n(41030),d=n(67543),p=n(97204),h=a.WeakMap;if(u){var g=f.state||(f.state=new h),v=g.get,m=g.has,y=g.set;r=function(e,t){return t.facade=e,y.call(g,e,t),t},o=function(e){return v.call(g,e)||{}},i=function(e){return m.call(g,e)}}else{var b=d("state");p[b]=!0,r=function(e,t){return t.facade=e,s(e,b,t),t},o=function(e){return l(e,b)?e[b]:{}},i=function(e){return l(e,b)}}e.exports={set:r,get:o,has:i,enforce:function(e){return i(e)?o(e):r(e,{})},getterFor:function(e){return function(t){var n;if(!c(t)||(n=o(t)).type!==e)throw TypeError("Incompatible receiver, "+e+" required");return n}}}},71713:function(e,t,n){"use strict";var r=n(55090),o=n(17080),i=r("iterator"),u=Array.prototype;e.exports=function(e){return e!==undefined&&(o.Array===e||u[i]===e)}},73707:function(e,t,n){"use strict";var r=n(74803);e.exports=Array.isArray||function(e){return"Array"==r(e)}},76799:function(e,t,n){"use strict";var r=n(62213),o=/#|\.prototype\./,i=function(e,t){var n=a[u(e)];return n==s||n!=c&&("function"==typeof t?r(t):!!t)},u=i.normalize=function(e){return String(e).replace(o,".").toLowerCase()},a=i.data={},c=i.NATIVE="N",s=i.POLYFILL="P";e.exports=i},92285:function(e,t,n){"use strict";var r=n(99766),o=Math.floor;e.exports=function(e){return!r(e)&&isFinite(e)&&o(e)===e}},99766:function(e){"use strict";e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},27689:function(e){"use strict";e.exports=!1},10874:function(e,t,n){"use strict";var r=n(99766),o=n(74803),i=n(55090)("match");e.exports=function(e){var t;return r(e)&&((t=e[i])!==undefined?!!t:"RegExp"==o(e))}},32732:function(e,t,n){"use strict";var r=n(34699),o=n(71713),i=n(19047),u=n(6738),a=n(3933),c=n(6816),s=function(e,t){this.stopped=e,this.result=t};e.exports=function(e,t,n){var l,f,d,p,h,g,v,m=n&&n.that,y=!(!n||!n.AS_ENTRIES),b=!(!n||!n.IS_ITERATOR),E=!(!n||!n.INTERRUPTED),D=u(t,m,1+y+E),x=function(e){return l&&c(l),new s(!0,e)},w=function(e){return y?(r(e),E?D(e[0],e[1],x):D(e[0],e[1])):E?D(e,x):D(e)};if(b)l=e;else{if("function"!=typeof(f=a(e)))throw TypeError("Target is not iterable");if(o(f)){for(d=0,p=i(e.length);p>d;d++)if((h=w(e[d]))&&h instanceof s)return h;return new s(!1)}l=f.call(e)}for(g=l.next;!(v=g.call(l)).done;){try{h=w(v.value)}catch(C){throw c(l),C}if("object"==typeof h&&h&&h instanceof s)return h}return new s(!1)}},6816:function(e,t,n){"use strict";var r=n(34699);e.exports=function(e){var t=e["return"];if(t!==undefined)return r(t.call(e)).value}},37916:function(e,t,n){"use strict";var r,o,i,u=n(62213),a=n(11993),c=n(57068),s=n(13375),l=n(55090),f=n(27689),d=l("iterator"),p=!1;[].keys&&("next"in(i=[].keys())?(o=a(a(i)))!==Object.prototype&&(r=o):p=!0);var h=r==undefined||u((function(){var e={};return r[d].call(e)!==e}));h&&(r={}),f&&!h||s(r,d)||c(r,d,(function(){return this})),e.exports={IteratorPrototype:r,BUGGY_SAFARI_ITERATORS:p}},17080:function(e){"use strict";e.exports={}},78216:function(e){"use strict";var t=Math.expm1,n=Math.exp;e.exports=!t||t(10)>22025.465794806718||t(10)<22025.465794806718||-2e-17!=t(-2e-17)?function(e){return 0==(e=+e)?e:e>-1e-6&&e<1e-6?e+e*e/2:n(e)-1}:t},69945:function(e,t,n){"use strict";var r=n(57845),o=Math.abs,i=Math.pow,u=i(2,-52),a=i(2,-23),c=i(2,127)*(2-a),s=i(2,-126);e.exports=Math.fround||function(e){var t,n,i=o(e),l=r(e);return ic||n!=n?l*Infinity:l*n}},90738:function(e){"use strict";var t=Math.log;e.exports=Math.log1p||function(e){return(e=+e)>-1e-8&&e<1e-8?e-e*e/2:t(1+e)}},57845:function(e){"use strict";e.exports=Math.sign||function(e){return 0==(e=+e)||e!=e?e:e<0?-1:1}},74317:function(e,t,n){"use strict";var r,o,i,u,a,c,s,l,f=n(93156),d=n(48378).f,p=n(24446).set,h=n(88621),g=n(68486),v=n(80597),m=f.MutationObserver||f.WebKitMutationObserver,y=f.document,b=f.process,E=f.Promise,D=d(f,"queueMicrotask"),x=D&&D.value;x||(r=function(){var e,t;for(v&&(e=b.domain)&&e.exit();o;){t=o.fn,o=o.next;try{t()}catch(n){throw o?u():i=undefined,n}}i=undefined,e&&e.enter()},h||v||g||!m||!y?E&&E.resolve?(s=E.resolve(undefined),l=s.then,u=function(){l.call(s,r)}):u=v?function(){b.nextTick(r)}:function(){p.call(f,r)}:(a=!0,c=y.createTextNode(""),new m(r).observe(c,{characterData:!0}),u=function(){c.data=a=!a})),e.exports=x||function(e){var t={fn:e,next:undefined};i&&(i.next=t),o||(o=t,u()),i=t}},77085:function(e,t,n){"use strict";var r=n(93156);e.exports=r.Promise},19530:function(e,t,n){"use strict";var r=n(62213);e.exports=!!Object.getOwnPropertySymbols&&!r((function(){return!String(Symbol())}))},60768:function(e,t,n){"use strict";var r=n(93156),o=n(59601),i=r.WeakMap;e.exports="function"==typeof i&&/native code/.test(o(i))},604:function(e,t,n){"use strict";var r=n(15453),o=function(e){var t,n;this.promise=new e((function(e,r){if(t!==undefined||n!==undefined)throw TypeError("Bad Promise constructor");t=e,n=r})),this.resolve=r(t),this.reject=r(n)};e.exports.f=function(e){return new o(e)}},90225:function(e,t,n){"use strict";var r=n(10874);e.exports=function(e){if(r(e))throw TypeError("The method doesn't accept regular expressions");return e}},5366:function(e,t,n){"use strict";var r=n(93156).isFinite;e.exports=Number.isFinite||function(e){return"number"==typeof e&&r(e)}},5868:function(e,t,n){"use strict";var r=n(93156),o=n(52420).trim,i=n(98398),u=r.parseFloat,a=1/u(i+"-0")!=-Infinity;e.exports=a?function(e){var t=o(String(e)),n=u(t);return 0===n&&"-"==t.charAt(0)?-0:n}:u},94219:function(e,t,n){"use strict";var r=n(93156),o=n(52420).trim,i=n(98398),u=r.parseInt,a=/^[+-]?0[Xx]/,c=8!==u(i+"08")||22!==u(i+"0x16");e.exports=c?function(e,t){var n=o(String(e));return u(n,t>>>0||(a.test(n)?16:10))}:u},3669:function(e,t,n){"use strict";var r=n(15289),o=n(62213),i=n(91165),u=n(84491),a=n(21058),c=n(62314),s=n(98475),l=Object.assign,f=Object.defineProperty;e.exports=!l||o((function(){if(r&&1!==l({b:1},l(f({},"a",{enumerable:!0,get:function(){f(this,"b",{value:3,enumerable:!1})}}),{b:2})).b)return!0;var e={},t={},n=Symbol(),o="abcdefghijklmnopqrst";return e[n]=7,o.split("").forEach((function(e){t[e]=e})),7!=l({},e)[n]||i(l({},t)).join("")!=o}))?function(e,t){for(var n=c(e),o=arguments.length,l=1,f=u.f,d=a.f;o>l;)for(var p,h=s(arguments[l++]),g=f?i(h).concat(f(h)):i(h),v=g.length,m=0;v>m;)p=g[m++],r&&!d.call(h,p)||(n[p]=h[p]);return n}:l},73072:function(e,t,n){"use strict";var r,o=n(34699),i=n(54550),u=n(92002),a=n(97204),c=n(73214),s=n(17765),l=n(67543),f=l("IE_PROTO"),d=function(){},p=function(e){return"