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"