diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm
index a336b8a7a3..90bb0347b6 100644
--- a/_maps/map_files/BoxStation/BoxStation.dmm
+++ b/_maps/map_files/BoxStation/BoxStation.dmm
@@ -3232,6 +3232,9 @@
},
/obj/structure/chair/comfy/black,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/machinery/atmospherics/pipe/simple/general/hidden{
+ dir = 8
+ },
/turf/open/floor/plasteel/white,
/area/science/xenobiology)
"alo" = (
@@ -3536,6 +3539,9 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
+/obj/machinery/atmospherics/pipe/simple/general/hidden{
+ dir = 5
+ },
/turf/open/floor/plasteel/white,
/area/science/xenobiology)
"alW" = (
@@ -3548,6 +3554,9 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 10
},
+/obj/machinery/atmospherics/pipe/simple/general/hidden{
+ dir = 8
+ },
/turf/open/floor/plasteel/white,
/area/science/xenobiology)
"alX" = (
@@ -27089,6 +27098,7 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
+/obj/machinery/atmospherics/pipe/simple/general/hidden,
/turf/open/floor/plasteel/white,
/area/science/xenobiology)
"bIu" = (
@@ -27260,6 +27270,9 @@
/area/science/xenobiology)
"bIO" = (
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden,
+/obj/machinery/atmospherics/pipe/simple/general/hidden{
+ dir = 8
+ },
/turf/open/floor/plasteel/white,
/area/science/xenobiology)
"bIP" = (
@@ -27634,6 +27647,7 @@
name = "test chamber blast door"
},
/obj/effect/spawner/structure/window/reinforced,
+/obj/machinery/atmospherics/pipe/simple/general/hidden,
/turf/open/floor/engine,
/area/science/xenobiology)
"bJJ" = (
@@ -28214,6 +28228,7 @@
/obj/effect/turf_decal/stripes/line{
dir = 6
},
+/obj/machinery/atmospherics/pipe/simple/general/hidden,
/turf/open/floor/plasteel,
/area/science/xenobiology)
"bKY" = (
@@ -28669,6 +28684,7 @@
/obj/structure/cable{
icon_state = "1-2"
},
+/obj/machinery/atmospherics/pipe/simple/general/hidden,
/turf/open/floor/plasteel/white,
/area/science/xenobiology)
"bMi" = (
@@ -29941,6 +29957,9 @@
/obj/effect/turf_decal/stripes/line{
dir = 1
},
+/obj/structure/sign/xenobio_guide{
+ pixel_y = -30
+ },
/turf/open/floor/plasteel,
/area/science/xenobiology)
"bPA" = (
@@ -29960,6 +29979,9 @@
dir = 9
},
/obj/machinery/portable_atmospherics/canister/bz,
+/obj/machinery/atmospherics/components/unary/portables_connector/visible{
+ dir = 8
+ },
/turf/open/floor/plasteel,
/area/science/xenobiology)
"bPF" = (
@@ -44682,6 +44704,15 @@
},
/turf/open/floor/plasteel/white,
/area/science/circuit)
+"dNl" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
+/obj/machinery/atmospherics/pipe/simple/general/hidden{
+ dir = 10
+ },
+/turf/open/floor/plasteel/white,
+/area/science/xenobiology)
"dNn" = (
/obj/structure/cable{
icon_state = "4-8"
@@ -54956,6 +54987,15 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plasteel/white,
/area/science/circuit)
+"mNG" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
+/obj/machinery/atmospherics/pipe/simple/general/hidden{
+ dir = 5
+ },
+/turf/open/floor/plasteel/white,
+/area/science/xenobiology)
"mOh" = (
/obj/structure/chair/office/dark{
dir = 8
@@ -63651,6 +63691,12 @@
},
/turf/open/floor/plasteel/showroomfloor,
/area/service/kitchen)
+"uKk" = (
+/obj/machinery/atmospherics/components/binary/pump{
+ dir = 8
+ },
+/turf/open/floor/plasteel/white,
+/area/science/xenobiology)
"uMb" = (
/obj/machinery/atmospherics/components/unary/vent_pump/on{
dir = 4
@@ -66942,6 +66988,10 @@
},
/turf/open/floor/plasteel/dark,
/area/ai_monitored/security/armory)
+"xBH" = (
+/obj/machinery/atmospherics/components/unary/outlet_injector/atmos,
+/turf/open/floor/engine,
+/area/science/xenobiology)
"xBN" = (
/obj/effect/turf_decal/tile/red{
dir = 4
@@ -110627,12 +110677,12 @@ bDb
bEm
bEm
cBz
-bEm
+xBH
bJI
bKX
bMh
bIt
-bOx
+mNG
bPz
bJN
bRU
@@ -111403,7 +111453,7 @@ bJM
bLc
bMi
bNo
-bOx
+dNl
alV
bQM
bMi
@@ -111918,7 +111968,7 @@ bJN
bMm
bNp
bOx
-bMi
+uKk
bQN
bRZ
bOx
diff --git a/_maps/map_files/CogStation/CogStation.dmm b/_maps/map_files/CogStation/CogStation.dmm
index 1b9d6fd1c2..2d775b5d65 100644
--- a/_maps/map_files/CogStation/CogStation.dmm
+++ b/_maps/map_files/CogStation/CogStation.dmm
@@ -33617,6 +33617,9 @@
"bFo" = (
/obj/machinery/smartfridge/extract/preloaded,
/obj/effect/turf_decal/stripes/line,
+/obj/structure/sign/xenobio_guide{
+ pixel_y = 32
+ },
/turf/open/floor/plasteel,
/area/science/xenobiology)
"bFp" = (
@@ -37593,9 +37596,6 @@
/turf/open/floor/plasteel,
/area/engineering/engine_smes)
"bOy" = (
-/obj/machinery/atmospherics/pipe/simple/general/visible{
- dir = 4
- },
/obj/effect/turf_decal/tile/green{
dir = 4
},
@@ -37667,10 +37667,6 @@
/turf/open/floor/plasteel,
/area/science/xenobiology)
"bOH" = (
-/obj/machinery/atmospherics/components/unary/portables_connector/visible{
- dir = 1
- },
-/obj/machinery/portable_atmospherics/canister,
/obj/effect/turf_decal/stripes/line{
dir = 1
},
@@ -37733,15 +37729,6 @@
/obj/structure/disposalpipe/trunk,
/turf/open/floor/plasteel,
/area/science/xenobiology)
-"bON" = (
-/obj/machinery/atmospherics/components/unary/portables_connector/visible{
- dir = 1
- },
-/obj/effect/turf_decal/stripes/line{
- dir = 1
- },
-/turf/open/floor/plasteel,
-/area/science/xenobiology)
"bOO" = (
/obj/machinery/portable_atmospherics/scrubber,
/obj/structure/disposalpipe/segment{
@@ -46695,9 +46682,6 @@
/turf/closed/wall/r_wall,
/area/science/lab)
"ckS" = (
-/obj/machinery/atmospherics/pipe/simple/general/visible{
- dir = 4
- },
/obj/effect/turf_decal/tile/green{
dir = 4
},
@@ -46781,10 +46765,12 @@
/turf/open/floor/plasteel,
/area/science/research)
"ckX" = (
-/obj/machinery/atmospherics/components/binary/valve,
/obj/structure/cable{
icon_state = "4-8"
},
+/obj/machinery/atmospherics/pipe/simple/general/visible/layer1{
+ dir = 8
+ },
/turf/open/floor/plasteel/dark,
/area/science/xenobiology)
"ckY" = (
@@ -47767,9 +47753,6 @@
/turf/open/floor/plasteel/white,
/area/medical/chemistry)
"cnl" = (
-/obj/machinery/atmospherics/pipe/simple/general/visible{
- dir = 4
- },
/obj/machinery/atmospherics/components/unary/vent_pump/on{
dir = 1;
pixel_x = 5
@@ -51059,9 +51042,6 @@
/turf/open/floor/plating/airless,
/area/science/xenobiology)
"ctR" = (
-/obj/machinery/atmospherics/pipe/simple/general/visible{
- dir = 4
- },
/obj/effect/turf_decal/tile/green{
dir = 1
},
@@ -51088,9 +51068,6 @@
/turf/open/floor/plasteel/white,
/area/science/xenobiology)
"ctT" = (
-/obj/machinery/atmospherics/pipe/manifold/general/visible{
- dir = 1
- },
/obj/effect/turf_decal/tile/green{
dir = 1
},
@@ -51105,12 +51082,12 @@
c_tag = "Xenobiology - Aft";
network = list("ss13","rd")
},
-/turf/open/floor/plasteel/dark,
-/area/science/xenobiology)
-"ctU" = (
/obj/machinery/atmospherics/pipe/simple/general/visible{
dir = 10
},
+/turf/open/floor/plasteel/dark,
+/area/science/xenobiology)
+"ctU" = (
/obj/effect/turf_decal/tile/green{
dir = 4
},
@@ -51796,13 +51773,6 @@
/turf/open/floor/plasteel/white,
/area/medical/virology)
"cvz" = (
-/obj/machinery/atmospherics/components/trinary/mixer{
- dir = 4;
- node1_concentration = 0.8;
- node2_concentration = 0.2;
- on = 1;
- target_pressure = 4500
- },
/obj/effect/turf_decal/tile/green{
dir = 1
},
@@ -51812,6 +51782,9 @@
/obj/machinery/airalarm{
pixel_y = 24
},
+/obj/machinery/atmospherics/components/binary/pump{
+ dir = 4
+ },
/turf/open/floor/plasteel/dark,
/area/science/xenobiology)
"cvA" = (
@@ -59591,16 +59564,22 @@
/obj/structure/cable{
icon_state = "2-4"
},
+/obj/machinery/portable_atmospherics/canister,
+/obj/machinery/atmospherics/components/unary/portables_connector/visible/layer1{
+ dir = 4
+ },
/turf/open/floor/plasteel/dark,
/area/science/xenobiology)
"cKA" = (
-/obj/machinery/atmospherics/components/binary/valve,
/obj/structure/cable{
icon_state = "4-8"
},
/obj/machinery/atmospherics/pipe/simple/orange/hidden{
dir = 8
},
+/obj/machinery/atmospherics/components/binary/pump/layer1{
+ dir = 8
+ },
/turf/open/floor/plasteel/dark,
/area/science/xenobiology)
"cKB" = (
@@ -59611,6 +59590,9 @@
/obj/machinery/atmospherics/pipe/simple/orange/hidden{
dir = 8
},
+/obj/machinery/atmospherics/pipe/simple/general/visible/layer1{
+ dir = 8
+ },
/turf/open/floor/plasteel/dark,
/area/science/xenobiology)
"cKC" = (
@@ -61945,6 +61927,9 @@
/obj/structure/cable{
icon_state = "2-4"
},
+/obj/machinery/atmospherics/pipe/simple/general/visible/layer1{
+ dir = 8
+ },
/turf/open/floor/plasteel/dark,
/area/science/xenobiology)
"cQG" = (
@@ -61954,6 +61939,9 @@
/obj/structure/cable{
icon_state = "2-8"
},
+/obj/machinery/atmospherics/pipe/simple/general/visible/layer1{
+ dir = 10
+ },
/turf/open/floor/plasteel/dark,
/area/science/xenobiology)
"cQH" = (
@@ -61989,6 +61977,9 @@
/obj/structure/cable{
icon_state = "1-2"
},
+/obj/machinery/atmospherics/pipe/simple/general/visible/layer1{
+ dir = 1
+ },
/turf/open/floor/plasteel,
/area/science/xenobiology)
"cQJ" = (
@@ -62034,6 +62025,9 @@
/obj/structure/cable{
icon_state = "0-4"
},
+/obj/machinery/atmospherics/pipe/simple/general/visible/layer1{
+ dir = 1
+ },
/turf/open/floor/plating,
/area/science/xenobiology)
"cQO" = (
@@ -70147,6 +70141,12 @@
},
/turf/open/floor/plasteel,
/area/tcommsat/computer)
+"wwC" = (
+/obj/machinery/atmospherics/components/unary/vent_pump/siphon/on/layer1{
+ dir = 1
+ },
+/turf/open/floor/engine,
+/area/science/xenobiology)
"wyk" = (
/obj/structure/disposalpipe/segment{
dir = 9
@@ -89211,7 +89211,7 @@ cQA
cQE
cbF
cnl
-cla
+ckX
bOK
cQM
bKM
@@ -89471,7 +89471,7 @@ ckS
cQG
cQI
cQN
-bKM
+wwC
bKM
bKM
bKM
@@ -89982,8 +89982,8 @@ cQB
cQo
bxT
ctU
-ckX
-bON
+cla
+bOH
cQP
bxT
bKM
diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index db0b3fc78a..a715e91431 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -40982,6 +40982,9 @@
"cTU" = (
/obj/effect/turf_decal/delivery,
/obj/machinery/chem_master,
+/obj/structure/sign/xenobio_guide{
+ pixel_y = 32
+ },
/turf/open/floor/plasteel,
/area/science/xenobiology)
"cTV" = (
@@ -45288,7 +45291,7 @@
pixel_y = -22
},
/obj/effect/turf_decal/delivery,
-/obj/machinery/atmospherics/components/binary/valve/digital{
+/obj/machinery/atmospherics/components/binary/pump{
dir = 8
},
/turf/open/floor/plasteel,
diff --git a/_maps/map_files/KiloStation/KiloStation.dmm b/_maps/map_files/KiloStation/KiloStation.dmm
index 3520c115fb..c2464ab762 100644
--- a/_maps/map_files/KiloStation/KiloStation.dmm
+++ b/_maps/map_files/KiloStation/KiloStation.dmm
@@ -2185,10 +2185,10 @@
/turf/open/floor/engine,
/area/ai_monitored/turret_protected/aisat/foyer)
"adT" = (
-/obj/effect/spawner/structure/window/reinforced,
/obj/structure/cable{
- icon_state = "4-8"
+ icon_state = "0-4"
},
+/obj/effect/spawner/structure/window/reinforced,
/turf/open/floor/plating,
/area/science/xenobiology)
"adU" = (
@@ -3546,9 +3546,6 @@
name = "xenobiology camera";
network = list("ss13","rd","xeno")
},
-/obj/structure/cable{
- icon_state = "4-8"
- },
/turf/open/floor/circuit/telecomms,
/area/science/xenobiology)
"agg" = (
@@ -3573,9 +3570,6 @@
external_pressure_bound = 120;
name = "server vent"
},
-/obj/structure/cable{
- icon_state = "4-8"
- },
/turf/open/floor/circuit/telecomms,
/area/science/xenobiology)
"agi" = (
@@ -73642,12 +73636,6 @@
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plasteel,
/area/engineering/atmos)
-"cqw" = (
-/obj/structure/sign/warning/deathsposal{
- layer = 4
- },
-/turf/closed/wall,
-/area/science/xenobiology)
"cqx" = (
/obj/structure/disposalpipe/trunk,
/obj/machinery/disposal/bin{
@@ -84108,6 +84096,11 @@
/obj/effect/spawner/bundle/costume/maid,
/turf/open/floor/wood,
/area/commons/vacant_room/office)
+"hDO" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/sign/departments/xenobio,
+/turf/closed/wall/r_wall,
+/area/maintenance/starboard/fore)
"hNk" = (
/turf/closed/wall/r_wall/rust,
/area/security/prison)
@@ -84614,6 +84607,9 @@
/obj/effect/turf_decal/bot,
/turf/open/floor/plating,
/area/maintenance/port/fore)
+"kwY" = (
+/turf/open/floor/circuit/telecomms,
+/area/science/xenobiology)
"kzw" = (
/obj/structure/chair/office/dark{
dir = 8
@@ -85181,6 +85177,17 @@
/obj/item/hilbertshotel/ghostdojo,
/turf/open/floor/plasteel,
/area/hallway/secondary/exit/departure_lounge)
+"qcu" = (
+/obj/structure/cable{
+ icon_state = "0-4"
+ },
+/obj/machinery/door/poddoor/preopen{
+ id = "xeno5";
+ name = "Creature Cell 5"
+ },
+/obj/effect/spawner/structure/window/reinforced,
+/turf/open/floor/plating,
+/area/science/xenobiology)
"qdz" = (
/obj/structure/cable{
icon_state = "1-4"
@@ -85546,6 +85553,10 @@
},
/turf/open/floor/plasteel,
/area/hallway/primary/starboard)
+"sVz" = (
+/obj/effect/decal/cleanable/dirt,
+/turf/closed/wall/r_wall,
+/area/maintenance/starboard/fore)
"tkP" = (
/obj/effect/turf_decal/tile/purple,
/obj/effect/turf_decal/tile/purple{
@@ -121879,8 +121890,8 @@ bfq
iMq
bbx
alB
-arx
-arx
+sVz
+hDO
alB
alB
alB
@@ -122136,8 +122147,8 @@ aWJ
ayv
aWJ
alB
-bdp
-bhl
+kwY
+kwY
alB
bfq
juX
@@ -122648,7 +122659,7 @@ alB
alB
bfM
bfM
-bfM
+qcu
aWR
agh
agQ
@@ -123170,7 +123181,7 @@ aWR
acw
bgn
bgB
-cqw
+aWR
bgM
bgn
bVA
diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm
index 114cafb980..dcd154f64e 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -43275,12 +43275,12 @@
/turf/open/floor/plasteel,
/area/science/xenobiology)
"cSk" = (
-/obj/machinery/atmospherics/pipe/manifold/general/visible{
- dir = 1
- },
/obj/effect/turf_decal/stripes/corner{
dir = 4
},
+/obj/machinery/atmospherics/pipe/simple/general/visible{
+ dir = 10
+ },
/turf/open/floor/plasteel/white,
/area/science/xenobiology)
"cSl" = (
@@ -43686,20 +43686,7 @@
},
/turf/open/floor/plasteel/white,
/area/science/xenobiology)
-"cSX" = (
-/obj/structure/disposalpipe/segment,
-/obj/machinery/atmospherics/pipe/simple/general/visible{
- dir = 4
- },
-/obj/structure/cable/yellow{
- icon_state = "1-2"
- },
-/turf/open/floor/plasteel/white,
-/area/science/xenobiology)
"cSZ" = (
-/obj/machinery/atmospherics/components/binary/pump{
- dir = 8
- },
/obj/machinery/firealarm{
pixel_y = 26
},
@@ -43707,15 +43694,19 @@
dir = 1
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/machinery/atmospherics/components/binary/pump{
+ dir = 4;
+ name = "input port pump"
+ },
/turf/open/floor/plasteel/white,
/area/science/xenobiology)
"cTa" = (
-/obj/machinery/atmospherics/pipe/simple/general/visible{
- dir = 4
- },
/obj/effect/turf_decal/stripes/corner{
dir = 8
},
+/obj/machinery/atmospherics/pipe/simple/general/visible{
+ dir = 6
+ },
/turf/open/floor/plasteel/white,
/area/science/xenobiology)
"cTb" = (
@@ -43880,6 +43871,7 @@
/obj/effect/turf_decal/stripes/line{
dir = 10
},
+/obj/machinery/atmospherics/pipe/simple/general/visible,
/turf/open/floor/plasteel,
/area/science/xenobiology)
"cTt" = (
@@ -44505,6 +44497,7 @@
/obj/structure/disposalpipe/trunk{
dir = 1
},
+/obj/machinery/atmospherics/pipe/simple/general/visible,
/turf/open/floor/engine,
/area/science/xenobiology)
"daE" = (
@@ -44913,6 +44906,9 @@
/obj/effect/turf_decal/tile/purple{
dir = 4
},
+/obj/structure/sign/xenobio_guide{
+ pixel_y = 32
+ },
/turf/open/floor/plasteel/white,
/area/science/xenobiology)
"dcf" = (
@@ -45139,6 +45135,13 @@
icon_state = "1-2"
},
/obj/effect/turf_decal/stripes/line,
+/obj/machinery/button/door{
+ id = "xenobio_e";
+ name = "Containment Blast Doors";
+ pixel_y = 4;
+ req_access_txt = "55"
+ },
+/obj/structure/table/glass,
/turf/open/floor/plasteel,
/area/science/xenobiology)
"dcx" = (
@@ -45591,6 +45594,7 @@
icon_state = "4-8"
},
/obj/effect/turf_decal/stripes/line,
+/obj/machinery/atmospherics/pipe/simple/general/visible,
/turf/open/floor/plasteel/white,
/area/science/xenobiology)
"ddo" = (
@@ -45653,6 +45657,7 @@
},
/obj/structure/disposalpipe/segment,
/obj/effect/spawner/structure/window/reinforced,
+/obj/machinery/atmospherics/pipe/simple/general/visible,
/turf/open/floor/plating,
/area/science/xenobiology)
"ddv" = (
@@ -48609,6 +48614,19 @@
},
/turf/open/floor/plating,
/area/cargo/storage)
+"dNg" = (
+/obj/effect/turf_decal/tile/purple{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/purple{
+ dir = 4
+ },
+/obj/machinery/door/poddoor/preopen{
+ id = "xenobio_e";
+ name = "containment blast door"
+ },
+/turf/open/floor/plasteel/white,
+/area/science/xenobiology)
"dNA" = (
/obj/machinery/door/airlock/maintenance{
req_one_access_txt = "12;27;76"
@@ -54219,6 +54237,12 @@
},
/turf/closed/wall/r_wall,
/area/maintenance/disposal/incinerator)
+"gYr" = (
+/obj/machinery/atmospherics/components/unary/vent_pump/siphon/on{
+ dir = 1
+ },
+/turf/open/floor/engine,
+/area/science/xenobiology)
"gZf" = (
/obj/structure/table,
/obj/item/paper_bin{
@@ -85910,6 +85934,14 @@
"xVW" = (
/turf/closed/wall/r_wall,
/area/ai_monitored/aisat/exterior)
+"xWc" = (
+/obj/effect/spawner/structure/window/reinforced,
+/obj/machinery/door/poddoor/preopen{
+ id = "xenobio_e";
+ name = "containment blast door"
+ },
+/turf/open/floor/plating,
+/area/science/xenobiology)
"xWg" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/structure/cable/yellow{
@@ -118603,7 +118635,7 @@ aaf
aaf
cRe
cZa
-cRe
+cSt
cRi
dbX
dcg
@@ -119123,7 +119155,7 @@ dbZ
dci
dcu
cRi
-cRe
+xWc
cRi
cSg
lbz
@@ -120146,7 +120178,7 @@ dvY
aaa
aaa
aaf
-cRe
+xWc
cRS
dcm
dcv
@@ -120178,7 +120210,7 @@ ddx
ddz
daR
cZv
-cRe
+xWc
aaa
aaa
aaa
@@ -120403,8 +120435,8 @@ dvY
aaa
aaa
aaf
-cRe
-cRS
+xWc
+dNg
dcn
dcw
cRk
@@ -120422,13 +120454,13 @@ nBJ
uiZ
cSV
cSJ
-cSX
+cSJ
ddm
cTt
daA
cSn
cSn
-cSn
+daH
daL
cRi
daQ
@@ -120660,7 +120692,7 @@ dvY
aaa
aaa
aaf
-cRe
+xWc
cRS
dco
dcx
@@ -120684,15 +120716,15 @@ ddn
cTs
ddu
daD
-cSn
-daH
+daB
+gYr
daK
cRi
bIv
ddz
ddB
cZv
-cRe
+xWc
aaa
aaf
aaa
@@ -122203,9 +122235,9 @@ aac
aaa
aaa
cRi
-cRe
-cRe
-cRe
+xWc
+xWc
+xWc
cRi
cRi
cRi
diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm
index 37992f1d8b..181500b17b 100644
--- a/_maps/map_files/OmegaStation/OmegaStation.dmm
+++ b/_maps/map_files/OmegaStation/OmegaStation.dmm
@@ -31305,6 +31305,9 @@
/area/science/xenobiology)
"bgd" = (
/obj/structure/closet/l3closet/scientist,
+/obj/structure/sign/xenobio_guide{
+ pixel_x = -32
+ },
/turf/open/floor/plasteel/dark/side{
dir = 8
},
diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm
index a803be6d61..2603c6ace0 100644
--- a/_maps/map_files/PubbyStation/PubbyStation.dmm
+++ b/_maps/map_files/PubbyStation/PubbyStation.dmm
@@ -54470,6 +54470,9 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
+/obj/machinery/atmospherics/pipe/simple/general/visible/layer1{
+ dir = 8
+ },
/turf/open/floor/plasteel/dark,
/area/science/xenobiology)
"ivO" = (
@@ -56269,7 +56272,10 @@
/turf/open/floor/plasteel/dark,
/area/security/brig)
"lhA" = (
-/obj/machinery/atmospherics/pipe/manifold/general/visible,
+/obj/machinery/atmospherics/pipe/simple/general/visible{
+ dir = 4
+ },
+/obj/machinery/atmospherics/pipe/simple/general/visible/layer1,
/turf/open/floor/plasteel/dark,
/area/science/xenobiology)
"liR" = (
@@ -56478,6 +56484,9 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
+/obj/machinery/atmospherics/pipe/simple/general/visible/layer1{
+ dir = 5
+ },
/turf/open/floor/plasteel/dark,
/area/science/xenobiology)
"lGp" = (
@@ -57776,6 +57785,9 @@
/area/command/heads_quarters/hop)
"nxT" = (
/obj/machinery/smartfridge/extract/preloaded,
+/obj/structure/sign/xenobio_guide{
+ pixel_x = 32
+ },
/turf/open/floor/plasteel,
/area/science/xenobiology)
"nyB" = (
@@ -58790,6 +58802,9 @@
icon_state = "2-8"
},
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden,
+/obj/machinery/atmospherics/pipe/simple/general/visible/layer1{
+ dir = 8
+ },
/turf/open/floor/plasteel/dark,
/area/science/xenobiology)
"oSP" = (
@@ -59505,6 +59520,9 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
+/obj/machinery/atmospherics/pipe/simple/general/visible/layer1{
+ dir = 8
+ },
/turf/open/floor/plating,
/area/science/xenobiology)
"pWF" = (
@@ -59596,13 +59614,13 @@
/turf/open/floor/plating,
/area/commons/storage/emergency/starboard)
"qcD" = (
-/obj/machinery/atmospherics/components/unary/portables_connector/visible,
/obj/effect/turf_decal/tile/green{
dir = 1
},
/obj/effect/turf_decal/tile/green{
dir = 4
},
+/obj/machinery/atmospherics/components/unary/portables_connector/visible/layer1,
/turf/open/floor/plasteel/dark,
/area/science/xenobiology)
"qcH" = (
@@ -60726,6 +60744,9 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
+/obj/machinery/atmospherics/components/unary/vent_pump/siphon/on/layer1{
+ dir = 8
+ },
/turf/open/floor/engine,
/area/science/xenobiology)
"rMV" = (
@@ -64632,7 +64653,9 @@
/turf/open/floor/carpet,
/area/service/chapel/main/monastery)
"xxw" = (
-/obj/machinery/atmospherics/components/binary/pump,
+/obj/machinery/atmospherics/components/binary/pump/layer1{
+ dir = 1
+ },
/turf/open/floor/plasteel/dark,
/area/science/xenobiology)
"xxK" = (
diff --git a/_maps/map_files/TauStation/TauStation.dmm b/_maps/map_files/TauStation/TauStation.dmm
index 4df14a633d..56e3773ce2 100644
--- a/_maps/map_files/TauStation/TauStation.dmm
+++ b/_maps/map_files/TauStation/TauStation.dmm
@@ -18140,6 +18140,9 @@
/obj/structure/cable{
icon_state = "4-8"
},
+/obj/machinery/atmospherics/pipe/simple/general/visible/layer1{
+ dir = 6
+ },
/turf/open/floor/engine,
/area/science/xenobiology)
"gll" = (
@@ -18574,6 +18577,9 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
+/obj/machinery/atmospherics/pipe/simple/general/visible/layer1{
+ dir = 8
+ },
/turf/open/floor/engine,
/area/science/xenobiology)
"guX" = (
@@ -28476,7 +28482,7 @@
/obj/effect/turf_decal/stripes/line{
dir = 4
},
-/obj/machinery/atmospherics/components/binary/pump{
+/obj/machinery/atmospherics/components/binary/pump/layer1{
dir = 1
},
/turf/open/floor/plasteel/dark,
@@ -29098,8 +29104,8 @@
/obj/effect/turf_decal/stripes/corner{
dir = 8
},
-/obj/machinery/atmospherics/pipe/manifold/general/visible{
- dir = 1
+/obj/machinery/atmospherics/pipe/simple/general/visible{
+ dir = 6
},
/turf/open/floor/plasteel/dark,
/area/science/xenobiology)
@@ -34133,6 +34139,9 @@
/obj/structure/cable{
icon_state = "1-8"
},
+/obj/machinery/atmospherics/pipe/simple/general/visible/layer1{
+ dir = 8
+ },
/turf/open/floor/engine,
/area/science/xenobiology)
"lPz" = (
@@ -38015,6 +38024,9 @@
/obj/effect/turf_decal/tile/purple{
dir = 8
},
+/obj/structure/sign/xenobio_guide{
+ pixel_x = -32
+ },
/turf/open/floor/plasteel/white,
/area/science/xenobiology)
"nck" = (
@@ -40391,9 +40403,6 @@
/turf/open/floor/plasteel/freezer,
/area/commons/toilet)
"nUv" = (
-/obj/machinery/atmospherics/pipe/simple/general/visible{
- dir = 6
- },
/turf/open/floor/plasteel/dark/side{
dir = 4
},
@@ -54285,6 +54294,10 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
+/obj/machinery/atmospherics/components/unary/vent_pump/siphon/on/layer1{
+ dir = 8;
+ pixel_y = 1
+ },
/turf/open/floor/engine,
/area/science/xenobiology)
"sRU" = (
@@ -57455,8 +57468,9 @@
/obj/effect/turf_decal/stripes/line{
dir = 5
},
-/obj/machinery/atmospherics/pipe/manifold/general/visible{
- dir = 1
+/obj/machinery/atmospherics/pipe/simple/general/visible/layer1,
+/obj/machinery/atmospherics/pipe/simple/general/visible{
+ dir = 4
},
/turf/open/floor/plasteel/dark,
/area/science/xenobiology)
@@ -59677,7 +59691,7 @@
/turf/open/floor/plasteel,
/area/engineering/lobby)
"uFf" = (
-/obj/machinery/atmospherics/components/unary/portables_connector/visible{
+/obj/machinery/atmospherics/components/unary/portables_connector/visible/layer1{
dir = 1
},
/turf/open/floor/plasteel/dark/side{
@@ -63656,9 +63670,6 @@
/turf/open/floor/plating,
/area/cargo/office)
"vVX" = (
-/obj/machinery/atmospherics/components/unary/thermomachine/freezer{
- dir = 1
- },
/turf/open/floor/plasteel/dark/corner{
dir = 4
},
diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm
index 36ecb1d402..26c2eb7f80 100644
--- a/code/__DEFINES/citadel_defines.dm
+++ b/code/__DEFINES/citadel_defines.dm
@@ -105,11 +105,6 @@
#define CITADEL_MENTOR_OOC_COLOUR "#224724"
-//xenobio console upgrade stuff
-#define XENOBIO_UPGRADE_MONKEYS 1
-#define XENOBIO_UPGRADE_SLIMEBASIC 2
-#define XENOBIO_UPGRADE_SLIMEADV 4
-
//Citadel toggles because bitflag memes
#define MEDIHOUND_SLEEPER (1<<0)
#define EATING_NOISES (1<<1)
diff --git a/code/__DEFINES/tgs.dm b/code/__DEFINES/tgs.dm
index 0cc106ec9c..b0e97e05e9 100644
--- a/code/__DEFINES/tgs.dm
+++ b/code/__DEFINES/tgs.dm
@@ -1,6 +1,6 @@
// tgstation-server DMAPI
-#define TGS_DMAPI_VERSION "6.6.2"
+#define TGS_DMAPI_VERSION "6.7.0"
// All functions and datums outside this document are subject to change with any version and should not be relied on.
diff --git a/code/game/objects/effects/anomalies.dm b/code/game/objects/effects/anomalies.dm
index 69a7bc906a..31e9d70462 100644
--- a/code/game/objects/effects/anomalies.dm
+++ b/code/game/objects/effects/anomalies.dm
@@ -235,6 +235,8 @@
for (var/atom/movable/A in urange(12, FROM )) // iterate thru list of mobs in the area
if(istype(A, /obj/item/beacon))
continue // don't teleport beacons because that's just insanely stupid
+ if(iscameramob(A))
+ continue // Don't mess with AI eye, blob eye, xenobio or advanced cameras
if(A.anchored)
continue
diff --git a/code/game/objects/structures/signs/_signs.dm b/code/game/objects/structures/signs/_signs.dm
index 0e4f85572c..e1235f929b 100644
--- a/code/game/objects/structures/signs/_signs.dm
+++ b/code/game/objects/structures/signs/_signs.dm
@@ -131,3 +131,8 @@
name = "nanotrasen logo"
desc = "The Nanotrasen corporate logo."
icon_state = "nanotrasen_sign1"
+
+/obj/structure/sign/xenobio_guide
+ name = "\improper Slime genealogy sign"
+ desc = "A sign depicting how the slime colors change with mutations, and the grey slime in the root."
+ icon_state = "xenobio-guide"
diff --git a/code/modules/events/wizard/magicarp.dm b/code/modules/events/wizard/magicarp.dm
index b900a2da9f..da8a4eef1f 100644
--- a/code/modules/events/wizard/magicarp.dm
+++ b/code/modules/events/wizard/magicarp.dm
@@ -52,7 +52,20 @@
color = "#00FFFF"
maxHealth = 75
health = 75
+ gold_core_spawnable = NO_SPAWN
/mob/living/simple_animal/hostile/carp/ranged/chaos/Shoot()
projectiletype = pick(allowed_projectile_types)
..()
+
+/mob/living/simple_animal/hostile/carp/ranged/xenobiology // these are for the xenobio gold slime pool
+ gold_core_spawnable = HOSTILE_SPAWN
+ allowed_projectile_types = list(/obj/item/projectile/magic/change, /obj/item/projectile/magic/animate, /obj/item/projectile/magic/resurrection,
+ /obj/item/projectile/magic/teleport, /obj/item/projectile/magic/door, /obj/item/projectile/magic/aoe/fireball, /obj/item/projectile/magic/spellblade,
+ /obj/item/projectile/magic/arcane_barrage) //thanks Lett1
+
+/mob/living/simple_animal/hostile/carp/ranged/chaos/xenobiology
+ gold_core_spawnable = HOSTILE_SPAWN
+ allowed_projectile_types = list(/obj/item/projectile/magic/change, /obj/item/projectile/magic/animate, /obj/item/projectile/magic/resurrection,
+ /obj/item/projectile/magic/teleport, /obj/item/projectile/magic/door, /obj/item/projectile/magic/aoe/fireball, /obj/item/projectile/magic/spellblade,
+ /obj/item/projectile/magic/arcane_barrage)
diff --git a/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm b/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm
index 2318c54508..1f01f1f5eb 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm
@@ -1,3 +1,5 @@
+GLOBAL_LIST_EMPTY(monkey_recyclers)
+
/obj/machinery/monkey_recycler
name = "monkey recycler"
desc = "A machine used for recycling dead monkeys into monkey cubes." // except it literally never does
@@ -9,24 +11,34 @@
idle_power_usage = 5
active_power_usage = 50
circuit = /obj/item/circuitboard/machine/monkey_recycler
- var/grinded = 0
- var/required_grind = 5
- var/cube_production = 1
+ var/stored_matter = 0
+ var/cube_production = 0.2
+ var/list/connected = list() //Keeps track of connected xenobio consoles, for deletion in /Destroy()
-/obj/machinery/monkey_recycler/RefreshParts()
- var/req_grind = 5
- var/cubes_made = 1
+/obj/machinery/monkey_recycler/Initialize(mapload)
+ . = ..()
+ if (mapload)
+ GLOB.monkey_recyclers += src
+
+/obj/machinery/monkey_recycler/Destroy()
+ GLOB.monkey_recyclers -= src
+ for(var/thing in connected)
+ var/obj/machinery/computer/camera_advanced/xenobio/console = thing
+ console.connected_recycler = null
+ connected.Cut()
+ return ..()
+
+/obj/machinery/monkey_recycler/RefreshParts() //Ranges from 0.2 to 0.8 per monkey recycled
+ cube_production = 0
for(var/obj/item/stock_parts/manipulator/B in component_parts)
- req_grind -= B.rating
+ cube_production += B.rating * 0.1
for(var/obj/item/stock_parts/matter_bin/M in component_parts)
- cubes_made = M.rating
- cube_production = cubes_made
- required_grind = req_grind
+ cube_production += M.rating * 0.1
/obj/machinery/monkey_recycler/examine(mob/user)
. = ..()
if(in_range(user, src) || isobserver(user))
- . += "The status display reads: Producing [cube_production] cubes for every monkey inserted."
+ to_chat(user, "The status display reads: Producing [cube_production] cubes for every monkey inserted.")
/obj/machinery/monkey_recycler/attackby(obj/item/O, mob/user, params)
if(default_deconstruction_screwdriver(user, "grinder_open", "grinder", O))
@@ -68,17 +80,23 @@
var/offset = prob(50) ? -2 : 2
animate(src, pixel_x = pixel_x + offset, time = 0.2, loop = 200) //start shaking
use_power(500)
- grinded++
+ stored_matter += cube_production
addtimer(VARSET_CALLBACK(src, pixel_x, initial(pixel_x)))
- addtimer(CALLBACK(GLOBAL_PROC, /proc/to_chat, user, "The machine now has [grinded] monkey\s worth of material stored."))
+ addtimer(CALLBACK(GLOBAL_PROC, /proc/to_chat, user, "The machine now has [stored_matter] monkey\s worth of material stored."))
/obj/machinery/monkey_recycler/interact(mob/user)
- if(grinded >= required_grind)
- to_chat(user, "The machine hisses loudly as it condenses the grinded monkey meat. After a moment, it dispenses a brand new monkey cube.")
+ if(stored_matter >= 1)
+ to_chat(user, "The machine hisses loudly as it condenses the ground monkey meat. After a moment, it dispenses a brand new monkey cube.")
playsound(src.loc, 'sound/machines/hiss.ogg', 50, 1)
- grinded -= required_grind
- for(var/i = 0, i < cube_production, i++)
+ for(var/i in 1 to FLOOR(stored_matter, 1))
new /obj/item/reagent_containers/food/snacks/cube/monkey(src.loc)
- to_chat(user, "The machine's display flashes that it has [grinded] monkeys worth of material left.")
+ stored_matter--
+ to_chat(user, "The machine's display flashes that it has [stored_matter] monkeys worth of material left.")
else
- to_chat(user, "The machine needs at least [required_grind] monkey(s) worth of material to produce a monkey cube. It only has [grinded].")
+ to_chat(user, "The machine needs at least 1 monkey worth of material to produce a monkey cube. It currently has [stored_matter].")
+
+/obj/machinery/monkey_recycler/multitool_act(mob/living/user, obj/item/multitool/I)
+ if(istype(I))
+ to_chat(user, "You log [src] in the multitool's buffer.")
+ I.buffer = src
+ return TRUE
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index 1509250dea..a7c1246728 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -415,7 +415,8 @@
"Meka" = image(icon = 'modular_splurt/icons/mob/robots_32x64.dmi', icon_state = "mekamed"), // SPLURT Addon
"Feline" = image(icon = 'modular_splurt/icons/mob/widerobot.dmi', icon_state = "vixmed-b"), // SPLURT Addon (ChompS Port)
"Raptor V-4" = image(icon = 'modular_splurt/icons/mob/robots_64x45.dmi', icon_state = "medraptor-b"), // SPLURT Addon (ChompS Port)
- "Raptor V-4 (alt)" = image(icon = 'modular_splurt/icons/mob/robots_64x45.dmi', icon_state = "traumaraptor-b") // SPLURT Addon (ChompS Port)
+ "Raptor V-4 (alt)" = image(icon = 'modular_splurt/icons/mob/robots_64x45.dmi', icon_state = "traumaraptor-b"), // SPLURT Addon (ChompS Port)
+ "Handy" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "handy_medical") // SPLURT Addon (Fallout 13)
)
var/list/L = list("Medihound" = "medihound", "Medihound Dark" = "medihounddark", "Vale" = "valemed")
for(var/a in L)
@@ -495,6 +496,10 @@
cyborg_base_icon = "haydeemedical"
cyborg_icon_override = 'modular_splurt/icons/mob/robots.dmi'
hat_offset = 3
+ if("Handy") // SPLURT Addon (Fallout 13)
+ cyborg_base_icon = "handy_medical"
+ cyborg_icon_override = 'modular_splurt/icons/mob/robots.dmi'
+ hat_offset = 3
if("Medihound")
cyborg_base_icon = "medihound"
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
@@ -643,7 +648,8 @@
"Assaultron" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "assaultron_engi"), // SPLURT Addon
"Haydee" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "haydeeengi"), // SPLURT Addon
"Feline" = image(icon = 'modular_splurt/icons/mob/widerobot.dmi', icon_state = "vixengi-b"), // SPLURT Addon (ChompS Port)
- "Raptor V-4" = image(icon = 'modular_splurt/icons/mob/robots_64x45.dmi', icon_state = "engiraptor-b") // SPLURT Addon (ChompS Port)
+ "Raptor V-4" = image(icon = 'modular_splurt/icons/mob/robots_64x45.dmi', icon_state = "engiraptor-b"), // SPLURT Addon (ChompS Port)
+ "Handy" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "handy_engineer") // SPLURT Addon (Fallout 13)
)
var/list/L = list("Pup Dozer" = "pupdozer", "Vale" = "valeeng")
for(var/a in L)
@@ -725,6 +731,10 @@
cyborg_base_icon = "bootyengineerS"
cyborg_icon_override = 'modular_splurt/icons/mob/robots.dmi'
hat_offset = 3
+ if("Handy") // SPLURT Addon (Fallout 13)
+ cyborg_base_icon = "handy_engineer"
+ cyborg_icon_override = 'modular_splurt/icons/mob/robots.dmi'
+ hat_offset = 3
if("Pup Dozer")
cyborg_base_icon = "pupdozer"
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
@@ -843,7 +853,10 @@
"Assaultron" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "assaultron_sec"), // SPLURT Addon
"Haydee" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "haydeesec"), // SPLURT Addon
"Feline" = image(icon = 'modular_splurt/icons/mob/widerobot.dmi', icon_state = "vixsec-b"), // SPLURT Addon (ChompS Port)
- "Raptor V-4" = image(icon = 'modular_splurt/icons/mob/robots_64x45.dmi', icon_state = "secraptor-b") // SPLURT Addon (ChompS Port)
+ "Raptor V-4" = image(icon = 'modular_splurt/icons/mob/robots_64x45.dmi', icon_state = "secraptor-b"), // SPLURT Addon (ChompS Port)
+ "Handy" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "handy_security"), // SPLURT Addon (Fallout 13)
+ "Sentry Bot" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "sentrybot"), // SPLURT Addon (Fallout 13)
+ "Securitron" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "securitron") // SPLURT Addon (Fallout 13)
)
var/list/L = list("K9" = "k9", "Vale" = "valesec", "K9 Dark" = "k9dark")
for(var/a in L)
@@ -918,6 +931,18 @@
cyborg_base_icon = "bootysecurityS"
cyborg_icon_override = 'modular_splurt/icons/mob/robots.dmi'
hat_offset = 3
+ if("Handy") // SPLURT Addon (Fallout 13)
+ cyborg_base_icon = "handy_security"
+ cyborg_icon_override = 'modular_splurt/icons/mob/robots.dmi'
+ hat_offset = 3
+ if("Sentry Bot") // SPLURT Addon (Fallout 13)
+ cyborg_base_icon = "sentrybot"
+ cyborg_icon_override = 'modular_splurt/icons/mob/robots.dmi'
+ hat_offset = 3
+ if("Securitron") // SPLURT Addon (Fallout 13)
+ cyborg_base_icon = "securitron"
+ cyborg_icon_override = 'modular_splurt/icons/mob/robots.dmi'
+ hat_offset = 3
if("K9")
cyborg_base_icon = "k9"
sleeper_overlay = "ksleeper"
@@ -1043,8 +1068,9 @@
"Assaultron" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "assaultron_peacekeeper"), // SPLURT Adoon
"Haydee" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "haydeepk"), // SPLURT Addon
"Meka" = image(icon = 'modular_splurt/icons/mob/robots_32x64.dmi', icon_state = "mekapeace"), // SPLURT Addon
- "Feline" = image(icon = 'modular_splurt/icons/mob/widerobot.dmi', icon_state = "vixpk-b") // SPLURT Addon (ChompS Port)
- ))
+ "Feline" = image(icon = 'modular_splurt/icons/mob/widerobot.dmi', icon_state = "vixpk-b"), // SPLURT Addon (ChompS Port)
+ "Handy" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "handy_peace") // SPLURT Addon (Fallout 13)
+ ))
var/peace_borg_icon = show_radial_menu(R, R , peace_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
switch(peace_borg_icon)
if("Default")
@@ -1084,6 +1110,10 @@
cyborg_base_icon = "bootypeaceS"
cyborg_icon_override = 'modular_splurt/icons/mob/robots.dmi'
hat_offset = 3
+ if("Handy") // SPLURT Addon (Fallout 13)
+ cyborg_base_icon = "handy_peace"
+ cyborg_icon_override = 'modular_splurt/icons/mob/robots.dmi'
+ hat_offset = 3
if("Borgi")
cyborg_base_icon = "borgi"
moduleselect_icon = "borgi"
@@ -1297,6 +1327,9 @@
"(Janitor) Raptor V-4" = image(icon = 'modular_splurt/icons/mob/robots_64x45.dmi', icon_state = "janiraptor-b"), // SPLURT Addon (ChompS Port)
"(Janitor Alt) Raptor V-4" = image(icon = 'modular_splurt/icons/mob/robots_64x45.dmi', icon_state = "sciraptor-b"), // SPLURT Addon (ChompS Port)
"(Waiter) Meka" = image(icon = 'modular_splurt/icons/mob/robots_32x64.dmi', icon_state = "mekaserve_alt"), // SPLURT Addon
+ "(Service) Handy" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "handy_service"), // SPLURT Addon (Fallout 13)
+ "(Janitor) Handy" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "handy_janitor"), // SPLURT Addon (Fallout 13)
+ "(Pleasure) Handy" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "handy_pleasure") // SPLURT Addon (Fallout 13)
)
var/list/L = list("(Service) DarkK9" = "k50", "(Service) Vale" = "valeserv", "(Service) ValeDark" = "valeservdark",
"(Janitor) Scrubpuppy" = "scrubpup")
@@ -1366,6 +1399,10 @@
cyborg_base_icon = "bootyserviceS"
cyborg_icon_override = 'modular_splurt/icons/mob/robots.dmi'
hat_offset = 3
+ if("(Service) Handy") // SPLURT Addon (Fallout 13)
+ cyborg_base_icon = "handy_service"
+ cyborg_icon_override = 'modular_splurt/icons/mob/robots.dmi'
+ hat_offset = 3
if("(Service) DarkK9")
cyborg_base_icon = "k50"
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
@@ -1472,6 +1509,10 @@
cyborg_base_icon = "bootyjanitorS"
cyborg_icon_override = 'modular_splurt/icons/mob/robots.dmi'
hat_offset = 3
+ if("(Janitor) Handy") // SPLURT Addon (Fallout 13)
+ cyborg_base_icon = "handy_janitor"
+ cyborg_icon_override = 'modular_splurt/icons/mob/robots.dmi'
+ hat_offset = 3
if("(Janitor) Scrubpuppy")
cyborg_base_icon = "scrubpup"
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
@@ -1532,6 +1573,10 @@
cyborg_base_icon = "mekaserve_alt"
cyborg_icon_override = 'modular_splurt/icons/mob/robots_32x64.dmi'
hat_offset = 3
+ if("(Pleasure) Handy") // SPLURT Addon (Fallout 13)
+ cyborg_base_icon = "handy_pleasure"
+ cyborg_icon_override = 'modular_splurt/icons/mob/robots.dmi'
+ hat_offset = 3
else
return FALSE
return ..()
@@ -1597,7 +1642,8 @@
"Haydee" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "haydeeminer"), // SPLURT Addon
"Meka" = image(icon = 'modular_splurt/icons/mob/robots_32x64.dmi', icon_state = "mekamine"), // SPLURT Addon
"Feline" = image(icon = 'modular_splurt/icons/mob/widerobot.dmi', icon_state = "vixmine-b"), // SPLURT Adoon (ChompS Port)
- "Raptor V-4" = image(icon = 'modular_splurt/icons/mob/robots_64x45.dmi', icon_state = "mineraptor-b") // SPLURT Adoon (ChompS Port)
+ "Raptor V-4" = image(icon = 'modular_splurt/icons/mob/robots_64x45.dmi', icon_state = "mineraptor-b"), // SPLURT Adoon (ChompS Port)
+ "Handy" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "handy_miner") // SPLURT Addon (Fallout 13)
)
var/list/L = list("Blade" = "blade", "Vale" = "valemine")
for(var/a in L)
@@ -1667,6 +1713,10 @@
cyborg_base_icon = "bootyminerS"
cyborg_icon_override = 'modular_splurt/icons/mob/robots.dmi'
hat_offset = 3
+ if("Handy") // SPLURT Addon (Fallout 13)
+ cyborg_base_icon = "handy_miner"
+ cyborg_icon_override = 'modular_splurt/icons/mob/robots.dmi'
+ hat_offset = 3
if("Blade")
cyborg_base_icon = "blade"
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm
index 02d0c17538..95eb1856d8 100644
--- a/code/modules/mob/living/simple_animal/slime/slime.dm
+++ b/code/modules/mob/living/simple_animal/slime/slime.dm
@@ -113,6 +113,10 @@
for (var/A in actions)
var/datum/action/AC = A
AC.Remove(src)
+ Target = null
+ Leader = null
+ Friends.Cut()
+ speech_buffer.Cut()
return ..()
/mob/living/simple_animal/slime/proc/initialize_mutations()
diff --git a/code/modules/research/designs/electronics_designs.dm b/code/modules/research/designs/electronics_designs.dm
index 7e5bedaf0e..b7314aa33d 100644
--- a/code/modules/research/designs/electronics_designs.dm
+++ b/code/modules/research/designs/electronics_designs.dm
@@ -140,29 +140,3 @@
build_path = /obj/item/drone_shell
category = list("Misc")
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
-
-/datum/design/xenobio_upgrade
- name = "owo"
- desc = "someone's bussin"
- build_type = PROTOLATHE
- materials = list(/datum/material/iron = 300, /datum/material/glass = 100)
- category = list("Electronics")
- departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
-
-/datum/design/xenobio_upgrade/xenobiomonkeys
- name = "Xenobiology console monkey upgrade disk"
- desc = "This disk will add the ability to remotely recycle monkeys via the Xenobiology console."
- id = "xenobio_monkeys"
- build_path = /obj/item/disk/xenobio_console_upgrade/monkey
-
-/datum/design/xenobio_upgrade/xenobioslimebasic
- name = "Xenobiology console basic slime upgrade disk"
- desc = "This disk will add the ability to remotely manipulate slimes via the Xenobiology console."
- id = "xenobio_slimebasic"
- build_path = /obj/item/disk/xenobio_console_upgrade/slimebasic
-
-/datum/design/xenobio_upgrade/xenobioslimeadv
- name = "Xenobiology console advanced slime upgrade disk"
- desc = "This disk will add the ability to remotely feed slimes potions via the Xenobiology console, and lift the restrictions on the number of slimes that can be stored inside the Xenobiology console. This includes the contents of the basic slime upgrade disk."
- id = "xenobio_slimeadv"
- build_path = /obj/item/disk/xenobio_console_upgrade/slimeadv
diff --git a/code/modules/research/techweb/nodes/bluespace_nodes.dm b/code/modules/research/techweb/nodes/bluespace_nodes.dm
index 21e002b359..c7ad71a4d3 100644
--- a/code/modules/research/techweb/nodes/bluespace_nodes.dm
+++ b/code/modules/research/techweb/nodes/bluespace_nodes.dm
@@ -5,7 +5,7 @@
display_name = "Basic Bluespace Theory"
description = "Basic studies into the mysterious alternate dimension known as bluespace."
prereq_ids = list("base", "datatheory")
- design_ids = list("beacon", "xenobioconsole", "telesci_gps", "xenobio_monkeys")
+ design_ids = list("beacon", "xenobioconsole", "telesci_gps")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
/datum/techweb_node/practical_bluespace
@@ -13,7 +13,7 @@
display_name = "Applied Bluespace Research"
description = "Using bluespace to make things faster and better."
prereq_ids = list("bluespace_basic", "engineering")
- design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "bluespacesmartdart", "xenobio_slimebasic", "bluespace_tray", "light_replacer_blue")
+ design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "bluespacesmartdart", "bluespace_tray", "light_replacer_blue")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
/datum/techweb_node/adv_bluespace
@@ -21,7 +21,7 @@
display_name = "Advanced Bluespace Research"
description = "Deeper understanding of how the Bluespace dimension works"
prereq_ids = list("practical_bluespace", "high_efficiency")
- design_ids = list("bluespace_matter_bin", "femto_mani", "triphasic_scanning", "bluespace_crystal", "xenobio_slimeadv")
+ design_ids = list("bluespace_matter_bin", "femto_mani", "triphasic_scanning", "bluespace_crystal")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000)
/datum/techweb_node/emp_super
diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm
index bccc738398..1d4c027125 100644
--- a/code/modules/research/xenobiology/xenobio_camera.dm
+++ b/code/modules/research/xenobiology/xenobio_camera.dm
@@ -30,11 +30,11 @@
var/datum/action/innate/feed_potion/potion_action
var/datum/action/innate/hotkey_help/hotkey_help
+ var/obj/machinery/monkey_recycler/connected_recycler
var/list/stored_slimes
var/obj/item/slimepotion/slime/current_potion
- var/max_slimes = 1
+ var/max_slimes = 10
var/monkeys = 0
- var/upgradetier = 0
icon_screen = "slime_comp"
icon_keyboard = "rd_key"
@@ -51,15 +51,27 @@
potion_action = new
hotkey_help = new
stored_slimes = list()
- RegisterSignal(src, COMSIG_ATOM_CONTENTS_DEL, .proc/on_contents_del)
+ for(var/obj/machinery/monkey_recycler/recycler in GLOB.monkey_recyclers)
+ if(get_area(recycler.loc) == get_area(loc))
+ connected_recycler = recycler
+ connected_recycler.connected += src
/obj/machinery/computer/camera_advanced/xenobio/Destroy()
- stored_slimes = null
QDEL_NULL(current_potion)
- for(var/i in contents)
- var/mob/living/simple_animal/slime/S = i
- if(istype(S))
- S.forceMove(drop_location())
+ for(var/thing in stored_slimes)
+ var/mob/living/simple_animal/slime/S = thing
+ S.forceMove(drop_location())
+ stored_slimes.Cut()
+ if(connected_recycler)
+ connected_recycler.connected -= src
+ connected_recycler = null
+ return ..()
+
+/obj/machinery/computer/camera_advanced/xenobio/handle_atom_del(atom/A)
+ if(A == current_potion)
+ current_potion = null
+ if(A in stored_slimes)
+ stored_slimes -= A
return ..()
/obj/machinery/computer/camera_advanced/xenobio/CreateEye()
@@ -72,22 +84,22 @@
/obj/machinery/computer/camera_advanced/xenobio/GrantActions(mob/living/user)
..()
- if(slime_up_action && (upgradetier & XENOBIO_UPGRADE_SLIMEBASIC)) //CIT CHANGE - makes slime-related actions require XENOBIO_UPGRADE_SLIMEBASIC
+ if(slime_up_action)
slime_up_action.target = src
slime_up_action.Grant(user)
actions += slime_up_action
- if(slime_place_action && (upgradetier & XENOBIO_UPGRADE_SLIMEBASIC)) //CIT CHANGE - makes slime-related actions require XENOBIO_UPGRADE_SLIMEBASIC
+ if(slime_place_action)
slime_place_action.target = src
slime_place_action.Grant(user)
actions += slime_place_action
- if(feed_slime_action && (upgradetier & XENOBIO_UPGRADE_MONKEYS)) //CIT CHANGE - makes monkey-related actions require XENOBIO_UPGRADE_MONKEYS
+ if(feed_slime_action)
feed_slime_action.target = src
feed_slime_action.Grant(user)
actions += feed_slime_action
- if(monkey_recycle_action && (upgradetier & XENOBIO_UPGRADE_MONKEYS)) //CIT CHANGE - makes monkey-related actions require XENOBIO_UPGRADE_MONKEYS
+ if(monkey_recycle_action)
monkey_recycle_action.target = src
monkey_recycle_action.Grant(user)
actions += monkey_recycle_action
@@ -97,7 +109,7 @@
scan_action.Grant(user)
actions += scan_action
- if(potion_action && (upgradetier & XENOBIO_UPGRADE_SLIMEADV)) // CIT CHANGE - makes giving slimes potions via console require XENOBIO_UPGRADE_SLIMEADV
+ if(potion_action)
potion_action.target = src
potion_action.Grant(user)
actions += potion_action
@@ -123,35 +135,13 @@
UnregisterSignal(user, COMSIG_XENO_MONKEY_CLICK_CTRL)
..()
-/obj/machinery/computer/camera_advanced/xenobio/proc/on_contents_del(atom/deleted)
- if(current_potion == deleted)
- current_potion = null
- if(deleted in stored_slimes)
- stored_slimes -= deleted
-
/obj/machinery/computer/camera_advanced/xenobio/attackby(obj/item/O, mob/user, params)
- if(istype(O, /obj/item/disk/xenobio_console_upgrade))
- var/obj/item/disk/xenobio_console_upgrade/diskthing = O
- var/successfulupgrade = FALSE
- for(var/I in diskthing.upgradetypes)
- if(upgradetier & I)
- continue
- else
- upgradetier |= I
- successfulupgrade = TRUE
- if(I == XENOBIO_UPGRADE_SLIMEADV)
- max_slimes = 10
- if(successfulupgrade)
- to_chat(user, "You have successfully upgraded [src] with [O].")
- else
- to_chat(user, "[src] already has the contents of [O] installed!")
- return
- if(istype(O, /obj/item/reagent_containers/food/snacks/cube/monkey) && (upgradetier & XENOBIO_UPGRADE_MONKEYS)) //CIT CHANGE - makes monkey-related actions require XENOBIO_UPGRADE_MONKEYS
+ if(istype(O, /obj/item/reagent_containers/food/snacks/cube/monkey))
monkeys++
to_chat(user, "You feed [O] to [src]. It now has [monkeys] monkey cubes stored.")
qdel(O)
return
- else if(istype(O, /obj/item/storage/bag) && (upgradetier & XENOBIO_UPGRADE_MONKEYS)) //CIT CHANGE - makes monkey-related actions require XENOBIO_UPGRADE_MONKEYS
+ else if(istype(O, /obj/item/storage/bag))
var/obj/item/storage/P = O
var/loaded = FALSE
for(var/obj/G in P.contents)
@@ -162,7 +152,7 @@
if(loaded)
to_chat(user, "You fill [src] with the monkey cubes stored in [O]. [src] now has [monkeys] monkey cubes stored.")
return
- else if(istype(O, /obj/item/slimepotion/slime) && (upgradetier & XENOBIO_UPGRADE_SLIMEADV)) // CIT CHANGE - makes giving slimes potions via console require XENOBIO_UPGRADE_SLIMEADV
+ else if(istype(O, /obj/item/slimepotion/slime))
var/replaced = FALSE
if(user && !user.transferItemToLoc(O, src))
return
@@ -174,6 +164,13 @@
return
..()
+/obj/machinery/computer/camera_advanced/xenobio/multitool_act(mob/living/user, obj/item/multitool/I)
+ if (istype(I) && istype(I.buffer,/obj/machinery/monkey_recycler))
+ to_chat(user, "You link [src] with [I.buffer] in [I] buffer.")
+ connected_recycler = I.buffer
+ connected_recycler.connected += src
+ return TRUE
+
/datum/action/innate/slime_place
name = "Place Slimes"
icon_icon = 'icons/mob/actions/actions_silicon.dmi'
@@ -237,12 +234,13 @@
var/mob/living/carbon/monkey/food = new /mob/living/carbon/monkey(remote_eye.loc, TRUE, owner)
if (!QDELETED(food))
food.LAssailant = WEAKREF(C)
- X.monkeys --
- to_chat(owner, "[X] now has [X.monkeys] monkey(s) left.")
+ X.monkeys--
+ X.monkeys = round(X.monkeys, 0.1) //Prevents rounding errors
+ to_chat(owner, "[X] now has [X.monkeys] monkeys stored.")
else
- to_chat(owner, "[X] needs to have at least 1 monkey stored. Currently has [X.monkeys] monkeys stored.")
+ to_chat(owner, "[X] needs to have at least 1 monkey stored. Currently has [X.monkeys] monkeys stored.")
else
- to_chat(owner, "Target is not near a camera. Cannot proceed.")
+ to_chat(owner, "Target is not near a camera. Cannot proceed.")
/datum/action/innate/monkey_recycle
@@ -256,13 +254,20 @@
var/mob/living/C = owner
var/mob/camera/aiEye/remote/xenobio/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/xenobio/X = target
+ var/obj/machinery/monkey_recycler/recycler = X.connected_recycler
+ if(!recycler)
+ to_chat(owner, "There is no connected monkey recycler. Use a multitool to link one.")
+ return
if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
for(var/mob/living/carbon/monkey/M in remote_eye.loc)
if(M.stat)
M.visible_message("[M] vanishes as [M.p_theyre()] reclaimed for recycling!")
- X.monkeys = round(X.monkeys + 0.2,0.1)
+ recycler.use_power(500)
+ X.monkeys += recycler.cube_production
+ X.monkeys = round(X.monkeys, 0.1) //Prevents rounding errors
qdel(M)
+ to_chat(owner, "[X] now has [X.monkeys] monkeys available.")
else
to_chat(owner, "Target is not near a camera. Cannot proceed.")
@@ -310,33 +315,6 @@
//Demodularized Code
-/obj/item/disk/xenobio_console_upgrade
- name = "Xenobiology console upgrade disk"
- desc = "Allan please add detail."
- icon_state = "datadisk5"
- var/list/upgradetypes = list()
-
-/obj/item/disk/xenobio_console_upgrade/admin
- name = "Xenobio all access thing"
- desc = "'the consoles are literally useless!!!!!!!!!!!!!!!'"
- upgradetypes = list(XENOBIO_UPGRADE_SLIMEBASIC, XENOBIO_UPGRADE_SLIMEADV, XENOBIO_UPGRADE_MONKEYS)
-
-/obj/item/disk/xenobio_console_upgrade/monkey
- name = "Xenobiology console monkey upgrade disk"
- desc = "This disk will add the ability to remotely recycle monkeys via the Xenobiology console."
- upgradetypes = list(XENOBIO_UPGRADE_MONKEYS)
-
-/obj/item/disk/xenobio_console_upgrade/slimebasic
- name = "Xenobiology console basic slime upgrade disk"
- desc = "This disk will add the ability to remotely manipulate slimes via the Xenobiology console."
- upgradetypes = list(XENOBIO_UPGRADE_SLIMEBASIC)
-
-/obj/item/disk/xenobio_console_upgrade/slimeadv
- name = "Xenobiology console advanced slime upgrade disk"
- desc = "This disk will add the ability to remotely feed slimes potions via the Xenobiology console, and lift the restrictions on the number of slimes that can be stored inside the Xenobiology console. This includes the contents of the basic slime upgrade disk."
- upgradetypes = list(XENOBIO_UPGRADE_SLIMEBASIC, XENOBIO_UPGRADE_SLIMEADV)
-
-
//Xenobio Hotkeys Port
/datum/action/innate/hotkey_help
@@ -399,9 +377,6 @@
//Feeds a potion to slime
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickAlt(mob/living/user, mob/living/simple_animal/slime/S)
- if(!(upgradetier & XENOBIO_UPGRADE_SLIMEADV)) //CIT CHANGE - makes slime-related actions require XENOBIO_UPGRADE_SLIMEADV
- to_chat(user, "This console does not have the advanced slime upgrade.")
- return
if(!GLOB.cameranet.checkTurfVis(S.loc))
to_chat(user, "Target is not near a camera. Cannot proceed.")
return
@@ -417,9 +392,6 @@
//Picks up slime
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickShift(mob/living/user, mob/living/simple_animal/slime/S)
- if(!(upgradetier & XENOBIO_UPGRADE_SLIMEBASIC)) //CIT CHANGE - makes slime-related actions require XENOBIO_UPGRADE_SLIMEBASIC
- to_chat(user, "This console does not have the basic slime upgrade.")
- return
if(!GLOB.cameranet.checkTurfVis(S.loc))
to_chat(user, "Target is not near a camera. Cannot proceed.")
return
@@ -442,9 +414,6 @@
//Place slimes
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoTurfClickShift(mob/living/user, turf/open/T)
- if(!(upgradetier & XENOBIO_UPGRADE_SLIMEBASIC)) //CIT CHANGE - makes slime-related actions require XENOBIO_UPGRADE_SLIMEBASIC
- to_chat(user, "This console does not have the basic slime upgrade.")
- return
if(!GLOB.cameranet.checkTurfVis(T))
to_chat(user, "Target is not near a camera. Cannot proceed.")
return
@@ -460,9 +429,6 @@
//Place monkey
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoTurfClickCtrl(mob/living/user, turf/open/T)
- if(!(upgradetier & XENOBIO_UPGRADE_MONKEYS)) // CIT CHANGE - makes monkey-related actions require XENOBIO_UPGRADE_MONKEYS
- to_chat(user, "This console does not have the monkey upgrade.")
- return
if(!GLOB.cameranet.checkTurfVis(T))
to_chat(user, "Target is not near a camera. Cannot proceed.")
return
@@ -477,15 +443,12 @@
food.LAssailant = WEAKREF(C)
X.monkeys--
X.monkeys = round(X.monkeys, 0.1) //Prevents rounding errors
- to_chat(C, "[X] now has [X.monkeys] monkey(s) stored.")
+ to_chat(C, "[X] now has [X.monkeys] monkeys stored.")
else
- to_chat(C, "[X] needs to have at least 1 monkey stored. Currently has [X.monkeys] monkeys stored.")
+ to_chat(C, "[X] needs to have at least 1 monkey stored. Currently has [X.monkeys] monkeys stored.")
//Pick up monkey
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoMonkeyClickCtrl(mob/living/user, mob/living/carbon/monkey/M)
- if(!(upgradetier & XENOBIO_UPGRADE_MONKEYS)) // CIT CHANGE - makes monkey-related actions require XENOBIO_UPGRADE_MONKEYS
- to_chat(user, "This console does not have the monkey upgrade.")
- return
if(!isturf(M.loc) || !GLOB.cameranet.checkTurfVis(M.loc))
to_chat(user, "Target is not near a camera. Cannot proceed.")
return
@@ -493,11 +456,15 @@
var/mob/camera/aiEye/remote/xenobio/E = C.remote_control
var/obj/machinery/computer/camera_advanced/xenobio/X = E.origin
var/area/mobarea = get_area(M.loc)
+ if(!X.connected_recycler)
+ to_chat(C, "There is no connected monkey recycler. Use a multitool to link one.")
+ return
if(mobarea.name == E.allowed_area || mobarea.xenobiology_compatible)
if(!M.stat)
return
M.visible_message("[M] vanishes as [p_theyre()] reclaimed for recycling!")
- X.monkeys = round(X.monkeys + 0.2,0.1)
+ X.connected_recycler.use_power(500)
+ X.monkeys += connected_recycler.cube_production
+ X.monkeys = round(X.monkeys, 0.1) //Prevents rounding errors
qdel(M)
- if (X.monkeys == (round(X.monkeys,1)))
- to_chat(C, "[X] now has [X.monkeys] monkey(s) available.")
+ to_chat(C, "[X] now has [X.monkeys] monkeys available.")
diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm
index 10fab0ed06..24a841a14f 100644
--- a/code/modules/research/xenobiology/xenobiology.dm
+++ b/code/modules/research/xenobiology/xenobiology.dm
@@ -940,6 +940,7 @@
M.visible_message("[M] has a new name, [new_name].", "Your old name of [M.real_name] fades away, and your new name [new_name] anchors itself in your mind.")
message_admins("[ADMIN_LOOKUPFLW(user)] used [src] on [ADMIN_LOOKUPFLW(M)], letting them rename themselves into [new_name].")
+ log_game("[key_name(user)] used [src] on [key_name(M)], letting them rename themselves into [new_name].")
// pass null as first arg to not update records or ID/PDA
M.fully_replace_character_name(null, new_name)
diff --git a/code/modules/tgs/v5/__interop_version.dm b/code/modules/tgs/v5/__interop_version.dm
index 1b52b31d6a..83420d130a 100644
--- a/code/modules/tgs/v5/__interop_version.dm
+++ b/code/modules/tgs/v5/__interop_version.dm
@@ -1 +1 @@
-"5.6.2"
+"5.7.0"
diff --git a/code/modules/tgs/v5/_defines.dm b/code/modules/tgs/v5/_defines.dm
index bdcd4e4dd5..48969c0c7d 100644
--- a/code/modules/tgs/v5/_defines.dm
+++ b/code/modules/tgs/v5/_defines.dm
@@ -80,6 +80,7 @@
#define DMAPI5_TOPIC_COMMAND_WATCHDOG_REATTACH 8
#define DMAPI5_TOPIC_COMMAND_SEND_CHUNK 9
#define DMAPI5_TOPIC_COMMAND_RECEIVE_CHUNK 10
+#define DMAPI5_TOPIC_COMMAND_RECEIVE_BROADCAST 11
#define DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE "commandType"
#define DMAPI5_TOPIC_PARAMETER_CHAT_COMMAND "chatCommand"
@@ -89,6 +90,7 @@
#define DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME "newInstanceName"
#define DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE "chatUpdate"
#define DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION "newServerVersion"
+#define DMAPI5_TOPIC_PARAMETER_BROADCAST_MESSAGE "broadcastMessage"
#define DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE "commandResponse"
#define DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE "commandResponseMessage"
diff --git a/code/modules/tgs/v5/topic.dm b/code/modules/tgs/v5/topic.dm
index d7d4712138..2ef0c70a97 100644
--- a/code/modules/tgs/v5/topic.dm
+++ b/code/modules/tgs/v5/topic.dm
@@ -94,7 +94,7 @@
if(DMAPI5_TOPIC_COMMAND_CHANGE_PORT)
var/new_port = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT]
if (!isnum(new_port) || !(new_port > 0))
- return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_PORT]]")
+ return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_PORT]")
if(event_handler != null)
event_handler.HandleEvent(TGS_EVENT_PORT_SWAP, new_port)
@@ -141,7 +141,7 @@
if(DMAPI5_TOPIC_COMMAND_SERVER_PORT_UPDATE)
var/new_port = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT]
if (!isnum(new_port) || !(new_port > 0))
- return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_PORT]]")
+ return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_PORT]")
server_port = new_port
return TopicResponse()
@@ -157,7 +157,7 @@
var/error_message = null
if (new_port != null)
if (!isnum(new_port) || !(new_port > 0))
- error_message = "Invalid [DMAPI5_TOPIC_PARAMETER_NEW_PORT]]"
+ error_message = "Invalid [DMAPI5_TOPIC_PARAMETER_NEW_PORT]"
else
server_port = new_port
@@ -165,7 +165,7 @@
if (!istext(new_version_string))
if(error_message != null)
error_message += ", "
- error_message += "Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION]]"
+ error_message += "Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION]"
else
var/datum/tgs_version/new_version = new(new_version_string)
if (event_handler)
@@ -267,4 +267,16 @@
return chunk_to_send
+ if(DMAPI5_TOPIC_COMMAND_RECEIVE_BROADCAST)
+ var/message = topic_parameters[DMAPI5_TOPIC_PARAMETER_BROADCAST_MESSAGE]
+ if (!istext(message))
+ return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_BROADCAST_MESSAGE]")
+
+ TGS_WORLD_ANNOUNCE(message)
+ return TopicResponse()
+
return TopicResponse("Unknown command: [command]")
+
+/datum/tgs_api/v5/proc/WorldBroadcast(message)
+ set waitfor = FALSE
+ TGS_WORLD_ANNOUNCE(message)
diff --git a/code/modules/tgs/v5/undefs.dm b/code/modules/tgs/v5/undefs.dm
index f163adaaaf..fd1ed7e4cf 100644
--- a/code/modules/tgs/v5/undefs.dm
+++ b/code/modules/tgs/v5/undefs.dm
@@ -78,6 +78,9 @@
#undef DMAPI5_TOPIC_COMMAND_SERVER_PORT_UPDATE
#undef DMAPI5_TOPIC_COMMAND_HEALTHCHECK
#undef DMAPI5_TOPIC_COMMAND_WATCHDOG_REATTACH
+#undef DMAPI5_TOPIC_COMMAND_SEND_CHUNK
+#undef DMAPI5_TOPIC_COMMAND_RECEIVE_CHUNK
+#undef DMAPI5_TOPIC_COMMAND_RECEIVE_BROADCAST
#undef DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE
#undef DMAPI5_TOPIC_PARAMETER_CHAT_COMMAND
@@ -87,6 +90,7 @@
#undef DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME
#undef DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE
#undef DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION
+#undef DMAPI5_TOPIC_PARAMETER_BROADCAST_MESSAGE
#undef DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE
#undef DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE
diff --git a/html/changelogs/archive/2023-11.yml b/html/changelogs/archive/2023-11.yml
index e74910f967..ef27529d3e 100644
--- a/html/changelogs/archive/2023-11.yml
+++ b/html/changelogs/archive/2023-11.yml
@@ -37,3 +37,14 @@
the OG PR.
- rscadd: Repurposes ported sciraptor and sci-catborg sprites to be an alternative
service (janitor) module.
+2023-11-18:
+ Chlorotrifluoride:
+ - imageadd: modified sprites of tall jackboots, toeless jackboots and toeless workboots.
+ MysteryMan21333:
+ - rscadd: Adds werewolves!
+ - rscadd: Added new borg sprites, Mr. Handy variations, Cyclone, Sentry Bot, Securitron,
+ Etc.
+ - balance: reworks magic carp for xenobiology, reworks monkey processors, & improved
+ code for xenobiology.
+ - bugfix: prevents bluespace anomalies from shitting on cameras & logging for sentience
+ potion on admin side.
diff --git a/icons/mob/slimes.dmi b/icons/mob/slimes.dmi
index f9998d6f10..56094049e2 100644
Binary files a/icons/mob/slimes.dmi and b/icons/mob/slimes.dmi differ
diff --git a/icons/obj/decals.dmi b/icons/obj/decals.dmi
index 892f974afd..9216c94b67 100644
Binary files a/icons/obj/decals.dmi and b/icons/obj/decals.dmi differ
diff --git a/modular_splurt/code/_onclick/ai.dm b/modular_splurt/code/_onclick/ai.dm
new file mode 100644
index 0000000000..722056d9af
--- /dev/null
+++ b/modular_splurt/code/_onclick/ai.dm
@@ -0,0 +1,2 @@
+/atom/AIShiftClick(mob/living/silicon/ai/user) //forward to human click if not overridden
+ user.examinate(src)
diff --git a/modular_splurt/code/modules/mob/living/silicon/ai/freelook/eye.dm b/modular_splurt/code/modules/mob/living/silicon/ai/freelook/eye.dm
new file mode 100644
index 0000000000..59c179233b
--- /dev/null
+++ b/modular_splurt/code/modules/mob/living/silicon/ai/freelook/eye.dm
@@ -0,0 +1,3 @@
+/mob/living/silicon/ai/create_eye()
+ . = ..()
+ eyeobj.relay_speech = TRUE
diff --git a/modular_splurt/code/modules/mob/living/silicon/robot/robot_modules.dm b/modular_splurt/code/modules/mob/living/silicon/robot/robot_modules.dm
index d9d74bff18..367aa09515 100644
--- a/modular_splurt/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/modular_splurt/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -20,8 +20,10 @@
"BootyF" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "bootystandard"),
"BootyM" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "bootystandardM"),
"BootyS" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "bootystandardS"),
- "Assaultron" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "assaultron_standard")
- )
+ "Handy" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "handy"),
+ "Robo-Brain" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "robobrain"),
+ "Cyclone" = image(icon = 'modular_splurt/icons/mob/robots.dmi', icon_state = "cyclone")
+ )
stand_icons = sortList(stand_icons)
var/stand_borg_icon = show_radial_menu(R, R , stand_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
if(!stand_borg_icon)
@@ -75,6 +77,18 @@
cyborg_base_icon = "assaultron_standard"
cyborg_icon_override = 'modular_splurt/icons/mob/robots.dmi'
hat_offset = 3
+ if("Handy")
+ cyborg_base_icon = "handy"
+ cyborg_icon_override = 'modular_splurt/icons/mob/robots.dmi'
+ hat_offset = 3
+ if("Robo-Brain")
+ cyborg_base_icon = "robobrain"
+ cyborg_icon_override = 'modular_splurt/icons/mob/robots.dmi'
+ hat_offset = 3
+ if("Cyclone")
+ cyborg_base_icon = "cyclone"
+ cyborg_icon_override = 'modular_splurt/icons/mob/robots.dmi'
+ hat_offset = 3
return ..()
/obj/item/robot_module/clown/be_transformed_to(obj/item/robot_module/old_module)
diff --git a/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/funwolf.dm b/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/funwolf.dm
new file mode 100644
index 0000000000..5ecbef8b41
--- /dev/null
+++ b/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/funwolf.dm
@@ -0,0 +1,848 @@
+/mob/living/simple_animal/hostile/werewolf/funwolf
+ name = "Fun Werewolf"
+ desc = "A massive, wolf like creature with powerful muscles, razor-sharp claws, and aggression to match. This one seems to have a strange look in its eyes.."
+ var/change_target_hole_cooldown = 0
+ var/chosen_hole
+ var/voremode = FALSE // Fixes runtime when grabbing victim
+ gold_core_spawnable = NO_SPAWN // Admin only
+ werewolf_mode = "rape"
+
+/mob/living/simple_animal/hostile/werewolf/funwolf/gentle
+ name = "Gentle Werewolf"
+ desc = "A massive, wolf like creature with powerful muscles, razor-sharp claws, and aggression to match. This one has the bedroom eyes.."
+ werewolf_mode = "gentle"
+
+/mob/living/simple_animal/hostile/werewolf/funwolf/abomination
+ name = "Exiled Werewolf"
+ desc = "A massive, wolf like creature with powerful muscles, razor-sharp claws, and aggression to match. This one has a strange smell for some reason.."
+ werewolf_mode = "abomination"
+
+/mob/living/simple_animal/hostile/werewolf/funwolf/AttackingTarget()
+ var/mob/living/M = target
+
+ var/onLewdCooldown = FALSE
+ var/wantsNoncon = FALSE
+
+ if(get_refraction_dif() > 0)
+ onLewdCooldown = TRUE
+
+ if(M.client && M.client?.prefs.erppref == "Yes" && CHECK_BITFIELD(M.client?.prefs.toggles, VERB_CONSENT) && M.client?.prefs.nonconpref == "Yes")
+ wantsNoncon = TRUE
+
+ switch(werewolf_mode)
+ if("gentle")
+ if(onLewdCooldown || !wantsNoncon)
+ return // Do nothing
+ if("abomination")
+ if(onLewdCooldown || !wantsNoncon)
+ return // Do nothing
+ if("rape")
+ if(onLewdCooldown || !wantsNoncon || M.health > 60)
+ ..() // Attack target
+ return
+
+ if(!M.pulledby)
+ if(!M.buckled && !M.density)
+ M.forceMove(src.loc)
+
+ start_pulling(M, supress_message = TRUE)
+ log_combat(src, M, "grabbed")
+ M.visible_message(span_warning("[src] violently grabs [M]!"), \
+ span_userdanger("[src] violently grabs you!"))
+ setGrabState(GRAB_NECK) //Instant neck grab
+
+ return
+
+ if(get_refraction_dif() > 0)
+ ..()
+ return
+
+ if(change_target_hole_cooldown < world.time)
+ chosen_hole = null
+ while (chosen_hole == null)
+ pickNewHole(M)
+ change_target_hole_cooldown = world.time + 100
+
+
+ do_lewd_action(M)
+ addtimer(CALLBACK(src, .proc/do_lewd_action, M), rand(8, 12))
+
+ // Regular sex has an extra action per tick to seem less slow and robotic
+ if(werewolf_mode != "abomination" || M.client?.prefs.unholypref != "Yes")
+ addtimer(CALLBACK(src, .proc/do_lewd_action, M), rand(12, 16))
+
+
+/mob/living/simple_animal/hostile/werewolf/funwolf/proc/pickNewHole(mob/living/M)
+ switch(rand(2))
+ if(0)
+ chosen_hole = CUM_TARGET_ANUS
+ if(1)
+ if(M.has_vagina())
+ chosen_hole = CUM_TARGET_VAGINA
+ else
+ chosen_hole = CUM_TARGET_ANUS
+ if(2)
+ chosen_hole = CUM_TARGET_THROAT
+
+/mob/living/simple_animal/hostile/werewolf/funwolf/proc/do_lewd_action(mob/living/M)
+ if(get_refraction_dif() > 0)
+ return
+
+ if(rand(1,7) == 7)
+ playlewdinteractionsound(loc, "modular_splurt/sound/lewd/deathclaw_grunt[rand(1, 5)].ogg", 30, 1, -1)
+
+ var/datum/interaction/I
+ switch(chosen_hole)
+ if(CUM_TARGET_ANUS)
+ if(tearSlot(M, ITEM_SLOT_OCLOTHING))
+ return
+ if(tearSlot(M, ITEM_SLOT_ICLOTHING))
+ return
+
+ // Abomination deathclaws do other stuff instead
+ if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes")
+ if(prob(1))
+ I = SSinteractions.interactions["/datum/interaction/lewd/grindmouth"]
+ else
+ I = SSinteractions.interactions["/datum/interaction/lewd/grindface"]
+ handle_post_sex(25, null, M)
+ else
+ I = SSinteractions.interactions["/datum/interaction/lewd/fuck/anal"]
+ I.display_interaction(src, M)
+
+ if(CUM_TARGET_VAGINA)
+ if(tearSlot(M, ITEM_SLOT_OCLOTHING))
+ return
+ if(tearSlot(M, ITEM_SLOT_ICLOTHING))
+ return
+
+ // Abomination deathclaws do other stuff instead
+ if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes")
+ I = SSinteractions.interactions["/datum/interaction/lewd/footjob/vagina"]
+ handle_post_sex(10, null, M)
+ else
+ I = SSinteractions.interactions["/datum/interaction/lewd/fuck"]
+ I.display_interaction(src, M)
+
+ if(CUM_TARGET_THROAT)
+ if(tearSlot(M, ITEM_SLOT_HEAD))
+ return
+ if(tearSlot(M, ITEM_SLOT_MASK))
+ return
+
+ // Abomination deathclaws do other stuff instead
+ if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes")
+ if(prob(1))
+ do_faceshit(M)
+ else
+ do_facefart(M)
+ handle_post_sex(25, null, M)
+ shake_camera(M, 6, 1)
+ else
+ I = SSinteractions.interactions["/datum/interaction/lewd/throatfuck"]
+ I.display_interaction(src, M)
+
+/mob/living/simple_animal/hostile/werewolf/funwolf/cum(mob/living/M)
+
+ if(get_refraction_dif() > 0)
+ return
+
+ var/message
+
+ if(!istype(M))
+ chosen_hole = null
+
+ switch(chosen_hole)
+ if(CUM_TARGET_THROAT)
+ if(M.has_mouth() && M.mouth_is_free())
+ message = "shoves their fat canine cock deep down \the [M]'s throat and cums."
+ else
+ message = "cums on \the [M]'s face."
+ if(CUM_TARGET_VAGINA)
+ if(M.is_bottomless() && M.has_vagina())
+ message = "rams its meaty cock into \the [M]'s pussy and fills it with sperm."
+ M.impregnate(src, M.getorganslot(ORGAN_SLOT_WOMB), src.type)
+ else
+ message = "cums on \the [M]'s belly."
+ if(CUM_TARGET_ANUS)
+ if(M.is_bottomless() && M.has_anus())
+ message = "hilts its knot into \the [M]'s ass and floods it with Werewolf jizz."
+ else
+ message = "cums on \the [M]'s backside."
+ else
+ message = "cums on the floor!"
+
+ if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes")
+ message = "cums all over [M]'s body"
+
+ if(istype(M, /mob/living/carbon))
+ M.reagents.add_reagent(/datum/reagent/consumable/semen, 30)
+ new /obj/effect/decal/cleanable/semen(loc)
+
+ playlewdinteractionsound(loc, "modular_splurt/sound/lewd/deathclaw[rand(1, 2)].ogg", 30, 1, -1)
+ visible_message("\The [src] [message]")
+ shake_camera(M, 6, 1)
+ set_is_fucking(null ,null)
+
+ refractory_period = world.time + rand(100, 150) // Sex cooldown
+ set_lust(0) // Nuts at 400
+
+ addtimer(CALLBACK(src, .proc/slap, M), 15)
+
+
+/mob/living/simple_animal/hostile/werewolf/funwolf/proc/slap(mob/living/M)
+ playlewdinteractionsound(loc, "modular_sand/sound/interactions/slap.ogg", 30, 1, -1)
+ visible_message(span_danger("\The [src] slaps \the [M] right on the ass!"), \
+ span_userdanger("\The [src] slaps \the [M] right on the ass!"), null, COMBAT_MESSAGE_RANGE)
+
+/mob/living/simple_animal/hostile/werewolf/funwolf/proc/tearSlot(mob/living/M, slot)
+ var/obj/item/W = M.get_item_by_slot(slot)
+ if(W)
+ M.dropItemToGround(W)
+ playlewdinteractionsound(loc, "sound/items/poster_ripped.ogg", 30, 1, -1)
+ visible_message(span_danger("\The [src] tears off \the [M]'s clothes!"), \
+ span_userdanger("\The [src] tears off \the [M]'s clothes!"), null, COMBAT_MESSAGE_RANGE)
+ return TRUE
+ return FALSE
+
+////////////////
+// //
+// Ice Wolf //
+// //
+////////////////
+
+/mob/living/simple_animal/hostile/ice_wolf/funwolf
+ name = "Fun Ice Wolf"
+ desc = "A massive, ice wolf like creature with powerful muscles, gleaming-cold claws, and aggression to match. This one seems to have a strange look in its eyes.."
+ var/change_target_hole_cooldown = 0
+ var/chosen_hole
+ var/voremode = FALSE // Fixes runtime when grabbing victim
+ gold_core_spawnable = NO_SPAWN // Admin only
+ werewolf_mode = "rape"
+
+/mob/living/simple_animal/hostile/ice_wolf/funwolf/gentle
+ name = "Gentle Ice Wolf"
+ desc = "A massive, ice wolf like creature with powerful muscles, gleaming-cold claws, and aggression to match. This one has the bedroom eyes.."
+ werewolf_mode = "gentle"
+
+/mob/living/simple_animal/hostile/ice_wolf/funwolf/abomination
+ name = "Exiled Ice Wolf"
+ desc = "A massive, ice wolf like creature with powerful muscles, gleaming-cold claws, and aggression to match. This one has a strange smell for some reason.."
+ werewolf_mode = "abomination"
+
+/mob/living/simple_animal/hostile/ice_wolf/funwolf/AttackingTarget()
+ var/mob/living/M = target
+
+ var/onLewdCooldown = FALSE
+ var/wantsNoncon = FALSE
+
+ if(get_refraction_dif() > 0)
+ onLewdCooldown = TRUE
+
+ if(M.client && M.client?.prefs.erppref == "Yes" && CHECK_BITFIELD(M.client?.prefs.toggles, VERB_CONSENT) && M.client?.prefs.nonconpref == "Yes")
+ wantsNoncon = TRUE
+
+ switch(werewolf_mode)
+ if("gentle")
+ if(onLewdCooldown || !wantsNoncon)
+ return // Do nothing
+ if("abomination")
+ if(onLewdCooldown || !wantsNoncon)
+ return // Do nothing
+ if("rape")
+ if(onLewdCooldown || !wantsNoncon || M.health > 60)
+ ..() // Attack target
+ return
+
+ if(!M.pulledby)
+ if(!M.buckled && !M.density)
+ M.forceMove(src.loc)
+
+ start_pulling(M, supress_message = TRUE)
+ log_combat(src, M, "grabbed")
+ M.visible_message(span_warning("[src] violently grabs [M]!"), \
+ span_userdanger("[src] violently grabs you!"))
+ setGrabState(GRAB_NECK) //Instant neck grab
+
+ return
+
+ if(get_refraction_dif() > 0)
+ ..()
+ return
+
+ if(change_target_hole_cooldown < world.time)
+ chosen_hole = null
+ while (chosen_hole == null)
+ pickNewHole(M)
+ change_target_hole_cooldown = world.time + 100
+
+
+ do_lewd_action(M)
+ addtimer(CALLBACK(src, .proc/do_lewd_action, M), rand(8, 12))
+
+ // Regular sex has an extra action per tick to seem less slow and robotic
+ if(werewolf_mode != "abomination" || M.client?.prefs.unholypref != "Yes")
+ addtimer(CALLBACK(src, .proc/do_lewd_action, M), rand(12, 16))
+
+
+/mob/living/simple_animal/hostile/ice_wolf/funwolf/proc/pickNewHole(mob/living/M)
+ switch(rand(2))
+ if(0)
+ chosen_hole = CUM_TARGET_ANUS
+ if(1)
+ if(M.has_vagina())
+ chosen_hole = CUM_TARGET_VAGINA
+ else
+ chosen_hole = CUM_TARGET_ANUS
+ if(2)
+ chosen_hole = CUM_TARGET_THROAT
+
+/mob/living/simple_animal/hostile/ice_wolf/funwolf/proc/do_lewd_action(mob/living/M)
+ if(get_refraction_dif() > 0)
+ return
+
+ if(rand(1,7) == 7)
+ playlewdinteractionsound(loc, "modular_splurt/sound/lewd/deathclaw_grunt[rand(1, 5)].ogg", 30, 1, -1)
+
+ var/datum/interaction/I
+ switch(chosen_hole)
+ if(CUM_TARGET_ANUS)
+ if(tearSlot(M, ITEM_SLOT_OCLOTHING))
+ return
+ if(tearSlot(M, ITEM_SLOT_ICLOTHING))
+ return
+
+ // Abomination deathclaws do other stuff instead
+ if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes")
+ if(prob(1))
+ I = SSinteractions.interactions["/datum/interaction/lewd/grindmouth"]
+ else
+ I = SSinteractions.interactions["/datum/interaction/lewd/grindface"]
+ handle_post_sex(25, null, M)
+ else
+ I = SSinteractions.interactions["/datum/interaction/lewd/fuck/anal"]
+ I.display_interaction(src, M)
+
+ if(CUM_TARGET_VAGINA)
+ if(tearSlot(M, ITEM_SLOT_OCLOTHING))
+ return
+ if(tearSlot(M, ITEM_SLOT_ICLOTHING))
+ return
+
+ // Abomination deathclaws do other stuff instead
+ if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes")
+ I = SSinteractions.interactions["/datum/interaction/lewd/footjob/vagina"]
+ handle_post_sex(10, null, M)
+ else
+ I = SSinteractions.interactions["/datum/interaction/lewd/fuck"]
+ I.display_interaction(src, M)
+
+ if(CUM_TARGET_THROAT)
+ if(tearSlot(M, ITEM_SLOT_HEAD))
+ return
+ if(tearSlot(M, ITEM_SLOT_MASK))
+ return
+
+ // Abomination deathclaws do other stuff instead
+ if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes")
+ if(prob(1))
+ do_faceshit(M)
+ else
+ do_facefart(M)
+ handle_post_sex(25, null, M)
+ shake_camera(M, 6, 1)
+ else
+ I = SSinteractions.interactions["/datum/interaction/lewd/throatfuck"]
+ I.display_interaction(src, M)
+
+/mob/living/simple_animal/hostile/ice_wolf/funwolf/cum(mob/living/M)
+
+ if(get_refraction_dif() > 0)
+ return
+
+ var/message
+
+ if(!istype(M))
+ chosen_hole = null
+
+ switch(chosen_hole)
+ if(CUM_TARGET_THROAT)
+ if(M.has_mouth() && M.mouth_is_free())
+ message = "shoves their fat canine cock deep down \the [M]'s throat and cums."
+ else
+ message = "cums on \the [M]'s face."
+ if(CUM_TARGET_VAGINA)
+ if(M.is_bottomless() && M.has_vagina())
+ message = "rams its meaty cock into \the [M]'s pussy and fills it with sperm."
+ M.impregnate(src, M.getorganslot(ORGAN_SLOT_WOMB), src.type)
+ else
+ message = "cums on \the [M]'s belly."
+ if(CUM_TARGET_ANUS)
+ if(M.is_bottomless() && M.has_anus())
+ message = "hilts its knot into \the [M]'s ass and floods it with Werewolf jizz."
+ else
+ message = "cums on \the [M]'s backside."
+ else
+ message = "cums on the floor!"
+
+ if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes")
+ message = "cums all over [M]'s body"
+
+ if(istype(M, /mob/living/carbon))
+ M.reagents.add_reagent(/datum/reagent/consumable/semen, 30)
+ new /obj/effect/decal/cleanable/semen(loc)
+
+ playlewdinteractionsound(loc, "modular_splurt/sound/lewd/deathclaw[rand(1, 2)].ogg", 30, 1, -1)
+ visible_message("\The [src] [message]")
+ shake_camera(M, 6, 1)
+ set_is_fucking(null ,null)
+
+ refractory_period = world.time + rand(100, 150) // Sex cooldown
+ set_lust(0) // Nuts at 400
+
+ addtimer(CALLBACK(src, .proc/slap, M), 15)
+
+
+/mob/living/simple_animal/hostile/ice_wolf/funwolf/proc/slap(mob/living/M)
+ playlewdinteractionsound(loc, "modular_sand/sound/interactions/slap.ogg", 30, 1, -1)
+ visible_message(span_danger("\The [src] slaps \the [M] right on the ass!"), \
+ span_userdanger("\The [src] slaps \the [M] right on the ass!"), null, COMBAT_MESSAGE_RANGE)
+
+/mob/living/simple_animal/hostile/ice_wolf/funwolf/proc/tearSlot(mob/living/M, slot)
+ var/obj/item/W = M.get_item_by_slot(slot)
+ if(W)
+ M.dropItemToGround(W)
+ playlewdinteractionsound(loc, "sound/items/poster_ripped.ogg", 30, 1, -1)
+ visible_message(span_danger("\The [src] tears off \the [M]'s clothes!"), \
+ span_userdanger("\The [src] tears off \the [M]'s clothes!"), null, COMBAT_MESSAGE_RANGE)
+ return TRUE
+ return FALSE
+
+
+////////////////
+// //
+// Hell Hound //
+// //
+////////////////
+
+/mob/living/simple_animal/hostile/hellhound/funwolf
+ name = "Fun Hell Hound"
+ desc = "A massive, firey wolf like creature with powerful muscles, magama-hot claws, and aggression to match. This one seems to have a strange look in its eyes.."
+ var/change_target_hole_cooldown = 0
+ var/chosen_hole
+ var/voremode = FALSE // Fixes runtime when grabbing victim
+ gold_core_spawnable = NO_SPAWN // Admin only
+ werewolf_mode = "rape"
+
+/mob/living/simple_animal/hostile/hellhound/funwolf/gentle
+ name = "Gentle Hell Hound"
+ desc = "A massive, firey wolf like creature with powerful muscles, magama-hot claws, and aggression to match. This one has the bedroom eyes.."
+ werewolf_mode = "gentle"
+
+/mob/living/simple_animal/hostile/hellhound/funwolf/abomination
+ name = "Exiled Hell Hound"
+ desc = "A massive, firey wolf like creature with powerful muscles, magama-hot claws, and aggression to match. This one has a strange smell for some reason.."
+ werewolf_mode = "abomination"
+
+/mob/living/simple_animal/hostile/hellhound/funwolf/AttackingTarget()
+ var/mob/living/M = target
+
+ var/onLewdCooldown = FALSE
+ var/wantsNoncon = FALSE
+
+ if(get_refraction_dif() > 0)
+ onLewdCooldown = TRUE
+
+ if(M.client && M.client?.prefs.erppref == "Yes" && CHECK_BITFIELD(M.client?.prefs.toggles, VERB_CONSENT) && M.client?.prefs.nonconpref == "Yes")
+ wantsNoncon = TRUE
+
+ switch(werewolf_mode)
+ if("gentle")
+ if(onLewdCooldown || !wantsNoncon)
+ return // Do nothing
+ if("abomination")
+ if(onLewdCooldown || !wantsNoncon)
+ return // Do nothing
+ if("rape")
+ if(onLewdCooldown || !wantsNoncon || M.health > 60)
+ ..() // Attack target
+ return
+
+ if(!M.pulledby)
+ if(!M.buckled && !M.density)
+ M.forceMove(src.loc)
+
+ start_pulling(M, supress_message = TRUE)
+ log_combat(src, M, "grabbed")
+ M.visible_message(span_warning("[src] violently grabs [M]!"), \
+ span_userdanger("[src] violently grabs you!"))
+ setGrabState(GRAB_NECK) //Instant neck grab
+
+ return
+
+ if(get_refraction_dif() > 0)
+ ..()
+ return
+
+ if(change_target_hole_cooldown < world.time)
+ chosen_hole = null
+ while (chosen_hole == null)
+ pickNewHole(M)
+ change_target_hole_cooldown = world.time + 100
+
+
+ do_lewd_action(M)
+ addtimer(CALLBACK(src, .proc/do_lewd_action, M), rand(8, 12))
+
+ // Regular sex has an extra action per tick to seem less slow and robotic
+ if(werewolf_mode != "abomination" || M.client?.prefs.unholypref != "Yes")
+ addtimer(CALLBACK(src, .proc/do_lewd_action, M), rand(12, 16))
+
+
+/mob/living/simple_animal/hostile/hellhound/funwolf/proc/pickNewHole(mob/living/M)
+ switch(rand(2))
+ if(0)
+ chosen_hole = CUM_TARGET_ANUS
+ if(1)
+ if(M.has_vagina())
+ chosen_hole = CUM_TARGET_VAGINA
+ else
+ chosen_hole = CUM_TARGET_ANUS
+ if(2)
+ chosen_hole = CUM_TARGET_THROAT
+
+/mob/living/simple_animal/hostile/hellhound/funwolf/proc/do_lewd_action(mob/living/M)
+ if(get_refraction_dif() > 0)
+ return
+
+ if(rand(1,7) == 7)
+ playlewdinteractionsound(loc, "modular_splurt/sound/lewd/deathclaw_grunt[rand(1, 5)].ogg", 30, 1, -1)
+
+ var/datum/interaction/I
+ switch(chosen_hole)
+ if(CUM_TARGET_ANUS)
+ if(tearSlot(M, ITEM_SLOT_OCLOTHING))
+ return
+ if(tearSlot(M, ITEM_SLOT_ICLOTHING))
+ return
+
+ // Abomination deathclaws do other stuff instead
+ if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes")
+ if(prob(1))
+ I = SSinteractions.interactions["/datum/interaction/lewd/grindmouth"]
+ else
+ I = SSinteractions.interactions["/datum/interaction/lewd/grindface"]
+ handle_post_sex(25, null, M)
+ else
+ I = SSinteractions.interactions["/datum/interaction/lewd/fuck/anal"]
+ I.display_interaction(src, M)
+
+ if(CUM_TARGET_VAGINA)
+ if(tearSlot(M, ITEM_SLOT_OCLOTHING))
+ return
+ if(tearSlot(M, ITEM_SLOT_ICLOTHING))
+ return
+
+ // Abomination deathclaws do other stuff instead
+ if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes")
+ I = SSinteractions.interactions["/datum/interaction/lewd/footjob/vagina"]
+ handle_post_sex(10, null, M)
+ else
+ I = SSinteractions.interactions["/datum/interaction/lewd/fuck"]
+ I.display_interaction(src, M)
+
+ if(CUM_TARGET_THROAT)
+ if(tearSlot(M, ITEM_SLOT_HEAD))
+ return
+ if(tearSlot(M, ITEM_SLOT_MASK))
+ return
+
+ // Abomination deathclaws do other stuff instead
+ if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes")
+ if(prob(1))
+ do_faceshit(M)
+ else
+ do_facefart(M)
+ handle_post_sex(25, null, M)
+ shake_camera(M, 6, 1)
+ else
+ I = SSinteractions.interactions["/datum/interaction/lewd/throatfuck"]
+ I.display_interaction(src, M)
+
+/mob/living/simple_animal/hostile/hellhound/funwolf/cum(mob/living/M)
+
+ if(get_refraction_dif() > 0)
+ return
+
+ var/message
+
+ if(!istype(M))
+ chosen_hole = null
+
+ switch(chosen_hole)
+ if(CUM_TARGET_THROAT)
+ if(M.has_mouth() && M.mouth_is_free())
+ message = "shoves their fat canine cock deep down \the [M]'s throat and cums."
+ else
+ message = "cums on \the [M]'s face."
+ if(CUM_TARGET_VAGINA)
+ if(M.is_bottomless() && M.has_vagina())
+ message = "rams its meaty cock into \the [M]'s pussy and fills it with sperm."
+ M.impregnate(src, M.getorganslot(ORGAN_SLOT_WOMB), src.type)
+ else
+ message = "cums on \the [M]'s belly."
+ if(CUM_TARGET_ANUS)
+ if(M.is_bottomless() && M.has_anus())
+ message = "hilts its knot into \the [M]'s ass and floods it with Werewolf jizz."
+ else
+ message = "cums on \the [M]'s backside."
+ else
+ message = "cums on the floor!"
+
+ if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes")
+ message = "cums all over [M]'s body"
+
+ if(istype(M, /mob/living/carbon))
+ M.reagents.add_reagent(/datum/reagent/consumable/semen, 30)
+ new /obj/effect/decal/cleanable/semen(loc)
+
+ playlewdinteractionsound(loc, "modular_splurt/sound/lewd/deathclaw[rand(1, 2)].ogg", 30, 1, -1)
+ visible_message("\The [src] [message]")
+ shake_camera(M, 6, 1)
+ set_is_fucking(null ,null)
+
+ refractory_period = world.time + rand(100, 150) // Sex cooldown
+ set_lust(0) // Nuts at 400
+
+ addtimer(CALLBACK(src, .proc/slap, M), 15)
+
+
+/mob/living/simple_animal/hostile/hellhound/funwolf/proc/slap(mob/living/M)
+ playlewdinteractionsound(loc, "modular_sand/sound/interactions/slap.ogg", 30, 1, -1)
+ visible_message(span_danger("\The [src] slaps \the [M] right on the ass!"), \
+ span_userdanger("\The [src] slaps \the [M] right on the ass!"), null, COMBAT_MESSAGE_RANGE)
+
+/mob/living/simple_animal/hostile/hellhound/funwolf/proc/tearSlot(mob/living/M, slot)
+ var/obj/item/W = M.get_item_by_slot(slot)
+ if(W)
+ M.dropItemToGround(W)
+ playlewdinteractionsound(loc, "sound/items/poster_ripped.ogg", 30, 1, -1)
+ visible_message(span_danger("\The [src] tears off \the [M]'s clothes!"), \
+ span_userdanger("\The [src] tears off \the [M]'s clothes!"), null, COMBAT_MESSAGE_RANGE)
+ return TRUE
+ return FALSE
+
+
+//////////////////
+// //
+// The Mosley //
+// //
+//////////////////
+
+/mob/living/simple_animal/hostile/the_mosley/funwolf
+ name = "Fun Mosley"
+ desc = "A massive, unknown creature with powerful muscles, glittering-purple claws, and aggression to match. This one seems to have a strange look in its eyes.."
+ var/change_target_hole_cooldown = 0
+ var/chosen_hole
+ var/voremode = FALSE // Fixes runtime when grabbing victim
+ gold_core_spawnable = NO_SPAWN // Admin only
+ werewolf_mode = "rape"
+
+/mob/living/simple_animal/hostile/the_mosley/funwolf/gentle
+ name = "Gentle Mosley"
+ desc = "A massive, unknown creature with powerful muscles, glittering-purple claws, and aggression to match. This one has the bedroom eyes.."
+ werewolf_mode = "gentle"
+
+/mob/living/simple_animal/hostile/the_mosley/funwolf/abomination
+ name = "Exiled Mosley"
+ desc = "A massive, unknown creature with powerful muscles, glittering-purple claws, and aggression to match. This one has a strange smell for some reason.."
+ werewolf_mode = "abomination"
+
+/mob/living/simple_animal/hostile/the_mosley/funwolf/AttackingTarget()
+ var/mob/living/M = target
+
+ var/onLewdCooldown = FALSE
+ var/wantsNoncon = FALSE
+
+ if(get_refraction_dif() > 0)
+ onLewdCooldown = TRUE
+
+ if(M.client && M.client?.prefs.erppref == "Yes" && CHECK_BITFIELD(M.client?.prefs.toggles, VERB_CONSENT) && M.client?.prefs.nonconpref == "Yes")
+ wantsNoncon = TRUE
+
+ switch(werewolf_mode)
+ if("gentle")
+ if(onLewdCooldown || !wantsNoncon)
+ return // Do nothing
+ if("abomination")
+ if(onLewdCooldown || !wantsNoncon)
+ return // Do nothing
+ if("rape")
+ if(onLewdCooldown || !wantsNoncon || M.health > 60)
+ ..() // Attack target
+ return
+
+ if(!M.pulledby)
+ if(!M.buckled && !M.density)
+ M.forceMove(src.loc)
+
+ start_pulling(M, supress_message = TRUE)
+ log_combat(src, M, "grabbed")
+ M.visible_message(span_warning("[src] violently grabs [M]!"), \
+ span_userdanger("[src] violently grabs you!"))
+ setGrabState(GRAB_NECK) //Instant neck grab
+
+ return
+
+ if(get_refraction_dif() > 0)
+ ..()
+ return
+
+ if(change_target_hole_cooldown < world.time)
+ chosen_hole = null
+ while (chosen_hole == null)
+ pickNewHole(M)
+ change_target_hole_cooldown = world.time + 100
+
+
+ do_lewd_action(M)
+ addtimer(CALLBACK(src, .proc/do_lewd_action, M), rand(8, 12))
+
+ // Regular sex has an extra action per tick to seem less slow and robotic
+ if(werewolf_mode != "abomination" || M.client?.prefs.unholypref != "Yes")
+ addtimer(CALLBACK(src, .proc/do_lewd_action, M), rand(12, 16))
+
+
+/mob/living/simple_animal/hostile/the_mosley/funwolf/proc/pickNewHole(mob/living/M)
+ switch(rand(2))
+ if(0)
+ chosen_hole = CUM_TARGET_ANUS
+ if(1)
+ if(M.has_vagina())
+ chosen_hole = CUM_TARGET_VAGINA
+ else
+ chosen_hole = CUM_TARGET_ANUS
+ if(2)
+ chosen_hole = CUM_TARGET_THROAT
+
+/mob/living/simple_animal/hostile/the_mosley/funwolf/proc/do_lewd_action(mob/living/M)
+ if(get_refraction_dif() > 0)
+ return
+
+ if(rand(1,7) == 7)
+ playlewdinteractionsound(loc, "modular_splurt/sound/lewd/deathclaw_grunt[rand(1, 5)].ogg", 30, 1, -1)
+
+ var/datum/interaction/I
+ switch(chosen_hole)
+ if(CUM_TARGET_ANUS)
+ if(tearSlot(M, ITEM_SLOT_OCLOTHING))
+ return
+ if(tearSlot(M, ITEM_SLOT_ICLOTHING))
+ return
+
+ // Abomination deathclaws do other stuff instead
+ if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes")
+ if(prob(1))
+ I = SSinteractions.interactions["/datum/interaction/lewd/grindmouth"]
+ else
+ I = SSinteractions.interactions["/datum/interaction/lewd/grindface"]
+ handle_post_sex(25, null, M)
+ else
+ I = SSinteractions.interactions["/datum/interaction/lewd/fuck/anal"]
+ I.display_interaction(src, M)
+
+ if(CUM_TARGET_VAGINA)
+ if(tearSlot(M, ITEM_SLOT_OCLOTHING))
+ return
+ if(tearSlot(M, ITEM_SLOT_ICLOTHING))
+ return
+
+ // Abomination deathclaws do other stuff instead
+ if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes")
+ I = SSinteractions.interactions["/datum/interaction/lewd/footjob/vagina"]
+ handle_post_sex(10, null, M)
+ else
+ I = SSinteractions.interactions["/datum/interaction/lewd/fuck"]
+ I.display_interaction(src, M)
+
+ if(CUM_TARGET_THROAT)
+ if(tearSlot(M, ITEM_SLOT_HEAD))
+ return
+ if(tearSlot(M, ITEM_SLOT_MASK))
+ return
+
+ // Abomination deathclaws do other stuff instead
+ if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes")
+ if(prob(1))
+ do_faceshit(M)
+ else
+ do_facefart(M)
+ handle_post_sex(25, null, M)
+ shake_camera(M, 6, 1)
+ else
+ I = SSinteractions.interactions["/datum/interaction/lewd/throatfuck"]
+ I.display_interaction(src, M)
+
+/mob/living/simple_animal/hostile/the_mosley/funwolf/cum(mob/living/M)
+
+ if(get_refraction_dif() > 0)
+ return
+
+ var/message
+
+ if(!istype(M))
+ chosen_hole = null
+
+ switch(chosen_hole)
+ if(CUM_TARGET_THROAT)
+ if(M.has_mouth() && M.mouth_is_free())
+ message = "shoves their fat canine cock deep down \the [M]'s throat and cums."
+ else
+ message = "cums on \the [M]'s face."
+ if(CUM_TARGET_VAGINA)
+ if(M.is_bottomless() && M.has_vagina())
+ message = "rams its meaty cock into \the [M]'s pussy and fills it with sperm."
+ M.impregnate(src, M.getorganslot(ORGAN_SLOT_WOMB), src.type)
+ else
+ message = "cums on \the [M]'s belly."
+ if(CUM_TARGET_ANUS)
+ if(M.is_bottomless() && M.has_anus())
+ message = "hilts its knot into \the [M]'s ass and floods it with Werewolf jizz."
+ else
+ message = "cums on \the [M]'s backside."
+ else
+ message = "cums on the floor!"
+
+ if(werewolf_mode == "abomination" && M.client?.prefs.unholypref == "Yes")
+ message = "cums all over [M]'s body"
+
+ if(istype(M, /mob/living/carbon))
+ M.reagents.add_reagent(/datum/reagent/consumable/semen, 30)
+ new /obj/effect/decal/cleanable/semen(loc)
+
+ playlewdinteractionsound(loc, "modular_splurt/sound/lewd/deathclaw[rand(1, 2)].ogg", 30, 1, -1)
+ visible_message("\The [src] [message]")
+ shake_camera(M, 6, 1)
+ set_is_fucking(null ,null)
+
+ refractory_period = world.time + rand(100, 150) // Sex cooldown
+ set_lust(0) // Nuts at 400
+
+ addtimer(CALLBACK(src, .proc/slap, M), 15)
+
+
+/mob/living/simple_animal/hostile/the_mosley/funwolf/proc/slap(mob/living/M)
+ playlewdinteractionsound(loc, "modular_sand/sound/interactions/slap.ogg", 30, 1, -1)
+ visible_message(span_danger("\The [src] slaps \the [M] right on the ass!"), \
+ span_userdanger("\The [src] slaps \the [M] right on the ass!"), null, COMBAT_MESSAGE_RANGE)
+
+/mob/living/simple_animal/hostile/the_mosley/funwolf/proc/tearSlot(mob/living/M, slot)
+ var/obj/item/W = M.get_item_by_slot(slot)
+ if(W)
+ M.dropItemToGround(W)
+ playlewdinteractionsound(loc, "sound/items/poster_ripped.ogg", 30, 1, -1)
+ visible_message(span_danger("\The [src] tears off \the [M]'s clothes!"), \
+ span_userdanger("\The [src] tears off \the [M]'s clothes!"), null, COMBAT_MESSAGE_RANGE)
+ return TRUE
+ return FALSE
+
diff --git a/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/hellhound.dm b/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/hellhound.dm
new file mode 100644
index 0000000000..68a3ee3edd
--- /dev/null
+++ b/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/hellhound.dm
@@ -0,0 +1,134 @@
+/mob/living/simple_animal/hostile/hellhound
+ name = "Hell Hound"
+ desc = "A massive, firey wolf like creature with powerful muscles, magama-hot claws, and aggression to match."
+ icon = 'modular_splurt/icons/mobs/werewolf.dmi'
+ icon_state = "Hell_Hound_idle"
+ icon_living = "Hell_Hound_idle"
+ icon_dead = "Hell_Hound__dead"
+ icon_gib = "syndicate_gib"
+ pixel_x = -16
+ gender = MALE
+ mob_biotypes = list(MOB_ORGANIC, MOB_BEAST)
+ stat_attack = UNCONSCIOUS
+ speak = list("ROAR!","Rawr!","GRRAAGH!","Growl!")
+ speak_emote = list("growls", "snarls")
+ emote_hear = list("grumbles.","snarls.")
+ emote_taunt = list("bares its teeth", "stomps")
+ speak_chance = 10
+ taunt_chance = 25
+ speed = 0
+ see_in_dark = 8
+ butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab= 4,
+ /obj/item/stack/sheet/animalhide = 2,
+ /obj/item/stack/sheet/bone = 4)
+ attack_verb_continuous = "claws"
+ attack_verb_simple = "claw"
+ maxHealth = 500
+ health = 500
+ obj_damage = 60
+ armour_penetration = 30
+ melee_damage_lower = 56
+ melee_damage_upper = 56
+ attack_sound = 'modular_splurt/sound/misc/claw_rend.ogg'
+ faction = list("werewolf")
+ 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 = 5
+ gold_core_spawnable = HOSTILE_SPAWN
+ var/charging = FALSE
+ has_penis = TRUE
+ has_butt = TRUE
+
+ footstep_type = FOOTSTEP_MOB_HEAVY
+
+ //**werewolf_mode**
+ // Hostile: Normal deathclaw murder machine
+ // Friendly: Does not attack
+ // Rape: Hurts and lewds people
+ // Gentle: lewds people
+ // Abomination: Hurts and does unspeakable lewd things to people
+ var/werewolf_mode = "hostile"
+
+/mob/living/simple_animal/hostile/hellhound/pacifist
+ name = "Friendly Hell Hound"
+ desc = "A massive, firey wolf like creature with powerful muscles, magama-hot claws, and aggression to match."
+ werewolf_mode = "friendly"
+ friendly_verb_continuous = "howls at"
+ friendly_verb_simple = "howl at"
+
+/mob/living/simple_animal/hostile/hellhound/bullet_act(obj/item/projectile/Proj)
+ if(!Proj)
+ return
+ if(prob(10))
+ visible_message(span_danger("\The [src] growls, enraged!"))
+ sleep(3)
+ Charge()
+ if(prob(85) || Proj.damage > 26) //prob(x) = chance for proj to actually do something, adjust depending on how OP you want deathclaws to be
+ return ..()
+ else
+ visible_message(span_danger("\The [Proj] bounces off \the [src]'s thick hide!"))
+ return 0
+
+/mob/living/simple_animal/hostile/hellhound/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
+ if(!charging)
+ ..()
+
+/mob/living/simple_animal/hostile/hellhound/AttackingTarget()
+ if (werewolf_mode == "friendly")
+ return // Do not attack
+
+ if(!charging)
+ return ..()
+
+/mob/living/simple_animal/hostile/hellhound/Goto(target, delay, minimum_distance)
+ if(!charging)
+ ..()
+
+/mob/living/simple_animal/hostile/hellhound/Move()
+ if(charging)
+ new /obj/effect/temp_visual/decoy/fading(loc,src)
+ DestroySurroundings()
+ . = ..()
+ if(charging)
+ DestroySurroundings()
+
+/mob/living/simple_animal/hostile/hellhound/proc/Charge()
+ var/turf/T = get_turf(target)
+ if(!T || T == loc)
+ return
+ charging = TRUE
+ visible_message(span_danger("[src] charges!"))
+ DestroySurroundings()
+ walk(src, 0)
+ setDir(get_dir(src, T))
+ var/obj/effect/temp_visual/decoy/D = new /obj/effect/temp_visual/decoy(loc,src)
+ animate(D, alpha = 0, color = "#FF0000", transform = matrix()*2, time = 1)
+ sleep(3)
+ throw_at(T, get_dist(src, T), 1, src, 0, callback = CALLBACK(src, .proc/charge_end))
+
+/mob/living/simple_animal/hostile/hellhound/charge_end(list/effects_to_destroy)
+ charging = FALSE
+ if(target)
+ Goto(target, move_to_delay, minimum_distance)
+
+/mob/living/simple_animal/hostile/hellhound/Bump(atom/A)
+ if(charging)
+ if(isturf(A) || isobj(A) && A.density)
+ A.ex_act(EXPLODE_HEAVY)
+ DestroySurroundings()
+ ..()
+
+/mob/living/simple_animal/hostile/hellhound/throw_impact(atom/A)
+ if(!charging)
+ return ..()
+
+ else if(isliving(A))
+ var/mob/living/L = A
+ L.visible_message(span_danger("[src] slams into [L]!"), span_userdanger("[src] slams into you!"))
+ L.apply_damage(melee_damage_lower/2, BRUTE)
+ playsound(get_turf(L), 'sound/effects/meteorimpact.ogg', 100, 1)
+ shake_camera(L, 4, 3)
+ shake_camera(src, 2, 3)
+ var/throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(L, src)))
+ L.throw_at(throwtarget, 3)
+
+ charging = FALSE
diff --git a/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/icewolf.dm b/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/icewolf.dm
new file mode 100644
index 0000000000..8f785c2b2b
--- /dev/null
+++ b/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/icewolf.dm
@@ -0,0 +1,134 @@
+/mob/living/simple_animal/hostile/ice_wolf
+ name = "Ice Werewolf"
+ desc = "A massive, ice wolf like creature with powerful muscles, gleaming-cold claws, and aggression to match."
+ icon = 'modular_splurt/icons/mobs/werewolf.dmi'
+ icon_state = "Ice_Wolf_idle"
+ icon_living = "Ice_Wolf_idle"
+ icon_dead = "Ice_Wolf_dead"
+ icon_gib = "syndicate_gib"
+ pixel_x = -16
+ gender = MALE
+ mob_biotypes = list(MOB_ORGANIC, MOB_BEAST)
+ stat_attack = UNCONSCIOUS
+ speak = list("ROAR!","Rawr!","GRRAAGH!","Growl!")
+ speak_emote = list("growls", "snarls")
+ emote_hear = list("grumbles.","snarls.")
+ emote_taunt = list("bares its teeth", "stomps")
+ speak_chance = 10
+ taunt_chance = 25
+ speed = 0
+ see_in_dark = 8
+ butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab= 4,
+ /obj/item/stack/sheet/animalhide = 2,
+ /obj/item/stack/sheet/bone = 4)
+ attack_verb_continuous = "claws"
+ attack_verb_simple = "claw"
+ maxHealth = 500
+ health = 500
+ obj_damage = 60
+ armour_penetration = 30
+ melee_damage_lower = 56
+ melee_damage_upper = 56
+ attack_sound = 'modular_splurt/sound/misc/claw_rend.ogg'
+ faction = list("werewolf")
+ 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 = 5
+ gold_core_spawnable = HOSTILE_SPAWN
+ var/charging = FALSE
+ has_penis = TRUE
+ has_butt = TRUE
+
+ footstep_type = FOOTSTEP_MOB_HEAVY
+
+ //**werewolf_mode**
+ // Hostile: Normal deathclaw murder machine
+ // Friendly: Does not attack
+ // Rape: Hurts and lewds people
+ // Gentle: lewds people
+ // Abomination: Hurts and does unspeakable lewd things to people
+ var/werewolf_mode = "hostile"
+
+/mob/living/simple_animal/hostile/ice_wolf/pacifist
+ name = "Friendly Ice Werewolf"
+ desc = "A massive, ice wolf like creature with powerful muscles, gleaming-cold claws, and aggression to match."
+ werewolf_mode = "friendly"
+ friendly_verb_continuous = "howls at"
+ friendly_verb_simple = "howl at"
+
+/mob/living/simple_animal/hostile/ice_wolf/bullet_act(obj/item/projectile/Proj)
+ if(!Proj)
+ return
+ if(prob(10))
+ visible_message(span_danger("\The [src] growls, enraged!"))
+ sleep(3)
+ Charge()
+ if(prob(85) || Proj.damage > 26) //prob(x) = chance for proj to actually do something, adjust depending on how OP you want deathclaws to be
+ return ..()
+ else
+ visible_message(span_danger("\The [Proj] bounces off \the [src]'s thick hide!"))
+ return 0
+
+/mob/living/simple_animal/hostile/ice_wolf/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
+ if(!charging)
+ ..()
+
+/mob/living/simple_animal/hostile/ice_wolf/AttackingTarget()
+ if (werewolf_mode == "friendly")
+ return // Do not attack
+
+ if(!charging)
+ return ..()
+
+/mob/living/simple_animal/hostile/ice_wolf/Goto(target, delay, minimum_distance)
+ if(!charging)
+ ..()
+
+/mob/living/simple_animal/hostile/ice_wolf/Move()
+ if(charging)
+ new /obj/effect/temp_visual/decoy/fading(loc,src)
+ DestroySurroundings()
+ . = ..()
+ if(charging)
+ DestroySurroundings()
+
+/mob/living/simple_animal/hostile/ice_wolf/proc/Charge()
+ var/turf/T = get_turf(target)
+ if(!T || T == loc)
+ return
+ charging = TRUE
+ visible_message(span_danger("[src] charges!"))
+ DestroySurroundings()
+ walk(src, 0)
+ setDir(get_dir(src, T))
+ var/obj/effect/temp_visual/decoy/D = new /obj/effect/temp_visual/decoy(loc,src)
+ animate(D, alpha = 0, color = "#FF0000", transform = matrix()*2, time = 1)
+ sleep(3)
+ throw_at(T, get_dist(src, T), 1, src, 0, callback = CALLBACK(src, .proc/charge_end))
+
+/mob/living/simple_animal/hostile/ice_wolf/charge_end(list/effects_to_destroy)
+ charging = FALSE
+ if(target)
+ Goto(target, move_to_delay, minimum_distance)
+
+/mob/living/simple_animal/hostile/ice_wolf/Bump(atom/A)
+ if(charging)
+ if(isturf(A) || isobj(A) && A.density)
+ A.ex_act(EXPLODE_HEAVY)
+ DestroySurroundings()
+ ..()
+
+/mob/living/simple_animal/hostile/ice_wolf/throw_impact(atom/A)
+ if(!charging)
+ return ..()
+
+ else if(isliving(A))
+ var/mob/living/L = A
+ L.visible_message(span_danger("[src] slams into [L]!"), span_userdanger("[src] slams into you!"))
+ L.apply_damage(melee_damage_lower/2, BRUTE)
+ playsound(get_turf(L), 'sound/effects/meteorimpact.ogg', 100, 1)
+ shake_camera(L, 4, 3)
+ shake_camera(src, 2, 3)
+ var/throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(L, src)))
+ L.throw_at(throwtarget, 3)
+
+ charging = FALSE
diff --git a/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/themosley.dm b/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/themosley.dm
new file mode 100644
index 0000000000..ba74e5bce4
--- /dev/null
+++ b/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/themosley.dm
@@ -0,0 +1,134 @@
+/mob/living/simple_animal/hostile/the_mosley
+ name = "The Mosley"
+ desc = "A massive, unknown creature with powerful muscles, glittering-purple claws, and aggression to match."
+ icon = 'modular_splurt/icons/mobs/werewolf.dmi'
+ icon_state = "The_Mosley_idle"
+ icon_living = "The_Mosley_idle"
+ icon_dead = "The_Mosley_dead"
+ icon_gib = "syndicate_gib"
+ pixel_x = -16
+ gender = MALE
+ mob_biotypes = list(MOB_ORGANIC, MOB_BEAST)
+ stat_attack = UNCONSCIOUS
+ speak = list("ROAR!","Rawr!","GRRAAGH!","Growl!")
+ speak_emote = list("growls", "snarls")
+ emote_hear = list("grumbles.","snarls.")
+ emote_taunt = list("bares its teeth", "stomps")
+ speak_chance = 10
+ taunt_chance = 25
+ speed = 0
+ see_in_dark = 8
+ butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab= 4,
+ /obj/item/stack/sheet/animalhide = 2,
+ /obj/item/stack/sheet/bone = 4)
+ attack_verb_continuous = "claws"
+ attack_verb_simple = "claw"
+ maxHealth = 500
+ health = 500
+ obj_damage = 60
+ armour_penetration = 30
+ melee_damage_lower = 56
+ melee_damage_upper = 56
+ attack_sound = 'modular_splurt/sound/misc/claw_rend.ogg'
+ faction = list("werewolf")
+ 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 = 5
+ gold_core_spawnable = FALSE
+ var/charging = FALSE
+ has_penis = TRUE
+ has_butt = TRUE
+
+ footstep_type = FOOTSTEP_MOB_HEAVY
+
+ //**werewolf_mode**
+ // Hostile: Normal deathclaw murder machine
+ // Friendly: Does not attack
+ // Rape: Hurts and lewds people
+ // Gentle: lewds people
+ // Abomination: Hurts and does unspeakable lewd things to people
+ var/werewolf_mode = "hostile"
+
+/mob/living/simple_animal/hostile/the_mosley/pacifist
+ name = "Friendly Mosley"
+ desc = "A massive, unknown creature with powerful muscles, glittering-purple claws, and aggression to match."
+ werewolf_mode = "friendly"
+ friendly_verb_continuous = "howls at"
+ friendly_verb_simple = "howl at"
+
+/mob/living/simple_animal/hostile/the_mosley/bullet_act(obj/item/projectile/Proj)
+ if(!Proj)
+ return
+ if(prob(10))
+ visible_message(span_danger("\The [src] growls, enraged!"))
+ sleep(3)
+ Charge()
+ if(prob(85) || Proj.damage > 26) //prob(x) = chance for proj to actually do something, adjust depending on how OP you want deathclaws to be
+ return ..()
+ else
+ visible_message(span_danger("\The [Proj] bounces off \the [src]'s thick hide!"))
+ return 0
+
+/mob/living/simple_animal/hostile/the_mosley/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
+ if(!charging)
+ ..()
+
+/mob/living/simple_animal/hostile/the_mosley/AttackingTarget()
+ if (werewolf_mode == "friendly")
+ return // Do not attack
+
+ if(!charging)
+ return ..()
+
+/mob/living/simple_animal/hostile/the_mosley/Goto(target, delay, minimum_distance)
+ if(!charging)
+ ..()
+
+/mob/living/simple_animal/hostile/the_mosley/Move()
+ if(charging)
+ new /obj/effect/temp_visual/decoy/fading(loc,src)
+ DestroySurroundings()
+ . = ..()
+ if(charging)
+ DestroySurroundings()
+
+/mob/living/simple_animal/hostile/the_mosley/proc/Charge()
+ var/turf/T = get_turf(target)
+ if(!T || T == loc)
+ return
+ charging = TRUE
+ visible_message(span_danger("[src] charges!"))
+ DestroySurroundings()
+ walk(src, 0)
+ setDir(get_dir(src, T))
+ var/obj/effect/temp_visual/decoy/D = new /obj/effect/temp_visual/decoy(loc,src)
+ animate(D, alpha = 0, color = "#FF0000", transform = matrix()*2, time = 1)
+ sleep(3)
+ throw_at(T, get_dist(src, T), 1, src, 0, callback = CALLBACK(src, .proc/charge_end))
+
+/mob/living/simple_animal/hostile/the_mosley/charge_end(list/effects_to_destroy)
+ charging = FALSE
+ if(target)
+ Goto(target, move_to_delay, minimum_distance)
+
+/mob/living/simple_animal/hostile/the_mosley/Bump(atom/A)
+ if(charging)
+ if(isturf(A) || isobj(A) && A.density)
+ A.ex_act(EXPLODE_HEAVY)
+ DestroySurroundings()
+ ..()
+
+/mob/living/simple_animal/hostile/the_mosley/throw_impact(atom/A)
+ if(!charging)
+ return ..()
+
+ else if(isliving(A))
+ var/mob/living/L = A
+ L.visible_message(span_danger("[src] slams into [L]!"), span_userdanger("[src] slams into you!"))
+ L.apply_damage(melee_damage_lower/2, BRUTE)
+ playsound(get_turf(L), 'sound/effects/meteorimpact.ogg', 100, 1)
+ shake_camera(L, 4, 3)
+ shake_camera(src, 2, 3)
+ var/throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(L, src)))
+ L.throw_at(throwtarget, 3)
+
+ charging = FALSE
diff --git a/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/werewolf.dm b/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/werewolf.dm
new file mode 100644
index 0000000000..46df07d37f
--- /dev/null
+++ b/modular_splurt/code/modules/mob/living/simple_animal/hostile/werewolves/werewolf.dm
@@ -0,0 +1,134 @@
+/mob/living/simple_animal/hostile/werewolf
+ name = "Werewolf"
+ desc = "A massive, wolf like creature with powerful muscles, razor-sharp claws, and aggression to match."
+ icon = 'modular_splurt/icons/mobs/werewolf.dmi'
+ icon_state = "Werewolf_idle"
+ icon_living = "Werewolf_idle"
+ icon_dead = "Werewolf_dead"
+ icon_gib = "syndicate_gib"
+ pixel_x = -16
+ gender = MALE
+ mob_biotypes = list(MOB_ORGANIC, MOB_BEAST)
+ stat_attack = UNCONSCIOUS
+ speak = list("ROAR!","Rawr!","GRRAAGH!","Growl!")
+ speak_emote = list("growls", "snarls")
+ emote_hear = list("grumbles.","snarls.")
+ emote_taunt = list("bares its teeth", "stomps")
+ speak_chance = 10
+ taunt_chance = 25
+ speed = 0
+ see_in_dark = 8
+ butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab= 4,
+ /obj/item/stack/sheet/animalhide = 2,
+ /obj/item/stack/sheet/bone = 4)
+ attack_verb_continuous = "claws"
+ attack_verb_simple = "claw"
+ maxHealth = 500
+ health = 500
+ obj_damage = 60
+ armour_penetration = 30
+ melee_damage_lower = 56
+ melee_damage_upper = 56
+ attack_sound = 'modular_splurt/sound/misc/claw_rend.ogg'
+ faction = list("werewolf")
+ 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 = 5
+ gold_core_spawnable = HOSTILE_SPAWN
+ var/charging = FALSE
+ has_penis = TRUE
+ has_butt = TRUE
+
+ footstep_type = FOOTSTEP_MOB_HEAVY
+
+ //**werewolf_mode**
+ // Hostile: Normal deathclaw murder machine
+ // Friendly: Does not attack
+ // Rape: Hurts and lewds people
+ // Gentle: lewds people
+ // Abomination: Hurts and does unspeakable lewd things to people
+ var/werewolf_mode = "hostile"
+
+/mob/living/simple_animal/hostile/werewolf/pacifist
+ name = "Friendly Werewolf"
+ desc = "A massive, wolf like creature with powerful muscles, razor-sharp claws, and aggression to match."
+ werewolf_mode = "friendly"
+ friendly_verb_continuous = "howls at"
+ friendly_verb_simple = "howl at"
+
+/mob/living/simple_animal/hostile/werewolf/bullet_act(obj/item/projectile/Proj)
+ if(!Proj)
+ return
+ if(prob(10))
+ visible_message(span_danger("\The [src] growls, enraged!"))
+ sleep(3)
+ Charge()
+ if(prob(85) || Proj.damage > 26) //prob(x) = chance for proj to actually do something, adjust depending on how OP you want deathclaws to be
+ return ..()
+ else
+ visible_message(span_danger("\The [Proj] bounces off \the [src]'s thick hide!"))
+ return 0
+
+/mob/living/simple_animal/hostile/werewolf/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
+ if(!charging)
+ ..()
+
+/mob/living/simple_animal/hostile/werewolf/AttackingTarget()
+ if (werewolf_mode == "friendly")
+ return // Do not attack
+
+ if(!charging)
+ return ..()
+
+/mob/living/simple_animal/hostile/werewolf/Goto(target, delay, minimum_distance)
+ if(!charging)
+ ..()
+
+/mob/living/simple_animal/hostile/werewolf/Move()
+ if(charging)
+ new /obj/effect/temp_visual/decoy/fading(loc,src)
+ DestroySurroundings()
+ . = ..()
+ if(charging)
+ DestroySurroundings()
+
+/mob/living/simple_animal/hostile/werewolf/proc/Charge()
+ var/turf/T = get_turf(target)
+ if(!T || T == loc)
+ return
+ charging = TRUE
+ visible_message(span_danger("[src] charges!"))
+ DestroySurroundings()
+ walk(src, 0)
+ setDir(get_dir(src, T))
+ var/obj/effect/temp_visual/decoy/D = new /obj/effect/temp_visual/decoy(loc,src)
+ animate(D, alpha = 0, color = "#FF0000", transform = matrix()*2, time = 1)
+ sleep(3)
+ throw_at(T, get_dist(src, T), 1, src, 0, callback = CALLBACK(src, .proc/charge_end))
+
+/mob/living/simple_animal/hostile/werewolf/charge_end(list/effects_to_destroy)
+ charging = FALSE
+ if(target)
+ Goto(target, move_to_delay, minimum_distance)
+
+/mob/living/simple_animal/hostile/werewolf/Bump(atom/A)
+ if(charging)
+ if(isturf(A) || isobj(A) && A.density)
+ A.ex_act(EXPLODE_HEAVY)
+ DestroySurroundings()
+ ..()
+
+/mob/living/simple_animal/hostile/werewolf/throw_impact(atom/A)
+ if(!charging)
+ return ..()
+
+ else if(isliving(A))
+ var/mob/living/L = A
+ L.visible_message(span_danger("[src] slams into [L]!"), span_userdanger("[src] slams into you!"))
+ L.apply_damage(melee_damage_lower/2, BRUTE)
+ playsound(get_turf(L), 'sound/effects/meteorimpact.ogg', 100, 1)
+ shake_camera(L, 4, 3)
+ shake_camera(src, 2, 3)
+ var/throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(L, src)))
+ L.throw_at(throwtarget, 3)
+
+ charging = FALSE
diff --git a/modular_splurt/icons/mob/clothing/shoes.dmi b/modular_splurt/icons/mob/clothing/shoes.dmi
index f0228a3c74..119cab3a7b 100644
Binary files a/modular_splurt/icons/mob/clothing/shoes.dmi and b/modular_splurt/icons/mob/clothing/shoes.dmi differ
diff --git a/modular_splurt/icons/mob/clothing/shoes_digi.dmi b/modular_splurt/icons/mob/clothing/shoes_digi.dmi
index 755d9c92e9..ca7b998e5e 100644
Binary files a/modular_splurt/icons/mob/clothing/shoes_digi.dmi and b/modular_splurt/icons/mob/clothing/shoes_digi.dmi differ
diff --git a/modular_splurt/icons/mob/robots.dmi b/modular_splurt/icons/mob/robots.dmi
index 4feb96cfab..5f5aaee248 100644
Binary files a/modular_splurt/icons/mob/robots.dmi and b/modular_splurt/icons/mob/robots.dmi differ
diff --git a/modular_splurt/icons/mobs/werewolf.dmi b/modular_splurt/icons/mobs/werewolf.dmi
index fb89c833ed..b7051253a8 100644
Binary files a/modular_splurt/icons/mobs/werewolf.dmi and b/modular_splurt/icons/mobs/werewolf.dmi differ
diff --git a/modular_splurt/icons/obj/clothing/shoes.dmi b/modular_splurt/icons/obj/clothing/shoes.dmi
index e3476a0f17..b4e0d3c95e 100644
Binary files a/modular_splurt/icons/obj/clothing/shoes.dmi and b/modular_splurt/icons/obj/clothing/shoes.dmi differ
diff --git a/modular_splurt/sound/misc/claw_rend.ogg b/modular_splurt/sound/misc/claw_rend.ogg
new file mode 100644
index 0000000000..a0acaa2a06
Binary files /dev/null and b/modular_splurt/sound/misc/claw_rend.ogg differ
diff --git a/tgstation.dme b/tgstation.dme
index cde3d0de81..bea02c1e0e 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -4358,6 +4358,7 @@
#include "modular_splurt\code\_globalvars\lists\objects.dm"
#include "modular_splurt\code\_globalvars\lists\pregnancy.dm"
#include "modular_splurt\code\_globalvars\lists\wendigo.dm"
+#include "modular_splurt\code\_onclick\ai.dm"
#include "modular_splurt\code\_onclick\observer.dm"
#include "modular_splurt\code\_onclick\hud\alien.dm"
#include "modular_splurt\code\_onclick\hud\alien_larva.dm"
@@ -4847,6 +4848,7 @@
#include "modular_splurt\code\modules\mob\living\carbon\human\species_types\xenochimera.dm"
#include "modular_splurt\code\modules\mob\living\carbon\human\species_types\zombies2.dm"
#include "modular_splurt\code\modules\mob\living\silicon\silicon.dm"
+#include "modular_splurt\code\modules\mob\living\silicon\ai\freelook\eye.dm"
#include "modular_splurt\code\modules\mob\living\silicon\pai\pai.dm"
#include "modular_splurt\code\modules\mob\living\silicon\robot\dogborg_equipment.dm"
#include "modular_splurt\code\modules\mob\living\silicon\robot\inventory.dm"
@@ -4878,6 +4880,11 @@
#include "modular_splurt\code\modules\mob\living\simple_animal\hostile\megafauna\king_of_goats.dm"
#include "modular_splurt\code\modules\mob\living\simple_animal\hostile\megafauna\penguinhiero.dm"
#include "modular_splurt\code\modules\mob\living\simple_animal\hostile\megafauna\sand.dm"
+#include "modular_splurt\code\modules\mob\living\simple_animal\hostile\werewolves\funwolf.dm"
+#include "modular_splurt\code\modules\mob\living\simple_animal\hostile\werewolves\hellhound.dm"
+#include "modular_splurt\code\modules\mob\living\simple_animal\hostile\werewolves\icewolf.dm"
+#include "modular_splurt\code\modules\mob\living\simple_animal\hostile\werewolves\themosley.dm"
+#include "modular_splurt\code\modules\mob\living\simple_animal\hostile\werewolves\werewolf.dm"
#include "modular_splurt\code\modules\paperwork\pen.dm"
#include "modular_splurt\code\modules\power\cell.dm"
#include "modular_splurt\code\modules\power\reactor\fluffed.dm"