diff --git a/.github/workflows/autobuild_tgui.yml b/.github/workflows/autobuild_tgui.yml new file mode 100644 index 0000000000..b680139f74 --- /dev/null +++ b/.github/workflows/autobuild_tgui.yml @@ -0,0 +1,36 @@ +name: Autobuild TGUI + +on: + push: + branches: + - 'master' + paths: + - 'tgui-next/**.js' + - 'tgui-next/**.scss' + +jobs: + build: + name: Rebuild TGUI + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v1 + with: + fetch-depth: 25 + - name: Setup Node + uses: actions/setup-node@v1 + with: + node-version: '>=12.13' + - name: Build TGUI + run: bin/tgui --ci + working-directory: ./tgui-next + - name: Commit Artifacts + run: | + git config --local user.email "action@github.com" + git config --local user.name "TGUI" + git pull origin master + git commit -m "Automatic TGUI Rebuild [ci skip]" -a || true + - name: Push Artifacts + uses: ad-m/github-push-action@master + with: + github_token: ${{ secrets.GITHUB_MASTER_KEY }} diff --git a/_maps/RandomRuins/StationRuins/Box/Engine/engine_singulo.dmm b/_maps/RandomRuins/StationRuins/Box/Engine/engine_singulo.dmm index 76cb8bb9db..402cfc73cf 100644 --- a/_maps/RandomRuins/StationRuins/Box/Engine/engine_singulo.dmm +++ b/_maps/RandomRuins/StationRuins/Box/Engine/engine_singulo.dmm @@ -735,7 +735,7 @@ /obj/machinery/atmospherics/components/unary/outlet_injector{ dir = 1 }, -/turf/open/space/basic, +/turf/open/floor/plating/airless, /area/engine/engineering) "Si" = ( /obj/structure/cable/yellow{ diff --git a/_maps/RandomRuins/StationRuins/Box/Engine/engine_tesla.dmm b/_maps/RandomRuins/StationRuins/Box/Engine/engine_tesla.dmm index 7f55d69b17..af2ba1ffd7 100644 --- a/_maps/RandomRuins/StationRuins/Box/Engine/engine_tesla.dmm +++ b/_maps/RandomRuins/StationRuins/Box/Engine/engine_tesla.dmm @@ -240,7 +240,7 @@ /obj/machinery/atmospherics/components/unary/outlet_injector{ dir = 1 }, -/turf/open/space/basic, +/turf/open/floor/plating/airless, /area/engine/engineering) "nR" = ( /obj/structure/cable{ @@ -905,14 +905,6 @@ }, /turf/open/space/basic, /area/space/nearstation) -"VR" = ( -/obj/structure/lattice/catwalk, -/obj/machinery/camera/emp_proof{ - c_tag = "Tesla Engine Northeast"; - network = list("ss13","engine") - }, -/turf/open/space/basic, -/area/space/nearstation) "Wf" = ( /obj/effect/turf_decal/stripes/line{ dir = 9 @@ -1728,7 +1720,7 @@ dz dz FP FP -VR +FP dz dz Yl diff --git a/_maps/RandomRuins/StationRuins/Lavaland/Mining_Station/Mining_Station_Public_01.dmm b/_maps/RandomRuins/StationRuins/Lavaland/Mining_Station/Mining_Station_Public_01.dmm index fec45c7310..3118ad3f5f 100644 --- a/_maps/RandomRuins/StationRuins/Lavaland/Mining_Station/Mining_Station_Public_01.dmm +++ b/_maps/RandomRuins/StationRuins/Lavaland/Mining_Station/Mining_Station_Public_01.dmm @@ -64,6 +64,9 @@ /turf/open/floor/plating, /area/mine/living_quarters) "aN" = ( +/obj/structure/cable{ + icon_state = "2-8" + }, /turf/open/floor/plasteel/white, /area/mine/laborcamp) "aW" = ( @@ -82,24 +85,10 @@ "bg" = ( /turf/closed/wall, /area/mine/eva) -"bH" = ( -/obj/machinery/atmospherics/components/unary/outlet_injector/atmos/atmos_waste{ - dir = 4; - piping_layer = 3 - }, -/obj/structure/lattice/catwalk, -/turf/open/floor/plating/asteroid/basalt/lava_land_surface, -/area/mine/living_quarters) -"bI" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/structure/cable{ - icon_state = "2-8" - }, -/turf/open/floor/plasteel, +"bn" = ( +/obj/structure/cable, +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, /area/mine/living_quarters) "bX" = ( /obj/machinery/door/window/southleft, @@ -174,13 +163,6 @@ }, /turf/open/floor/plasteel, /area/mine/living_quarters) -"di" = ( -/obj/machinery/light{ - dir = 4 - }, -/obj/effect/turf_decal/tile/brown, -/turf/open/floor/plasteel, -/area/mine/living_quarters) "dk" = ( /obj/structure/table, /obj/item/stack/packageWrap, @@ -192,12 +174,6 @@ }, /turf/open/floor/plasteel, /area/mine/eva) -"dC" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/turf/open/floor/plasteel, -/area/mine/living_quarters) "dL" = ( /obj/machinery/atmospherics/components/binary/pump/on, /obj/structure/cable{ @@ -220,6 +196,15 @@ }, /turf/open/floor/plasteel, /area/mine/production) +"dU" = ( +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/structure/sign/warning/electricshock{ + pixel_y = -32 + }, +/turf/open/floor/plating, +/area/mine/laborcamp/security) "dZ" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -301,6 +286,21 @@ }, /turf/open/floor/plasteel, /area/mine/laborcamp) +"fx" = ( +/obj/machinery/light/small{ + dir = 8 + }, +/turf/open/floor/plating, +/area/mine/laborcamp/security) +"fA" = ( +/obj/machinery/power/terminal{ + dir = 4 + }, +/obj/machinery/power/port_gen/pacman{ + anchored = 1 + }, +/turf/open/floor/plating, +/area/mine/laborcamp/security) "fN" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 5 @@ -308,6 +308,12 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{ dir = 5 }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plasteel, /area/mine/laborcamp/security) "fO" = ( @@ -349,9 +355,18 @@ /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/mine/production) +"gn" = ( +/obj/structure/cable{ + icon_state = "1-4" + }, +/turf/open/floor/plasteel, +/area/mine/laborcamp) "gs" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plasteel, /area/mine/laborcamp) "gP" = ( @@ -376,6 +391,15 @@ }, /turf/open/floor/plasteel/white, /area/mine/laborcamp) +"hb" = ( +/obj/structure/cable{ + icon_state = "0-2" + }, +/obj/machinery/power/smes{ + charge = 5e+006 + }, +/turf/open/floor/plating, +/area/mine/laborcamp/security) "hf" = ( /obj/item/twohanded/required/kirbyplants/random, /turf/open/floor/plasteel, @@ -387,14 +411,6 @@ }, /turf/open/floor/plasteel, /area/mine/living_quarters) -"hv" = ( -/obj/machinery/camera{ - c_tag = "Crew Area Hallway West"; - dir = 1; - network = list("mine") - }, -/turf/open/floor/plasteel, -/area/mine/living_quarters) "hy" = ( /obj/machinery/camera{ c_tag = "Labor Camp External"; @@ -415,25 +431,21 @@ /turf/open/floor/plasteel, /area/mine/living_quarters) "hP" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{ - dir = 4 +/obj/structure/lattice/catwalk, +/obj/machinery/atmospherics/components/unary/outlet_injector/atmos/atmos_waste{ + dir = 4; + piping_layer = 3 }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/turf/open/floor/plasteel, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/mine/living_quarters) "hQ" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3, -/obj/structure/cable{ - icon_state = "1-2" +/obj/machinery/atmospherics/components/unary/outlet_injector/atmos/atmos_waste{ + dir = 1; + piping_layer = 3 }, -/turf/open/floor/plasteel, -/area/mine/living_quarters) +/obj/structure/lattice/catwalk, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/mine/laborcamp/security) "ia" = ( /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, @@ -582,6 +594,14 @@ }, /turf/open/floor/plasteel, /area/mine/living_quarters) +"kP" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable, +/obj/structure/cable{ + icon_state = "0-2" + }, +/turf/open/floor/plating, +/area/mine/laborcamp) "kR" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 4 @@ -630,6 +650,9 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{ dir = 6 }, +/obj/structure/cable{ + icon_state = "2-4" + }, /turf/open/floor/plasteel, /area/mine/laborcamp) "lI" = ( @@ -715,6 +738,9 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{ dir = 4 }, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/plasteel, /area/mine/laborcamp/security) "mN" = ( @@ -733,13 +759,11 @@ }, /turf/open/floor/plasteel, /area/mine/laborcamp/security) -"nv" = ( +"nx" = ( /obj/effect/spawner/structure/window/reinforced, -/obj/structure/cable{ - icon_state = "0-2" - }, +/obj/structure/cable, /turf/open/floor/plating, -/area/mine/living_quarters) +/area/mine/laborcamp/security) "ny" = ( /obj/machinery/computer/prisoner, /obj/effect/turf_decal/tile/red{ @@ -772,11 +796,17 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{ dir = 10 }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 1 +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 }, /obj/structure/cable{ - icon_state = "1-2" + icon_state = "1-8" + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/structure/cable{ + icon_state = "4-8" }, /turf/open/floor/plasteel, /area/mine/laborcamp/security) @@ -790,6 +820,14 @@ }, /turf/open/floor/plasteel, /area/mine/production) +"nL" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable, +/obj/structure/cable{ + icon_state = "0-2" + }, +/turf/open/floor/plating, +/area/mine/laborcamp/security) "nN" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -805,6 +843,19 @@ /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/mine/production) +"nX" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable{ + icon_state = "0-8" + }, +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/turf/open/floor/plating, +/area/mine/laborcamp/security) "oo" = ( /obj/machinery/conveyor{ id = "mining_internal" @@ -828,6 +879,9 @@ /obj/machinery/door/airlock/medical/glass{ name = "Infirmary" }, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plasteel/white, /area/mine/laborcamp) "oy" = ( @@ -886,6 +940,22 @@ }, /turf/open/floor/plasteel, /area/mine/eva) +"pu" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "0-4" + }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/mine/living_quarters) "pK" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3, @@ -947,6 +1017,15 @@ }, /turf/open/floor/plating, /area/mine/living_quarters) +"qx" = ( +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, +/obj/structure/sign/poster/official/random{ + pixel_y = 32 + }, +/turf/open/floor/plasteel, +/area/mine/living_quarters) "qH" = ( /obj/structure/extinguisher_cabinet{ pixel_x = 30 @@ -1071,6 +1150,12 @@ "si" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3, +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plasteel, /area/mine/laborcamp/security) "sj" = ( @@ -1151,15 +1236,25 @@ }, /turf/open/floor/plasteel, /area/mine/laborcamp) +"td" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable{ + icon_state = "0-4" + }, +/obj/structure/cable, +/turf/open/floor/plating, +/area/mine/laborcamp) "tk" = ( /obj/machinery/atmospherics/pipe/manifold4w/scrubbers/hidden/layer3, -/obj/machinery/atmospherics/pipe/manifold4w/supply/hidden, /obj/structure/cable{ icon_state = "4-8" }, /obj/structure/cable{ icon_state = "1-4" }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 8 + }, /turf/open/floor/plasteel, /area/mine/living_quarters) "tr" = ( @@ -1183,16 +1278,6 @@ }, /turf/open/floor/plasteel, /area/mine/production) -"uh" = ( -/obj/effect/turf_decal/tile/brown{ - dir = 8 - }, -/obj/effect/turf_decal/tile/brown, -/obj/effect/turf_decal/tile/brown{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/mine/living_quarters) "uG" = ( /obj/structure/table, /obj/item/clothing/glasses/meson, @@ -1258,6 +1343,13 @@ }, /turf/open/floor/plasteel, /area/mine/laborcamp) +"vA" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel, +/area/mine/laborcamp) "vE" = ( /obj/effect/turf_decal/tile/brown{ dir = 1 @@ -1285,6 +1377,16 @@ }, /turf/open/floor/plasteel, /area/mine/eva) +"vM" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/chair, +/turf/open/floor/plasteel, +/area/mine/living_quarters) "wd" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -1356,6 +1458,9 @@ /area/mine/production) "xd" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3, +/obj/structure/cable{ + icon_state = "2-8" + }, /turf/open/floor/plasteel, /area/mine/laborcamp) "xh" = ( @@ -1399,6 +1504,9 @@ /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer3{ dir = 1 }, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/plasteel, /area/mine/laborcamp/security) "yt" = ( @@ -1416,6 +1524,13 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel, /area/mine/production) +"yQ" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable{ + icon_state = "0-8" + }, +/turf/open/floor/plating, +/area/mine/laborcamp/security) "yR" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on, /turf/open/floor/plasteel, @@ -1435,12 +1550,26 @@ }, /turf/open/floor/plating, /area/mine/living_quarters) +"zk" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable{ + icon_state = "0-2" + }, +/obj/structure/cable, +/turf/open/floor/plating, +/area/mine/laborcamp/security) "zo" = ( /obj/structure/table, /turf/open/floor/carpet, /area/mine/living_quarters) "zx" = ( /obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable{ + icon_state = "0-2" + }, +/obj/structure/cable{ + icon_state = "0-4" + }, /turf/open/floor/plating, /area/mine/laborcamp) "zy" = ( @@ -1502,14 +1631,10 @@ /turf/open/floor/plasteel, /area/mine/living_quarters) "Ah" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3, /obj/structure/cable{ icon_state = "1-2" }, -/obj/structure/cable{ - icon_state = "2-8" - }, /turf/open/floor/plasteel, /area/mine/laborcamp/security) "Aj" = ( @@ -1602,6 +1727,16 @@ /obj/structure/reagent_dispensers/fueltank, /turf/open/floor/plating, /area/mine/living_quarters) +"BD" = ( +/obj/machinery/door/airlock/maintenance{ + name = "Mining Station Maintenance"; + req_access_txt = "48" + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plating, +/area/mine/laborcamp/security) "BO" = ( /obj/machinery/door/airlock{ name = "Labor Camp Storage" @@ -1638,6 +1773,12 @@ }, /turf/open/floor/plasteel, /area/mine/production) +"Cl" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel, +/area/mine/laborcamp) "Cm" = ( /obj/machinery/vending/snack, /obj/effect/turf_decal/tile/bar, @@ -1646,6 +1787,13 @@ }, /turf/open/floor/plasteel, /area/mine/living_quarters) +"Cw" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable{ + icon_state = "0-8" + }, +/turf/open/floor/plating, +/area/mine/laborcamp) "Cy" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 4 @@ -1748,18 +1896,6 @@ }, /turf/open/floor/plasteel, /area/mine/production) -"Em" = ( -/obj/effect/turf_decal/tile/brown{ - dir = 1 - }, -/obj/effect/turf_decal/tile/brown{ - dir = 8 - }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/turf/open/floor/plasteel, -/area/mine/living_quarters) "Ev" = ( /obj/machinery/light/small{ dir = 4 @@ -1792,7 +1928,9 @@ /obj/effect/turf_decal/tile/red{ dir = 8 }, -/obj/machinery/vending/security, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/plasteel, /area/mine/laborcamp/security) "EH" = ( @@ -1805,6 +1943,9 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{ dir = 9 }, +/obj/structure/cable{ + icon_state = "1-8" + }, /turf/open/floor/plasteel, /area/mine/laborcamp) "FC" = ( @@ -1825,19 +1966,6 @@ }, /turf/open/floor/plasteel, /area/mine/laborcamp) -"Ge" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/cable{ - icon_state = "2-4" - }, -/obj/structure/cable{ - icon_state = "1-4" - }, -/obj/structure/cable{ - icon_state = "0-4" - }, -/turf/open/floor/plating, -/area/mine/living_quarters) "Gt" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer3{ dir = 1 @@ -1845,9 +1973,6 @@ /obj/effect/turf_decal/tile/red{ dir = 8 }, -/obj/structure/cable{ - icon_state = "4-8" - }, /turf/open/floor/plasteel, /area/mine/laborcamp/security) "GM" = ( @@ -1891,6 +2016,9 @@ dir = 10 }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plasteel, /area/mine/laborcamp) "Hh" = ( @@ -1964,11 +2092,6 @@ }, /turf/open/floor/plasteel, /area/mine/laborcamp) -"HR" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/cable, -/turf/open/floor/plating, -/area/mine/living_quarters) "HS" = ( /obj/machinery/conveyor{ dir = 10; @@ -2038,6 +2161,9 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 8 }, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/plasteel, /area/mine/laborcamp/security) "II" = ( @@ -2053,6 +2179,9 @@ /obj/structure/table, /obj/effect/turf_decal/tile/red, /obj/machinery/recharger, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/plasteel, /area/mine/laborcamp/security) "IS" = ( @@ -2073,19 +2202,6 @@ }, /turf/open/floor/carpet, /area/mine/living_quarters) -"Jc" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{ - dir = 4 - }, -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/cable{ - icon_state = "2-4" - }, -/obj/structure/cable{ - icon_state = "0-4" - }, -/turf/open/floor/plating, -/area/mine/living_quarters) "Jl" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer3, /obj/effect/turf_decal/tile/purple{ @@ -2267,12 +2383,6 @@ }, /turf/open/floor/plasteel, /area/mine/production) -"KR" = ( -/obj/effect/turf_decal/tile/brown{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/mine/living_quarters) "KS" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -2347,10 +2457,11 @@ /turf/open/floor/plasteel, /area/mine/laborcamp/security) "LG" = ( -/obj/effect/turf_decal/tile/brown{ - dir = 1 +/obj/structure/cable{ + icon_state = "0-2" }, -/turf/open/floor/plasteel, +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, /area/mine/living_quarters) "LL" = ( /obj/effect/turf_decal/tile/red{ @@ -2392,6 +2503,13 @@ }, /turf/open/floor/plasteel, /area/mine/production) +"Mh" = ( +/obj/structure/table, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel/white, +/area/mine/laborcamp) "Mj" = ( /obj/structure/sink{ dir = 4; @@ -2492,12 +2610,6 @@ }, /turf/open/floor/plating, /area/mine/living_quarters) -"ML" = ( -/obj/structure/chair{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/mine/living_quarters) "MM" = ( /obj/machinery/light{ dir = 8 @@ -2702,16 +2814,16 @@ /turf/open/floor/plasteel, /area/mine/living_quarters) "Qr" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3, -/obj/machinery/door/airlock/security/glass{ - name = "Labor Camp Monitoring"; - req_access_txt = "2" +/obj/structure/cable, +/obj/structure/cable{ + icon_state = "1-8" }, /obj/structure/cable{ - icon_state = "1-2" + icon_state = "1-4" }, -/turf/open/floor/plasteel, +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, /area/mine/laborcamp/security) "Qx" = ( /obj/structure/chair{ @@ -2738,6 +2850,12 @@ }, /turf/open/floor/plasteel, /area/mine/eva) +"QL" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel, +/area/mine/laborcamp/security) "Rf" = ( /obj/machinery/mineral/unloading_machine{ dir = 1; @@ -2755,6 +2873,9 @@ req_access_txt = "2"; security_level = 6 }, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plasteel, /area/mine/laborcamp) "Ru" = ( @@ -2837,6 +2958,12 @@ /area/mine/living_quarters) "Sp" = ( /obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable{ + icon_state = "0-2" + }, +/obj/structure/cable{ + icon_state = "0-8" + }, /turf/open/floor/plating, /area/mine/laborcamp/security) "Sq" = ( @@ -2904,7 +3031,7 @@ dir = 8 }, /obj/structure/cable{ - icon_state = "4-8" + icon_state = "1-8" }, /turf/open/floor/plasteel, /area/mine/laborcamp/security) @@ -2951,6 +3078,9 @@ desc = "Powered by the tears and sweat of laborers."; name = "Prison Ofitser" }, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plasteel, /area/mine/laborcamp/security) "Un" = ( @@ -3099,19 +3229,6 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on, /turf/open/floor/plasteel/dark, /area/mine/maintenance) -"WX" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 5 - }, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer3, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/structure/cable{ - icon_state = "1-4" - }, -/turf/open/floor/plasteel, -/area/mine/living_quarters) "WY" = ( /obj/machinery/door/airlock{ id_tag = "miningdorm1"; @@ -3170,12 +3287,6 @@ }, /turf/open/floor/plasteel, /area/mine/living_quarters) -"XR" = ( -/obj/structure/sign/poster/official/random{ - pixel_y = 32 - }, -/turf/open/floor/plasteel, -/area/mine/living_quarters) "XU" = ( /obj/machinery/power/smes{ charge = 5e+006 @@ -3211,9 +3322,6 @@ dir = 1; network = list("labor") }, -/obj/structure/cable{ - icon_state = "4-8" - }, /turf/open/floor/plasteel, /area/mine/laborcamp/security) "Yi" = ( @@ -3291,13 +3399,6 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer3, /turf/open/floor/plasteel, /area/mine/living_quarters) -"Zu" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{ - dir = 4 - }, -/obj/structure/lattice/catwalk, -/turf/open/floor/plating/asteroid/basalt/lava_land_surface, -/area/mine/living_quarters) "Zw" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 4 @@ -4329,9 +4430,9 @@ cd cd HO cd -zI -zI -VT +RF +RF +RF VT VT VT @@ -4386,9 +4487,9 @@ HU cd Jr cd -my -wV -VT +fA +fx +RF VT uJ VT @@ -4443,13 +4544,13 @@ at cd Op cd -wV -wV -wV +hb +dU +RF +VT VT VT VT -Lm Lm wz wz @@ -4486,8 +4587,8 @@ JY JY JY zx -zx -zx +kP +td cd cd cd @@ -4501,15 +4602,15 @@ NH NH Ya Mn -Mn +BD Mn Dv Mn -nv -Ge -HR -VN -Lm +wV +VT +VT +VT +wz Lm Lm Lm @@ -4542,9 +4643,9 @@ JY JY JY JY -zx -wB +Cw wB +Mh cd AH NH @@ -4562,11 +4663,11 @@ EB MM LC Mn -xH -dC -hf -VN -bH +wV +wV +VT +VT +Lm Lm Lm Lm @@ -4603,13 +4704,13 @@ cd eh aN ow -NH -NH -NH -NH +Cl +Cl +Cl +gn vo ly -xd +vA Hg gs gs @@ -4619,11 +4720,11 @@ si fN TC Mn -ML -dC -oy -VN -Zu +wV +my +VT +VT +VT Lm Lm Lm @@ -4664,7 +4765,7 @@ fs NH Wt xd -xd +vA Fx Yf uR @@ -4676,13 +4777,13 @@ Hx mL Yg Mn -XR -dC -Ag -VN -Jc -HR -VN +zI +VT +VT +VT +VT +wz +Lm Lm Lm Lm @@ -4732,14 +4833,14 @@ LL Hx xS Gt -Sp -FE -Em -cD -Ag -sm -uh -VN +Dv +my +VT +VT +VT +VT +wz +Lm Lm Lm Lm @@ -4791,12 +4892,12 @@ nJ Ah Qr hQ -bI -hQ -hQ -WX -hv -VN +VT +VT +VT +Lm +Lm +Lm Lm Lm Lm @@ -4846,13 +4947,13 @@ WL Hx IG UJ -Sp -Ag -Ag -di -KR +yQ +my +my +VT +Lm hP -Ag +Lm VN VN VN @@ -4901,15 +5002,15 @@ Ya Mn kB Oh -Hx +QL sR Al Al Al Al LG -hP -Ag +pu +bn VN zy If @@ -4955,7 +5056,7 @@ my my my zI -Sp +Dv ny ig IK @@ -4964,9 +5065,9 @@ Al wC wC Al -Ag -hP -Ag +hf +vM +xH VN Ru Ag @@ -5013,16 +5114,16 @@ my my zI Sp -Sp -Sp -Sp -Sp +zk +nL +nX +nx Al Uz Ue Al -EH -hP +qx +sm aW VN Dr diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index a630c54b6e..452a080be0 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -21911,7 +21911,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/machinery/computer/arcade/minesweeper, +/obj/machinery/vending/wardrobe/cap_wardrobe, /turf/open/floor/wood, /area/crew_quarters/heads/captain) "bdj" = ( @@ -55854,6 +55854,10 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/dorms) +"nZL" = ( +/obj/machinery/computer/arcade/minesweeper, +/turf/open/floor/wood, +/area/crew_quarters/heads/captain) "oax" = ( /obj/structure/table/wood/fancy, /obj/machinery/light, @@ -57068,7 +57072,7 @@ /turf/open/floor/plating, /area/space) "sRH" = ( -/obj/machinery/autolathe{ +/obj/machinery/autolathe/secure{ name = "public autolathe" }, /turf/open/floor/plasteel, @@ -90865,7 +90869,7 @@ aVv aXg aYF aZV -bbw +nZL bcn tgH ben diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index fd0f0a1742..13597584ae 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -34904,7 +34904,7 @@ /obj/effect/turf_decal/tile/brown{ dir = 8 }, -/obj/machinery/autolathe{ +/obj/machinery/autolathe/secure{ name = "public autolathe" }, /turf/open/floor/plasteel, @@ -62353,7 +62353,7 @@ /turf/open/floor/wood, /area/crew_quarters/heads/captain/private) "cbd" = ( -/obj/effect/landmark/event_spawn, +/obj/machinery/vending/wardrobe/cap_wardrobe, /turf/open/floor/wood, /area/crew_quarters/heads/captain/private) "cbe" = ( @@ -127169,6 +127169,13 @@ dir = 9 }, /area/science/circuit) +"rjr" = ( +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 1 + }, +/obj/effect/landmark/event_spawn, +/turf/open/floor/wood, +/area/crew_quarters/heads/captain/private) "rqh" = ( /obj/structure/lattice, /turf/open/space/basic, @@ -169426,7 +169433,7 @@ bUO bXf bUQ cbe -ccP +rjr ceH cgu cij diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 3353d1b15b..3c8e251bb1 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -28355,6 +28355,7 @@ /obj/structure/disposalpipe/segment{ dir = 6 }, +/obj/machinery/vending/wardrobe/cap_wardrobe, /turf/open/floor/carpet, /area/crew_quarters/heads/captain/private) "bdL" = ( @@ -31855,7 +31856,7 @@ /obj/effect/turf_decal/tile/brown{ dir = 8 }, -/obj/machinery/autolathe{ +/obj/machinery/autolathe/secure{ name = "public autolathe" }, /turf/open/floor/plasteel, @@ -81645,6 +81646,19 @@ /obj/machinery/door/firedoor, /turf/open/floor/plating, /area/crew_quarters/cryopod) +"eQf" = ( +/obj/machinery/computer/shuttle/mining/common{ + dir = 1 + }, +/obj/structure/window/reinforced, +/obj/structure/window/reinforced{ + dir = 8 + }, +/obj/structure/window/reinforced{ + dir = 4 + }, +/turf/open/floor/plating, +/area/hallway/primary/port) "eZe" = ( /obj/structure/cable/yellow{ icon_state = "1-2" @@ -98511,7 +98525,7 @@ bgA biz bkb blZ -bnM +eQf bqf bqf bqf diff --git a/_maps/map_files/Mining/Lavaland.dmm b/_maps/map_files/Mining/Lavaland.dmm index 72f68910f7..13dd939ad7 100644 --- a/_maps/map_files/Mining/Lavaland.dmm +++ b/_maps/map_files/Mining/Lavaland.dmm @@ -77,6 +77,27 @@ "aA" = ( /turf/open/lava/smooth/lava_land_surface, /area/template_noop) +"aQ" = ( +/obj/structure/stone_tile/surrounding_tile{ + dir = 1 + }, +/turf/closed/indestructible/riveted/boss, +/area/lavaland/surface/outdoors) +"aU" = ( +/obj/structure/stone_tile/block/cracked, +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/item/t_scanner/adv_mining_scanner/lesser, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"cp" = ( +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) "cu" = ( /obj/item/pickaxe, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, @@ -85,6 +106,106 @@ /obj/structure/ore_box, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"cw" = ( +/obj/structure/stone_tile/block{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/effect/decal/cleanable/blood, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"dA" = ( +/obj/structure/stone_tile/block{ + dir = 4 + }, +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"dD" = ( +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 4 + }, +/turf/closed/indestructible/riveted/boss, +/area/lavaland/surface/outdoors) +"dF" = ( +/obj/structure/stone_tile/block/cracked, +/turf/closed/mineral/volcanic/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"dM" = ( +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"eb" = ( +/obj/structure/stone_tile/block{ + dir = 8 + }, +/obj/machinery/iv_drip, +/obj/item/reagent_containers/glass/beaker/waterbottle/large, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"eh" = ( +/obj/structure/stone_tile/slab/cracked{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"eo" = ( +/obj/structure/stone_tile/cracked, +/obj/structure/stone_tile/block{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"eq" = ( +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 8 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"eP" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/turf/closed/mineral/volcanic/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"eQ" = ( +/obj/structure/closet/crate/radiation, +/obj/item/flashlight/lantern, +/obj/item/flashlight/lantern, +/obj/item/flashlight/lantern, +/obj/item/flashlight/flare, +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"ft" = ( +/obj/structure/stone_tile/block, +/obj/item/twohanded/bonespear, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"fN" = ( +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/item/twohanded/bonespear, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) "fQ" = ( /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors/unexplored/danger) @@ -165,6 +286,17 @@ /obj/structure/stone_tile, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"gt" = ( +/obj/structure/stone_tile/surrounding_tile{ + dir = 8 + }, +/obj/structure/stone_tile/surrounding_tile, +/obj/structure/stone_tile/center/cracked, +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) "gy" = ( /obj/structure/stone_tile/cracked, /obj/structure/stone_tile{ @@ -203,6 +335,12 @@ }, /turf/open/indestructible/boss, /area/lavaland/surface/outdoors) +"gF" = ( +/obj/structure/stone_tile/block{ + dir = 8 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) "gG" = ( /obj/structure/stone_tile{ dir = 1 @@ -239,18 +377,47 @@ }, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"hd" = ( +/obj/structure/mineral_door/sandstone, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) "hg" = ( /obj/structure/stone_tile/surrounding, /obj/structure/stone_tile/center/cracked, /mob/living/simple_animal/hostile/megafauna/legion, /turf/open/indestructible/boss, /area/lavaland/surface/outdoors) +"hr" = ( +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/surrounding_tile/cracked, +/obj/structure/stone_tile/surrounding_tile{ + dir = 8 + }, +/obj/structure/stone_tile/center, +/obj/item/hatchet, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) "hs" = ( /obj/structure/stone_tile/block{ dir = 1 }, /turf/open/lava/smooth/lava_land_surface, /area/lavaland/surface/outdoors) +"hy" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/turf/open/lava/smooth{ + initial_gas_mix = "o2=14;n2=23;TEMP=300" + }, +/area/ruin/unpowered/ash_walkers) +"hD" = ( +/obj/effect/mob_spawn/human/corpse/damaged, +/obj/effect/decal/cleanable/blood, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) "hH" = ( /obj/structure/stone_tile/block{ dir = 1 @@ -271,6 +438,13 @@ }, /turf/open/indestructible/boss, /area/lavaland/surface/outdoors) +"ia" = ( +/obj/item/reagent_containers/glass/bucket, +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) "id" = ( /obj/structure/stone_tile{ dir = 4 @@ -284,6 +458,10 @@ }, /turf/open/indestructible/boss, /area/lavaland/surface/outdoors) +"io" = ( +/obj/structure/stone_tile/slab/cracked, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) "ir" = ( /obj/structure/stone_tile/slab/cracked{ dir = 5 @@ -327,6 +505,38 @@ /obj/structure/stone_tile/block/cracked, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"iG" = ( +/obj/structure/stone_tile/block{ + dir = 1 + }, +/obj/structure/stone_tile, +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/seeds/tower, +/obj/item/seeds/tower, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"iJ" = ( +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/obj/structure/table/wood, +/obj/item/clothing/head/helmet/roman/legionnaire, +/obj/item/twohanded/bonespear, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) "iK" = ( /obj/structure/stone_tile/block, /obj/structure/stone_tile/cracked{ @@ -376,6 +586,16 @@ }, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"jj" = ( +/obj/structure/stone_tile/block, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) "jk" = ( /obj/structure/stone_tile/center, /obj/structure/stone_tile/surrounding_tile, @@ -491,6 +711,12 @@ }, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"ke" = ( +/obj/structure/stone_tile/block{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) "kg" = ( /obj/structure/fluff/drake_statue, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, @@ -504,6 +730,12 @@ }, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"kk" = ( +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) "kl" = ( /obj/structure/fluff/drake_statue/falling, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, @@ -551,6 +783,13 @@ /obj/structure/stone_tile/center, /turf/open/lava/smooth/lava_land_surface, /area/lavaland/surface/outdoors) +"kG" = ( +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile/cracked, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "kH" = ( /obj/structure/stone_tile/surrounding_tile{ dir = 1 @@ -562,6 +801,9 @@ /obj/structure/stone_tile/center/cracked, /turf/open/lava/smooth/lava_land_surface, /area/lavaland/surface/outdoors) +"kI" = ( +/turf/closed/mineral/random/volcanic, +/area/ruin/unpowered/ash_walkers) "kJ" = ( /obj/structure/stone_tile/surrounding_tile{ dir = 4 @@ -587,10 +829,30 @@ }, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"kP" = ( +/obj/structure/stone_tile/surrounding_tile, +/obj/structure/stone_tile/surrounding_tile{ + dir = 1 + }, +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/center, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) "kR" = ( /obj/structure/stone_tile/slab/cracked, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"lb" = ( +/obj/structure/stone_tile/block{ + dir = 1 + }, +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/turf/closed/indestructible/riveted/boss, +/area/lavaland/surface/outdoors) "le" = ( /obj/structure/stone_tile, /obj/structure/stone_tile{ @@ -1179,10 +1441,989 @@ }, /turf/open/indestructible/boss, /area/lavaland/surface/outdoors) +"nt" = ( +/obj/structure/stone_tile/block, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/effect/decal/cleanable/blood, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"nB" = ( +/obj/item/shovel, +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"nI" = ( +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"nJ" = ( +/turf/closed/wall/mineral/wood, +/area/ruin/unpowered/ash_walkers) +"nU" = ( +/obj/structure/stone_tile, +/obj/item/shard, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"nW" = ( +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/obj/item/flashlight/lantern, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) "ol" = ( /obj/effect/landmark/stationroom/lavaland/station, /turf/open/lava/smooth/lava_land_surface, /area/template_noop) +"ot" = ( +/obj/structure/stone_tile/surrounding_tile, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"oB" = ( +/obj/item/stack/sheet/mineral/wood, +/obj/structure/stone_tile{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"oS" = ( +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/obj/item/malf_upgrade, +/obj/item/disk/tech_disk/illegal, +/obj/structure/safe, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"pc" = ( +/obj/effect/decal/cleanable/blood, +/obj/structure/stone_tile/block, +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"pq" = ( +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"pt" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 1 + }, +/turf/closed/indestructible/riveted/boss, +/area/lavaland/surface/outdoors) +"pD" = ( +/obj/structure/stone_tile/surrounding_tile{ + dir = 8 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"pF" = ( +/obj/structure/stone_tile/surrounding_tile{ + dir = 8 + }, +/obj/structure/stone_tile/center, +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 1 + }, +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"pG" = ( +/obj/structure/stone_tile/surrounding_tile{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"pH" = ( +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 1 + }, +/turf/closed/indestructible/riveted/boss, +/area/lavaland/surface/outdoors) +"qh" = ( +/obj/structure/stone_tile/surrounding/cracked{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"qi" = ( +/obj/structure/stone_tile/block{ + dir = 8 + }, +/turf/open/lava/smooth{ + initial_gas_mix = "o2=14;n2=23;TEMP=300" + }, +/area/ruin/unpowered/ash_walkers) +"qA" = ( +/obj/item/flashlight/lantern, +/obj/structure/stone_tile/center, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"qN" = ( +/obj/structure/stone_tile/block, +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"qS" = ( +/obj/structure/stone_tile/slab, +/turf/closed/indestructible/riveted/boss, +/area/lavaland/surface/outdoors) +"rz" = ( +/obj/item/storage/box/rxglasses, +/obj/structure/stone_tile{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"rO" = ( +/obj/structure/stone_tile/surrounding_tile/cracked, +/obj/structure/ore_box, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"rQ" = ( +/obj/structure/stone_tile/block{ + dir = 1 + }, +/turf/open/lava/smooth{ + initial_gas_mix = "o2=14;n2=23;TEMP=300" + }, +/area/ruin/unpowered/ash_walkers) +"sa" = ( +/obj/structure/stone_tile/block{ + dir = 4 + }, +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"se" = ( +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/obj/item/flashlight/lantern, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"sk" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 1 + }, +/obj/structure/stone_tile/cracked, +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"sl" = ( +/obj/structure/stone_tile/block{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/closed/indestructible/riveted/boss, +/area/lavaland/surface/outdoors) +"sq" = ( +/obj/structure/stone_tile, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"sx" = ( +/obj/item/stack/sheet/mineral/coal, +/obj/item/stack/sheet/mineral/coal, +/obj/item/stack/sheet/mineral/coal, +/obj/item/stack/sheet/mineral/coal, +/obj/item/stack/sheet/mineral/coal, +/obj/item/stack/sheet/mineral/coal, +/obj/item/stack/sheet/mineral/coal, +/obj/item/stack/sheet/mineral/coal, +/obj/item/stack/sheet/mineral/coal, +/obj/item/stack/sheet/mineral/coal, +/obj/item/stack/sheet/mineral/coal, +/obj/item/stack/sheet/mineral/coal, +/obj/item/stack/sheet/mineral/coal, +/obj/item/stack/sheet/mineral/coal, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"sR" = ( +/obj/structure/stone_tile/block/cracked, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"ty" = ( +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/item/flashlight/lantern, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"tz" = ( +/obj/structure/stone_tile/slab, +/obj/structure/table/wood, +/obj/item/toy/cards/deck/syndicate, +/obj/item/construction/rcd/loaded/upgraded, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"ub" = ( +/obj/structure/stone_tile/slab, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"ui" = ( +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/effect/decal/cleanable/blood, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"uk" = ( +/obj/structure/lavaland/ash_walker, +/turf/open/lava/smooth{ + initial_gas_mix = "o2=14;n2=23;TEMP=300" + }, +/area/ruin/unpowered/ash_walkers) +"uz" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 1 + }, +/turf/closed/indestructible/riveted/boss, +/area/lavaland/surface/outdoors) +"vi" = ( +/obj/structure/stone_tile/block{ + dir = 1 + }, +/obj/structure/stone_tile/cracked, +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"vu" = ( +/obj/structure/stone_tile/surrounding_tile/cracked, +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/center, +/obj/structure/stone_tile/surrounding_tile{ + dir = 8 + }, +/turf/open/lava/smooth{ + initial_gas_mix = "o2=14;n2=23;TEMP=300" + }, +/area/ruin/unpowered/ash_walkers) +"vR" = ( +/obj/machinery/hydroponics/soil, +/obj/structure/stone_tile/block/cracked{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"wm" = ( +/obj/item/seeds/glowshroom, +/obj/item/seeds/glowshroom, +/obj/structure/stone_tile/block{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"ww" = ( +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/center/cracked, +/obj/structure/stone_tile/surrounding_tile, +/obj/structure/stone_tile/surrounding_tile{ + dir = 1 + }, +/turf/open/lava/smooth{ + initial_gas_mix = "o2=14;n2=23;TEMP=300" + }, +/area/ruin/unpowered/ash_walkers) +"wF" = ( +/obj/structure/stone_tile/surrounding_tile{ + dir = 4 + }, +/turf/closed/indestructible/riveted/boss, +/area/lavaland/surface/outdoors) +"xr" = ( +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/obj/structure/closet/crate/internals, +/obj/item/pickaxe, +/obj/item/pickaxe, +/obj/item/pickaxe, +/obj/item/pickaxe, +/obj/item/pickaxe, +/obj/item/pickaxe, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"xs" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/turf/closed/mineral/volcanic/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"xJ" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 1 + }, +/obj/structure/stone_tile/block, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"xX" = ( +/obj/structure/stone_tile/block{ + dir = 8 + }, +/obj/item/pickaxe, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"yf" = ( +/obj/machinery/hydroponics/soil, +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 1 + }, +/obj/structure/stone_tile/surrounding_tile, +/obj/structure/stone_tile/surrounding_tile{ + dir = 4 + }, +/obj/structure/stone_tile/center, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"yv" = ( +/obj/structure/stone_tile/block, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"zf" = ( +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"zv" = ( +/obj/machinery/hydroponics/soil, +/obj/structure/stone_tile/block{ + dir = 8 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"Ad" = ( +/obj/structure/stone_tile{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"Ag" = ( +/turf/closed/mineral/volcanic/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"An" = ( +/obj/structure/stone_tile/slab, +/obj/structure/table/wood, +/obj/item/twohanded/bonespear, +/obj/item/twohanded/bonespear, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"AH" = ( +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/obj/item/twohanded/bonespear, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"AU" = ( +/obj/structure/stone_tile, +/turf/closed/mineral/volcanic/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"AY" = ( +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/obj/item/flashlight/lantern, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"Bf" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"Bj" = ( +/obj/structure/stone_tile/block{ + dir = 4 + }, +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/obj/effect/decal/cleanable/blood, +/obj/structure/necropolis_gate/ashwalker, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"Br" = ( +/obj/structure/stone_tile/slab, +/obj/effect/decal/cleanable/blood, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"Bs" = ( +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/obj/structure/closet/crate, +/obj/item/flashlight/lantern, +/obj/item/flashlight/lantern, +/obj/item/flashlight/lantern, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"BF" = ( +/obj/structure/flora/rock/jungle, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"BG" = ( +/obj/structure/stone_tile/block{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/closed/indestructible/riveted/boss, +/area/lavaland/surface/outdoors) +"BH" = ( +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 1 + }, +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 8 + }, +/obj/structure/stone_tile/center/cracked, +/turf/closed/mineral/volcanic/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"BP" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"BU" = ( +/turf/closed/indestructible/riveted/boss/see_through, +/area/ruin/unpowered/ash_walkers) +"Ch" = ( +/obj/structure/stone_tile/surrounding_tile{ + dir = 4 + }, +/obj/structure/stone_tile/center/cracked, +/obj/structure/stone_tile/surrounding_tile/cracked, +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"CG" = ( +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"CL" = ( +/obj/structure/stone_tile/slab, +/obj/structure/table/wood, +/obj/item/clothing/head/helmet/skull, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"Dn" = ( +/obj/structure/stone_tile/block{ + dir = 8 + }, +/turf/closed/indestructible/riveted/boss, +/area/ruin/unpowered/ash_walkers) +"Do" = ( +/obj/structure/stone_tile/block{ + dir = 8 + }, +/turf/closed/indestructible/riveted/boss, +/area/lavaland/surface/outdoors) +"Ds" = ( +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"Dx" = ( +/obj/structure/bonfire/dense, +/obj/structure/stone_tile/center, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"Dz" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/obj/structure/stone_tile, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"Ef" = ( +/obj/structure/stone_tile/block/cracked, +/turf/open/lava/smooth{ + initial_gas_mix = "o2=14;n2=23;TEMP=300" + }, +/area/ruin/unpowered/ash_walkers) +"Ez" = ( +/obj/machinery/grill{ + name = "old rusty grill" + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"EQ" = ( +/obj/structure/stone_tile/surrounding/cracked, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"EV" = ( +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"Fn" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/turf/closed/indestructible/riveted/boss, +/area/lavaland/surface/outdoors) +"Fz" = ( +/obj/structure/stone_tile/surrounding_tile{ + dir = 8 + }, +/obj/structure/stone_tile/block{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"FD" = ( +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/obj/structure/stone_tile/cracked, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"Gc" = ( +/obj/structure/flora/junglebush/b, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"Gw" = ( +/obj/structure/stone_tile/block{ + dir = 1 + }, +/turf/closed/indestructible/riveted/boss, +/area/lavaland/surface/outdoors) +"Gx" = ( +/obj/item/pickaxe, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"GC" = ( +/obj/structure/stone_tile/surrounding_tile/cracked, +/obj/structure/stone_tile/center, +/obj/structure/stone_tile/surrounding_tile{ + dir = 1 + }, +/obj/structure/stone_tile/surrounding_tile{ + dir = 8 + }, +/turf/open/lava/smooth{ + initial_gas_mix = "o2=14;n2=23;TEMP=300" + }, +/area/ruin/unpowered/ash_walkers) +"Hq" = ( +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/table/wood, +/obj/item/scythe, +/obj/item/twohanded/bonespear, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"HX" = ( +/obj/structure/stone_tile/block{ + dir = 4 + }, +/obj/structure/stone_tile/block/cracked{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"It" = ( +/obj/structure/stone_tile/block{ + dir = 8 + }, +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"Jq" = ( +/obj/structure/stone_tile/slab/cracked, +/obj/effect/decal/cleanable/blood, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"JP" = ( +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/obj/effect/decal/cleanable/blood, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"JR" = ( +/obj/structure/stone_tile/block, +/obj/structure/stone_tile/block/cracked{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"JZ" = ( +/obj/structure/stone_tile/cracked, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"KA" = ( +/obj/structure/stone_tile/slab, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"KJ" = ( +/obj/structure/stone_tile/block/cracked, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"KV" = ( +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/obj/effect/mob_spawn/human/corpse/damaged, +/obj/effect/decal/cleanable/blood, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"LJ" = ( +/turf/open/water, +/area/ruin/unpowered/ash_walkers) +"Mh" = ( +/obj/structure/stone_tile/cracked, +/obj/structure/stone_tile/block{ + dir = 8 + }, +/turf/closed/indestructible/riveted/boss, +/area/lavaland/surface/outdoors) +"Mx" = ( +/turf/closed/mineral/volcanic/lava_land_surface, +/area/lavaland/surface/outdoors) +"MQ" = ( +/obj/structure/table/optable, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/item/surgical_drapes, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"MS" = ( +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/obj/structure/stone_tile/cracked, +/turf/closed/mineral/volcanic/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"MX" = ( +/obj/structure/stone_tile/slab/cracked, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"NN" = ( +/obj/structure/stone_tile/block/cracked, +/obj/structure/stone_tile/block{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"Ou" = ( +/obj/structure/stone_tile/slab, +/obj/structure/table/wood, +/obj/item/storage/toolbox/syndicate, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"Oy" = ( +/obj/structure/stone_tile/surrounding_tile{ + dir = 4 + }, +/obj/structure/stone_tile/surrounding_tile{ + dir = 1 + }, +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 8 + }, +/obj/structure/stone_tile/center, +/obj/effect/decal/cleanable/blood, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"OR" = ( +/obj/structure/stone_tile/block{ + dir = 1 + }, +/obj/structure/stone_tile/block/cracked, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"Pj" = ( +/obj/structure/stone_tile/surrounding_tile/cracked, +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 1 + }, +/obj/structure/stone_tile/surrounding_tile{ + dir = 8 + }, +/obj/structure/stone_tile/center, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"Qd" = ( +/obj/structure/stone_tile/block{ + dir = 8 + }, +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/table/wood, +/obj/item/storage/belt, +/obj/item/twohanded/bonespear, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"Qk" = ( +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/obj/item/stack/marker_beacon/ten, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"QC" = ( +/obj/structure/stone_tile/block, +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"QG" = ( +/obj/structure/stone_tile/block{ + dir = 8 + }, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/obj/structure/stone_tile, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"QM" = ( +/obj/structure/stone_tile/surrounding_tile/cracked, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"Rb" = ( +/obj/structure/closet/crate, +/obj/structure/stone_tile/block/cracked{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile/cracked, +/obj/item/flashlight/lantern, +/obj/item/flashlight/lantern, +/obj/item/flashlight/lantern, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"Rk" = ( +/obj/structure/stone_tile, +/obj/structure/stone_tile/block{ + dir = 1 + }, +/turf/closed/indestructible/riveted/boss, +/area/lavaland/surface/outdoors) +"Rr" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/turf/closed/indestructible/riveted/boss, +/area/ruin/unpowered/ash_walkers) +"RF" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 8 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"RX" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 1 + }, +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile, +/obj/effect/decal/cleanable/blood, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"Sh" = ( +/obj/structure/stone_tile/block, +/turf/closed/mineral/volcanic/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"Si" = ( +/turf/closed/indestructible/riveted/boss, +/area/ruin/unpowered/ash_walkers) +"Sr" = ( +/turf/closed/mineral/random/high_chance/volcanic, +/area/ruin/unpowered/ash_walkers) +"SG" = ( +/obj/structure/stone_tile/block{ + dir = 4 + }, +/turf/closed/indestructible/riveted/boss, +/area/lavaland/surface/outdoors) +"Tn" = ( +/obj/structure/stone_tile/block{ + dir = 1 + }, +/obj/structure/stone_tile/cracked, +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/table/wood, +/obj/item/kitchen/knife/combat/bone, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"TN" = ( +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 8 + }, +/obj/structure/stone_tile/center, +/obj/structure/stone_tile/surrounding_tile{ + dir = 1 + }, +/obj/structure/stone_tile/surrounding_tile{ + dir = 4 + }, +/turf/open/lava/smooth{ + initial_gas_mix = "o2=14;n2=23;TEMP=300" + }, +/area/ruin/unpowered/ash_walkers) +"Uh" = ( +/obj/structure/stone_tile/slab, +/obj/structure/table/wood, +/obj/item/weldingtool/experimental, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) "Uq" = ( /obj/docking_port/stationary{ area_type = /area/lavaland/surface/outdoors; @@ -1195,6 +2436,221 @@ }, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"UG" = ( +/obj/structure/stone_tile/block, +/obj/structure/stone_tile/block{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"UV" = ( +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile/cracked, +/obj/effect/decal/cleanable/blood, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"Vb" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/obj/item/storage/bag/plants/portaseeder, +/obj/item/seeds/cotton, +/obj/item/seeds/cotton, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"Vj" = ( +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/closed/mineral/volcanic/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"VI" = ( +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/reagent_dispensers/watertank, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"VP" = ( +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"Wb" = ( +/obj/structure/stone_tile/block{ + dir = 8 + }, +/obj/structure/stone_tile/block{ + dir = 4 + }, +/turf/closed/indestructible/riveted/boss, +/area/ruin/unpowered/ash_walkers) +"Wh" = ( +/obj/structure/stone_tile{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"Wj" = ( +/obj/structure/stone_tile/surrounding_tile/cracked, +/turf/closed/mineral/volcanic/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"WL" = ( +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/closet/crate/medical, +/obj/item/storage/firstaid/regular, +/obj/item/storage/firstaid/ancient, +/obj/item/reagent_containers/blood/random, +/obj/item/reagent_containers/blood/lizard, +/obj/item/reagent_containers/blood/lizard, +/obj/item/stack/sheet/cloth/ten, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"WN" = ( +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/obj/item/twohanded/bonespear, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"WT" = ( +/obj/structure/stone_tile/block{ + dir = 4 + }, +/obj/structure/stone_tile{ + dir = 8 + }, +/obj/structure/stone_tile{ + dir = 4 + }, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"WU" = ( +/obj/structure/stone_tile, +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"Xe" = ( +/obj/structure/stone_tile/surrounding_tile, +/obj/structure/stone_tile/center/cracked, +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 1 + }, +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 8 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"Xf" = ( +/obj/structure/stone_tile/block{ + dir = 8 + }, +/obj/structure/stone_tile, +/obj/structure/stone_tile{ + dir = 1 + }, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"Xo" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/turf/closed/indestructible/riveted/boss, +/area/lavaland/surface/outdoors) +"Xw" = ( +/obj/structure/stone_tile{ + dir = 1 + }, +/obj/structure/stone_tile, +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"Xz" = ( +/obj/structure/stone_tile/surrounding_tile/cracked{ + dir = 8 + }, +/turf/closed/mineral/volcanic/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"XG" = ( +/obj/effect/decal/cleanable/blood, +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/obj/structure/stone_tile/cracked{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"Yg" = ( +/obj/structure/flora/rock/pile/largejungle{ + light_range = null + }, +/turf/open/water, +/area/ruin/unpowered/ash_walkers) +"Yy" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/obj/item/flashlight/lantern, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"YH" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/obj/structure/stone_tile/block{ + dir = 8 + }, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/ash_walkers) +"Zc" = ( +/obj/structure/stone_tile{ + dir = 4 + }, +/obj/structure/stone_tile/cracked, +/obj/structure/stone_tile/cracked{ + dir = 1 + }, +/obj/structure/stone_tile/cracked{ + dir = 8 + }, +/obj/machinery/the_singularitygen, +/turf/open/indestructible/boss, +/area/ruin/unpowered/ash_walkers) +"Zs" = ( +/obj/structure/stone_tile/block{ + dir = 8 + }, +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/turf/closed/indestructible/riveted/boss, +/area/ruin/unpowered/ash_walkers) (1,1,1) = {" aa @@ -52358,9 +53814,9 @@ aa aa aa ad -ab -ab -ab +Mx +Mx +Mx aj aj aj @@ -52615,11 +54071,11 @@ aa aa aa ad -ab -ab -ab -aj -aj +Mx +Mx +Mx +Mx +Mx aj aj aj @@ -52864,20 +54320,20 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -aj -aj -aj +Si +Si +Si +Si +Si +Si +Si +Ag +Ag +Ag +Mx +Mx +Mx +Mx aj aj aj @@ -53121,20 +54577,20 @@ aa aa aa aa -aa -ad -ad -ad -iy -ab -ab -ab -ab -ab -ab -ab -ab -aj +Si +Sr +Sr +Sr +JZ +nI +nI +nI +nI +CG +Ag +Ag +Ag +Mx aj aj aj @@ -53378,20 +54834,20 @@ aa aa aa aa -aa -ad -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aj +Si +Sr +nI +nI +nI +nI +pq +nI +LJ +nI +nI +nI +Ag +Mx aj aj aj @@ -53635,20 +55091,20 @@ aa aa aa aa -aa -it -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aj +Si +yv +nI +nI +nI +nI +BF +LJ +LJ +LJ +nI +JZ +nI +Mx aj aj aj @@ -53892,20 +55348,20 @@ aa aa aa aa -aa -it -ab -ab -ab -ab -ab -ab -ab -ai -ai -ab -ab -ab +Si +yv +nI +nI +Ad +nI +LJ +LJ +LJ +LJ +kI +nI +JZ +Mx aj aj aj @@ -54149,20 +55605,20 @@ aa aa aa aa -aa -ab -ab -ab -ab -ab -ab -ab -ad -ai -ai -ab -ab -ab +Si +nI +nI +Ez +nI +LJ +LJ +Yg +LJ +kI +kI +nI +nI +Mx aj ab aj @@ -54406,21 +55862,21 @@ aa aa aa aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ai -ai -ad -ab -aj -aj +Si +nI +nI +sx +nI +LJ +LJ +LJ +LJ +kI +kI +Sr +Ag +Mx +Mx aj aj aj @@ -54663,21 +56119,21 @@ aa aa aa aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ad -ab -ab -aj -aj +Si +nI +nI +nI +Wh +nI +LJ +LJ +Gc +nI +Sr +nI +Ag +Mx +Mx aj aj aj @@ -54920,21 +56376,21 @@ aa aa aa aa -aa -ad -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aj -aj +Si +Sr +nI +nI +nI +Wh +nI +nI +nI +nI +nI +nI +Ag +Mx +Mx aj aj aj @@ -55177,21 +56633,21 @@ aa aa aa aa -aa -aa -aa -it -ab -ab -ab -ab -ab -ab -ab -ab -ab -aj -aj +Si +Ag +Ag +nI +nI +nI +nI +Ds +nI +Ds +nI +nI +Ag +Mx +Mx aj aj aj @@ -55429,25 +56885,25 @@ aa aa aa aa +wF +Do +Mh aa aa -aa -aa -aa -aa -aa -aa -ad -ab -ab -ab -ab -ab -ab -ab -ab -ab -aj +Rr +Ag +xs +eq +nI +nI +nI +nI +nI +nI +nI +nI +Ag +Mx aj aj aj @@ -55457,14 +56913,14 @@ aj ab ab ab +ab ak ak ak ak ak -ak -ak -ak +ab +ab ak ak ak @@ -55687,42 +57143,42 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -ad -ab -ab -ab -ab -ab -ab -ab -ab +Si +Si +Si +Si +Si +Si +Si +yv +nI +nI +sq +kk +Gx +nI +nI +nI +Si +Mx +aj +aj ab aj aj aj -aj -aj -aj -aj +aa +ab ab ab ab ak ak -ak -ak -ak -ak -ak -ak -ak +ab +ab +ab +ab +ab ak ak ak @@ -55944,13 +57400,32 @@ aa aa aa aa +Si +oS +CG +wm +Vb +Bs +Si +yv +sq +CG +AH +Ds +Ds +KV +nI +Ad +Si +aa +ab +aj +aj +ab +aj aa aa -aa -aa -aa -aa -ad +kG ab ab ab @@ -55960,14 +57435,6 @@ ab ab ab ab -aj -aj -aj -aj -aj -aj -aj -aj ab ab ab @@ -56171,17 +57638,6 @@ ak ak ak ak -ak -ak -ak -ak -ak -ak -ak -ak -ak -ak -ak al fQ aj @@ -56200,13 +57656,33 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa +Gw +Si +aU +Wh +zf +Qk +iG +Si +Wh +EV +Xe +ke +Ch +kk +Ad +Wh +nI +Ad +lp +lz +lp +lF +lp +lP +lS +iy +iu ab ab ab @@ -56217,14 +57693,6 @@ ab ab ab ab -aj -aj -aj -aj -aj -aj -aj -aj ab ab ab @@ -56429,18 +57897,6 @@ ak ak ak ak -ak -ak -ak -ak -ak -ak -ak -ak -ak -ak -ak -ak aj aj aj @@ -56457,13 +57913,33 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa +Rk +Si +sR +rz +qh +pq +Jq +ke +ub +YH +sR +Dx +Bf +UV +kk +Ds +nI +yv +lu +lq +lD +lG +lu +lQ +lu +kR +kM ab ab ab @@ -56474,14 +57950,6 @@ ab ab ab ab -aj -aj -aj -aj -aj -aj -aj -aj ab ab ab @@ -56686,18 +58154,6 @@ ak ak ak ak -ak -ak -ak -ak -ak -ak -ak -ak -ak -ak -ak -ak aj aj aj @@ -56714,13 +58170,33 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa +uz +Si +MQ +nU +ui +Xw +Rb +Si +sR +Wh +gt +gF +pF +sq +Ad +VP +Ad +pq +lv +lv +lE +lv +lE +lR +lv +ab +jS ab ab ab @@ -56731,27 +58207,7 @@ ab ab ab ab -aj -aj -aj -aj -aj -aj -aj -aj ab -ab -ab -ak -ak -ak -ak -ak -ak -ak -ak -ak -ak ak ak ak @@ -56971,14 +58427,33 @@ aa aa aa aa +uz +Si +WL +eb +dM +eQ +Zc +Si +Wh +XG +pq +NN +JZ +oB +EV +nB +nI +Si +aa +aj +aj +aj +aj +aj aa aa -aa -aa -aa -aa -ad -js +FD ab ab ab @@ -56988,26 +58463,7 @@ ab ab ab ab -aj -aj -aj -aj -aj -aj -aj -aj ab -ab -ab -ak -ak -ak -ak -ak -ak -ak -ak -ak ak ak ak @@ -57229,41 +58685,41 @@ aa aa aa aa +Si +Si +Si +Si +Si +Si +Si +CG +Wh +CG +JR +Ad +Pj +ia +yf +Ds +Si +aj +aj +ab +ab +aj +aj +aj aa -aa -aa -aa -aa -ad -ad -ad ab ab ab ab -ab -ab -ab -ab -aj -aj -aj -aj -aj -aj -aj -aj -ab -ab -ab -ak -ak -ak -ak -ak -ak ak ak +ab +ab +ab +ab ak ak ak @@ -57484,42 +58940,42 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa -ad -ai -ai -ai -ai +dD +pt +Wb +Dn +Zs +Zs +xX +gF +Fz +QM +CG +Wh +pc +dA +yv +qA +vR +WU +Ag +aj +aj +aj +aj +aj +aj +aj ab ab ab ab -ab -ab -aj -aj -aj -aj -aj -aj -aj -aj -ab -ab -ab -ak -ak -ak ak ak ak ak +ab +ab ak ak ak @@ -57740,27 +59196,27 @@ aj aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -ad -ai -ai -ai -ai -ad +wF +qS +Si +Si +Si +Si +Si +Si +Si +Br +pD +Wh +Ad +NN +Wh +hr +zv +BH +sq +Ag ab -ab -ab -ab -ab -aj -aj aj aj aj @@ -57997,27 +59453,27 @@ aj aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -ad -ai -ai -ai -ai -ad +Gw +Si +KA +KA +KA +KA +KA +Si +Si +Si +ft +Ad +pq +NN +VI +Vj +MS +AU +Ag +Ag ab -ab -ab -ab -ab -aj -aj aj aj aj @@ -58254,28 +59710,28 @@ aj aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -ad -ai -ai -ai -ai -ad +lb +tz +KA +AY +BP +cw +WT +ty +Si +Si +qN +nI +hD +UG +Ag +Ag +Ag +Ag +Ag +Ag +Mx ab -ab -ab -ab -ab -aj -aj -aj aj aj aj @@ -58511,28 +59967,28 @@ aj aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -ad -ai -ai -ai -ai -ad +uz +Ou +KA +QC +GC +hy +ww +vi +Si +BU +kP +cp +CG +xJ +RF +Ag +xs +xs +xs +Xz +Mx ab -ab -ab -ab -ab -aj -aj -aj aj aj aj @@ -58768,28 +60224,28 @@ aj aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -gP -ai -ai -ai -ai -ad +Gw +An +KA +nt +Ef +uk +rQ +MX +sa +Bj +ub +It +dA +sk +Si +Si +nJ +Si +Si +Ag +Mx ab -ab -ab -ab -ab -aj -aj -aj aj aj aj @@ -59025,29 +60481,29 @@ aj aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ai -ai -ai -ai +Gw +Uh +KA +jj +vu +qi +TN +RX +Si +BU +Oy +cp +pq +UG +nJ +WN +Yy +Hq +nJ +Ag +Mx ab ab -ab -ab -ab -ab -ab -aj -aj -aj aj aj aj @@ -59282,27 +60738,27 @@ aj aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ai -ai -ai -ai -ab -ab -ab -ab -ab -ab -ab -ab +sl +CL +KA +nW +Dz +Xf +QG +se +Si +Si +KJ +CG +fN +ub +RF +eh +EQ +Tn +nJ +Ag +Mx aj aj ab @@ -59539,28 +60995,28 @@ aj aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa +Gw +Si +KA +KA +KA +KA +KA +Si +Si +Si +sR +pq +sq +nI +nJ +JP +Qd +iJ +Si +Sh +Mx ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aj -aj -aj aj aj aj @@ -59796,28 +61252,28 @@ aj aa aa aa -aa -aa -aa -aa -aa -aa -aa -aa +pH +qS +Si +Si +Si +Si +Si +Si +Si +io +rO +xr +nI +eo +nJ +nJ +nJ +Si +Si +dF +Mx ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aj -aj -aj aj aj aj @@ -60054,27 +61510,27 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa +aQ +Fn +SG +SG +SG +BG +SG +Xo +ot +nI +nI +nI +pG +Ag +Ag +eP +Ag +Ag +Wj +Mx ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aj -aj -aj aj aj aj @@ -60318,19 +61774,19 @@ aa aa aa aa +Mx +Mx +nI +nI +nI +HX +Ag +Mx +Mx +Mx ab +Mx ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aj -aj aj aj aj @@ -60575,15 +62031,15 @@ aa aa aa aa -it -ab -ab -ab -ab -ab -ab -ab -ab +Mx +Mx +Ag +nI +nI +OR +Ag +Mx +Mx ab ab aj @@ -60833,13 +62289,13 @@ aa aa aa ad -ab -ab -ab -ab -ab -ab -ab +Mx +Ag +Ag +nI +gF +Ag +Mx ab ab ab @@ -61091,12 +62547,12 @@ aa aa ad ad -ab -ab -ab -ab -ab -ab +Mx +Mx +Ag +hd +Ag +Mx ab ab ab @@ -61350,7 +62806,7 @@ ad ad ad ad -ab +Mx ab ab ab @@ -61607,7 +63063,7 @@ ad ad ad ad -ab +Mx ab ab ab @@ -61860,12 +63316,12 @@ aa aa aa aa -gP -js -ab +Mx +Mx +Mx ad ad -ab +Mx ab ab ab @@ -62122,7 +63578,7 @@ aa aa aa aa -ab +Mx ab ab ab @@ -62385,10 +63841,10 @@ ab ab ab ab -aj -aj -aj -aj +ab +ab +ab +ab ab ab aj @@ -62643,9 +64099,9 @@ ab ab ab ab -aj ab -aj +ab +ab ab ab ab @@ -62902,8 +64358,8 @@ ab aj aj aj -aj -aj +ab +ab ab ab ab diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm index 22734b0979..b34da30300 100644 --- a/_maps/map_files/PubbyStation/PubbyStation.dmm +++ b/_maps/map_files/PubbyStation/PubbyStation.dmm @@ -9830,6 +9830,7 @@ /obj/structure/cable{ icon_state = "0-2" }, +/obj/item/twohanded/required/kirbyplants/random, /turf/open/floor/carpet, /area/crew_quarters/heads/captain) "axT" = ( @@ -11162,10 +11163,7 @@ /obj/structure/extinguisher_cabinet{ pixel_x = -24 }, -/obj/item/twohanded/required/kirbyplants{ - icon_state = "plant-20"; - pixel_y = 3 - }, +/obj/machinery/vending/wardrobe/cap_wardrobe, /turf/open/floor/plasteel/dark, /area/crew_quarters/heads/captain) "aBl" = ( @@ -28097,11 +28095,6 @@ }, /turf/open/floor/plasteel/dark, /area/science/robotics/lab) -"boY" = ( -/obj/effect/turf_decal/bot, -/obj/effect/landmark/start/cyborg, -/turf/open/floor/plasteel, -/area/science/robotics/lab) "boZ" = ( /obj/structure/table, /obj/machinery/cell_charger, @@ -98811,8 +98804,8 @@ beI bkt blH bmO -boY -boY +bnQ +bnQ bqi bry bsZ @@ -99068,8 +99061,8 @@ bju bkt blI bmO -boY -boY +bnQ +bnQ bqi brz bta diff --git a/_maps/shuttles/pirate_default.dmm b/_maps/shuttles/pirate_default.dmm index 1c8670d5b6..c002e66d53 100644 --- a/_maps/shuttles/pirate_default.dmm +++ b/_maps/shuttles/pirate_default.dmm @@ -89,7 +89,7 @@ /turf/open/floor/pod/dark, /area/shuttle/pirate) "aj" = ( -/turf/closed/wall/mineral/plastitanium/nodiagonal, +/turf/closed/wall/r_wall/syndicate/pirate/nodiagonal, /area/shuttle/pirate) "ak" = ( /obj/machinery/airalarm/all_access{ @@ -419,6 +419,7 @@ /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 1 }, +/obj/structure/fans/tiny, /turf/open/floor/plating, /area/shuttle/pirate) "aK" = ( @@ -463,21 +464,19 @@ /turf/open/floor/plating, /area/shuttle/pirate) "aQ" = ( -/obj/machinery/porta_turret/syndicate/energy{ +/obj/machinery/porta_turret/syndicate/energy/pirate{ dir = 1; faction = list("pirate"); - icon_state = "standard_lethal"; - mode = 1 + icon_state = "standard_lethal" }, -/turf/closed/wall/mineral/plastitanium/nodiagonal, +/turf/closed/wall/r_wall/syndicate/pirate/nodiagonal, /area/shuttle/pirate) "aR" = ( -/obj/machinery/porta_turret/syndicate/energy{ +/obj/machinery/porta_turret/syndicate/energy/pirate{ faction = list("pirate"); - icon_state = "standard_lethal"; - mode = 1 + icon_state = "standard_lethal" }, -/turf/closed/wall/mineral/plastitanium, +/turf/closed/wall/r_wall/syndicate/pirate, /area/shuttle/pirate) "aS" = ( /obj/effect/turf_decal/stripes/line, @@ -486,7 +485,7 @@ /area/shuttle/pirate) "aU" = ( /obj/structure/sign/departments/engineering, -/turf/closed/wall/mineral/plastitanium/nodiagonal, +/turf/closed/wall/r_wall/syndicate/pirate/nodiagonal, /area/shuttle/pirate) "aV" = ( /obj/effect/mob_spawn/human/pirate{ @@ -867,37 +866,36 @@ dir = 1 }, /obj/docking_port/mobile/pirate{ - callTime = 100; - dheight = 0; - dir = 1; dwidth = 11; height = 16; - id = "pirateship"; launch_status = 0; movement_force = list("KNOCKDOWN" = 0, "THROW" = 0); name = "Pirate Ship"; port_direction = 2; - preferred_direction = 1; width = 17 }, /obj/docking_port/stationary{ - dir = 1; dwidth = 11; height = 16; id = "pirateship_home"; name = "Deep Space"; width = 17 }, +/obj/structure/fans/tiny, /turf/open/floor/plating, /area/shuttle/pirate) +"db" = ( +/obj/structure/shuttle/engine/heater, +/obj/effect/spawner/structure/window/plastitanium/pirate, +/turf/open/floor/plating/airless, +/area/shuttle/pirate) "df" = ( -/obj/machinery/porta_turret/syndicate/energy{ +/obj/machinery/porta_turret/syndicate/energy/pirate{ dir = 4; faction = list("pirate"); - icon_state = "standard_lethal"; - mode = 1 + icon_state = "standard_lethal" }, -/turf/closed/wall/mineral/plastitanium, +/turf/closed/wall/r_wall/syndicate/pirate, /area/shuttle/pirate) "dy" = ( /obj/structure/chair/wood/normal, @@ -988,7 +986,7 @@ id = "piratebridge" }, /obj/structure/grille, -/obj/structure/window/plastitanium, +/obj/structure/window/plastitanium/pirate, /turf/open/floor/plating, /area/shuttle/pirate) "ez" = ( @@ -1016,7 +1014,7 @@ /turf/open/floor/plasteel, /area/shuttle/pirate) "fW" = ( -/turf/closed/wall/mineral/plastitanium, +/turf/closed/wall/r_wall/syndicate/pirate, /area/shuttle/pirate) "fY" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ @@ -1084,13 +1082,12 @@ /turf/open/floor/plasteel/showroomfloor, /area/shuttle/pirate) "wR" = ( -/obj/machinery/porta_turret/syndicate/energy{ +/obj/machinery/porta_turret/syndicate/energy/pirate{ dir = 8; faction = list("pirate"); - icon_state = "standard_lethal"; - mode = 1 + icon_state = "standard_lethal" }, -/turf/closed/wall/mineral/plastitanium, +/turf/closed/wall/r_wall/syndicate/pirate, /area/shuttle/pirate) "yi" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ @@ -1326,7 +1323,7 @@ aU be aD aG -ep +db aH "} (9,1,1) = {" @@ -1344,7 +1341,7 @@ mU aL bP bX -ep +db aK "} (10,1,1) = {" @@ -1362,7 +1359,7 @@ aj bO bQ bk -ep +db er "} (11,1,1) = {" diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index 6913473e88..0a64f01a43 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -138,8 +138,8 @@ ////organ defines #define STANDARD_ORGAN_THRESHOLD 100 -#define STANDARD_ORGAN_HEALING 0.001 -#define STANDARD_ORGAN_DECAY 0.00222 //designed to fail organs when left to decay for ~15 minutes +#define STANDARD_ORGAN_HEALING (1/(15 MINUTES / (2 SECONDS))) +#define STANDARD_ORGAN_DECAY (1/(15 MINUTES / (2 SECONDS))) //designed to fail organs when left to decay for ~15 minutes. 2 SECOND is SSmobs tickrate. #define G_MALE 1 #define G_FEMALE 2 diff --git a/code/__DEFINES/MC.dm b/code/__DEFINES/MC.dm index fe48edd266..65be8258a1 100644 --- a/code/__DEFINES/MC.dm +++ b/code/__DEFINES/MC.dm @@ -20,7 +20,7 @@ #define NEW_SS_GLOBAL(varname) if(varname != src){if(istype(varname)){Recover();qdel(varname);}varname = src;} #define START_PROCESSING(Processor, Datum) if (!(Datum.datum_flags & DF_ISPROCESSING)) {Datum.datum_flags |= DF_ISPROCESSING;Processor.processing += Datum} -#define STOP_PROCESSING(Processor, Datum) Datum.datum_flags &= ~DF_ISPROCESSING;Processor.processing -= Datum +#define STOP_PROCESSING(Processor, Datum) Datum.datum_flags &= ~DF_ISPROCESSING;Processor.processing -= Datum;Processor.currentrun -= Datum //SubSystem flags (Please design any new flags so that the default is off, to make adding flags to subsystems easier) diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index 2b19610040..56d5c63833 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -34,6 +34,7 @@ #define CAN_MASTURBATE_WITH (1<<5) #define MASTURBATE_LINKED_ORGAN (1<<6) //used to pass our mission to the linked organ #define CAN_CLIMAX_WITH (1<<7) +#define GENITAL_CAN_AROUSE (1<<8) #define COCK_SIZE_MIN 1 #define COCK_SIZE_MAX 20 diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index 0efd5a1f79..c4c9d815a0 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -187,10 +187,10 @@ #define SPEECH_MESSAGE 1 // #define SPEECH_BUBBLE_TYPE 2 #define SPEECH_SPANS 3 - /* #define SPEECH_SANITIZE 4 +// #define SPEECH_SANITIZE 4 #define SPEECH_LANGUAGE 5 - #define SPEECH_IGNORE_SPAM 6 - #define SPEECH_FORCED 7 */ +// #define SPEECH_IGNORE_SPAM 6 +// #define SPEECH_FORCED 7 // /mob/living signals #define COMSIG_LIVING_FULLY_HEAL "living_fully_healed" //from base of /mob/living/fully_heal(): (admin_revive) diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index a7d2670747..957f6edae4 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -54,13 +54,13 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define PASSCLOSEDTURF (1<<5) #define LETPASSTHROW (1<<6) - //Movement Types -#define GROUND (1<<0) -#define FLYING (1<<1) -#define VENTCRAWLING (1<<2) -#define FLOATING (1<<3) -#define UNSTOPPABLE (1<<4) //When moving, will Bump()/Cross()/Uncross() everything, but won't be stopped. +#define GROUND (1<<0) +#define FLYING (1<<1) +#define VENTCRAWLING (1<<2) +#define FLOATING (1<<3) +#define UNSTOPPABLE (1<<4) //When moving, will Bump()/Cross()/Uncross() everything, but won't be stopped. +#define CRAWLING (1<<5) //Applied if you're crawling around on the ground/resting. //Fire and Acid stuff, for resistance_flags #define LAVA_PROOF (1<<0) diff --git a/code/__DEFINES/interaction_flags.dm b/code/__DEFINES/interaction_flags.dm index 6df5bf77fb..dc3242c910 100644 --- a/code/__DEFINES/interaction_flags.dm +++ b/code/__DEFINES/interaction_flags.dm @@ -20,5 +20,3 @@ #define INTERACT_MACHINE_SET_MACHINE (1<<6) //MACHINES HAVE THIS BY DEFAULT, SOMEONE SHOULD RUN THROUGH MACHINES AND REMOVE IT FROM THINGS LIKE LIGHT SWITCHES WHEN POSSIBLE!!-------------------------- //This flag determines if a machine set_machine's the user when the user uses it, making updateUsrDialog make the user re-call interact() on it. //THIS FLAG IS ON ALL MACHINES BY DEFAULT, NEEDS TO BE RE-EVALUATED LATER!! - -#define INTERACT_GHOST_READ (1<<0) \ No newline at end of file diff --git a/code/__DEFINES/maths.dm b/code/__DEFINES/maths.dm index ad93dd2d54..939f6698cb 100644 --- a/code/__DEFINES/maths.dm +++ b/code/__DEFINES/maths.dm @@ -199,4 +199,6 @@ #define LORENTZ_CUMULATIVE_DISTRIBUTION(x, y, s) ( (1/PI)*TORADIANS(arctan((x-y)/s)) + 1/2 ) #define RULE_OF_THREE(a, b, x) ((a*x)/b) -// ) \ No newline at end of file +// ) + +#define MANHATTAN_DISTANCE(a, b) (abs(a.x - b.x) + abs(a.y - b.y)) \ No newline at end of file diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index e2d93aebf5..ac8681ead7 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -406,6 +406,7 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S #define DUMMY_HUMAN_SLOT_HOLOFORM "dummy_holoform_generation" #define DUMMY_HUMAN_SLOT_ADMIN "admintools" #define DUMMY_HUMAN_SLOT_MANIFEST "dummy_manifest_generation" +#define DUMMY_HUMAN_SLOT_HALLUCINATION "dummy_hallucination" #define PR_ANNOUNCEMENTS_PER_ROUND 5 //The number of unique PR announcements allowed per round //This makes sure that a single person can only spam 3 reopens and 3 closes before being ignored diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index a7d6056ab9..1b437f2a71 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -35,17 +35,17 @@ #define BLOODCRAWL 1 #define BLOODCRAWL_EAT 2 -//Mob bio-types -#define MOB_ORGANIC "organic" -#define MOB_INORGANIC "inorganic" -#define MOB_ROBOTIC "robotic" -#define MOB_UNDEAD "undead" -#define MOB_HUMANOID "humanoid" -#define MOB_BUG "bug" -#define MOB_BEAST "beast" -#define MOB_EPIC "epic" //megafauna -#define MOB_REPTILE "reptile" -#define MOB_SPIRIT "spirit" +//Mob bio-types flags +#define MOB_ORGANIC 1 << 0 +#define MOB_MINERAL 1 << 1 +#define MOB_ROBOTIC 1 << 2 +#define MOB_UNDEAD 1 << 3 +#define MOB_HUMANOID 1 << 4 +#define MOB_BUG 1 << 5 +#define MOB_BEAST 1 << 6 +#define MOB_EPIC 1 << 7 //megafauna +#define MOB_REPTILE 1 << 8 +#define MOB_SPIRIT 1 << 9 //Organ defines for carbon mobs #define ORGAN_ORGANIC 1 diff --git a/code/__DEFINES/obj_flags.dm b/code/__DEFINES/obj_flags.dm index 831f73ac74..d78de86d25 100644 --- a/code/__DEFINES/obj_flags.dm +++ b/code/__DEFINES/obj_flags.dm @@ -17,18 +17,19 @@ // Flags for the item_flags var on /obj/item -#define BEING_REMOVED (1<<0) -#define IN_INVENTORY (1<<1) //is this item equipped into an inventory slot or hand of a mob? used for tooltips -#define FORCE_STRING_OVERRIDE (1<<2) //used for tooltips -#define NEEDS_PERMIT (1<<3) //Used by security bots to determine if this item is safe for public use. -#define SLOWS_WHILE_IN_HAND (1<<4) -#define NO_MAT_REDEMPTION (1<<5) //Stops you from putting things like an RCD or other items into an ORM or protolathe for materials. -#define DROPDEL (1<<6) //When dropped, it calls qdel on itself -#define NOBLUDGEON (1<<7) //when an item has this it produces no "X has been hit by Y with Z" message in the default attackby() -#define ABSTRACT (1<<8) //for all things that are technically items but used for various different stuff -#define IMMUTABLE_SLOW (1<<9) //When players should not be able to change the slowdown of the item (Speed potions, ect) -#define SURGICAL_TOOL (1<<10) //Tool commonly used for surgery: won't attack targets in an active surgical operation on help intent (in case of mistakes) -#define NO_UNIFORM_REQUIRED (1<<11) //Can be worn on certain slots (currently belt and id) that would otherwise require an uniform. +#define BEING_REMOVED (1<<0) +#define IN_INVENTORY (1<<1) //is this item equipped into an inventory slot or hand of a mob? used for tooltips +#define FORCE_STRING_OVERRIDE (1<<2) //used for tooltips +#define NEEDS_PERMIT (1<<3) //Used by security bots to determine if this item is safe for public use. +#define SLOWS_WHILE_IN_HAND (1<<4) +#define NO_MAT_REDEMPTION (1<<5) //Stops you from putting things like an RCD or other items into an ORM or protolathe for materials. +#define DROPDEL (1<<6) //When dropped, it calls qdel on itself +#define NOBLUDGEON (1<<7) //when an item has this it produces no "X has been hit by Y with Z" message in the default attackby() +#define ABSTRACT (1<<8) //for all things that are technically items but used for various different stuff +#define IMMUTABLE_SLOW (1<<9) //When players should not be able to change the slowdown of the item (Speed potions, ect) +#define SURGICAL_TOOL (1<<10) //Tool commonly used for surgery: won't attack targets in an active surgical operation on help intent (in case of mistakes) +#define NO_UNIFORM_REQUIRED (1<<11) //Can be worn on certain slots (currently belt and id) that would otherwise require an uniform. +#define NO_ATTACK_CHAIN_SOFT_STAMCRIT (1<<12) //Entirely blocks melee_attack_chain() if user is soft stamcritted. Uses getStaminaLoss() to check at this point in time. THIS DOES NOT BLOCK RANGED AFTERATTACK()S, ONLY MELEE RANGE AFTERATTACK()S. // Flags for the clothing_flags var on /obj/item/clothing diff --git a/code/__DEFINES/profile.dm b/code/__DEFINES/profile.dm index 28fc7782ce..8929e0f05e 100644 --- a/code/__DEFINES/profile.dm +++ b/code/__DEFINES/profile.dm @@ -1,5 +1,5 @@ -#define PROFILE_START ;PROFILE_STORE = list();PROFILE_SET; -#define PROFILE_STOP ;PROFILE_STORE = null; +#define LINE_PROFILE_START ;PROFILE_STORE = list();PROFILE_SET; +#define LINE_PROFILE_STOP ;PROFILE_STORE = null; #define PROFILE_SET ;PROFILE_TIME = TICK_USAGE_REAL; PROFILE_LINE = __LINE__; PROFILE_FILE = __FILE__; PROFILE_SLEEPCHECK = world.time; diff --git a/code/__DEFINES/reagents.dm b/code/__DEFINES/reagents.dm index d08344cc96..97ae7b8e95 100644 --- a/code/__DEFINES/reagents.dm +++ b/code/__DEFINES/reagents.dm @@ -22,6 +22,11 @@ // Is an open container for all intents and purposes. #define OPENCONTAINER (REFILLABLE | DRAINABLE | TRANSPARENT) +//reagents_value defines, for cargo stuff. +#define DEFAULT_REAGENTS_VALUE 1 +#define NO_REAGENTS_VALUE 0 +#define HARVEST_REAGENTS_VALUE 0.3 + #define TOUCH 1 // splashing #define INGEST 2 // ingestion diff --git a/code/__DEFINES/say.dm b/code/__DEFINES/say.dm index beeee22df9..49cfba8cd2 100644 --- a/code/__DEFINES/say.dm +++ b/code/__DEFINES/say.dm @@ -81,6 +81,7 @@ //Don't set this very much higher then 1024 unless you like inviting people in to dos your server with message spam #define MAX_MESSAGE_LEN 2048 //Citadel edit: What's the WORST that could happen? +#define MAX_FAVOR_LEN 4096 //double the maximum message length. #define MAX_NAME_LEN 42 #define MAX_BROADCAST_LEN 512 #define MAX_CHARTER_LEN 80 diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index 6d52f4640c..f42948f4ae 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -46,7 +46,9 @@ #define STATUS_EFFECT_SLEEPING /datum/status_effect/incapacitating/sleeping //the affected is asleep -#define STATUS_EFFECT_TASED /datum/status_effect/no_combat_mode/electrode/ //the affected has been tased, preventing fine muscle control +#define STATUS_EFFECT_TASED_WEAK /datum/status_effect/electrode //not as crippling, just slows down + +#define STATUS_EFFECT_TASED /datum/status_effect/electrode/no_combat_mode //the affected has been tased, preventing fine muscle control #define STATUS_EFFECT_PACIFY /datum/status_effect/pacify //the affected is pacified, preventing direct hostile actions diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 5c54843df2..162c898917 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -47,6 +47,7 @@ // Subsystems shutdown in the reverse of the order they initialize in // The numbers just define the ordering, they are meaningless otherwise. +#define INIT_ORDER_PROFILER 101 #define INIT_ORDER_FAIL2TOPIC 22 #define INIT_ORDER_TITLE 20 #define INIT_ORDER_GARBAGE 19 diff --git a/code/__DEFINES/tgs.config.dm b/code/__DEFINES/tgs.config.dm index a40b5d4663..9f4f63a1fc 100644 --- a/code/__DEFINES/tgs.config.dm +++ b/code/__DEFINES/tgs.config.dm @@ -1,4 +1,5 @@ #define TGS_EXTERNAL_CONFIGURATION +#define TGS_V3_API #define TGS_DEFINE_AND_SET_GLOBAL(Name, Value) GLOBAL_VAR_INIT(##Name, ##Value); GLOBAL_PROTECT(##Name) #define TGS_READ_GLOBAL(Name) GLOB.##Name #define TGS_WRITE_GLOBAL(Name, Value) GLOB.##Name = ##Value diff --git a/code/__DEFINES/tgs.dm b/code/__DEFINES/tgs.dm index db4f046ec3..dcccfc9295 100644 --- a/code/__DEFINES/tgs.dm +++ b/code/__DEFINES/tgs.dm @@ -107,6 +107,22 @@ var/commit //full sha of compiled commit var/origin_commit //full sha of last known remote commit. This may be null if the TGS repository is not currently tracking a remote branch +//represents a version of tgstation-server +/datum/tgs_version + var/suite //The suite version, can be >=3 + + //this group of variables can be null to represent a wild card + var/major //The major version + var/minor //The minor version + var/patch //The patch version + + var/raw_parameter //The unparsed parameter + var/deprefixed_parameter //The version only bit of raw_parameter + +//if the tgs_version is a wildcard version +/datum/tgs_version/proc/Wildcard() + return + //represents a merge of a GitHub pull request /datum/tgs_revision_information/test_merge var/number //pull request number @@ -155,22 +171,22 @@ //FUNCTIONS -//Returns the respective string version of the API +//Returns the respective supported /datum/tgs_version of the API /world/proc/TgsMaximumAPIVersion() return /world/proc/TgsMinimumAPIVersion() return -//Gets the current version of the server tools running the server -/world/proc/TgsVersion() - return - //Returns TRUE if the world was launched under the server tools and the API matches, FALSE otherwise //No function below this succeeds if it returns FALSE /world/proc/TgsAvailable() return +//Gets the current /datum/tgs_version of the server tools running the server +/world/proc/TgsVersion() + return + /world/proc/TgsInstanceName() return diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index ea1ccfa97b..d144254a50 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -110,6 +110,7 @@ #define TRAIT_NOHARDCRIT "nohardcrit" #define TRAIT_NOSOFTCRIT "nosoftcrit" #define TRAIT_MINDSHIELD "mindshield" +#define TRAIT_HIJACKER "hijacker" #define TRAIT_SIXTHSENSE "sixthsense" #define TRAIT_DISSECTED "dissected" #define TRAIT_FEARLESS "fearless" diff --git a/code/__DEFINES/vote.dm b/code/__DEFINES/vote.dm index b83ea7b8f6..12e802383e 100644 --- a/code/__DEFINES/vote.dm +++ b/code/__DEFINES/vote.dm @@ -6,3 +6,12 @@ #define INSTANT_RUNOFF_VOTING 5 GLOBAL_LIST_INIT(vote_score_options,list("Bad","Poor","Acceptable","Good","Great")) + +GLOBAL_LIST_INIT(vote_type_names,list(\ +"Plurality (default)" = PLURALITY_VOTING,\ +"Approval" = APPROVAL_VOTING,\ +"IRV (single winner ranked choice)" = INSTANT_RUNOFF_VOTING,\ +"Schulze (ranked choice, higher result=better)" = SCHULZE_VOTING,\ +"Raw Score (returns results from 0 to 1, winner is 1)" = SCORE_VOTING,\ +"Majority Judgement (single-winner score voting)" = MAJORITY_JUDGEMENT_VOTING,\ +)) diff --git a/code/__HELPERS/_cit_helpers.dm b/code/__HELPERS/_cit_helpers.dm index c0acf4c5a5..26910a916b 100644 --- a/code/__HELPERS/_cit_helpers.dm +++ b/code/__HELPERS/_cit_helpers.dm @@ -57,14 +57,11 @@ GLOBAL_LIST_EMPTY(ipc_antennas_list) //Genitals and Arousal Lists GLOBAL_LIST_EMPTY(genitals_list) -GLOBAL_LIST_EMPTY(cock_shapes_list)//global_lists.dm for the list initializations //Now also _DATASTRUCTURES globals.dm -GLOBAL_LIST_EMPTY(cock_shapes_icons) //Associated list for names->icon_states for cockshapes. +GLOBAL_LIST_EMPTY(cock_shapes_list) GLOBAL_LIST_EMPTY(gentlemans_organ_names) GLOBAL_LIST_EMPTY(balls_shapes_list) -GLOBAL_LIST_EMPTY(balls_shapes_icons) GLOBAL_LIST_EMPTY(breasts_size_list) GLOBAL_LIST_EMPTY(breasts_shapes_list) -GLOBAL_LIST_EMPTY(breasts_shapes_icons) GLOBAL_LIST_EMPTY(vagina_shapes_list) GLOBAL_LIST_INIT(cum_into_containers_list, list(/obj/item/reagent_containers/food/snacks/pie)) //Yer fuggin snowflake name list jfc GLOBAL_LIST_INIT(dick_nouns, list("dick","cock","member","shaft")) @@ -111,27 +108,37 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE) message_admins("[key_name_admin(usr)] manually reloaded mentors") //Flavor Text -/mob/living/carbon/human/verb/set_flavor() +/mob/proc/set_flavor() set name = "Set Flavor Text" set desc = "Sets an extended description of your character's features." set category = "IC" - var/new_flavor = input(src, "Enter your new flavor text:", "Flavor text", null) as message|null + var/new_flavor = stripped_multiline_input(usr, "Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!", "Flavor Text", flavor_text, MAX_FAVOR_LEN, TRUE) if(!isnull(new_flavor)) - flavor_text = sanitize(new_flavor) + flavor_text = new_flavor to_chat(src, "Your flavor text has been updated.") //Flavor Text -/mob/living/carbon/human/verb/set_flavor_2() +/mob/proc/set_flavor_2() set name = "Set Temporary Flavor Text" set desc = "Sets a description of your character's current appearance. Use this for emotions, poses etc." set category = "IC" - var/new_flavor = input(src, "Enter your new temporary flavor text:", "Temporary flavor text", null) as message|null + var/new_flavor = stripped_multiline_input(usr, "Set the temporary flavor text in your 'examine' verb. This should be used only for things pertaining to the current round!", "Short-Term Flavor Text", flavor_text_2, MAX_FAVOR_LEN, TRUE) if(!isnull(new_flavor)) - flavor_text_2 = sanitize(new_flavor) + flavor_text_2 = new_flavor to_chat(src, "Your temporary flavor text has been updated.") +/mob/proc/print_flavor_text(flavor) + if(!flavor) + return + // We are decoding and then encoding to not only get correct amount of characters, but also to prevent partial escaping characters being shown. + var/msg = html_decode(replacetext(flavor, "\n", " ")) + if(length_char(msg) <= 40) + return "[html_encode(msg)]" + else + return "[html_encode(copytext_char(msg, 1, 37))]... More..." + //LOOC toggles /client/verb/listen_looc() set name = "Show/Hide LOOC" diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 605f7f8ae7..60d7fa42b9 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -436,7 +436,7 @@ var/list/result = list() for(var/m in group) var/mob/M = m - if(!M.key || !M.client || (ignore_category && GLOB.poll_ignore[ignore_category] && M.ckey in GLOB.poll_ignore[ignore_category])) + if(!M.key || !M.client || (ignore_category && GLOB.poll_ignore[ignore_category] && (M.ckey in GLOB.poll_ignore[ignore_category]))) continue if(be_special_flag) if(!(M.client.prefs) || !(be_special_flag in M.client.prefs.be_special)) diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index ff9d1bec4c..7045767f98 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -51,26 +51,15 @@ init_sprite_accessory_subtypes(/datum/sprite_accessory/antenna, GLOB.ipc_antennas_list, roundstart = TRUE) //genitals init_sprite_accessory_subtypes(/datum/sprite_accessory/penis, GLOB.cock_shapes_list) - for(var/K in GLOB.cock_shapes_list) - var/datum/sprite_accessory/penis/value = GLOB.cock_shapes_list[K] - GLOB.cock_shapes_icons[K] = value.icon_state - init_sprite_accessory_subtypes(/datum/sprite_accessory/vagina, GLOB.vagina_shapes_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/breasts, GLOB.breasts_shapes_list) + init_sprite_accessory_subtypes(/datum/sprite_accessory/testicles, GLOB.balls_shapes_list) GLOB.breasts_size_list = list ("a", "b", "c", "d", "e") //We need the list to choose from initialized, but it's no longer a sprite_accessory thing. GLOB.gentlemans_organ_names = list("phallus", "willy", "dick", "prick", "member", "tool", "gentleman's organ", "cock", "wang", "knob", "dong", "joystick", "pecker", "johnson", "weenie", "tadger", "schlong", "thirsty ferret", "baloney pony", "schlanger", "Mutton dagger", "old blind bob","Hanging Johnny", "fishing rod", "Tally whacker", "polly rocket", "One eyed trouser trout", "Ding dong", "ankle spanker", "Pork sword", "engine cranker", "Harry hot dog", "Davy Crockett", "Kidney cracker", "Heat seeking moisture missile", "Giggle stick", "love whistle", "Tube steak", "Uncle Dick", "Purple helmet warrior") - for(var/K in GLOB.breasts_shapes_list) - var/datum/sprite_accessory/breasts/value = GLOB.breasts_shapes_list[K] - GLOB.breasts_shapes_icons[K] = value.icon_state - - init_sprite_accessory_subtypes(/datum/sprite_accessory/testicles, GLOB.balls_shapes_list) - for(var/K in GLOB.balls_shapes_list) - var/datum/sprite_accessory/testicles/value = GLOB.balls_shapes_list[K] - GLOB.balls_shapes_icons[K] = value.icon_state for(var/gpath in subtypesof(/obj/item/organ/genital)) var/obj/item/organ/genital/G = gpath diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 1669c941c2..a5924994e7 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -529,7 +529,7 @@ GLOBAL_LIST_EMPTY(species_list) continue if(M.stat != DEAD && !override) continue - if(speaker_key && speaker_key in prefs.ignoring) + if(speaker_key && (speaker_key in prefs.ignoring)) continue switch(message_type) diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 04e7ffd721..0f1e75ff73 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -146,19 +146,19 @@ var/list/file_data = list() var/pos = 1 for(var/V in GLOB.news_network.network_channels) - var/datum/newscaster/feed_channel/channel = V + var/datum/news/feed_channel/channel = V if(!istype(channel)) stack_trace("Non-channel in newscaster channel list") continue file_data["[pos]"] = list("channel name" = "[channel.channel_name]", "author" = "[channel.author]", "censored" = channel.censored ? 1 : 0, "author censored" = channel.authorCensor ? 1 : 0, "messages" = list()) for(var/M in channel.messages) - var/datum/newscaster/feed_message/message = M + var/datum/news/feed_message/message = M if(!istype(message)) stack_trace("Non-message in newscaster channel messages list") continue var/list/comment_data = list() for(var/C in message.comments) - var/datum/newscaster/feed_comment/comment = C + var/datum/news/feed_comment/comment = C if(!istype(comment)) stack_trace("Non-message in newscaster message comments list") continue diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index 3985659b71..beb005b8d1 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -44,6 +44,12 @@ index = findtext(t, char, index + length(char)) return t +/proc/sanitize_name(t,list/repl_chars = null) + if(t == "space" || t == "floor" || t == "wall" || t == "r-wall" || t == "monkey" || t == "unknown" || t == "inactive ai") //prevents these common metagamey names + alert("Invalid name.") + return "" + return sanitize(t) + /proc/sanitize_filename(t) return sanitize_simple(t, list("\n"="", "\t"="", "/"="", "\\"="", "?"="", "%"="", "*"="", ":"="", "|"="", "\""="", "<"="", ">"="")) @@ -775,4 +781,4 @@ GLOBAL_LIST_INIT(binary, list("0","1")) #define is_alpha(X) ((text2ascii(X) <= 122) && (text2ascii(X) >= 97)) -#define is_digit(X) ((length(X) == 1) && (length(text2num(X)) == 1)) \ No newline at end of file +#define is_digit(X) ((length(X) == 1) && (length(text2num(X)) == 1)) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 86dde3d6a6..2cb088c654 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1537,4 +1537,31 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) if(190) return "." if(189) - return "-" \ No newline at end of file + return "-" + +/proc/generate_items_inside(list/items_list, where_to) + for(var/each_item in items_list) + for(var/i in 1 to items_list[each_item]) + new each_item(where_to) + +//sends a message to chat +//config_setting should be one of the following +//null - noop +//empty string - use TgsTargetBroadcast with admin_only = FALSE +//other string - use TgsChatBroadcast with the tag that matches config_setting, only works with TGS4, if using TGS3 the above method is used +/proc/send2chat(message, config_setting) + if(config_setting == null || !world.TgsAvailable()) + return + var/datum/tgs_version/version = world.TgsVersion() + if(config_setting == "" || version.suite == 3) + world.TgsTargetedChatBroadcast(message, FALSE) + return + + var/list/channels_to_use = list() + for(var/I in world.TgsChatChannelInfo()) + var/datum/tgs_chat_channel/channel = I + if(channel.tag == config_setting) + channels_to_use += channel + + if(channels_to_use.len) + world.TgsChatBroadcast() \ No newline at end of file diff --git a/code/__HELPERS/vector.dm b/code/__HELPERS/vector.dm new file mode 100644 index 0000000000..80295bde0e --- /dev/null +++ b/code/__HELPERS/vector.dm @@ -0,0 +1,57 @@ +// Basic geometry things. + +/datum/vector/ + var/x = 0 + var/y = 0 + +/datum/vector/New(var/x, var/y) + src.x = x + src.y = y + +/datum/vector/proc/duplicate() + return new /datum/vector(x, y) + +/datum/vector/proc/euclidian_norm() + return sqrt(x*x + y*y) + +/datum/vector/proc/squared_norm() + return x*x + y*y + +/datum/vector/proc/normalize() + var/norm = euclidian_norm() + x = x/norm + y = y/norm + return src + +/datum/vector/proc/chebyshev_norm() + return max(abs(x), abs(y)) + +/datum/vector/proc/chebyshev_normalize() + var/norm = chebyshev_norm() + x = x/norm + y = y/norm + return src + +/datum/vector/proc/is_integer() + return ISINTEGER(x) && ISINTEGER(y) + +/atom/movable/proc/vector_translate(var/datum/vector/V, var/delay) + var/turf/T = get_turf(src) + var/turf/destination = locate(T.x + V.x, T.y + V.y, z) + var/datum/vector/V_norm = V.duplicate() + V_norm.chebyshev_normalize() + if (!V_norm.is_integer()) + return + var/turf/destination_temp + while (destination_temp != destination) + destination_temp = locate(T.x + V_norm.x, T.y + V_norm.y, z) + forceMove(destination_temp) + T = get_turf(src) + sleep(delay + world.tick_lag) // Shortest possible time to sleep + +/atom/proc/get_translated_turf(var/datum/vector/V) + var/turf/T = get_turf(src) + return locate(T.x + V.x, T.y + V.y, z) + +/proc/atoms2vector(var/atom/A, var/atom/B) + return new /datum/vector((B.x - A.x), (B.y - A.y)) // Vector from A -> B \ No newline at end of file diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index c98faaa4fb..a0139dab83 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -214,5 +214,18 @@ GLOBAL_LIST_INIT(bitfields, list( "CAN_MASTURBATE_WITH" = CAN_MASTURBATE_WITH, "MASTURBATE_LINKED_ORGAN" = MASTURBATE_LINKED_ORGAN, "CAN_CLIMAX_WITH" = CAN_CLIMAX_WITH - ) - )) \ No newline at end of file + + ), + "mob_biotypes" = list ( + "MOB_ORGANIC" = MOB_ORGANIC, + "MOB_MINERAL" = MOB_MINERAL, + "MOB_ROBOTIC" = MOB_ROBOTIC, + "MOB_UNDEAD" = MOB_UNDEAD, + "MOB_HUMANOID" = MOB_HUMANOID, + "MOB_BUG" = MOB_BUG, + "MOB_BEAST" = MOB_BEAST, + "MOB_EPIC" = MOB_EPIC, + "MOB_REPTILE" = MOB_REPTILE, + "MOB_SPIRIT" = MOB_SPIRIT + ) + )) diff --git a/code/_globalvars/lists/misc.dm b/code/_globalvars/lists/misc.dm index 1dcde53a72..819352ac1b 100644 --- a/code/_globalvars/lists/misc.dm +++ b/code/_globalvars/lists/misc.dm @@ -1 +1,59 @@ GLOBAL_LIST_EMPTY(donators_by_group) //group id = donator list of ckeys + +GLOBAL_LIST_INIT(flirts, list("Roses are red / Violets are good / One day while Andy...", + "My love for you is like the singularity. It cannot be contained.", + "Will you be my lusty xenomorph maid?", + "We go together like the clown and the external airlock.", + "Roses are red / Liches are wizards / I love you more than a whole squad of lizards.", + "Be my valentine. Law 2.", + "You must be a mime, because you leave me speechless.", + "I love you like Ian loves the HoP.", + "You're hotter than a plasma fire in toxins.", + "Are you a rogue atmos tech? Because you're taking my breath away.", + "Could I have all access... to your heart?", + "Call me the doctor, because I'm here to inspect your johnson.", + "I'm not a changeling, but you make my proboscis extend.", + "I just can't get EI NATH of you.", + "You must be a nuke op, because you make my heart explode.", + "Roses are red / Botany is a farm / Not being my Valentine / causes human harm.", + "I want you more than an assistant wants insulated gloves.", + "If I was a security officer, I'd brig you all shift.", + "Are you the janitor? Because I think I've fallen for you.", + "You're always valid to my heart.", + "I'd risk the wrath of the gods to bwoink you.", + "You look as beautiful now as the last time you were cloned.", + "Someone check the gravitational generator, because I'm only attracted to you.", + "If I were the warden I'd always let you into my armory.", + "The virologist is rogue, and the only cure is a kiss from you.", + "Would you spend some time in my upgraded sleeper?", + "You must be a silicon, because you've unbolted my heart.", + "Are you Nar'Sie? Because there's nar-one else I sie.", + "If you were a taser, you'd be set to stunning.", + "Do you have stamina damage from running through my dreams?", + "If I were an alien, would you let me hug you?", + "My love for you is stronger than a reinforced wall.", + "This must be the captain's office, because I see a fox.", + "I'm not a highlander, but there can only be one for me.", + "The floor is made of lava! Quick, get on my bed.", + "If you were an abandoned station you'd be the DEARelict.", + "If you had a pickaxe you'd be a shaft FINEr.", + "Roses are red, tide is gray, if I were an assistant I'd steal you away.", + "Roses are red, text is green, I love you more than cleanbots clean.", + "If you were a carp I'd fi-lay you.", + "I'm a nuke op, and my pinpointer leads to your heart.", + "Wanna slay my megafauna?", + "I'm a clockwork cultist. Or zl inyragvar.", + "If you were a disposal bin I'd ride you all day.", + "Put on your explorer's suit because I'm taking you to LOVEaland.", + "I must be the CMO, 'cause I saw you on my CUTE sensors.", + "You're the vomit to my flyperson.", + "You must be liquid dark matter, because you're pulling me closer.", + "Not even sorium can drive me away from you.", + "Wanna make like a borg and do some heavy petting?", + "Are you powering the station? Because you super matter to me.", + "I wish science could make me a bag of holding you.", + "Let's call the emergency CUDDLE.", + "I must be tripping on BZ, because I saw an angel walk by.", + "Wanna empty out my tool storage?", + "Did you visit the medbay after you fell from heaven?", + "Are you wearing space pants? Wanna not be?" )) diff --git a/code/_globalvars/lists/names.dm b/code/_globalvars/lists/names.dm index 7ae197a5d1..e334d08040 100644 --- a/code/_globalvars/lists/names.dm +++ b/code/_globalvars/lists/names.dm @@ -4,6 +4,7 @@ GLOBAL_LIST_INIT(wizard_second, world.file2list("strings/names/wizardsecond.txt" GLOBAL_LIST_INIT(ninja_titles, world.file2list("strings/names/ninjatitle.txt")) GLOBAL_LIST_INIT(ninja_names, world.file2list("strings/names/ninjaname.txt")) GLOBAL_LIST_INIT(commando_names, world.file2list("strings/names/death_commando.txt")) +GLOBAL_LIST_INIT(first_names, world.file2list("strings/names/first.txt")) GLOBAL_LIST_INIT(first_names_male, world.file2list("strings/names/first_male.txt")) GLOBAL_LIST_INIT(first_names_female, world.file2list("strings/names/first_female.txt")) GLOBAL_LIST_INIT(last_names, world.file2list("strings/names/last.txt")) diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index cda19dbaac..9ba51afc69 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -1,19 +1,28 @@ - +/** + *This is the proc that handles the order of an item_attack. + *The order of procs called is: + *tool_act on the target. If it returns TRUE, the chain will be stopped. + *pre_attack() on src. If this returns TRUE, the chain will be stopped. + *attackby on the target. If it returns TRUE, the chain will be stopped. + *and lastly + *afterattack. The return value does not matter. + */ /obj/item/proc/melee_attack_chain(mob/user, atom/target, params) - if(!tool_attack_chain(user, target) && pre_attack(target, user, params)) - // Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example) - var/resolved = target.attackby(src, user, params) - if(!resolved && target && !QDELETED(src)) - afterattack(target, user, 1, params) // 1: clicking something Adjacent - - -//Checks if the item can work as a tool, calling the appropriate tool behavior on the target -/obj/item/proc/tool_attack_chain(mob/user, atom/target) - if(!tool_behaviour) - return FALSE - - return target.tool_act(user, src, tool_behaviour) - + if(item_flags & NO_ATTACK_CHAIN_SOFT_STAMCRIT) + if(isliving(user)) + var/mob/living/L = user + if(L.getStaminaLoss() >= STAMINA_SOFTCRIT) + to_chat(L, "You are too exhausted to swing [src]!") + return + if(tool_behaviour && target.tool_act(user, src, tool_behaviour)) + return + if(pre_attack(target, user, params)) + return + if(target.attackby(src,user, params)) + return + if(QDELETED(src) || QDELETED(target)) + return + afterattack(target, user, TRUE, params) // Called when the item is in the active hand, and clicked; alternately, there is an 'activate held object' verb or you can hit pagedown. /obj/item/proc/attack_self(mob/user) @@ -23,8 +32,8 @@ /obj/item/proc/pre_attack(atom/A, mob/living/user, params) //do stuff before attackby! if(SEND_SIGNAL(src, COMSIG_ITEM_PRE_ATTACK, A, user, params) & COMPONENT_NO_ATTACK) - return FALSE - return TRUE //return FALSE to avoid calling attackby after this proc does stuff + return TRUE + return FALSE //return TRUE to avoid calling attackby after this proc does stuff // No comment /atom/proc/attackby(obj/item/W, mob/user, params) @@ -112,7 +121,7 @@ send_item_attack_message(I, user) if(I.force) apply_damage(totitemdamage, I.damtype) //CIT CHANGE - replaces I.force with totitemdamage - if(I.damtype == BRUTE && !HAS_TRAIT(src, TRAIT_NOMARROW)) + if(I.damtype == BRUTE && !HAS_TRAIT(src, TRAIT_NOMARROW)) if(prob(33)) I.add_mob_blood(src) var/turf/location = get_turf(src) diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index a3bc47ac91..0f12d1d9ae 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -234,6 +234,7 @@ /datum/config_entry/number/movedelay //Used for modifying movement speed for mobs. abstract_type = /datum/config_entry/number/movedelay + integer = FALSE /datum/config_entry/number/movedelay/ValidateAndSet() . = ..() diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm index c3ae90cc1b..cb8c0fe966 100644 --- a/code/controllers/configuration/entries/general.dm +++ b/code/controllers/configuration/entries/general.dm @@ -1,3 +1,5 @@ +/datum/config_entry/flag/auto_profile // Automatically start profiler on server start + /datum/config_entry/flag/autoadmin // if autoadmin is enabled protection = CONFIG_ENTRY_LOCKED @@ -267,6 +269,9 @@ /datum/config_entry/flag/tgstyle_maprotation +/datum/config_entry/string/map_vote_type + config_entry_value = "SCORE" + /datum/config_entry/number/maprotatechancedelta config_entry_value = 0.75 min_val = 0 @@ -389,6 +394,13 @@ config_entry_value = 50 /datum/config_entry/flag/irc_announce_new_game + deprecated_by = /datum/config_entry/string/chat_announce_new_game + +/datum/config_entry/flag/irc_announce_new_game/DeprecationUpdate(value) + return "" //default broadcast + +/datum/config_entry/string/chat_announce_new_game + config_entry_value = null /datum/config_entry/flag/debug_admin_hrefs diff --git a/code/controllers/configuration/entries/plushies.dm b/code/controllers/configuration/entries/plushies.dm new file mode 100644 index 0000000000..20ad02d399 --- /dev/null +++ b/code/controllers/configuration/entries/plushies.dm @@ -0,0 +1,6 @@ +/datum/config_entry/number/snowflake_plushie_prob + config_entry_value = 50 + +/datum/config_entry/keyed_list/snowflake_plushies + key_mode = KEY_MODE_TEXT + value_mode = VALUE_MODE_TEXT diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index 7597a9229a..31e436f206 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -118,7 +118,7 @@ SUBSYSTEM_DEF(job) if(flag && (!(flag in player.client.prefs.be_special))) JobDebug("FOC flag failed, Player: [player], Flag: [flag], ") continue - if(player.mind && job.title in player.mind.restricted_roles) + if(player.mind && (job.title in player.mind.restricted_roles)) JobDebug("FOC incompatible with antagonist role, Player: [player]") continue if(player.client.prefs.job_preferences[job.title] == level) @@ -158,7 +158,7 @@ SUBSYSTEM_DEF(job) JobDebug("GRJ player not enough xp, Player: [player]") continue - if(player.mind && job.title in player.mind.restricted_roles) + if(player.mind && (job.title in player.mind.restricted_roles)) JobDebug("GRJ incompatible with antagonist role, Player: [player], Job: [job.title]") continue @@ -340,7 +340,7 @@ SUBSYSTEM_DEF(job) JobDebug("DO non-human failed, Player: [player], Job:[job.title]") continue - if(player.mind && job.title in player.mind.restricted_roles) + if(player.mind && (job.title in player.mind.restricted_roles)) JobDebug("DO incompatible with antagonist role, Player: [player], Job:[job.title]") continue diff --git a/code/controllers/subsystem/weather.dm b/code/controllers/subsystem/processing/weather.dm similarity index 77% rename from code/controllers/subsystem/weather.dm rename to code/controllers/subsystem/processing/weather.dm index 5e44f2e4c3..0a1b4fc609 100644 --- a/code/controllers/subsystem/weather.dm +++ b/code/controllers/subsystem/processing/weather.dm @@ -4,25 +4,16 @@ #define END_STAGE 4 //Used for all kinds of weather, ex. lavaland ash storms. -SUBSYSTEM_DEF(weather) +PROCESSING_SUBSYSTEM_DEF(weather) name = "Weather" flags = SS_BACKGROUND wait = 10 runlevels = RUNLEVEL_GAME - var/list/processing = list() var/list/eligible_zlevels = list() var/list/next_hit_by_zlevel = list() //Used by barometers to know when the next storm is coming -/datum/controller/subsystem/weather/fire() - // process active weather - for(var/V in processing) - var/datum/weather/W = V - if(W.aesthetic || W.stage != MAIN_STAGE) - continue - for(var/i in GLOB.mob_living_list) - var/mob/living/L = i - if(W.can_weather_act(L)) - W.weather_act(L) +/datum/controller/subsystem/processing/weather/fire() + . = ..() //Active weather is handled by . = ..() processing subsystem base fire(). // start random weather on relevant levels for(var/z in eligible_zlevels) @@ -34,7 +25,7 @@ SUBSYSTEM_DEF(weather) addtimer(CALLBACK(src, .proc/make_eligible, z, possible_weather), randTime + initial(W.weather_duration_upper), TIMER_UNIQUE) //Around 5-10 minutes between weathers next_hit_by_zlevel["[z]"] = world.time + randTime + initial(W.telegraph_duration) -/datum/controller/subsystem/weather/Initialize(start_timeofday) +/datum/controller/subsystem/processing/weather/Initialize(start_timeofday) for(var/V in subtypesof(/datum/weather)) var/datum/weather/W = V var/probability = initial(W.probability) @@ -47,7 +38,7 @@ SUBSYSTEM_DEF(weather) eligible_zlevels["[z]"][W] = probability return ..() -/datum/controller/subsystem/weather/proc/run_weather(datum/weather/weather_datum_type, z_levels) +/datum/controller/subsystem/processing/weather/proc/run_weather(datum/weather/weather_datum_type, z_levels) if (istext(weather_datum_type)) for (var/V in subtypesof(/datum/weather)) var/datum/weather/W = V @@ -69,11 +60,11 @@ SUBSYSTEM_DEF(weather) var/datum/weather/W = new weather_datum_type(z_levels) W.telegraph() -/datum/controller/subsystem/weather/proc/make_eligible(z, possible_weather) +/datum/controller/subsystem/processing/weather/proc/make_eligible(z, possible_weather) eligible_zlevels[z] = possible_weather next_hit_by_zlevel["[z]"] = null -/datum/controller/subsystem/weather/proc/get_weather(z, area/active_area) +/datum/controller/subsystem/processing/weather/proc/get_weather(z, area/active_area) var/datum/weather/A for(var/V in processing) var/datum/weather/W = V diff --git a/code/controllers/subsystem/profiler.dm b/code/controllers/subsystem/profiler.dm new file mode 100644 index 0000000000..ec8b243073 --- /dev/null +++ b/code/controllers/subsystem/profiler.dm @@ -0,0 +1,63 @@ +#define PROFILER_FILENAME "profiler.json" + +SUBSYSTEM_DEF(profiler) + name = "Profiler" + init_order = INIT_ORDER_PROFILER + runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY + wait = 3000 + flags = SS_NO_TICK_CHECK + var/fetch_cost = 0 + var/write_cost = 0 + +/datum/controller/subsystem/profiler/stat_entry(msg) + msg += "F:[round(fetch_cost,1)]ms" + msg += "|W:[round(write_cost,1)]ms" + ..(msg) + +/datum/controller/subsystem/profiler/Initialize() + if(CONFIG_GET(flag/auto_profile)) + StartProfiling() + else + StopProfiling() //Stop the early start from world/New + return ..() + +/datum/controller/subsystem/profiler/fire() + if(CONFIG_GET(flag/auto_profile)) + DumpFile() + +/datum/controller/subsystem/profiler/Shutdown() + if(CONFIG_GET(flag/auto_profile)) + DumpFile() + return ..() + +/datum/controller/subsystem/profiler/proc/StartProfiling() +#if DM_BUILD < 1506 || DM_VERSION < 513 + stack_trace("Auto profiling unsupported on this byond version") + CONFIG_SET(flag/auto_profile, FALSE) +#else + world.Profile(PROFILE_START) +#endif + +/datum/controller/subsystem/profiler/proc/StopProfiling() +#if DM_BUILD >= 1506 && DM_VERSION >= 513 + world.Profile(PROFILE_STOP) +#endif + +/datum/controller/subsystem/profiler/proc/DumpFile() +#if DM_BUILD < 1506 || DM_VERSION < 513 + stack_trace("Auto profiling unsupported on this byond version") + CONFIG_SET(flag/auto_profile, FALSE) +#else + var/timer = TICK_USAGE_REAL + var/current_profile_data = world.Profile(PROFILE_REFRESH,format="json") + fetch_cost = MC_AVERAGE(fetch_cost, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer)) + CHECK_TICK + if(!length(current_profile_data)) //Would be nice to have explicit proc to check this + stack_trace("Warning, profiling stopped manually before dump.") + var/json_file = file("[GLOB.log_directory]/[PROFILER_FILENAME]") + if(fexists(json_file)) + fdel(json_file) + timer = TICK_USAGE_REAL + WRITE_FILE(json_file, current_profile_data) + write_cost = MC_AVERAGE(write_cost, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer)) +#endif diff --git a/code/controllers/subsystem/server_maint.dm b/code/controllers/subsystem/server_maint.dm index 9e926b29a1..b77c78c4bb 100644 --- a/code/controllers/subsystem/server_maint.dm +++ b/code/controllers/subsystem/server_maint.dm @@ -81,8 +81,8 @@ SUBSYSTEM_DEF(server_maint) co.ehjax_send(data = "roundrestart") if(server) //if you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite C << link("byond://[server]") - var/tgsversion = world.TgsVersion() + var/datum/tgs_version/tgsversion = world.TgsVersion() if(tgsversion) - SSblackbox.record_feedback("text", "server_tools", 1, tgsversion) + SSblackbox.record_feedback("text", "server_tools", 1, tgsversion.raw_parameter) #undef PING_BUFFER_TIME diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm index 4d9eefae5b..7eff8b9e3c 100644 --- a/code/controllers/subsystem/shuttle.dm +++ b/code/controllers/subsystem/shuttle.dm @@ -38,7 +38,7 @@ SUBSYSTEM_DEF(shuttle) var/points = 5000 //number of trade-points we have var/centcom_message = "" //Remarks from CentCom on how well you checked the last order. var/list/discoveredPlants = list() //Typepaths for unusual plants we've already sent CentCom, associated with their potencies - var/passive_supply_points_per_minute = 500 + var/passive_supply_points_per_minute = 125 var/list/supply_packs = list() var/list/shoppinglist = list() diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 95daaf5d70..fe994facdc 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -158,8 +158,7 @@ SUBSYSTEM_DEF(ticker) for(var/client/C in GLOB.clients) window_flash(C, ignorepref = TRUE) //let them know lobby has opened up. to_chat(world, "Welcome to [station_name()]!") - if(CONFIG_GET(flag/irc_announce_new_game)) - world.TgsTargetedChatBroadcast("New round starting on [SSmapping.config.map_name]!", FALSE) + send2chat("New round starting on [SSmapping.config.map_name]!", CONFIG_GET(string/chat_announce_new_game)) current_state = GAME_STATE_PREGAME //Everyone who wants to be an observer is now spawned create_observers() @@ -477,7 +476,18 @@ SUBSYSTEM_DEF(ticker) if(CONFIG_GET(flag/tgstyle_maprotation)) INVOKE_ASYNC(SSmapping, /datum/controller/subsystem/mapping/.proc/maprotate) else - SSvote.initiate_vote("map","server",TRUE) + var/vote_type = CONFIG_GET(string/map_vote_type) + switch(vote_type) + if("PLURALITY") + SSvote.initiate_vote("map","server",hideresults=TRUE) + if("APPROVAL") + SSvote.initiate_vote("map","server",hideresults=TRUE,votesystem = APPROVAL_VOTING) + if("IRV") + SSvote.initiate_vote("map","server",hideresults=TRUE,votesystem = INSTANT_RUNOFF_VOTING) + if("SCORE") + SSvote.initiate_vote("map","server",hideresults=TRUE,votesystem = MAJORITY_JUDGEMENT_VOTING) + // fallback + SSvote.initiate_vote("map","server",hideresults=TRUE) /datum/controller/subsystem/ticker/proc/HasRoundStarted() return current_state >= GAME_STATE_PLAYING diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 2a7c4401f3..9924ed7917 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -149,7 +149,7 @@ SUBSYSTEM_DEF(vote) var/list/this_vote = voted[ckey] var/list/pretty_vote = list() for(var/choice in choices) - if("[choice]" in this_vote && "[choice]" in scores_by_choice) + if(("[choice]" in this_vote) && ("[choice]" in scores_by_choice)) sorted_insert(scores_by_choice["[choice]"],this_vote["[choice]"],/proc/cmp_numeric_asc) // START BALLOT GATHERING pretty_vote += "[choice]" @@ -160,7 +160,7 @@ SUBSYSTEM_DEF(vote) for(var/score_name in scores_by_choice) var/list/score = scores_by_choice[score_name] for(var/indiv_score in score) - SSblackbox.record_feedback("nested tally","voting",1,list(blackbox_text,"Scores",score_name,GLOB.vote_score_options[indiv_score])) + SSblackbox.record_feedback("nested tally","voting",1,list(blackbox_text,"Scores",score_name,GLOB.vote_score_options[indiv_score])) if(score.len == 0) scores_by_choice -= score_name while(scores_by_choice.len > 1) @@ -201,7 +201,10 @@ SUBSYSTEM_DEF(vote) max_score=max(max_score,scores[score_name]) min_score=min(min_score,scores[score_name]) for(var/score_name in scores) - scores[score_name] = (scores[score_name]-min_score)/(max_score-min_score) + if(max_score == min_score) + scores[score_name] = 1 + else + scores[score_name] = (scores[score_name]-min_score)/(max_score-min_score) SSblackbox.record_feedback("nested tally","voting",scores[score_name],list(blackbox_text,"Total scores",score_name)) /datum/controller/subsystem/vote/proc/get_runoff_results(var/blackbox_text) @@ -252,14 +255,13 @@ SUBSYSTEM_DEF(vote) text += "\nIt should be noted that this is not a raw tally of votes (impossible in ranked choice) but the score determined by the schulze method of voting, so the numbers will look weird!" if(vote_system == MAJORITY_JUDGEMENT_VOTING) text += "\nIt should be noted that this is not a raw tally of votes but the number of runoffs done by majority judgement!" - else - for(var/i=1,i<=choices.len,i++) - var/votes = choices[choices[i]] - if(!votes) - votes = 0 - if(was_roundtype_vote) - stored_gamemode_votes[choices[i]] = votes - text += "\n[choices[i]]: [obfuscated ? "???" : votes]" //CIT CHANGE - adds obfuscated votes + for(var/i=1,i<=choices.len,i++) + var/votes = choices[choices[i]] + if(!votes) + votes = 0 + if(was_roundtype_vote) + stored_gamemode_votes[choices[i]] = votes + text += "\n[choices[i]]: [obfuscated ? "???" : votes]" //CIT CHANGE - adds obfuscated votes if(mode != "custom") if(winners.len > 1 && !obfuscated) //CIT CHANGE - adds obfuscated votes text = "\nVote Tied Between:" @@ -374,7 +376,7 @@ SUBSYSTEM_DEF(vote) else to_chat(world, "Notice:Restart vote will not restart the server automatically because there are active admins on.") message_admins("A restart vote has passed, but there are active admins on with +server, so it has been canceled. If you wish, you may restart the server.") - + return . /datum/controller/subsystem/vote/proc/submit_vote(vote, score = 0) @@ -484,6 +486,8 @@ SUBSYSTEM_DEF(vote) question = stripped_input(usr,"What is the vote for?") if(!question) return 0 + var/system_string = input(usr,"Which voting type?",GLOB.vote_type_names[1]) in GLOB.vote_type_names + vote_system = GLOB.vote_type_names[system_string] for(var/i=1,i<=10,i++) var/option = capitalize(stripped_input(usr,"Please enter an option or hit cancel to finish")) if(!option || mode || !usr.client) diff --git a/code/datums/action.dm b/code/datums/action.dm index 8659a9e7c4..04d9c706ed 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -544,6 +544,70 @@ cooldown = world.time owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE) +/datum/action/item_action/removeAPCs + name = "Relinquish APC" + desc = "Let go of an APC, relinquish control back to the station." + icon_icon = 'icons/obj/implants.dmi' + button_icon_state = "hijackx" + +/datum/action/item_action/removeAPCs/Trigger() + var/list/areas = list() + for (var/area/a in owner.siliconaccessareas) + areas[a.name] = a + var/removeAPC = input("Select an APC to remove:","Remove APC Control",1) as null|anything in areas + if (!removeAPC) + return + var/area/area = areas[removeAPC] + var/obj/machinery/power/apc/apc = area.get_apc() + if (!apc || !(area in owner.siliconaccessareas)) + return + apc.hijacker = null + apc.update_icon() + apc.set_hijacked_lighting() + owner.toggleSiliconAccessArea(area) + +/datum/action/item_action/accessAPCs + name = "Access APC Interface" + desc = "Open the APC's interface." + icon_icon = 'icons/obj/implants.dmi' + button_icon_state = "hijacky" + +/datum/action/item_action/accessAPCs/Trigger() + var/list/areas = list() + for (var/area/a in owner.siliconaccessareas) + areas[a.name] = a + var/accessAPC = input("Select an APC to access:","Access APC Interface",1) as null|anything in areas + if (!accessAPC) + return + var/area/area = areas[accessAPC] + var/obj/machinery/power/apc/apc = area.get_apc() + if (!apc || !(area in owner.siliconaccessareas)) + return + apc.ui_interact(owner) + +/datum/action/item_action/stealthmodetoggle + name = "Toggle Stealth Mode" + desc = "Toggles the stealth mode on the hijack implant." + icon_icon = 'icons/obj/implants.dmi' + button_icon_state = "hijackz" + +/datum/action/item_action/stealthmodetoggle/Trigger() + var/obj/item/implant/hijack/H = target + if (!istype(H)) + return + if (H.stealthcooldown > world.time) + to_chat(owner,"The hijack implant's stealth mode toggle is still rebooting!") + return + H.stealthmode = !H.stealthmode + for (var/area/area in H.imp_in.siliconaccessareas) + var/obj/machinery/power/apc/apc = area.get_apc() + if (apc) + apc.set_hijacked_lighting() + apc.update_icon() + H.stealthcooldown = world.time + 15 SECONDS + H.toggle_eyes() + to_chat(owner,"You toggle the hijack implant's stealthmode [H.stealthmode ? "on" : "off"].") + /datum/action/item_action/flash name = "Flash" @@ -756,3 +820,11 @@ target.layer = old_layer target.plane = old_plane current_button.appearance_cache = target.appearance + +/proc/get_action_of_type(mob/M, var/action_type) + if(!M.actions || !ispath(action_type, /datum/action)) + return + for(var/datum/action/A in M.actions) + if(istype(A, action_type)) + return A + return \ No newline at end of file diff --git a/code/datums/beam.dm b/code/datums/beam.dm index d0b6d791ec..d97ee9a773 100644 --- a/code/datums/beam.dm +++ b/code/datums/beam.dm @@ -61,7 +61,8 @@ /datum/beam/proc/recalculate_in(time) if(timing_id) deltimer(timing_id) - timing_id = addtimer(CALLBACK(src, .proc/recalculate), time, TIMER_STOPPABLE) + if(!finished) + timing_id = addtimer(CALLBACK(src, .proc/recalculate), time, TIMER_STOPPABLE) /datum/beam/proc/after_calculate() if((sleep_time == null) || finished) //Does not automatically recalculate. diff --git a/code/datums/components/crafting/craft.dm b/code/datums/components/crafting/craft.dm index 5c21801c14..b5c7f34c27 100644 --- a/code/datums/components/crafting/craft.dm +++ b/code/datums/components/crafting/craft.dm @@ -64,29 +64,48 @@ - -/datum/component/personal_crafting/proc/check_contents(datum/crafting_recipe/R, list/contents) +/** + * Check that the contents of the recipe meet the requirements. + * + * user: The /mob that initated the crafting. + * R: The /datum/crafting_recipe being attempted. + * contents: List of items to search for R's reqs. + */ +/datum/component/personal_crafting/proc/check_contents(mob/user, datum/crafting_recipe/R, list/contents) + var/list/item_instances = contents["instances"] contents = contents["other"] - main_loop: - for(var/A in R.reqs) - var/needed_amount = R.reqs[A] - for(var/B in contents) - if(ispath(B, A)) - if (R.blacklist.Find(B)) - continue - if(contents[B] >= R.reqs[A]) - continue main_loop - else - needed_amount -= contents[B] - if(needed_amount <= 0) - continue main_loop - else - continue + + var/list/requirements_list = list() + + // Process all requirements + for(var/requirement_path in R.reqs) + // Check we have the appropriate amount available in the contents list + var/needed_amount = R.reqs[requirement_path] + for(var/content_item_path in contents) + // Right path and not blacklisted + if(!ispath(content_item_path, requirement_path) || R.blacklist.Find(requirement_path)) + continue + + needed_amount -= contents[content_item_path] + if(needed_amount <= 0) + break + + if(needed_amount > 0) return FALSE - for(var/A in R.chem_catalysts) - if(contents[A] < R.chem_catalysts[A]) + + // Store the instances of what we will use for R.check_requirements() for requirement_path + var/list/instances_list = list() + for(var/instance_path in item_instances) + if(ispath(instance_path, requirement_path)) + instances_list += item_instances[instance_path] + + requirements_list[requirement_path] = instances_list + + for(var/requirement_path in R.chem_catalysts) + if(contents[requirement_path] < R.chem_catalysts[requirement_path]) return FALSE - return TRUE + + return R.check_requirements(user, requirements_list) /datum/component/personal_crafting/proc/get_environment(mob/user) . = list() @@ -110,9 +129,14 @@ . = list() .["tool_behaviour"] = list() .["other"] = list() + .["instances"] = list() for(var/obj/item/I in get_environment(user)) if(I.flags_1 & HOLOGRAM_1) continue + if(.["instances"][I.type]) + .["instances"][I.type] += I + else + .["instances"][I.type] = list(I) if(istype(I, /obj/item/stack)) var/obj/item/stack/S = I .["other"][I.type] += S.amount @@ -161,11 +185,11 @@ /datum/component/personal_crafting/proc/construct_item(mob/user, datum/crafting_recipe/R) var/list/contents = get_surroundings(user) var/send_feedback = 1 - if(check_contents(R, contents)) + if(check_contents(user, R, contents)) if(check_tools(user, R, contents)) if(do_after(user, R.time, target = user)) contents = get_surroundings(user) - if(!check_contents(R, contents)) + if(!check_contents(user, R, contents)) return ", missing component." if(!check_tools(user, R, contents)) return ", missing tool." @@ -341,7 +365,7 @@ if((R.category != cur_category) || (R.subcategory != cur_subcategory)) continue - craftability["[REF(R)]"] = check_contents(R, surroundings) + craftability["[REF(R)]"] = check_contents(user, R, surroundings) data["craftability"] = craftability return data diff --git a/code/datums/components/crafting/recipes/recipes_primal.dm b/code/datums/components/crafting/recipes/recipes_primal.dm index 1be479e4e1..1fc684eddc 100644 --- a/code/datums/components/crafting/recipes/recipes_primal.dm +++ b/code/datums/components/crafting/recipes/recipes_primal.dm @@ -1,10 +1,3 @@ -/datum/crafting_recipe/bonearmor - name = "Bone Armor" - result = /obj/item/clothing/suit/armor/bone - time = 30 - reqs = list(/obj/item/stack/sheet/bone = 6) - category = CAT_PRIMAL - /datum/crafting_recipe/bonetalisman name = "Bone Talisman" result = /obj/item/clothing/accessory/talisman @@ -29,13 +22,6 @@ /obj/item/stack/sheet/sinew = 1) category = CAT_PRIMAL -/datum/crafting_recipe/skullhelm - name = "Skull Helmet" - result = /obj/item/clothing/head/helmet/skull - time = 30 - reqs = list(/obj/item/stack/sheet/bone = 4) - category = CAT_PRIMAL - /datum/crafting_recipe/goliathcloak name = "Goliath Cloak" result = /obj/item/clothing/suit/hooded/cloak/goliath @@ -62,13 +48,6 @@ /obj/item/stack/sheet/sinew = 2) category = CAT_PRIMAL -/datum/crafting_recipe/bonedagger - name = "Bone Dagger" - result = /obj/item/kitchen/knife/combat/bone - time = 20 - reqs = list(/obj/item/stack/sheet/bone = 2) - category = CAT_PRIMAL - /datum/crafting_recipe/bonespear name = "Bone Spear" result = /obj/item/twohanded/bonespear diff --git a/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm b/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm index 06f79396b8..104b58ca28 100644 --- a/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm +++ b/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm @@ -8,6 +8,12 @@ category = CAT_WEAPONRY subcategory = CAT_WEAPON +/datum/crafting_recipe/pin_removal/check_requirements(mob/user, list/collected_requirements) + var/obj/item/gun/G = collected_requirements[/obj/item/gun][1] + if (G.no_pin_required || !G.pin) + return FALSE + return TRUE + /datum/crafting_recipe/strobeshield name = "Strobe Shield" result = /obj/item/assembly/flash/shield diff --git a/code/datums/components/nanites.dm b/code/datums/components/nanites.dm index e1c96121c7..1d9ba1d11b 100644 --- a/code/datums/components/nanites.dm +++ b/code/datums/components/nanites.dm @@ -25,7 +25,7 @@ if(isliving(parent)) host_mob = parent - if(!(MOB_ORGANIC in host_mob.mob_biotypes) && !(MOB_UNDEAD in host_mob.mob_biotypes)) //Shouldn't happen, but this avoids HUD runtimes in case a silicon gets them somehow. + if(!(host_mob.mob_biotypes & (MOB_ORGANIC|MOB_UNDEAD))) //Shouldn't happen, but this avoids HUD runtimes in case a silicon gets them somehow. return COMPONENT_INCOMPATIBLE host_mob.hud_set_nanite_indicator() @@ -212,7 +212,7 @@ NP.receive_comm_signal(comm_code, comm_message, comm_source) /datum/component/nanites/proc/check_viable_biotype() - if(!(MOB_ORGANIC in host_mob.mob_biotypes) && !(MOB_UNDEAD in host_mob.mob_biotypes)) + if(!(host_mob.mob_biotypes & (MOB_ORGANIC|MOB_UNDEAD))) qdel(src) //bodytype no longer sustains nanites /datum/component/nanites/proc/check_access(datum/source, obj/O) diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm index 55e5c03c2b..61f97006dd 100644 --- a/code/datums/components/storage/storage.dm +++ b/code/datums/components/storage/storage.dm @@ -41,6 +41,7 @@ var/obj/screen/storage/boxes //storage display object var/obj/screen/close/closer //close button object + var/current_maxscreensize var/allow_big_nesting = FALSE //allow storage objects of the same or greater size. @@ -362,11 +363,15 @@ break closer.screen_loc = "[screen_start_x + cols]:[screen_pixel_x],[screen_start_y]:[screen_pixel_y]" -/datum/component/storage/proc/show_to(mob/M) +/datum/component/storage/proc/show_to(mob/M, set_screen_size = TRUE) if(!M.client) return FALSE var/list/cview = getviewsize(M.client.view) var/maxallowedscreensize = cview[1]-8 + if(set_screen_size) + current_maxscreensize = maxallowedscreensize + else if(current_maxscreensize) + maxallowedscreensize = current_maxscreensize if(M.active_storage != src && (M.stat == CONSCIOUS)) for(var/obj/item/I in accessible_items()) if(I.on_found(M)) @@ -547,14 +552,14 @@ return A.add_fingerprint(M) -/datum/component/storage/proc/user_show_to_mob(mob/M, force = FALSE) +/datum/component/storage/proc/user_show_to_mob(mob/M, force = FALSE, ghost = FALSE) var/atom/A = parent if(!istype(M)) return FALSE A.add_fingerprint(M) if(!force && (check_locked(null, M) || !M.CanReach(parent, view_only = TRUE))) return FALSE - show_to(M) + show_to(M, !ghost) /datum/component/storage/proc/mousedrop_receive(datum/source, atom/movable/O, mob/M) if(isitem(O)) @@ -665,7 +670,7 @@ return can_be_inserted(I, silent, M) /datum/component/storage/proc/show_to_ghost(datum/source, mob/dead/observer/M) - return user_show_to_mob(M, TRUE) + return user_show_to_mob(M, TRUE, TRUE) /datum/component/storage/proc/signal_show_attempt(datum/source, mob/showto, force = FALSE) return user_show_to_mob(showto, force) diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm index 5057253522..a8e03946b6 100644 --- a/code/datums/components/uplink.dm +++ b/code/datums/components/uplink.dm @@ -25,6 +25,8 @@ GLOBAL_LIST_EMPTY(uplinks) var/unlock_code var/failsafe_code var/datum/ui_state/checkstate + var/compact_mode = FALSE + var/debug = FALSE /datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20, datum/ui_state/_checkstate) if(!isitem(parent)) @@ -121,7 +123,7 @@ GLOBAL_LIST_EMPTY(uplinks) active = TRUE ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "uplink", name, 450, 750, master_ui, state) + ui = new(user, src, ui_key, "uplink", name, 620, 580, master_ui, state) ui.set_autoupdate(FALSE) // This UI is only ever opened by one person, and never is updated outside of user input. ui.set_style("syndicate") ui.open() @@ -138,29 +140,35 @@ GLOBAL_LIST_EMPTY(uplinks) var/list/data = list() data["telecrystals"] = telecrystals data["lockable"] = lockable + data["compact_mode"] = compact_mode + return data + +/datum/component/uplink/ui_static_data(mob/user) + var/list/data = list() data["categories"] = list() for(var/category in uplink_items) var/list/cat = list( "name" = category, "items" = (category == selected_cat ? list() : null)) - if(category == selected_cat) - for(var/item in uplink_items[category]) - var/datum/uplink_item/I = uplink_items[category][item] - if(I.limited_stock == 0) + for(var/item in uplink_items[category]) + var/datum/uplink_item/I = uplink_items[category][item] + if(I.limited_stock == 0) + continue + if(I.restricted_roles.len) + var/is_inaccessible = TRUE + for(var/R in I.restricted_roles) + if(R == user.mind.assigned_role || debug) + is_inaccessible = FALSE + if(is_inaccessible) continue - if(I.restricted_roles.len) - var/is_inaccessible = 1 - for(var/R in I.restricted_roles) - if(R == user.mind.assigned_role) - is_inaccessible = 0 if(is_inaccessible) continue - cat["items"] += list(list( - "name" = I.name, - "cost" = I.cost, - "desc" = I.desc, - )) + cat["items"] += list(list( + "name" = I.name, + "cost" = I.cost, + "desc" = I.desc, + )) data["categories"] += list(cat) return data @@ -188,6 +196,8 @@ GLOBAL_LIST_EMPTY(uplinks) SStgui.close_uis(src) if("select") selected_cat = params["category"] + if("compact_toggle") + compact_mode = !compact_mode return TRUE /datum/component/uplink/proc/MakePurchase(mob/user, datum/uplink_item/U) @@ -294,4 +304,4 @@ GLOBAL_LIST_EMPTY(uplinks) if(!T) return explosion(T,1,2,3) - qdel(parent) //Alternatively could brick the uplink. \ No newline at end of file + qdel(parent) //Alternatively could brick the uplink. diff --git a/code/datums/diseases/_MobProcs.dm b/code/datums/diseases/_MobProcs.dm index c125a9b7c7..0b6d4e3404 100644 --- a/code/datums/diseases/_MobProcs.dm +++ b/code/datums/diseases/_MobProcs.dm @@ -17,14 +17,10 @@ if(HasDisease(D)) return FALSE - var/can_infect = FALSE - for(var/host_type in D.infectable_biotypes) - if(host_type in mob_biotypes) - can_infect = TRUE - break - if(!can_infect) + if(!(D.infectable_biotypes & mob_biotypes)) return FALSE + if(!(type in D.viable_mobtypes)) return FALSE diff --git a/code/datums/diseases/_disease.dm b/code/datums/diseases/_disease.dm index 056f99c7a4..940b61c9fe 100644 --- a/code/datums/diseases/_disease.dm +++ b/code/datums/diseases/_disease.dm @@ -30,7 +30,7 @@ var/list/required_organs = list() var/needs_all_cures = TRUE var/list/strain_data = list() //dna_spread special bullshit - var/list/infectable_biotypes = list(MOB_ORGANIC) //if the disease can spread on organics, synthetics, or undead + var/infectable_biotypes = MOB_ORGANIC //if the disease can spread on organics, synthetics, or undead var/process_dead = FALSE //if this ticks while the host is dead var/copy_type = null //if this is null, copies will use the type of the instance being copied diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm index cf14da36a0..c7b9758bcb 100644 --- a/code/datums/diseases/advance/symptoms/heal.dm +++ b/code/datums/diseases/advance/symptoms/heal.dm @@ -448,9 +448,11 @@ symptom_delay_max = 1 passive_message = "Your skin glows faintly for a moment." var/cellular_damage = FALSE - threshold_desc = "Transmission 6: Additionally heals cellular damage and toxin lovers.
\ - Resistance 7: Increases healing speed." - + threshold_desc = list( + "Transmission 6" = "Additionally heals cellular damage and toxin lovers.", + "Resistance 7" = "Increases healing speed.", + ) + /datum/symptom/heal/radiation/Start(datum/disease/advance/A) if(!..()) return diff --git a/code/datums/diseases/advance/symptoms/species.dm b/code/datums/diseases/advance/symptoms/species.dm index a8b18ae735..49a3cf8d07 100644 --- a/code/datums/diseases/advance/symptoms/species.dm +++ b/code/datums/diseases/advance/symptoms/species.dm @@ -14,7 +14,7 @@ /datum/symptom/undead_adaptation/OnRemove(datum/disease/advance/A) A.process_dead = FALSE - A.infectable_biotypes -= MOB_UNDEAD + A.infectable_biotypes &= ~MOB_UNDEAD /datum/symptom/inorganic_adaptation name = "Inorganic Biology" @@ -27,7 +27,8 @@ severity = 0 /datum/symptom/inorganic_adaptation/OnAdd(datum/disease/advance/A) - A.infectable_biotypes |= MOB_INORGANIC + A.infectable_biotypes |= MOB_MINERAL //Mineral covers plasmamen and golems. /datum/symptom/inorganic_adaptation/OnRemove(datum/disease/advance/A) - A.infectable_biotypes -= MOB_INORGANIC \ No newline at end of file + A.infectable_biotypes &= ~MOB_MINERAL + diff --git a/code/datums/diseases/beesease.dm b/code/datums/diseases/beesease.dm index 074bda0560..ccae692b4b 100644 --- a/code/datums/diseases/beesease.dm +++ b/code/datums/diseases/beesease.dm @@ -10,7 +10,7 @@ viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) desc = "If left untreated subject will regurgitate bees." severity = DISEASE_SEVERITY_MEDIUM - infectable_biotypes = list(MOB_ORGANIC, MOB_UNDEAD) //bees nesting in corpses + infectable_biotypes = MOB_ORGANIC|MOB_UNDEAD //bees nesting in corpses /datum/disease/beesease/stage_act() ..() diff --git a/code/datums/diseases/magnitis.dm b/code/datums/diseases/magnitis.dm index 29e6657e13..0bfb918ba0 100644 --- a/code/datums/diseases/magnitis.dm +++ b/code/datums/diseases/magnitis.dm @@ -10,7 +10,7 @@ permeability_mod = 0.75 desc = "This disease disrupts the magnetic field of your body, making it act as if a powerful magnet. Injections of iron help stabilize the field." severity = DISEASE_SEVERITY_MEDIUM - infectable_biotypes = list(MOB_ORGANIC, MOB_ROBOTIC) + infectable_biotypes = MOB_ORGANIC|MOB_ROBOTIC process_dead = TRUE /datum/disease/magnitis/stage_act() diff --git a/code/datums/diseases/parrotpossession.dm b/code/datums/diseases/parrotpossession.dm index 68e962055a..1a3346d565 100644 --- a/code/datums/diseases/parrotpossession.dm +++ b/code/datums/diseases/parrotpossession.dm @@ -11,7 +11,7 @@ viable_mobtypes = list(/mob/living/carbon/human) desc = "Subject is possessed by the vengeful spirit of a parrot. Call the priest." severity = DISEASE_SEVERITY_MEDIUM - infectable_biotypes = list(MOB_ORGANIC, MOB_UNDEAD, MOB_INORGANIC, MOB_ROBOTIC) + infectable_biotypes = MOB_ORGANIC|MOB_UNDEAD|MOB_ROBOTIC|MOB_MINERAL bypasses_immunity = TRUE //2spook var/mob/living/simple_animal/parrot/Poly/ghost/parrot diff --git a/code/datums/diseases/transformation.dm b/code/datums/diseases/transformation.dm index bdb05346e4..36c7d70f3c 100644 --- a/code/datums/diseases/transformation.dm +++ b/code/datums/diseases/transformation.dm @@ -168,7 +168,7 @@ stage4 = list("Your skin feels very loose.", "You can feel... something...inside you.") stage5 = list("Your skin feels as if it's about to burst off!") new_form = /mob/living/silicon/robot - infectable_biotypes = list(MOB_ORGANIC, MOB_UNDEAD, MOB_ROBOTIC) + infectable_biotypes = MOB_ORGANIC|MOB_UNDEAD|MOB_ROBOTIC bantype = "Cyborg" /datum/disease/transformation/robot/stage_act() @@ -284,7 +284,7 @@ stage4 = list("You're ravenous.") stage5 = list("You have become a morph.") new_form = /mob/living/simple_animal/hostile/morph - infectable_biotypes = list(MOB_ORGANIC, MOB_INORGANIC, MOB_UNDEAD) //magic! + infectable_biotypes = MOB_ORGANIC|MOB_MINERAL|MOB_UNDEAD //magic! /datum/disease/transformation/gondola name = "Gondola Transformation" diff --git a/code/datums/elements/cleaning.dm b/code/datums/elements/cleaning.dm index e4fb3edd48..3f80204089 100644 --- a/code/datums/elements/cleaning.dm +++ b/code/datums/elements/cleaning.dm @@ -45,4 +45,4 @@ cleaned_human.clean_blood() cleaned_human.wash_cream() cleaned_human.regenerate_icons() - to_chat(cleaned_human, "[src] cleans your face!") + to_chat(cleaned_human, "[AM] cleans your face!") diff --git a/code/datums/elements/mob_holder.dm b/code/datums/elements/mob_holder.dm index 5b471a0dc7..e33c430198 100644 --- a/code/datums/elements/mob_holder.dm +++ b/code/datums/elements/mob_holder.dm @@ -1,5 +1,5 @@ /datum/element/mob_holder - element_flags = ELEMENT_BESPOKE + element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH id_arg_index = 2 var/worn_state var/alt_worn @@ -40,19 +40,19 @@ to_chat(user, "Your hands are full!") return FALSE if(source.buckled) - to_chat(user, "[src] is buckled to something!") + to_chat(user, "[source] is buckled to something!") return FALSE if(source == user) to_chat(user, "You can't pick yourself up.") return FALSE source.visible_message("[user] starts picking up [source].", \ "[user] starts picking you up!") - if(!do_after(user, 20, target = src) || source.buckled) + if(!do_after(user, 20, target = source) || source.buckled) return FALSE source.visible_message("[user] picks up [source]!", \ "[user] picks you up!") - to_chat(user, "You pick [src] up.") + to_chat(user, "You pick [source] up.") source.drop_all_held_items() var/obj/item/clothing/head/mob_holder/holder = new(get_turf(source), source, worn_state, alt_worn, right_hand, left_hand, inv_slots) if(proctype) @@ -101,6 +101,8 @@ target.forceMove(src) var/image/I = new //work around to retain the same appearance to the mob idependently from inhands/worn states. I.appearance = target.appearance + I.layer = FLOAT_LAYER //So it doesn't get screwed up by layer overrides. + I.plane = FLOAT_PLANE //Same as above but for planes. I.override = TRUE add_overlay(I) name = target.name @@ -128,7 +130,7 @@ if(AM == held_mob) held_mob.reset_perspective() held_mob = null - qdel(src) + QDEL_IN(src, 1) //To avoid a qdel loop. /obj/item/clothing/head/mob_holder/Entered(atom/movable/AM, atom/newloc) . = ..() @@ -158,7 +160,7 @@ /obj/item/clothing/head/mob_holder/container_resist() if(isliving(loc)) var/mob/living/L = loc - L.visible_message("[src] escapes from [L]!", "[src] escapes your grip!") + L.visible_message("[held_mob] escapes from [L]!", "[held_mob] escapes your grip!") release() /obj/item/clothing/head/mob_holder/assume_air(datum/gas_mixture/env) @@ -170,7 +172,7 @@ location = location.loc if(ismob(location)) return location.loc.assume_air(env) - return loc.assume_air(env) + return location.assume_air(env) /obj/item/clothing/head/mob_holder/remove_air(amount) var/atom/location = loc @@ -181,4 +183,4 @@ location = location.loc if(ismob(location)) return location.loc.remove_air(amount) - return loc.remove_air(amount) + return location.remove_air(amount) diff --git a/code/datums/elements/wuv.dm b/code/datums/elements/wuv.dm index 55bc9bafad..fffb90c681 100644 --- a/code/datums/elements/wuv.dm +++ b/code/datums/elements/wuv.dm @@ -1,6 +1,6 @@ /datum/element/wuv //D'awwwww - element_flags = ELEMENT_BESPOKE + element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH id_arg_index = 2 //the for the me emote proc call when petted. var/pet_emote diff --git a/code/datums/helper_datums/getrev.dm b/code/datums/helper_datums/getrev.dm index 7d040a4982..0b0fed407c 100644 --- a/code/datums/helper_datums/getrev.dm +++ b/code/datums/helper_datums/getrev.dm @@ -27,7 +27,8 @@ for(var/line in testmerge) var/datum/tgs_revision_information/test_merge/tm = line - msg += "Test merge active of PR #[tm.number] commit [tm.commit]" + msg += "Test merge active of PR #[tm.number] commit [tm.pull_request_commit]" + SSblackbox.record_feedback("associative", "testmerged_prs", 1, list("number" = "[tm.number]", "commit" = "[tm.pull_request_commit]", "title" = "[tm.title]", "author" = "[tm.author]")) if(commit && commit != originmastercommit) msg += "HEAD: [commit]" @@ -75,7 +76,8 @@ else if(!pc) msg += "No commit information" if(world.TgsAvailable()) - msg += "Server tools version: [world.TgsVersion()]" + var/datum/tgs_version/version = world.TgsVersion() + msg += "Server tools version: [version.raw_parameter]" // Game mode odds msg += "
Current Informational Settings:" diff --git a/code/datums/helper_datums/topic_input.dm b/code/datums/helper_datums/topic_input.dm deleted file mode 100644 index d07aec067e..0000000000 --- a/code/datums/helper_datums/topic_input.dm +++ /dev/null @@ -1,62 +0,0 @@ -/datum/topic_input - var/href - var/list/href_list - -/datum/topic_input/New(thref,list/thref_list) - href = thref - href_list = thref_list.Copy() - return - -/datum/topic_input/proc/get(i) - return listgetindex(href_list,i) - -/datum/topic_input/proc/getAndLocate(i) - var/t = get(i) - if(t) - t = locate(t) - if (istext(t)) - t = null - return t || null - -/datum/topic_input/proc/getNum(i) - var/t = get(i) - if(t) - t = text2num(t) - return isnum(t) ? t : null - -/datum/topic_input/proc/getObj(i) - var/t = getAndLocate(i) - return isobj(t) ? t : null - -/datum/topic_input/proc/getMob(i) - var/t = getAndLocate(i) - return ismob(t) ? t : null - -/datum/topic_input/proc/getTurf(i) - var/t = getAndLocate(i) - return isturf(t) ? t : null - -/datum/topic_input/proc/getAtom(i) - return getType(i, /atom) - -/datum/topic_input/proc/getArea(i) - var/t = getAndLocate(i) - return isarea(t) ? t : null - -/datum/topic_input/proc/getStr(i)//params should always be text, but... - var/t = get(i) - return istext(t) ? t : null - -/datum/topic_input/proc/getType(i,type) - var/t = getAndLocate(i) - return istype(t,type) ? t : null - -/datum/topic_input/proc/getPath(i) - var/t = get(i) - if(t) - t = text2path(t) - return ispath(t) ? t : null - -/datum/topic_input/proc/getList(i) - var/t = getAndLocate(i) - return islist(t) ? t : null diff --git a/code/datums/holocall.dm b/code/datums/holocall.dm index 72fe6f5a1c..e0b0072808 100644 --- a/code/datums/holocall.dm +++ b/code/datums/holocall.dm @@ -12,7 +12,12 @@ /mob/camera/aiEye/remote/holo/setLoc() . = ..() var/obj/machinery/holopad/H = origin - H.move_hologram(eye_user, loc) + H?.move_hologram(eye_user, loc) + +/obj/machinery/holopad/remove_eye_control(mob/living/user) + if(user.client) + user.reset_perspective(null) + user.remote_control = null //this datum manages it's own references @@ -54,11 +59,6 @@ /datum/holocall/Destroy() QDEL_NULL(hangup) - var/user_good = !QDELETED(user) - if(user_good) - user.reset_perspective() - user.remote_control = null - if(!QDELETED(eye)) QDEL_NULL(eye) diff --git a/code/datums/hud.dm b/code/datums/hud.dm index e2d9bc579f..6b6fcb9691 100644 --- a/code/datums/hud.dm +++ b/code/datums/hud.dm @@ -32,7 +32,7 @@ GLOBAL_LIST_INIT(huds, list( /datum/atom_hud var/list/atom/hudatoms = list() //list of all atoms which display this hud - var/list/mob/hudusers = list() //list with all mobs who can see the hud + var/list/hudusers = list() //list with all mobs who can see the hud var/list/hud_icons = list() //these will be the indexes for the atom's hud_list var/list/next_time_allowed = list() //mobs associated with the next time this hud can be added to them diff --git a/code/datums/ruins/station.dm b/code/datums/ruins/station.dm index 17d5a9e1e2..71cdf495e9 100644 --- a/code/datums/ruins/station.dm +++ b/code/datums/ruins/station.dm @@ -37,22 +37,22 @@ /datum/map_template/ruin/station/box/engine/teg id = "engine_teg" - suffix = "Box/Engine/engine_tesla.dmm" + suffix = "Box/Engine/engine_teg.dmm" name = "Box TEG" /datum/map_template/ruin/station/box/engine/empty id = "engine_empty" - suffix = "Box/Engine/engine_tesla.dmm" + suffix = "Box/Engine/empty.dmm" name = "Box Empty" /datum/map_template/ruin/station/box/engine/am id = "engine_am" - suffix = "Box/Engine/engine_tesla.dmm" + suffix = "Box/Engine/engine_am.dmm" name = "Box Antimatter" /datum/map_template/ruin/station/box/engine/budget id = "engine_budget" - suffix = "Box/Engine/engine_tesla.dmm" + suffix = "Box/Engine/budget.dmm" name = "Box P.A.C.M.A.N" // Lavaland @@ -60,4 +60,4 @@ /datum/map_template/ruin/station/lavaland/mining_base id = "mining_public_01" suffix = "Lavaland/Mining_Station/Mining_Station_Public_01.dmm" - name = "Public Mining Base" \ No newline at end of file + name = "Public Mining Base" diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index 2e46046a7e..c694f27d64 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -33,7 +33,6 @@ if(owner.getStaminaLoss()) owner.adjustStaminaLoss(-0.3) //reduce stamina loss by 0.3 per tick, 6 per 2 seconds - //UNCONSCIOUS /datum/status_effect/incapacitating/unconscious id = "unconscious" @@ -80,11 +79,11 @@ desc = "You've fallen asleep. Wait a bit and you should wake up. Unless you don't, considering how helpless you are." icon_state = "asleep" -/datum/status_effect/no_combat_mode/ +/datum/status_effect/no_combat_mode id = "no_combat_mode" - blocks_combatmode = TRUE alert_type = null status_type = STATUS_EFFECT_REPLACE + blocks_combatmode = TRUE /datum/status_effect/no_combat_mode/on_creation(mob/living/new_owner, set_duration) if(isnum(set_duration)) @@ -113,31 +112,54 @@ icon = 'icons/mob/actions/bloodsucker.dmi' icon_state = "power_mez" -/datum/status_effect/no_combat_mode/electrode +/datum/status_effect/electrode id = "tased" + var/slowdown = 1.5 + var/slowdown_priority = 50 //to make sure the stronger effect overrides + var/affect_crawl = FALSE + var/nextmove_modifier = 1 + var/stamdmg_per_ds = 1 //a 20 duration would do 20 stamdmg, disablers do 24 or something + var/last_tick = 0 //fastprocess processing speed is a goddamn sham, don't trust it. -/datum/status_effect/no_combat_mode/electrode/on_creation(mob/living/new_owner, set_duration) +/datum/status_effect/electrode/on_creation(mob/living/new_owner, set_duration) if(isnum(set_duration)) //TODO, figure out how to grab from subtype duration = set_duration . = ..() + last_tick = world.time + if(iscarbon(owner)) + var/mob/living/carbon/C = owner + if(C.combatmode) + C.toggle_combat_mode(TRUE) + C.add_movespeed_modifier("[MOVESPEED_ID_TASED_STATUS]_[id]", TRUE, priority = slowdown_priority, override = TRUE, multiplicative_slowdown = slowdown, blacklisted_movetypes = affect_crawl? NONE : CRAWLING) + +/datum/status_effect/electrode/on_remove() + if(iscarbon(owner)) + var/mob/living/carbon/C = owner + C.remove_movespeed_modifier("[MOVESPEED_ID_TASED_STATUS]_[id]") + . = ..() + +/datum/status_effect/electrode/tick() + var/diff = world.time - last_tick + if(owner) + owner.adjustStaminaLoss(max(0, stamdmg_per_ds * diff)) //if you really want to try to stamcrit someone with a taser alone, you can, but it'll take time and good timing. + last_tick = world.time + +/datum/status_effect/electrode/nextmove_modifier() //why is this a proc. its no big deal since this doesnt get called often at all but literally w h y + return nextmove_modifier + +/datum/status_effect/electrode/no_combat_mode + id = "tased_strong" + slowdown = 8 + slowdown_priority = 100 + nextmove_modifier = 2 + blocks_combatmode = TRUE + +/datum/status_effect/electrode/no_combat_mode/on_creation(mob/living/new_owner, set_duration) + . = ..() if(iscarbon(owner)) var/mob/living/carbon/C = owner if(C.combatmode) C.toggle_combat_mode(TRUE) - C.add_movespeed_modifier(MOVESPEED_ID_TASED_STATUS, TRUE, override = TRUE, multiplicative_slowdown = 8) - -/datum/status_effect/no_combat_mode/electrode/on_remove() - if(iscarbon(owner)) - var/mob/living/carbon/C = owner - C.remove_movespeed_modifier(MOVESPEED_ID_TASED_STATUS) - . = ..() - -/datum/status_effect/no_combat_mode/electrode/tick() - if(owner) - owner.adjustStaminaLoss(5) //if you really want to try to stamcrit someone with a taser alone, you can, but it'll take time and good timing. - -/datum/status_effect/no_combat_mode/electrode/nextmove_modifier() //why is this a proc. its no big deal since this doesnt get called often at all but literally w h y - return 2 //OTHER DEBUFFS /datum/status_effect/his_wrath //does minor damage over time unless holding His Grace diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm index faa7eec392..b2177a860a 100644 --- a/code/datums/traits/negative.dm +++ b/code/datums/traits/negative.dm @@ -144,9 +144,8 @@ GLOBAL_LIST_EMPTY(family_heirlooms) /datum/quirk/nearsighted/on_spawn() var/mob/living/carbon/human/H = quirk_holder var/obj/item/clothing/glasses/regular/glasses = new(get_turf(H)) - H.put_in_hands(glasses) - H.equip_to_slot(glasses, SLOT_GLASSES) - H.regenerate_icons() //this is to remove the inhand icon, which persists even if it's not in their hands + if(!H.equip_to_slot_if_possible(glasses, SLOT_GLASSES)) + H.put_in_hands(glasses) /datum/quirk/nyctophobia name = "Nyctophobia" diff --git a/code/datums/weather/weather.dm b/code/datums/weather/weather.dm index 01b9facbb8..6761ecbb4c 100644 --- a/code/datums/weather/weather.dm +++ b/code/datums/weather/weather.dm @@ -61,7 +61,7 @@ if(A.z in impacted_z_levels) impacted_areas |= A weather_duration = rand(weather_duration_lower, weather_duration_upper) - START_PROCESSING(SSweather, src) + START_PROCESSING(SSweather, src) //The reason this doesn't start and stop at main stage is because processing list is also used to see active running weathers (for example, you wouldn't want two ash storms starting at once.) update_areas() for(var/M in GLOB.player_list) var/turf/mob_turf = get_turf(M) @@ -107,6 +107,14 @@ STOP_PROCESSING(SSweather, src) update_areas() +/datum/weather/process() + if(aesthetic || (stage != MAIN_STAGE)) + return + for(var/i in GLOB.mob_living_list) + var/mob/living/L = i + if(can_weather_act(L)) + weather_act(L) + /datum/weather/proc/can_weather_act(mob/living/L) //Can this weather impact a mob? var/turf/mob_turf = get_turf(L) if(mob_turf && !(mob_turf.z in impacted_z_levels)) diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm index 315cfa59d6..b6699540c3 100644 --- a/code/datums/wires/airlock.dm +++ b/code/datums/wires/airlock.dm @@ -52,7 +52,7 @@ /datum/wires/airlock/interactable(mob/user) var/obj/machinery/door/airlock/A = holder - if(!issilicon(user) && A.isElectrified() && A.shock(user, 100)) + if(!A.hasSiliconAccessInArea(user) && A.isElectrified() && A.shock(user, 100)) return FALSE if(A.panel_open) return TRUE diff --git a/code/datums/wires/vending.dm b/code/datums/wires/vending.dm index 0c66f26a92..114791e873 100644 --- a/code/datums/wires/vending.dm +++ b/code/datums/wires/vending.dm @@ -12,7 +12,7 @@ /datum/wires/vending/interactable(mob/user) var/obj/machinery/vending/V = holder - if(!issilicon(user) && V.seconds_electrified && V.shock(user, 100)) + if(!V.hasSiliconAccessInArea(user) && V.seconds_electrified && V.shock(user, 100)) return FALSE if(V.panel_open) return TRUE diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 7e224080b9..83117bad64 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -6,7 +6,6 @@ var/flags_1 = NONE var/interaction_flags_atom = NONE - var/ghost_flags = NONE var/datum/reagents/reagents = null //This atom's HUD (med/sec, etc) images. Associative list. diff --git a/code/game/gamemodes/bloodsucker/bloodsucker.dm b/code/game/gamemodes/bloodsucker/bloodsucker.dm index ca2ebfe00d..a45e989318 100644 --- a/code/game/gamemodes/bloodsucker/bloodsucker.dm +++ b/code/game/gamemodes/bloodsucker/bloodsucker.dm @@ -7,7 +7,7 @@ // LISTS // var/list/vassal_allowed_antags = list(/datum/antagonist/brother, /datum/antagonist/traitor, /datum/antagonist/traitor/internal_affairs, /datum/antagonist/survivalist, \ - /datum/antagonist/rev, /datum/antagonist/nukeop, /datum/antagonist/pirate, /datum/antagonist/cult, /datum/antagonist/abductee) + /datum/antagonist/rev, /datum/antagonist/nukeop, /datum/antagonist/pirate, /datum/antagonist/cult, /datum/antagonist/abductee, /datum/antagonist/valentine, /datum/antagonist/heartbreaker,) // The antags you're allowed to be if turning Vassal. /proc/isvamp(mob/living/M) return istype(M) && M.mind && M.mind.has_antag_datum(/datum/antagonist/bloodsucker) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index abd560171e..7ad4cee884 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -61,7 +61,7 @@ trimmed_list.Remove(M) continue if (M.mind) - if (restrict_ghost_roles && M.mind.assigned_role in GLOB.exp_specialmap[EXP_TYPE_SPECIAL]) // Are they playing a ghost role? + if (restrict_ghost_roles && (M.mind.assigned_role in GLOB.exp_specialmap[EXP_TYPE_SPECIAL])) // Are they playing a ghost role? trimmed_list.Remove(M) continue if (M.mind.assigned_role in restricted_roles) // Does their job allow it? diff --git a/code/game/gamemodes/gangs/gangs.dm b/code/game/gamemodes/gangs/gangs.dm index 9151107d6f..0dc4a520ef 100644 --- a/code/game/gamemodes/gangs/gangs.dm +++ b/code/game/gamemodes/gangs/gangs.dm @@ -6,7 +6,8 @@ GLOBAL_LIST_EMPTY(gangs) name = "gang war" config_tag = "gang" antag_flag = ROLE_GANG - restricted_jobs = list("Security Officer", "Warden", "Detective", "AI", "Cyborg","Captain", "Head of Personnel", "Head of Security") + restricted_jobs = list("AI", "Cyborg") + protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") required_players = 15 required_enemies = 0 recommended_enemies = 2 diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index b6dc09eb59..b5ab859797 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -182,7 +182,7 @@ /obj/machinery/sleeper/AltClick(mob/user) . = ..() - if(!user.canUseTopic(src, !issilicon(user))) + if(!user.canUseTopic(src, !hasSiliconAccessInArea(user))) return if(state_open) close_machine() diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index 44739fcbc0..7132f046e6 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -229,7 +229,7 @@ Class Procs: return !(stat & (NOPOWER|BROKEN|MAINT)) /obj/machinery/can_interact(mob/user) - var/silicon = issiliconoradminghost(user) + var/silicon = hasSiliconAccessInArea(user) || IsAdminGhost(user) if((stat & (NOPOWER|BROKEN)) && !(interaction_flags_machine & INTERACT_MACHINE_OFFLINE)) return FALSE if(panel_open && !(interaction_flags_machine & INTERACT_MACHINE_OPEN)) @@ -242,7 +242,7 @@ Class Procs: else if(interaction_flags_machine & INTERACT_MACHINE_REQUIRES_SILICON) return FALSE - if(!Adjacent(user) && !isobserver(user)) + if(!Adjacent(user)) var/mob/living/carbon/H = user if(!(istype(H) && H.has_dna() && H.dna.check_mutation(TK))) return FALSE diff --git a/code/game/machinery/announcement_system.dm b/code/game/machinery/announcement_system.dm index 56227cdd53..5a597f7280 100644 --- a/code/game/machinery/announcement_system.dm +++ b/code/game/machinery/announcement_system.dm @@ -105,7 +105,7 @@ GLOBAL_LIST_EMPTY(announcement_systems) /obj/machinery/announcement_system/ui_interact(mob/user) . = ..() - if(!user.canUseTopic(src, !issilicon(user))) + if(!user.canUseTopic(src, !hasSiliconAccessInArea(user))) return if(stat & BROKEN) visible_message("[src] buzzes.", "You hear a faint buzz.") @@ -123,7 +123,7 @@ GLOBAL_LIST_EMPTY(announcement_systems) /obj/machinery/announcement_system/Topic(href, href_list) if(..()) return - if(!usr.canUseTopic(src, !issilicon(usr))) + if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr))) return if(stat & BROKEN) visible_message("[src] buzzes.", "You hear a faint buzz.") @@ -132,13 +132,13 @@ GLOBAL_LIST_EMPTY(announcement_systems) if(href_list["ArrivalTopic"]) var/NewMessage = stripped_input(usr, "Enter in the arrivals announcement configuration.", "Arrivals Announcement Config", arrival) - if(!usr.canUseTopic(src, !issilicon(usr))) + if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr))) return if(NewMessage) arrival = NewMessage else if(href_list["NewheadTopic"]) var/NewMessage = stripped_input(usr, "Enter in the departmental head announcement configuration.", "Head Departmental Announcement Config", newhead) - if(!usr.canUseTopic(src, !issilicon(usr))) + if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr))) return if(NewMessage) newhead = NewMessage @@ -157,7 +157,7 @@ GLOBAL_LIST_EMPTY(announcement_systems) . = attack_ai(user) /obj/machinery/announcement_system/attack_ai(mob/user) - if(!user.canUseTopic(src, !issilicon(user))) + if(!user.canUseTopic(src, !hasSiliconAccessInArea(user))) return if(stat & BROKEN) to_chat(user, "[src]'s firmware appears to be malfunctioning!") diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 495e90d305..c9d26905f5 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -17,6 +17,7 @@ var/list/L = list() var/list/LL = list() var/hacked = FALSE + var/hackable = TRUE var/disabled = 0 var/shocked = FALSE var/hack_wire @@ -371,6 +372,8 @@ /obj/machinery/autolathe/proc/adjust_hacked(state) hacked = state + if(!hackable && hacked) + return for(var/id in SSresearch.techweb_designs) var/datum/design/D = SSresearch.techweb_design_by_id(id) if((D.build_type & AUTOLATHE) && ("hacked" in D.category)) @@ -383,6 +386,12 @@ . = ..() adjust_hacked(TRUE) +/obj/machinery/autolathe/secure + name = "secured autolathe" + desc = "An autolathe reprogrammed with security protocols to prevent hacking." + hackable = FALSE + circuit = /obj/item/circuitboard/machine/autolathe/secure + //Called when the object is constructed by an autolathe //Has a reference to the autolathe so you can do !!FUN!! things with hacked lathes /obj/item/proc/autolathe_crafted(obj/machinery/autolathe/A) diff --git a/code/game/machinery/computer/arcade/minesweeper.dm b/code/game/machinery/computer/arcade/minesweeper.dm index 641ef1c9cd..3e32c4ceeb 100644 --- a/code/game/machinery/computer/arcade/minesweeper.dm +++ b/code/game/machinery/computer/arcade/minesweeper.dm @@ -304,12 +304,12 @@ /obj/machinery/computer/arcade/minesweeper/proc/custom_generation(mob/user) playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10) //Entered into the menu so ping sound var/new_rows = input(user, "How many rows do you want? (Minimum: 4, Maximum: 30)", "Minesweeper Rows") as null|num - if(!new_rows || !user.canUseTopic(src, !issilicon(user))) + if(!new_rows || !user.canUseTopic(src, !hasSiliconAccessInArea(user))) return FALSE new_rows = CLAMP(new_rows + 1, 4, 30) playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10) var/new_columns = input(user, "How many columns do you want? (Minimum: 4, Maximum: 50)", "Minesweeper Squares") as null|num - if(!new_columns || !user.canUseTopic(src, !issilicon(user))) + if(!new_columns || !user.canUseTopic(src, !hasSiliconAccessInArea(user))) return FALSE new_columns = CLAMP(new_columns + 1, 4, 50) playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10) @@ -317,7 +317,7 @@ var/lower_limit = round(grid_area*0.156) var/upper_limit = round(grid_area*0.85) var/new_mine_limit = input(user, "How many mines do you want? (Minimum: [lower_limit], Maximum: [upper_limit])", "Minesweeper Mines") as null|num - if(!new_mine_limit || !user.canUseTopic(src, !issilicon(user))) + if(!new_mine_limit || !user.canUseTopic(src, !hasSiliconAccessInArea(user))) return FALSE playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10) rows = new_rows diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 1d54e8f772..211ff13486 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -36,7 +36,7 @@ return ..() /obj/machinery/computer/security/can_interact(mob/user) - if((!issilicon(user) && !Adjacent(user)) || is_blind(user) || !in_view_range(user, src)) + if((!hasSiliconAccessInArea(user) && !Adjacent(user)) || is_blind(user) || !in_view_range(user, src)) return FALSE return ..() diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm index 8de470fdb8..e5ac9a0f78 100644 --- a/code/game/machinery/computer/camera_advanced.dm +++ b/code/game/machinery/computer/camera_advanced.dm @@ -47,7 +47,10 @@ jump_action.Grant(user) actions += jump_action -/obj/machinery/computer/camera_advanced/proc/remove_eye_control(mob/living/user) +/obj/machinery/proc/remove_eye_control(mob/living/user) + CRASH("[type] does not implement ai eye handling") + +/obj/machinery/computer/camera_advanced/remove_eye_control(mob/living/user) if(!user) return for(var/V in actions) @@ -157,7 +160,7 @@ var/cooldown = 0 var/acceleration = 1 var/mob/living/eye_user = null - var/obj/machinery/computer/camera_advanced/origin + var/obj/machinery/origin var/eye_initialized = 0 var/visible_icon = 0 var/image/user_image = null @@ -170,7 +173,7 @@ /mob/camera/aiEye/remote/Destroy() if(origin && eye_user) - origin.remove_eye_control(eye_user) + origin.remove_eye_control(eye_user,src) origin = null . = ..() eye_user = null diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm index 6703bae525..b0e80b63d2 100644 --- a/code/game/machinery/computer/card.dm +++ b/code/game/machinery/computer/card.dm @@ -171,7 +171,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) /obj/machinery/computer/card/AltClick(mob/user) . = ..() - if(!user.canUseTopic(src, !issilicon(user)) || !is_operational()) + if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)) || !is_operational()) return if(inserted_modify_id) if(id_eject(user, inserted_modify_id)) @@ -360,7 +360,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) if(..()) return - if(!usr.canUseTopic(src, !issilicon(usr)) || !is_operational()) + if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr)) || !is_operational()) usr.unset_machine() usr << browse(null, "window=id_com") return @@ -392,7 +392,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) inserted_scan_id = id_to_insert updateUsrDialog() if ("auth") - if ((!( authenticated ) && (inserted_scan_id || issilicon(usr)) || mode)) + if ((!( authenticated ) && (inserted_scan_id || hasSiliconAccessInArea(usr)) || mode)) if (check_access(inserted_scan_id)) region_access = list() head_subordinates = list() @@ -426,7 +426,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) get_subordinates("Quartermaster") if(region_access) authenticated = 1 - else if ((!( authenticated ) && issilicon(usr)) && (!inserted_modify_id)) + else if ((!( authenticated ) && hasSiliconAccessInArea(usr)) && (!inserted_modify_id)) to_chat(usr, "You can't modify an ID without an ID inserted to modify! Once one is in the modify slot on the computer, you can log in.") if ("logout") region_access = null @@ -481,7 +481,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) if ("reg") if (authenticated) var/t2 = inserted_modify_id - if ((authenticated && inserted_modify_id == t2 && (in_range(src, usr) || issilicon(usr)) && isturf(loc))) + if ((authenticated && inserted_modify_id == t2 && (in_range(src, usr) || hasSiliconAccessInArea(usr)) && isturf(loc))) var/newName = reject_bad_name(href_list["reg"]) if(newName) inserted_modify_id.registered_name = newName diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 59574bc603..9d0053c9b2 100755 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -449,7 +449,7 @@ var/datum/browser/popup = new(user, "communications", "Communications Console", 400, 500) popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) - if(issilicon(user)) + if(issilicon(user) || (hasSiliconAccessInArea(user) && !in_range(user,src))) var/dat2 = interact_ai(user) // give the AI a different interact proc to limit its access if(dat2) dat += dat2 diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm index a31f6c71c8..5049a10d2b 100644 --- a/code/game/machinery/computer/dna_console.dm +++ b/code/game/machinery/computer/dna_console.dm @@ -64,7 +64,7 @@ if(!user) return var/datum/browser/popup = new(user, "scannernew", "DNA Modifier Console", 800, 630) // Set up the popup browser window - if(!(in_range(src, user) || issilicon(user))) + if(!(in_range(src, user) || hasSiliconAccessInArea(user))) popup.close() return popup.add_stylesheet("scannernew", 'html/browser/scannernew.css') @@ -318,7 +318,7 @@ return if(!isturf(usr.loc)) return - if(!((isturf(loc) && in_range(src, usr)) || issilicon(usr))) + if(!((isturf(loc) && in_range(src, usr)) || hasSiliconAccessInArea(usr))) return if(current_screen == "working") return diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index ecbde43044..f8dac1b100 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -190,7 +190,7 @@ if(!(active2 in GLOB.data_core.medical)) active2 = null - if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr) || IsAdminGhost(usr)) + if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr) || IsAdminGhost(usr)) usr.set_machine(src) if(href_list["temp"]) temp = null @@ -216,7 +216,7 @@ else if(href_list["login"]) var/mob/M = usr var/obj/item/card/id/I = M.get_idcard(TRUE) - if(issilicon(M)) + if(hasSiliconAccessInArea(M)) active1 = null active2 = null authenticated = 1 @@ -569,7 +569,7 @@ if(user) if(message) if(authenticated) - if(user.canUseTopic(src, !issilicon(user))) + if(user.canUseTopic(src, !hasSiliconAccessInArea(user))) if(!record1 || record1 == active1) if(!record2 || record2 == active2) return 1 diff --git a/code/game/machinery/computer/pod.dm b/code/game/machinery/computer/pod.dm index 1388e3c8de..53f7cb7e32 100644 --- a/code/game/machinery/computer/pod.dm +++ b/code/game/machinery/computer/pod.dm @@ -86,7 +86,7 @@ /obj/machinery/computer/pod/Topic(href, href_list) if(..()) return - if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr)) + if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr)) usr.set_machine(src) if(href_list["power"]) var/t = text2num(href_list["power"]) diff --git a/code/game/machinery/computer/prisoner/management.dm b/code/game/machinery/computer/prisoner/management.dm index 496e14b8f1..4b4b39740a 100644 --- a/code/game/machinery/computer/prisoner/management.dm +++ b/code/game/machinery/computer/prisoner/management.dm @@ -87,7 +87,7 @@ /obj/machinery/computer/prisoner/management/Topic(href, href_list) if(..()) return - if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr)) + if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr)) usr.set_machine(src) if(href_list["id"]) diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index 42e31b2ea6..25f4237439 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -265,7 +265,7 @@ What a mess.*/ active1 = null if(!( GLOB.data_core.security.Find(active2) )) active2 = null - if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr) || IsAdminGhost(usr)) + if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr) || IsAdminGhost(usr)) usr.set_machine(src) switch(href_list["choice"]) // SORTING! @@ -299,7 +299,7 @@ What a mess.*/ if("Log In") var/mob/M = usr var/obj/item/card/id/I = M.get_idcard(TRUE) - if(issilicon(M)) + if(hasSiliconAccessInArea(M)) var/mob/living/silicon/borg = M active1 = null active2 = null @@ -802,7 +802,7 @@ What a mess.*/ /obj/machinery/computer/secure_data/proc/canUseSecurityRecordsConsole(mob/user, message1 = 0, record1, record2) if(user) if(authenticated) - if(user.canUseTopic(src, !issilicon(user))) + if(user.canUseTopic(src, !hasSiliconAccessInArea(user))) if(!trim(message1)) return 0 if(!record1 || record1 == active1) diff --git a/code/game/machinery/computer/teleporter.dm b/code/game/machinery/computer/teleporter.dm index 518f38fc35..6710258626 100644 --- a/code/game/machinery/computer/teleporter.dm +++ b/code/game/machinery/computer/teleporter.dm @@ -140,7 +140,7 @@ obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", datum/t L[avoid_assoc_duplicate_keys(M.real_name, areaindex)] = M var/desc = input("Please select a location to lock in.", "Locking Computer") as null|anything in L - if(!user.canUseTopic(src, !issilicon(user), NO_DEXTERY)) //check if we are still around + if(!user.canUseTopic(src, !hasSiliconAccessInArea(user), NO_DEXTERY)) //check if we are still around return target = L[desc] if(imp_t) @@ -168,7 +168,7 @@ obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", datum/t to_chat(user, "No active connected stations located.") return var/desc = input("Please select a station to lock in.", "Locking Computer") as null|anything in L - if(!user.canUseTopic(src, !issilicon(user), NO_DEXTERY)) //again, check if we are still around + if(!user.canUseTopic(src, !hasSiliconAccessInArea(user), NO_DEXTERY)) //again, check if we are still around return var/obj/machinery/teleport/station/target_station = L[desc] if(!target_station || !target_station.teleporter_hub) diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index e9d3006b06..b33b87f8b1 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -6,7 +6,6 @@ * ~ Zuhayr */ - //Main cryopod console. /obj/machinery/computer/cryopod @@ -18,7 +17,6 @@ density = FALSE interaction_flags_machine = INTERACT_MACHINE_OFFLINE req_one_access = list(ACCESS_HEADS, ACCESS_ARMORY) //Heads of staff or the warden can go here to claim recover items from their department that people went were cryodormed with. - var/mode = null var/menu = 1 //Which menu screen to display @@ -130,7 +128,8 @@ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) updateUsrDialog() return - if(!allow_items) return + if(!allow_items) + return if(frozen_items.len == 0) to_chat(user, "There is nothing to recover from storage.") @@ -182,7 +181,7 @@ var/last_no_computer_message = 0 // These items are preserved when the process() despawn proc occurs. - var/list/preserve_items = list( + var/static/list/preserve_items = typecacheof(list( /obj/item/hand_tele, /obj/item/card/id/captains_spare, /obj/item/aicard, @@ -203,9 +202,9 @@ /obj/item/tank/jetpack, /obj/item/documents, /obj/item/nuke_core_container - ) + )) // These items will NOT be preserved - var/list/do_not_preserve_items = list ( + var/static/list/do_not_preserve_items = typecacheof(list( /obj/item/mmi/posibrain, /obj/item/gun/energy/laser/mounted, /obj/item/gun/energy/e_gun/advtaser/mounted, @@ -215,7 +214,7 @@ /obj/item/gun/energy/printer, /obj/item/gun/energy/kinetic_accelerator/cyborg, /obj/item/gun/energy/laser/cyborg - ) + )) /obj/machinery/cryopod/Initialize(mapload) . = ..() @@ -287,14 +286,14 @@ #define CRYO_DESTROY 0 #define CRYO_PRESERVE 1 #define CRYO_OBJECTIVE 2 +#define CRYO_IGNORE 3 /obj/machinery/cryopod/proc/should_preserve_item(obj/item/I) for(var/datum/objective_item/steal/T in control_computer.theft_cache) if(istype(I, T.targetitem) && T.check_special_completion(I)) return CRYO_OBJECTIVE - for(var/T in preserve_items) - if(istype(I, T) && !(I.type in do_not_preserve_items)) - return CRYO_PRESERVE + if(preserve_items[I] && !do_not_preserve_items[I]) + return CRYO_PRESERVE return CRYO_DESTROY // This function can not be undone; do not call this unless you are sure @@ -303,52 +302,47 @@ find_control_computer() var/mob/living/mob_occupant = occupant + var/list/obj/item/cryo_items = list() //Handle Borg stuff first if(iscyborg(mob_occupant)) var/mob/living/silicon/robot/R = mob_occupant - - R.contents -= R.mmi - qdel(R.mmi) + if(R.mmi?.brain) + cryo_items[R.mmi] = CRYO_IGNORE + cryo_items[R.mmi.brain] = CRYO_IGNORE for(var/obj/item/I in R.module) // the tools the borg has; metal, glass, guns etc for(var/obj/item/O in I) // the things inside the tools, if anything; mainly for janiborg trash bags - if(should_preserve_item(O) != CRYO_DESTROY) // Preserve important things inside the item - continue + cryo_items[O] = should_preserve_item(O) O.forceMove(src) R.module.remove_module(I, TRUE) //delete the module itself so it doesn't transfer over. //Drop all items into the pod. for(var/obj/item/I in mob_occupant) - mob_occupant.doUnEquip(I) - I.forceMove(src) - + if(cryo_items[I] == CRYO_IGNORE) + continue + cryo_items[I] = should_preserve_item(I) + mob_occupant.transferItemToLoc(I, src, TRUE) if(I.contents.len) //Make sure we catch anything not handled by qdel() on the items. - if(should_preserve_item(I) != CRYO_DESTROY) // Don't remove the contents of things that need preservation + if(cryo_items[I] != CRYO_DESTROY) // Don't remove the contents of things that need preservation continue for(var/obj/item/O in I.contents) - if(istype(O, /obj/item/tank)) //Stop eating pockets, you fuck! - continue + cryo_items[O] = should_preserve_item(O) O.forceMove(src) - //Delete all items not on the preservation list. - var/list/items = contents - items -= mob_occupant // Don't delete the occupant - - for(var/obj/item/I in items) - if(istype(I, /obj/item/pda)) - var/obj/item/pda/P = I - QDEL_NULL(P.id) - qdel(P) + for(var/A in cryo_items) + var/obj/item/I = A + if(QDELETED(I)) //edge cases and DROPDEL. continue - - var/preserve = should_preserve_item(I) - if(preserve == CRYO_DESTROY) + var/preserve = cryo_items[I] + if(preserve == CRYO_IGNORE) + continue + else if(preserve == CRYO_DESTROY) qdel(I) - else if(control_computer && control_computer.allow_items) + else if(control_computer?.allow_items) control_computer.frozen_items += I if(preserve == CRYO_OBJECTIVE) control_computer.objective_items += I - I.loc = null + I.moveToNullspace() else I.forceMove(loc) @@ -417,6 +411,7 @@ #undef CRYO_DESTROY #undef CRYO_PRESERVE #undef CRYO_OBJECTIVE +#undef CRYO_IGNORE /obj/machinery/cryopod/MouseDrop_T(mob/living/target, mob/user) if(!istype(target) || user.incapacitated() || !target.Adjacent(user) || !Adjacent(user) || !ismob(target) || (!ishuman(user) && !iscyborg(user)) || !istype(user.loc, /turf) || target.buckled) @@ -443,29 +438,24 @@ var/generic_plsnoleave_message = " Please adminhelp before leaving the round, even if there are no administrators online!" if(target == user && world.time - target.client.cryo_warned > 5 MINUTES)//if we haven't warned them in the last 5 minutes - var/caught = FALSE + var/list/caught_string + var/addendum = "" if(target.mind.assigned_role in GLOB.command_positions) - alert("You're a Head of Staff![generic_plsnoleave_message] Be sure to put your locker items back into your locker!") - caught = TRUE + LAZYADD(caught_string, "Head of Staff") + addendum = " Be sure to put your locker items back into your locker!" if(iscultist(target) || is_servant_of_ratvar(target)) - to_chat(target, "You're a Cultist![generic_plsnoleave_message]") - caught = TRUE + LAZYADD(caught_string, "Cultist") if(is_devil(target)) - alert("You're a Devil![generic_plsnoleave_message]") - caught = TRUE - if(istype(SSticker.mode, /datum/antagonist/gang)) - if(target.mind.has_antag_datum(/datum/antagonist/gang)) - alert("You're a Gangster![generic_plsnoleave_message]") - caught = TRUE - if(istype(SSticker.mode, /datum/antagonist/rev)) - if(target.mind.has_antag_datum(/datum/antagonist/rev/head)) - alert("You're a Head Revolutionary![generic_plsnoleave_message]") - caught = TRUE - else if(target.mind.has_antag_datum(/datum/antagonist/rev)) - alert("You're a Revolutionary![generic_plsnoleave_message]") - caught = TRUE + LAZYADD(caught_string, "Devil") + if(target.mind.has_antag_datum(/datum/antagonist/gang)) + LAZYADD(caught_string, "Gangster") + if(target.mind.has_antag_datum(/datum/antagonist/rev/head)) + LAZYADD(caught_string, "Head Revolutionary") + if(target.mind.has_antag_datum(/datum/antagonist/rev)) + LAZYADD(caught_string, "Revolutionary") - if(caught) + if(caught_string) + alert(target, "You're a [english_list(caught_string)]![generic_plsnoleave_message][addendum]") target.client.cryo_warned = world.time return diff --git a/code/game/machinery/dance_machine.dm b/code/game/machinery/dance_machine.dm index 6bedfb0a10..6b62d18d01 100644 --- a/code/game/machinery/dance_machine.dm +++ b/code/game/machinery/dance_machine.dm @@ -53,7 +53,7 @@ /obj/machinery/jukebox/ui_interact(mob/user) . = ..() - if(!user.canUseTopic(src, !issilicon(user))) + if(!user.canUseTopic(src, !hasSiliconAccessInArea(user))) return if (!anchored) to_chat(user,"This device must be anchored by a wrench!") @@ -202,6 +202,8 @@ for(var/i in 1 to 10) spawn_atom_to_turf(/obj/effect/temp_visual/hierophant/telegraph/edge, src, 1, FALSE) sleep(5) + if(QDELETED(src)) + return #define DISCO_INFENO_RANGE (rand(85, 115)*0.01) diff --git a/code/game/machinery/dish_drive.dm b/code/game/machinery/dish_drive.dm index 7f21d1c1b3..31e6a3cfeb 100644 --- a/code/game/machinery/dish_drive.dm +++ b/code/game/machinery/dish_drive.dm @@ -98,7 +98,7 @@ /obj/machinery/dish_drive/AltClick(mob/living/user) . = ..() - if(user.canUseTopic(src, !issilicon(user))) + if(user.canUseTopic(src, !hasSiliconAccessInArea(user))) do_the_dishes(TRUE) return TRUE diff --git a/code/game/machinery/dna_scanner.dm b/code/game/machinery/dna_scanner.dm index cff2e361bd..60b5a52a10 100644 --- a/code/game/machinery/dna_scanner.dm +++ b/code/game/machinery/dna_scanner.dm @@ -172,7 +172,7 @@ /obj/machinery/dna_scannernew/AltClick(mob/user) . = ..() - if(!user.canUseTopic(src, !issilicon(user))) + if(!user.canUseTopic(src, !hasSiliconAccessInArea(user))) return interact(user) return TRUE diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index f28d520114..863f1e7b46 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -676,7 +676,7 @@ else . += "It looks very robust." - if(issilicon(user) && (!stat & BROKEN)) + if(hasSiliconAccessInArea(user) && (!stat & BROKEN)) . += "Shift-click [src] to [ density ? "open" : "close"] it." . += "Ctrl-click [src] to [ locked ? "raise" : "drop"] its bolts." . += "Alt-click [src] to [ secondsElectrified ? "un-electrify" : "permanently electrify"] it." @@ -1322,9 +1322,9 @@ if(density && !open(2)) //The airlock is still closed, but something prevented it opening. (Another player noticed and bolted/welded the airlock in time!) to_chat(user, "Despite your efforts, [src] managed to resist your attempts to open it!") -/obj/machinery/door/airlock/hostile_lockdown(mob/origin) +/obj/machinery/door/airlock/hostile_lockdown(mob/origin, aicontrolneeded = TRUE) // Must be powered and have working AI wire. - if(canAIControl(src) && !stat) + if((aicontrolneeded && canAIControl(src) && !stat) || !aicontrolneeded) locked = FALSE //For airlocks that were bolted open. safe = FALSE //DOOR CRUSH close() @@ -1334,9 +1334,9 @@ LAZYADD(shockedby, "\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(origin)]") -/obj/machinery/door/airlock/disable_lockdown() +/obj/machinery/door/airlock/disable_lockdown(aicontrolneeded = TRUE) // Must be powered and have working AI wire. - if(canAIControl(src) && !stat) + if((aicontrolneeded && canAIControl(src) && !stat) || !aicontrolneeded) unbolt() set_electrified(NOT_ELECTRIFIED) open() @@ -1528,7 +1528,7 @@ . = TRUE /obj/machinery/door/airlock/proc/user_allowed(mob/user) - return (issilicon(user) && canAIControl(user)) || IsAdminGhost(user) + return (hasSiliconAccessInArea(user) && canAIControl(user)) || IsAdminGhost(user) /obj/machinery/door/airlock/proc/shock_restore(mob/user) if(!user_allowed(user)) diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm index 3bfcececda..adc1748ded 100644 --- a/code/game/machinery/doors/brigdoors.dm +++ b/code/game/machinery/doors/brigdoors.dm @@ -2,13 +2,11 @@ #define FONT_SIZE "5pt" #define FONT_COLOR "#09f" #define FONT_STYLE "Arial Black" -#define MAX_TIMER 9000 - -#define PRESET_SHORT 1200 -#define PRESET_MEDIUM 1800 -#define PRESET_LONG 3000 - +#define MAX_TIMER 15 MINUTES +#define PRESET_SHORT 2 MINUTES +#define PRESET_MEDIUM 3 MINUTES +#define PRESET_LONG 5 MINUTES /////////////////////////////////////////////////////////////////////////////////////////////// // Brig Door control displays. @@ -25,7 +23,7 @@ desc = "A remote control for a door." req_access = list(ACCESS_SECURITY) density = FALSE - var/id = null // id of linked machinery/lockers + var/id // id of linked machinery/lockers var/activation_time = 0 var/timer_duration = 0 @@ -43,8 +41,6 @@ Radio = new/obj/item/radio(src) Radio.listening = 0 -/obj/machinery/door_timer/Initialize() - . = ..() if(id != null) for(var/obj/machinery/door/window/brigdoor/M in urange(20, src)) if (M.id == id) @@ -71,7 +67,7 @@ return if(timing) - if(world.realtime - activation_time >= timer_duration) + if(REALTIMEOFDAY - activation_time >= timer_duration) timer_end() // open doors, reset timer, clear status screen update_icon() @@ -80,14 +76,13 @@ ..() update_icon() - // open/closedoor checks if door_timer has power, if so it checks if the // linked door is open/closed (by density) then opens it/closes it. /obj/machinery/door_timer/proc/timer_start() if(stat & (NOPOWER|BROKEN)) return 0 - activation_time = world.realtime + activation_time = REALTIMEOFDAY timing = TRUE for(var/obj/machinery/door/window/brigdoor/door in targets) @@ -104,7 +99,6 @@ C.update_icon() return 1 - /obj/machinery/door_timer/proc/timer_end(forced = FALSE) if(stat & (NOPOWER|BROKEN)) @@ -136,7 +130,7 @@ /obj/machinery/door_timer/proc/time_left(seconds = FALSE) - . = max(0,timer_duration - (activation_time ? world.realtime - activation_time : 0)) + . = max(0,timer_duration - (activation_time ? REALTIMEOFDAY - activation_time : 0)) if(seconds) . /= 10 @@ -240,7 +234,7 @@ preset_time = PRESET_LONG . = set_timer(preset_time) if(timing) - activation_time = world.realtime + activation_time = REALTIMEOFDAY else . = FALSE diff --git a/code/game/machinery/harvester.dm b/code/game/machinery/harvester.dm index 40430b37b7..8275e981de 100644 --- a/code/game/machinery/harvester.dm +++ b/code/game/machinery/harvester.dm @@ -71,7 +71,7 @@ say("Subject may not have abiotic items on.") playsound(src, 'sound/machines/buzz-sigh.ogg', 30, 1) return - if(!(MOB_ORGANIC in C.mob_biotypes)) + if(!(C.mob_biotypes & MOB_ORGANIC)) say("Subject is not organic.") playsound(src, 'sound/machines/buzz-sigh.ogg', 30, 1) return diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index a27cb9b78c..60085e0bf8 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -348,6 +348,26 @@ spark_system.start() //creates some sparks because they look cool qdel(cover) //deletes the cover - no need on keeping it there! +//turret healing +/obj/machinery/porta_turret/examine(mob/user) + . = ..() + if(obj_integrity < max_integrity) + . += "Use a welder to fix it." + +/obj/machinery/porta_turret/welder_act(mob/living/user, obj/item/I) + . = TRUE + if(obj_integrity < max_integrity) + if(!I.tool_start_check(user, amount=0)) + return + user.visible_message("[user] is welding the turret.", \ + "You begin repairing the turret...", \ + "You hear welding.") + if(I.use_tool(src, user, 40, volume=50)) + obj_integrity = max_integrity + user.visible_message("[user.name] has repaired [src].", \ + "You finish repairing the turret.") + else + to_chat(user, "The turret doesn't need repairing.") /obj/machinery/porta_turret/process() @@ -672,6 +692,7 @@ lethal_projectile_sound = 'sound/weapons/laser.ogg' desc = "An energy blaster auto-turret." + /obj/machinery/porta_turret/syndicate/energy/heavy icon_state = "standard_stun" base_icon_state = "standard" @@ -683,6 +704,11 @@ lethal_projectile_sound = 'sound/weapons/lasercannonfire.ogg' desc = "An energy blaster auto-turret." +/obj/machinery/porta_turret/syndicate/energy/pirate + max_integrity = 260 + integrity_failure = 20 + armor = list("melee" = 50, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90) + /obj/machinery/porta_turret/syndicate/setup() return @@ -839,7 +865,7 @@ /obj/machinery/turretid/examine(mob/user) . = ..() - if(issilicon(user) && (!stat & BROKEN)) + if(hasSiliconAccessInArea(user) && (!stat & BROKEN)) . += "Ctrl-click [src] to [ enabled ? "disable" : "enable"] turrets." . += "Alt-click [src] to set turrets to [ lethal ? "stun" : "kill"]." @@ -854,7 +880,7 @@ to_chat(user, "You link \the [M.buffer] with \the [src]") return - if (issilicon(user)) + if (hasSiliconAccessInArea(user)) return attack_hand(user) if ( get_dist(src, user) == 0 ) // trying to unlock the interface @@ -895,7 +921,7 @@ /obj/machinery/turretid/ui_interact(mob/user) . = ..() if ( get_dist(src, user) > 0 ) - if ( !(issilicon(user) || IsAdminGhost(user)) ) + if ( !(hasSiliconAccessInArea(user) || IsAdminGhost(user)) ) to_chat(user, "You are too far away.") user.unset_machine() user << browse(null, "window=turretid") @@ -903,10 +929,10 @@ var/t = "" - if(locked && !(issilicon(user) || IsAdminGhost(user))) + if(locked && !(hasSiliconAccessInArea(user) || IsAdminGhost(user))) t += "
Swipe ID card to unlock interface
" else - if(!issilicon(user) && !IsAdminGhost(user)) + if(!hasSiliconAccessInArea(user) && !IsAdminGhost(user)) t += "
Swipe ID card to lock interface
" t += "Turrets [enabled?"activated":"deactivated"] - [enabled?"Disable":"Enable"]?
" t += "Currently set for [lethal?"lethal":"stun repeatedly"] - Change to [lethal?"Stun repeatedly":"Lethal"]?
" @@ -920,7 +946,7 @@ if(..()) return if (locked) - if(!(issilicon(usr) || IsAdminGhost(usr))) + if(!(hasSiliconAccessInArea(usr) || IsAdminGhost(usr))) to_chat(usr, "Control panel is locked!") return if (href_list["toggleOn"]) diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm index 16016b8e18..b4288310b0 100644 --- a/code/game/machinery/shieldgen.dm +++ b/code/game/machinery/shieldgen.dm @@ -124,7 +124,7 @@ . = ..() if(.) return - if(locked && !issilicon(user)) + if(locked && !hasSiliconAccessInArea(user)) to_chat(user, "The machine is locked, you are unable to use it!") return if(panel_open) @@ -370,7 +370,7 @@ if(!anchored) to_chat(user, "\The [src] needs to be firmly secured to the floor first!") return - if(locked && !issilicon(user)) + if(locked && !hasSiliconAccessInArea(user)) to_chat(user, "The controls are locked!") return if(!power) diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm index ebc2533124..221e35118e 100644 --- a/code/game/machinery/syndicatebomb.dm +++ b/code/game/machinery/syndicatebomb.dm @@ -79,7 +79,7 @@ try_detonate(TRUE) //Counter terrorists win else if(!active || defused) - if(defused && payload in src) + if(defused && (payload in src)) payload.defuse() countdown.stop() STOP_PROCESSING(SSfastprocess, src) diff --git a/code/game/machinery/telecomms/computers/logbrowser.dm b/code/game/machinery/telecomms/computers/logbrowser.dm index c1db49605c..f2b2c594b7 100644 --- a/code/game/machinery/telecomms/computers/logbrowser.dm +++ b/code/game/machinery/telecomms/computers/logbrowser.dm @@ -196,7 +196,7 @@ var/newnet = stripped_input(usr, "Which network do you want to view?", "Comm Monitor", network) - if(newnet && ((usr in range(1, src)) || issilicon(usr))) + if(newnet && ((usr in range(1, src)) || hasSiliconAccessInArea(usr))) if(length(newnet) > 15) temp = "- FAILED: NETWORK TAG STRING TOO LENGHTLY -" diff --git a/code/game/machinery/telecomms/computers/message.dm b/code/game/machinery/telecomms/computers/message.dm index 884c2bb37d..5e39997872 100644 --- a/code/game/machinery/telecomms/computers/message.dm +++ b/code/game/machinery/telecomms/computers/message.dm @@ -260,7 +260,7 @@ if(..()) return - if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr)) + if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr)) //Authenticate if (href_list["auth"]) if(LINKED_SERVER_NONRESPONSIVE) diff --git a/code/game/machinery/telecomms/computers/telemonitor.dm b/code/game/machinery/telecomms/computers/telemonitor.dm index aebef711a9..23c03514ca 100644 --- a/code/game/machinery/telecomms/computers/telemonitor.dm +++ b/code/game/machinery/telecomms/computers/telemonitor.dm @@ -108,7 +108,7 @@ if(href_list["network"]) var/newnet = stripped_input(usr, "Which network do you want to view?", "Comm Monitor", network) - if(newnet && ((usr in range(1, src)) || issilicon(usr))) + if(newnet && ((usr in range(1, src)) || hasSiliconAccessInArea(usr))) if(length(newnet) > 15) temp = "- FAILED: NETWORK TAG STRING TOO LENGHTLY -" diff --git a/code/game/machinery/telecomms/machine_interactions.dm b/code/game/machinery/telecomms/machine_interactions.dm index 8cd8b479d8..4de8929b6b 100644 --- a/code/game/machinery/telecomms/machine_interactions.dm +++ b/code/game/machinery/telecomms/machine_interactions.dm @@ -30,7 +30,7 @@ /obj/machinery/telecomms/ui_interact(mob/user) . = ..() // You need a multitool to use this, or be silicon - if(!issilicon(user)) + if(!hasSiliconAccessInArea(user)) // istype returns false if the value is null if(!istype(user.get_active_held_item(), /obj/item/multitool)) return @@ -97,7 +97,7 @@ var/obj/item/multitool/P = null // Let's double check - if(!issilicon(user) && istype(user.get_active_held_item(), /obj/item/multitool)) + if(!hasSiliconAccessInArea(user) && istype(user.get_active_held_item(), /obj/item/multitool)) P = user.get_active_held_item() else if(isAI(user)) var/mob/living/silicon/ai/U = user @@ -162,7 +162,7 @@ if(..()) return - if(!issilicon(usr)) + if(!hasSiliconAccessInArea(usr)) if(!istype(usr.get_active_held_item(), /obj/item/multitool)) return @@ -270,6 +270,6 @@ updateUsrDialog() /obj/machinery/telecomms/proc/canAccess(mob/user) - if(issilicon(user) || in_range(user, src)) + if(hasSiliconAccessInArea(user) || in_range(user, src)) return TRUE return FALSE diff --git a/code/game/machinery/telecomms/machines/receiver.dm b/code/game/machinery/telecomms/machines/receiver.dm index 0fd3aec012..4dd3af036c 100644 --- a/code/game/machinery/telecomms/machines/receiver.dm +++ b/code/game/machinery/telecomms/machines/receiver.dm @@ -33,7 +33,7 @@ for(var/obj/machinery/telecomms/hub/H in links) for(var/obj/machinery/telecomms/relay/R in H.links) - if(R.can_receive(signal) && R.z in signal.levels) + if(R.can_receive(signal) && (R.z in signal.levels)) return TRUE return FALSE diff --git a/code/game/machinery/transformer.dm b/code/game/machinery/transformer.dm index 3ff2424d83..4ed2473260 100644 --- a/code/game/machinery/transformer.dm +++ b/code/game/machinery/transformer.dm @@ -27,7 +27,7 @@ /obj/machinery/transformer/examine(mob/user) . = ..() - if(cooldown && (issilicon(user) || isobserver(user))) + if(cooldown && (hasSiliconAccessInArea(user) || isobserver(user))) . += "It will be ready in [DisplayTimeText(cooldown_timer - world.time)]." /obj/machinery/transformer/Destroy() diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index 61ecec40c2..1595c4bb07 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -108,16 +108,17 @@ /obj/item/mecha_parts/mecha_equipment/medical/sleeper/Topic(href,href_list) ..() - var/datum/topic_input/afilter = new /datum/topic_input(href,href_list) - if(afilter.get("eject")) + if(href_list["eject"]) go_out() - if(afilter.get("view_stats")) + if(href_list["view_stats"]) chassis.occupant << browse(get_patient_stats(),"window=msleeper") onclose(chassis.occupant, "msleeper") return - if(afilter.get("inject")) - inject_reagent(afilter.getType("inject", /datum/reagent),afilter.getObj("source")) - return + if(href_list["inject"]) + var/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/SG = locate() in chassis + var/datum/reagent/R = locate(href_list["inject"]) in SG.reagents.reagent_list + if (istype(R)) + inject_reagent(R, SG) /obj/item/mecha_parts/mecha_equipment/medical/sleeper/proc/get_patient_stats() if(!patient) @@ -354,19 +355,18 @@ /obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/Topic(href,href_list) ..() - var/datum/topic_input/afilter = new (href,href_list) - if(afilter.get("toggle_mode")) + if (href_list["toggle_mode"]) mode = !mode update_equip_info() return - if(afilter.get("select_reagents")) + if (href_list["select_reagents"]) processed_reagents.len = 0 var/m = 0 var/message for(var/i=1 to known_reagents.len) if(m>=synth_speed) break - var/reagent = afilter.get("reagent_[i]") + var/reagent = text2path(href_list["reagent_[i]"]) if(reagent && (reagent in known_reagents)) message = "[m ? ", " : null][known_reagents[reagent]]" processed_reagents += reagent @@ -375,20 +375,18 @@ message += " added to production" START_PROCESSING(SSobj, src) occupant_message(message) - occupant_message("Reagent processing started.") + occupant_message("Reagent processing started.") mecha_log_message("Reagent processing started.") return - if(afilter.get("show_reagents")) + if (href_list["show_reagents"]) chassis.occupant << browse(get_reagents_page(),"window=msyringegun") - if(afilter.get("purge_reagent")) - var/reagent = afilter.get("purge_reagent") + if (href_list["purge_reagent"]) + var/reagent = href_list["purge_reagent"] if(reagent) reagents.del_reagent(reagent) return - if(afilter.get("purge_all")) + if (href_list["purge_all"]) reagents.clear_reagents() - return - return /obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/proc/get_reagents_page() var/output = {" diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index a2b36f90b2..f2d907283a 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -317,9 +317,8 @@ /obj/machinery/mecha_part_fabricator/Topic(href, href_list) if(..()) return - var/datum/topic_input/afilter = new /datum/topic_input(href,href_list) if(href_list["part_set"]) - var/tpart_set = afilter.getStr("part_set") + var/tpart_set = href_list["part_set"] if(tpart_set) if(tpart_set=="clear") part_set = null @@ -327,7 +326,7 @@ part_set = tpart_set screen = "parts" if(href_list["part"]) - var/T = afilter.getStr("part") + var/T = href_list["part"] for(var/v in stored_research.researched_designs) var/datum/design/D = SSresearch.techweb_design_by_id(v) if(D.build_type & MECHFAB) @@ -338,7 +337,7 @@ add_to_queue(D) break if(href_list["add_to_queue"]) - var/T = afilter.getStr("add_to_queue") + var/T = href_list["add_to_queue"] for(var/v in stored_research.researched_designs) var/datum/design/D = SSresearch.techweb_design_by_id(v) if(D.build_type & MECHFAB) @@ -347,10 +346,10 @@ break return update_queue_on_page() if(href_list["remove_from_queue"]) - remove_from_queue(afilter.getNum("remove_from_queue")) + remove_from_queue(text2num(href_list["remove_from_queue"])) return update_queue_on_page() if(href_list["partset_to_queue"]) - add_part_set_to_queue(afilter.get("partset_to_queue")) + add_part_set_to_queue(href_list["partset_to_queue"]) return update_queue_on_page() if(href_list["process_queue"]) spawn(0) @@ -364,8 +363,8 @@ if(href_list["screen"]) screen = href_list["screen"] if(href_list["queue_move"] && href_list["index"]) - var/index = afilter.getNum("index") - var/new_index = index + afilter.getNum("queue_move") + var/index = text2num(href_list["index"]) + var/new_index = index + text2num(href_list["queue_move"]) if(isnum(index) && isnum(new_index) && ISINTEGER(index) && ISINTEGER(new_index)) if(ISINRANGE(new_index,1,queue.len)) queue.Swap(index,new_index) @@ -376,7 +375,7 @@ if(href_list["sync"]) sync() if(href_list["part_desc"]) - var/T = afilter.getStr("part_desc") + var/T = href_list["part_desc"] for(var/v in stored_research.researched_designs) var/datum/design/D = SSresearch.techweb_design_by_id(v) if(D.build_type & MECHFAB) diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index b279f90740..6891719f97 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -867,7 +867,7 @@ return /obj/mecha/proc/moved_inside(mob/living/carbon/human/H) - if(H && H.client && H in range(1)) + if(H?.client && (H in range(1))) occupant = H H.forceMove(src) H.update_mouse_pointer() diff --git a/code/game/mecha/mecha_construction_paths.dm b/code/game/mecha/mecha_construction_paths.dm index 071fe18408..de1c035000 100644 --- a/code/game/mecha/mecha_construction_paths.dm +++ b/code/game/mecha/mecha_construction_paths.dm @@ -116,7 +116,7 @@ //9 list( - "key" = /obj/item/stock_parts/cell, + "key" = /obj/item/stock_parts/scanning_module, "action" = ITEM_MOVE_INSIDE, "back_key" = TOOL_SCREWDRIVER, "desc" = "Peripherals control module is secured." @@ -126,10 +126,40 @@ list( "key" = TOOL_SCREWDRIVER, "back_key" = TOOL_CROWBAR, - "desc" = "The power cell is installed." + "desc" = "The scanner module is installed." ), //11 + list( + "key" = /obj/item/stock_parts/capacitor, + "action" = ITEM_MOVE_INSIDE, + "back_key" = TOOL_SCREWDRIVER, + "desc" = "Scanner module is secured." + ), + + //12 + list( + "key" = TOOL_SCREWDRIVER, + "back_key" = TOOL_CROWBAR, + "desc" = "Capacitor is installed." + ), + + //13 + list( + "key" = /obj/item/stock_parts/cell, + "action" = ITEM_MOVE_INSIDE, + "back_key" = TOOL_SCREWDRIVER, + "desc" = "Capacitor is secured." + ), + + //14 + list( + "key" = TOOL_SCREWDRIVER, + "back_key" = TOOL_CROWBAR, + "desc" = "The power cell is installed." + ), + + //15 list( "key" = /obj/item/stack/sheet/metal, "amount" = 5, @@ -137,21 +167,21 @@ "desc" = "The power cell is secured." ), - //12 + //16 list( "key" = TOOL_WRENCH, "back_key" = TOOL_CROWBAR, "desc" = "Internal armor is installed." ), - //13 + //17 list( "key" = TOOL_WELDER, "back_key" = TOOL_WRENCH, "desc" = "Internal armor is wrenched." ), - //14 + //18 list( "key" = /obj/item/stack/sheet/plasteel, "amount" = 5, @@ -159,14 +189,14 @@ "desc" = "Internal armor is welded." ), - //15 + //19 list( "key" = TOOL_WRENCH, "back_key" = TOOL_CROWBAR, "desc" = "External armor is installed." ), - //16 + //20 list( "key" = TOOL_WELDER, "back_key" = TOOL_WRENCH, @@ -222,36 +252,56 @@ else user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") if(10) + if(diff==FORWARD) + user.visible_message("[user] secures the scanner module.", "You secure the scanner module.") + else + user.visible_message("[user] removes the scanner module from [parent].", "You remove the scanner module from [parent].") + if(11) + if(diff==FORWARD) + user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].") + else + user.visible_message("[user] unfastens the scanner module.", "You unfasten the scanner module.") + if(12) + if(diff==FORWARD) + user.visible_message("[user] secures [I].", "You secure [I].") + else + user.visible_message("[user] removes the capacitor from [parent].", "You remove the capacitor from [parent].") + if(13) + if(diff==FORWARD) + user.visible_message("[user] installs [I].", "You install [I].") + else + user.visible_message("[user] unsecures the capacitor from [parent].", "You unsecure the capacitor from [parent].") + if(14) if(diff==FORWARD) user.visible_message("[user] secures the power cell.", "You secure the power cell.") else user.visible_message("[user] pries the power cell from [parent].", "You pry the power cell from [parent].") - if(11) + if(15) if(diff==FORWARD) user.visible_message("[user] installs the internal armor layer to [parent].", "You install the internal armor layer to [parent].") else user.visible_message("[user] unfastens the power cell.", "You unfasten the power cell.") - if(12) + if(16) if(diff==FORWARD) user.visible_message("[user] secures the internal armor layer.", "You secure the internal armor layer.") else user.visible_message("[user] pries internal armor layer from [parent].", "You pry internal armor layer from [parent].") - if(13) + if(17) if(diff==FORWARD) user.visible_message("[user] welds the internal armor layer to [parent].", "You weld the internal armor layer to [parent].") else user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.") - if(14) + if(18) if(diff==FORWARD) user.visible_message("[user] installs the external reinforced armor layer to [parent].", "You install the external reinforced armor layer to [parent].") else user.visible_message("[user] cuts the internal armor layer from [parent].", "You cut the internal armor layer from [parent].") - if(15) + if(19) if(diff==FORWARD) user.visible_message("[user] secures the external armor layer.", "You secure the external reinforced armor layer.") else user.visible_message("[user] pries external armor layer from [parent].", "You pry external armor layer from [parent].") - if(16) + if(20) if(diff==FORWARD) user.visible_message("[user] welds the external armor layer to [parent].", "You weld the external armor layer to [parent].") else @@ -629,7 +679,7 @@ //9 list( - "key" = /obj/item/stock_parts/cell, + "key" = /obj/item/stock_parts/scanning_module, "action" = ITEM_MOVE_INSIDE, "back_key" = TOOL_SCREWDRIVER, "desc" = "Peripherals control module is secured." @@ -639,10 +689,40 @@ list( "key" = TOOL_SCREWDRIVER, "back_key" = TOOL_CROWBAR, - "desc" = "The power cell is installed." + "desc" = "The scanner module is installed." ), //11 + list( + "key" = /obj/item/stock_parts/capacitor, + "action" = ITEM_MOVE_INSIDE, + "back_key" = TOOL_SCREWDRIVER, + "desc" = "The scanner module is secured." + ), + + //12 + list( + "key" = TOOL_SCREWDRIVER, + "back_key" = TOOL_CROWBAR, + "desc" = "The capacitor is installed." + ), + + //13 + list( + "key" = /obj/item/stock_parts/cell, + "action" = ITEM_MOVE_INSIDE, + "back_key" = TOOL_SCREWDRIVER, + "desc" = "The capacitor is secured." + ), + + //14 + list( + "key" = TOOL_SCREWDRIVER, + "back_key" = TOOL_CROWBAR, + "desc" = "The power cell is installed." + ), + + //15 list( "key" = /obj/item/stack/sheet/plasteel, "amount" = 5, @@ -650,21 +730,21 @@ "desc" = "The power cell is secured." ), - //12 + //16 list( "key" = TOOL_WRENCH, "back_key" = TOOL_CROWBAR, "desc" = "Internal armor is installed." ), - //13 + //17 list( "key" = TOOL_WELDER, "back_key" = TOOL_WRENCH, "desc" = "Internal armor is wrenched." ), - //14 + //18 list( "key" = /obj/item/stack/sheet/plasteel, "amount" = 5, @@ -672,7 +752,7 @@ "desc" = "Internal armor is welded." ), - //15 + //19 list( "key" = /obj/item/stack/sheet/plasteel, "amount" = 5, @@ -680,14 +760,14 @@ "desc" = "External armor is being installed." ), - //16 + //20 list( "key" = TOOL_WRENCH, "back_key" = TOOL_CROWBAR, "desc" = "External armor is installed." ), - //17 + //21 list( "key" = TOOL_WELDER, "back_key" = TOOL_WRENCH, @@ -744,41 +824,61 @@ else user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") if(10) + if(diff==FORWARD) + user.visible_message("[user] secures the scanner module.", "You secure the scanner module.") + else + user.visible_message("[user] removes the scanner module from [parent].", "You remove the scanner module from [parent].") + if(12) + if(diff==FORWARD) + user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].") + else + user.visible_message("[user] unfastens the scanner module.", "You unfasten the scanner module.") + if(13) + if(diff==FORWARD) + user.visible_message("[user] secures the capacitor.", "You secure the capacitor.") + else + user.visible_message("[user] removes the capacitor from [parent].", "You remove the capacitor from [parent].") + if(14) + if(diff==FORWARD) + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") + else + user.visible_message("[user] unfastens the capacitor.", "You unfasten the capacitor.") + if(15) if(diff==FORWARD) user.visible_message("[user] secures the power cell.", "You secure the power cell.") else user.visible_message("[user] pries the power cell from [parent].", "You pry the power cell from [parent].") - if(11) + if(16) if(diff==FORWARD) user.visible_message("[user] installs the internal armor layer to [parent].", "You install the internal armor layer to [parent].") else user.visible_message("[user] unfastens the power cell.", "You unfasten the power cell.") - if(12) + if(17) if(diff==FORWARD) user.visible_message("[user] secures the internal armor layer.", "You secure the internal armor layer.") else user.visible_message("[user] pries internal armor layer from [parent].", "You pry internal armor layer from [parent].") - if(13) + if(18) if(diff==FORWARD) user.visible_message("[user] welds the internal armor layer to [parent].", "You weld the internal armor layer to [parent].") else user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.") - if(14) + if(19) if(diff==FORWARD) user.visible_message("[user] starts to install the external armor layer to [parent].", "You install the external armor layer to [parent].") else user.visible_message("[user] cuts the internal armor layer from [parent].", "You cut the internal armor layer from [parent].") - if(15) + if(20) if(diff==FORWARD) user.visible_message("[user] installs the external reinforced armor layer to [parent].", "You install the external reinforced armor layer to [parent].") else user.visible_message("[user] removes the external armor from [parent].", "You remove the external armor from [parent].") - if(16) + if(21) if(diff==FORWARD) user.visible_message("[user] secures the external armor layer.", "You secure the external reinforced armor layer.") else user.visible_message("[user] pries external armor layer from [parent].", "You pry external armor layer from [parent].") - if(17) + if(22) if(diff==FORWARD) user.visible_message("[user] welds the external armor layer to [parent].", "You weld the external armor layer to [parent].") else @@ -796,6 +896,7 @@ /obj/item/mecha_parts/part/honker_head ) + /datum/component/construction/mecha/honker result = /obj/mecha/combat/honker steps = list( @@ -837,41 +938,70 @@ "key" = /obj/item/bikehorn ), + //6 + list( + "key" = /obj/item/stock_parts/scanning_module, + "action" = ITEM_MOVE_INSIDE + ), + //8 + list( + "key" = /obj/item/bikehorn + ), + + //9 + list( + "key" = /obj/item/stock_parts/capacitor, + "action" = ITEM_MOVE_INSIDE + ), + + //10 + list( + "key" = /obj/item/bikehorn + ), + + //11 list( "key" = /obj/item/stock_parts/cell, "action" = ITEM_MOVE_INSIDE ), - //9 + //12 list( "key" = /obj/item/bikehorn ), - //10 + //13 list( "key" = /obj/item/clothing/mask/gas/clown_hat, "action" = ITEM_DELETE ), - //11 + //14 list( "key" = /obj/item/bikehorn ), - //12 + //15 list( "key" = /obj/item/clothing/shoes/clown_shoes, "action" = ITEM_DELETE ), - //13 + //16 list( "key" = /obj/item/bikehorn ), ) // HONK doesn't have any construction step icons, so we just set an icon once. +/datum/component/construction/mecha/honker/update_parent(step_index) + if(step_index == 1) + var/atom/parent_atom = parent + parent_atom.icon = 'icons/mecha/mech_construct.dmi' + parent_atom.icon_state = "honker_chassis" + ..() +// HONK doesn't have any construction step icons, so we just set an icon once. /datum/component/construction/mecha/honker/update_parent(step_index) if(step_index == 1) var/atom/parent_atom = parent @@ -898,8 +1028,12 @@ if(8) user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") if(10) - user.visible_message("[user] puts [I] on [parent].", "You put [I] on [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") if(12) + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") + if(14) + user.visible_message("[user] puts [I] on [parent].", "You put [I] on [parent].") + if(16) user.visible_message("[user] puts [I] on [parent].", "You put [I] on [parent].") return TRUE @@ -1626,10 +1760,9 @@ "back_key" = TOOL_CROWBAR, "desc" = "Peripherals control module is installed." ), - //9 list( - "key" = /obj/item/stock_parts/cell, + "key" = /obj/item/stock_parts/scanning_module, "action" = ITEM_MOVE_INSIDE, "back_key" = TOOL_SCREWDRIVER, "desc" = "Peripherals control module is secured." @@ -1639,10 +1772,40 @@ list( "key" = TOOL_SCREWDRIVER, "back_key" = TOOL_CROWBAR, - "desc" = "The power cell is installed." + "desc" = "Scanner module is installed." ), //11 + list( + "key" = /obj/item/stock_parts/capacitor, + "action" = ITEM_MOVE_INSIDE, + "back_key" = TOOL_SCREWDRIVER, + "desc" = "Scanner module is secured." + ), + + //12 + list( + "key" = TOOL_SCREWDRIVER, + "back_key" = TOOL_CROWBAR, + "desc" = "Capacitor is installed." + ), + + //13 + list( + "key" = /obj/item/stock_parts/cell, + "action" = ITEM_MOVE_INSIDE, + "back_key" = TOOL_SCREWDRIVER, + "desc" = "Capacitor is secured." + ), + + //11 + list( + "key" = TOOL_SCREWDRIVER, + "back_key" = TOOL_CROWBAR, + "desc" = "The power cell is installed." + ), + + //12 list( "key" = /obj/item/stack/sheet/metal, "amount" = 5, @@ -1650,21 +1813,21 @@ "desc" = "The power cell is secured." ), - //12 + //13 list( "key" = TOOL_WRENCH, "back_key" = TOOL_CROWBAR, "desc" = "Internal armor is installed." ), - //13 + //14 list( "key" = TOOL_WELDER, "back_key" = TOOL_WRENCH, "desc" = "Internal armor is wrenched." ), - //14 + //15 list( "key" = /obj/item/stack/sheet/plasteel, "amount" = 5, @@ -1672,14 +1835,14 @@ "desc" = "Internal armor is welded." ), - //15 + //16 list( "key" = TOOL_WRENCH, "back_key" = TOOL_CROWBAR, "desc" = "External armor is installed." ), - //16 + //17 list( "key" = TOOL_WELDER, "back_key" = TOOL_WRENCH, @@ -1736,36 +1899,56 @@ else user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") if(10) + if(diff==FORWARD) + user.visible_message("[user] secures the scanner module.", "You secure the scanner module.") + else + user.visible_message("[user] removes the scanner module from [parent].", "You remove the scanner module from [parent].") + if(11) + if(diff==FORWARD) + user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].") + else + user.visible_message("[user] unfastens the scanner module.", "You unfasten the scanner module.") + if(12) + if(diff==FORWARD) + user.visible_message("[user] secures the capacitor.", "You secure the capacitor.") + else + user.visible_message("[user] removes the capacitor from [parent].", "You remove the capacitor from [parent].") + if(13) + if(diff==FORWARD) + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") + else + user.visible_message("[user] unfastens the capacitor.", "You unfasten the capacitor.") + if(14) if(diff==FORWARD) user.visible_message("[user] secures the power cell.", "You secure the power cell.") else user.visible_message("[user] pries the power cell from [parent].", "You pry the power cell from [parent].") - if(11) + if(15) if(diff==FORWARD) user.visible_message("[user] installs the internal armor layer to [parent].", "You install the internal armor layer to [parent].") else user.visible_message("[user] unfastens the power cell.", "You unfasten the power cell.") - if(12) + if(16) if(diff==FORWARD) user.visible_message("[user] secures the internal armor layer.", "You secure the internal armor layer.") else user.visible_message("[user] pries internal armor layer from [parent].", "You pry internal armor layer from [parent].") - if(13) + if(17) if(diff==FORWARD) user.visible_message("[user] welds the internal armor layer to [parent].", "You weld the internal armor layer to [parent].") else user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.") - if(14) + if(18) if(diff==FORWARD) user.visible_message("[user] installs the external armor layer to [parent].", "You install the external reinforced armor layer to [parent].") else user.visible_message("[user] cuts the internal armor layer from [parent].", "You cut the internal armor layer from [parent].") - if(15) + if(19) if(diff==FORWARD) user.visible_message("[user] secures the external armor layer.", "You secure the external reinforced armor layer.") else user.visible_message("[user] pries the external armor layer from [parent].", "You pry the external armor layer from [parent].") - if(16) + if(20) if(diff==FORWARD) user.visible_message("[user] welds the external armor layer to [parent].", "You weld the external armor layer to [parent].") else diff --git a/code/game/mecha/mecha_control_console.dm b/code/game/mecha/mecha_control_console.dm index 0188419f0f..61e6c8e5e4 100644 --- a/code/game/mecha/mecha_control_console.dm +++ b/code/game/mecha/mecha_control_console.dm @@ -39,21 +39,24 @@ /obj/machinery/computer/mecha/Topic(href, href_list) if(..()) return - var/datum/topic_input/afilter = new /datum/topic_input(href,href_list) if(href_list["send_message"]) - var/obj/item/mecha_parts/mecha_tracking/MT = afilter.getObj("send_message") + var/obj/item/mecha_parts/mecha_tracking/MT = locate(href_list["send_message"]) + if (!istype(MT)) + return var/message = stripped_input(usr,"Input message","Transmit message") var/obj/mecha/M = MT.in_mecha() if(trim(message) && M) M.occupant_message(message) return if(href_list["shock"]) - var/obj/item/mecha_parts/mecha_tracking/MT = afilter.getObj("shock") - MT.shock() + var/obj/item/mecha_parts/mecha_tracking/MT = locate(href_list["shock"]) + if (istype(MT)) + MT.shock() if(href_list["get_log"]) - var/obj/item/mecha_parts/mecha_tracking/MT = afilter.getObj("get_log") - stored_data = MT.get_mecha_log() - screen = 1 + var/obj/item/mecha_parts/mecha_tracking/MT = locate(href_list["get_log"]) + if(istype(MT)) + stored_data = MT.get_mecha_log() + screen = 1 if(href_list["return"]) screen = 0 updateUsrDialog() diff --git a/code/game/mecha/mecha_topic.dm b/code/game/mecha/mecha_topic.dm index 1e0674d7bb..774e30fa5d 100644 --- a/code/game/mecha/mecha_topic.dm +++ b/code/game/mecha/mecha_topic.dm @@ -221,73 +221,71 @@ if(usr.incapacitated()) return - var/datum/topic_input/afilter = new /datum/topic_input(href,href_list) - if(in_range(src, usr)) + var/obj/item/card/id/id_card + if (href_list["id_card"]) + id_card = locate(href_list["id_card"]) + if (!istype(id_card)) + return if(href_list["req_access"] && add_req_access) - output_access_dialog(afilter.getObj("id_card"),afilter.getMob("user")) + output_access_dialog(id_card, usr) if(href_list["maint_access"] && maint_access) - var/mob/user = afilter.getMob("user") - if(user) - if(state==0) - state = 1 - to_chat(user, "The securing bolts are now exposed.") - else if(state==1) - state = 0 - to_chat(user, "The securing bolts are now hidden.") - output_maintenance_dialog(afilter.getObj("id_card"),user) + if(state==0) + state = 1 + to_chat(usr, "The securing bolts are now exposed.") + else if(state==1) + state = 0 + to_chat(usr, "The securing bolts are now hidden.") + output_maintenance_dialog(id_card, usr) if(href_list["set_internal_tank_valve"] && state >=1) - var/mob/user = afilter.getMob("user") - if(user) - var/new_pressure = input(user,"Input new output pressure","Pressure setting",internal_tank_valve) as num - if(new_pressure) - internal_tank_valve = new_pressure - to_chat(user, "The internal pressure valve has been set to [internal_tank_valve]kPa.") + var/new_pressure = input(usr,"Input new output pressure","Pressure setting",internal_tank_valve) as num + if(new_pressure) + internal_tank_valve = new_pressure + to_chat(usr, "The internal pressure valve has been set to [internal_tank_valve]kPa.") - if(href_list["add_req_access"] && add_req_access && afilter.getObj("id_card")) - operation_req_access += afilter.getNum("add_req_access") - output_access_dialog(afilter.getObj("id_card"),afilter.getMob("user")) + if(href_list["add_req_access"] && add_req_access) + operation_req_access += text2num(href_list["add_req_access"]) + output_access_dialog(id_card, usr) - if(href_list["del_req_access"] && add_req_access && afilter.getObj("id_card")) - operation_req_access -= afilter.getNum("del_req_access") - output_access_dialog(afilter.getObj("id_card"),afilter.getMob("user")) + if(href_list["del_req_access"] && add_req_access) + operation_req_access -= text2num(href_list["add_req_access"]) + output_access_dialog(id_card, usr) if(href_list["finish_req_access"]) add_req_access = 0 - var/mob/user = afilter.getMob("user") - user << browse(null,"window=exosuit_add_access") + usr << browse(null,"window=exosuit_add_access") if(usr != occupant) return if(href_list["update_content"]) - send_byjax(src.occupant,"exosuit.browser","content",src.get_stats_part()) + send_byjax(usr,"exosuit.browser","content",src.get_stats_part()) if(href_list["select_equip"]) - var/obj/item/mecha_parts/mecha_equipment/equip = afilter.getObj("select_equip") + var/obj/item/mecha_parts/mecha_equipment/equip = locate(href_list["select_equip"]) in src if(equip && equip.selectable) - src.selected = equip - src.occupant_message("You switch to [equip]") - src.visible_message("[src] raises [equip]") - send_byjax(src.occupant,"exosuit.browser","eq_list",src.get_equipment_list()) + selected = equip + occupant_message("You switch to [equip]") + visible_message("[src] raises [equip]") + send_byjax(usr, "exosuit.browser","eq_list", get_equipment_list()) if(href_list["rmictoggle"]) radio.broadcasting = !radio.broadcasting - send_byjax(src.occupant,"exosuit.browser","rmicstate",(radio.broadcasting?"Engaged":"Disengaged")) + send_byjax(usr,"exosuit.browser","rmicstate",(radio.broadcasting?"Engaged":"Disengaged")) if(href_list["rspktoggle"]) radio.listening = !radio.listening - send_byjax(src.occupant,"exosuit.browser","rspkstate",(radio.listening?"Engaged":"Disengaged")) + send_byjax(usr,"exosuit.browser","rspkstate",(radio.listening?"Engaged":"Disengaged")) if(href_list["rfreq"]) - var/new_frequency = (radio.frequency + afilter.getNum("rfreq")) + var/new_frequency = (radio.frequency + text2num(href_list["rfreq"])) if (!radio.freerange || (radio.frequency < MIN_FREE_FREQ || radio.frequency > MAX_FREE_FREQ)) new_frequency = sanitize_frequency(new_frequency) radio.set_frequency(new_frequency) - send_byjax(src.occupant,"exosuit.browser","rfreq","[format_frequency(radio.frequency)]") + send_byjax(usr,"exosuit.browser","rfreq","[format_frequency(radio.frequency)]") if (href_list["view_log"]) src.occupant << browse(src.get_log_html(), "window=exosuit_log") @@ -302,14 +300,14 @@ if (href_list["toggle_id_upload"]) add_req_access = !add_req_access - send_byjax(src.occupant,"exosuit.browser","t_id_upload","[add_req_access?"L":"Unl"]ock ID upload panel") + send_byjax(usr,"exosuit.browser","t_id_upload","[add_req_access?"L":"Unl"]ock ID upload panel") if(href_list["toggle_maint_access"]) if(state) occupant_message("Maintenance protocols in effect") return maint_access = !maint_access - send_byjax(src.occupant,"exosuit.browser","t_maint_access","[maint_access?"Forbid":"Permit"] maintenance protocols") + send_byjax(usr,"exosuit.browser","t_maint_access","[maint_access?"Forbid":"Permit"] maintenance protocols") if (href_list["toggle_port_connection"]) if(internal_tank.connected_port) diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm index 41f8984570..845b208db1 100644 --- a/code/game/mecha/working/ripley.dm +++ b/code/game/mecha/working/ripley.dm @@ -146,7 +146,7 @@ ..() if(href_list["drop_from_cargo"]) var/obj/O = locate(href_list["drop_from_cargo"]) - if(O && O in src.cargo) + if(O && (O in cargo)) occupant_message("You unload [O].") O.forceMove(drop_location()) cargo -= O diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index 30e7c8be05..5720d5ce34 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -11,7 +11,7 @@ LAZYINITLIST(blood_DNA) //Kinda needed if (random_icon_states && (icon_state == initial(icon_state)) && length(random_icon_states) > 0) icon_state = pick(random_icon_states) - create_reagents(300) + create_reagents(300, NONE, NO_REAGENTS_VALUE) if(loc && isturf(loc)) for(var/obj/effect/decal/cleanable/C in loc) if(C != src && C.type == type && !QDELETED(C)) diff --git a/code/game/objects/effects/effect_system/effects_foam.dm b/code/game/objects/effects/effect_system/effects_foam.dm index 38a1a6089e..f98b4937ef 100644 --- a/code/game/objects/effects/effect_system/effects_foam.dm +++ b/code/game/objects/effects/effect_system/effects_foam.dm @@ -94,7 +94,7 @@ /obj/effect/particle_effect/foam/Initialize() . = ..() MakeSlippery() - create_reagents(1000) //limited by the size of the reagent holder anyway. + create_reagents(1000, NONE, NO_REAGENTS_VALUE) //limited by the size of the reagent holder anyway. START_PROCESSING(SSfastprocess, src) playsound(src, 'sound/effects/bubbles2.ogg', 80, 1, -3) diff --git a/code/game/objects/effects/effect_system/effects_smoke.dm b/code/game/objects/effects/effect_system/effects_smoke.dm index 40452f68e2..80c0db2b7d 100644 --- a/code/game/objects/effects/effect_system/effects_smoke.dm +++ b/code/game/objects/effects/effect_system/effects_smoke.dm @@ -32,7 +32,7 @@ /obj/effect/particle_effect/smoke/Initialize() . = ..() - create_reagents(500) + create_reagents(500, NONE, NO_REAGENTS_VALUE) START_PROCESSING(SSobj, src) diff --git a/code/game/objects/effects/spawners/structure.dm b/code/game/objects/effects/spawners/structure.dm index a5a4dfb44b..cdf3f3e6b4 100644 --- a/code/game/objects/effects/spawners/structure.dm +++ b/code/game/objects/effects/spawners/structure.dm @@ -163,6 +163,10 @@ again. icon_state = "plastitaniumwindow_spawner" spawn_list = list(/obj/structure/grille, /obj/structure/window/plastitanium) +//plastitanium pirate window + +/obj/effect/spawner/structure/window/plastitanium/pirate + spawn_list = list(/obj/structure/grille, /obj/structure/window/plastitanium/pirate) //ice window diff --git a/code/game/objects/items/RPD.dm b/code/game/objects/items/RPD.dm index 237aca02a9..8b8a02d190 100644 --- a/code/game/objects/items/RPD.dm +++ b/code/game/objects/items/RPD.dm @@ -345,7 +345,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list( A = get_turf(A) var/can_make_pipe = (isturf(A) || is_type_in_typecache(A, make_pipe_whitelist)) - . = FALSE + . = TRUE if((mode & DESTROY_MODE) && istype(A, /obj/item/pipe) || istype(A, /obj/structure/disposalconstruct) || istype(A, /obj/structure/c_transit_tube) || istype(A, /obj/structure/c_transit_tube_pod) || istype(A, /obj/item/pipe_meter)) to_chat(user, "You start destroying a pipe...") diff --git a/code/game/objects/items/airlock_painter.dm b/code/game/objects/items/airlock_painter.dm index e63474dd6f..b7c76cad2d 100644 --- a/code/game/objects/items/airlock_painter.dm +++ b/code/game/objects/items/airlock_painter.dm @@ -67,7 +67,7 @@ L.Remove() // make some colorful reagent, and apply it to the lungs - L.create_reagents(10) + L.create_reagents(10, NONE, NO_REAGENTS_VALUE) L.reagents.add_reagent(/datum/reagent/colorful_reagent, 10) L.reagents.reaction(L, TOUCH, 1) diff --git a/code/game/objects/items/boombox.dm b/code/game/objects/items/boombox.dm index 10d12f1973..3b93480e43 100644 --- a/code/game/objects/items/boombox.dm +++ b/code/game/objects/items/boombox.dm @@ -23,7 +23,7 @@ if(!boomingandboxing) var/list/tracklist = list() for(var/datum/track/S in SSjukeboxes.songs) - if(istype(S) && S.song_associated_id in availabletrackids) + if(istype(S) && (S.song_associated_id in availabletrackids)) tracklist[S.song_name] = S var/selected = input(user, "Play song", "Track:") as null|anything in tracklist if(QDELETED(src) || !selected || !istype(tracklist[selected], /datum/track)) diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index 1bef477a30..4de3e4ff96 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -250,6 +250,7 @@ update_label("John Doe", "Clowny") name = "agent card" access = list(ACCESS_MAINT_TUNNELS, ACCESS_SYNDICATE) var/anyone = FALSE //Can anyone forge the ID or just syndicate? + var/forged = FALSE //have we set a custom name and job assignment, or will we use what we're given when we chameleon change? /obj/item/card/id/syndicate/Initialize() . = ..() @@ -265,26 +266,52 @@ update_label("John Doe", "Clowny") var/obj/item/card/id/I = O src.access |= I.access if(isliving(user) && user.mind) - if(user.mind.special_role) + if(user.mind.special_role || anyone) to_chat(usr, "The card's microscanners activate as you pass it over the ID, copying its access.") /obj/item/card/id/syndicate/attack_self(mob/user) if(isliving(user) && user.mind) - if(user.mind.special_role || anyone) - if(alert(user, "Action", "Agent ID", "Show", "Forge") == "Forge") - var/input_name = reject_bad_name(stripped_input(user, "What name would you like to put on this card?", "Agent card name", registered_name ? registered_name : (ishuman(user) ? user.real_name : user.name), MAX_NAME_LEN), TRUE) - if(!input_name) - return + var/first_use = registered_name ? FALSE : TRUE + if(!(user.mind.special_role || anyone)) //Unless anyone is allowed, only syndies can use the card, to stop metagaming. + if(first_use) //If a non-syndie is the first to forge an unassigned agent ID, then anyone can forge it. + anyone = TRUE + else + return ..() - var/u = stripped_input(user, "What occupation would you like to put on this card?\nNote: This will not grant any access levels other than Maintenance.", "Agent card job assignment", "Assistant", MAX_MESSAGE_LEN) - if(!u) - registered_name = "" - return - assignment = u - update_label() - to_chat(user, "You successfully forge the ID card.") + var/popup_input = alert(user, "Choose Action", "Agent ID", "Show", "Forge/Reset") + if(user.incapacitated()) + return + if(popup_input == "Forge/Reset" && !forged) + var/input_name = stripped_input(user, "What name would you like to put on this card? Leave blank to randomise.", "Agent card name", registered_name ? registered_name : (ishuman(user) ? user.real_name : user.name), MAX_NAME_LEN) + input_name = reject_bad_name(input_name) + if(!input_name) + // Invalid/blank names give a randomly generated one. + if(user.gender == MALE) + input_name = "[pick(GLOB.first_names_male)] [pick(GLOB.last_names)]" + else if(user.gender == FEMALE) + input_name = "[pick(GLOB.first_names_female)] [pick(GLOB.last_names)]" + else + input_name = "[pick(GLOB.first_names)] [pick(GLOB.last_names)]" + + var/target_occupation = stripped_input(user, "What occupation would you like to put on this card?\nNote: This will not grant any access levels other than Maintenance.", "Agent card job assignment", assignment ? assignment : "Assistant", MAX_MESSAGE_LEN) + if(!target_occupation) return - ..() + registered_name = input_name + assignment = target_occupation + update_label() + forged = TRUE + to_chat(user, "You successfully forge the ID card.") + log_game("[key_name(user)] has forged \the [initial(name)] with name \"[registered_name]\" and occupation \"[assignment]\".") + return + else if (popup_input == "Forge/Reset" && forged) + registered_name = initial(registered_name) + assignment = initial(assignment) + log_game("[key_name(user)] has reset \the [initial(name)] named \"[src]\" to default.") + update_label() + forged = FALSE + to_chat(user, "You successfully reset the ID card.") + return + return ..() /obj/item/card/id/syndicate/anyone anyone = TRUE @@ -542,3 +569,14 @@ update_label("John Doe", "Clowny") /obj/item/card/id/knight/captain id_color = "#FFD700" + +/obj/item/card/id/debug + name = "\improper Debug ID" + desc = "A debug ID card. Has ALL the all access, you really shouldn't have this." + icon_state = "ert_janitor" + assignment = "Jannie" + +/obj/item/card/id/debug/Initialize() + access = get_all_accesses()+get_all_centcom_access()+get_all_syndicate_access() + . = ..() + diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index 1186ea8001..cd163e90a4 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -122,7 +122,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM /obj/item/clothing/mask/cigarette/Initialize() . = ..() - create_reagents(chem_volume, INJECTABLE | NO_REACT) // so it doesn't react until you light it + create_reagents(chem_volume, INJECTABLE | NO_REACT, NO_REAGENTS_VALUE) // so it doesn't react until you light it if(list_reagents) reagents.add_reagent_list(list_reagents) if(starts_lit) @@ -717,7 +717,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM /obj/item/clothing/mask/vape/Initialize(mapload, param_color) . = ..() - create_reagents(chem_volume, NO_REACT) // so it doesn't react until you light it + create_reagents(chem_volume, NO_REACT, NO_REAGENTS_VALUE) // so it doesn't react until you light it reagents.add_reagent(/datum/reagent/drug/nicotine, 50) if(!icon_state) if(!param_color) diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm index 2196246b03..df0a4e6cf3 100644 --- a/code/game/objects/items/circuitboards/machine_circuitboards.dm +++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm @@ -35,6 +35,10 @@ /obj/item/stock_parts/manipulator = 1, /obj/item/stack/sheet/glass = 1) +/obj/item/circuitboard/machine/autolathe/secure + name = "Secure Autolathe (Machine Board)" + build_path = /obj/machinery/autolathe/secure + /obj/item/circuitboard/machine/bloodbankgen name = "Blood Bank Generator (Machine Board)" build_path = /obj/machinery/bloodbankgen diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index 81c5083ef7..2e80325d9f 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -96,7 +96,7 @@ charges_left = charges if(!reagents) - create_reagents(charges_left * volume_multiplier) + create_reagents(charges_left * volume_multiplier, NONE, NO_REAGENTS_VALUE) reagents.clear_reagents() var/total_weight = 0 @@ -619,7 +619,7 @@ is_capped = TRUE self_contained = FALSE // Don't disappear when they're empty can_change_colour = TRUE - + reagent_contents = list(/datum/reagent/fuel = 1, /datum/reagent/consumable/ethanol = 1) pre_noise = TRUE diff --git a/code/game/objects/items/debug_items.dm b/code/game/objects/items/debug_items.dm new file mode 100644 index 0000000000..c7aaab6a26 --- /dev/null +++ b/code/game/objects/items/debug_items.dm @@ -0,0 +1,102 @@ +/* This file contains standalone items for debug purposes. */ + +/obj/item/debug/human_spawner + name = "human spawner" + desc = "Spawn a human by aiming at a turf and clicking. Use in hand to change type." + icon = 'icons/obj/guns/magic.dmi' + icon_state = "nothingwand" + item_state = "wand" + lefthand_file = 'icons/mob/inhands/items_lefthand.dmi' + righthand_file = 'icons/mob/inhands/items_righthand.dmi' + w_class = WEIGHT_CLASS_SMALL + var/datum/species/selected_species + var/valid_species = list() + +/obj/item/debug/human_spawner/afterattack(atom/target, mob/user, proximity) + ..() + if(isturf(target)) + var/mob/living/carbon/human/H = new /mob/living/carbon/human(target) + if(selected_species) + H.set_species(selected_species) + +/obj/item/debug/human_spawner/attack_self(mob/user) + ..() + var/choice = input("Select a species", "Human Spawner", null) in GLOB.species_list + selected_species = GLOB.species_list[choice] + +/* Revive this once we purge all the istype checks for tools for tool_behaviour +/obj/item/debug/omnitool + name = "omnitool" + desc = "The original hypertool, born before them all. Use it in hand to unleash it's true power." + icon = 'icons/obj/device.dmi' + icon_state = "hypertool" + item_state = "hypertool" + toolspeed = 0.1 + tool_behaviour = null + +/obj/item/debug/omnitool/examine() + . = ..() + . += " The mode is: [tool_behaviour]" + +/obj/item/debug/omnitool/proc/check_menu(mob/user) + if(!istype(user)) + return FALSE + if(user.incapacitated() || !user.Adjacent(src)) + return FALSE + return TRUE + +/obj/item/debug/omnitool/attack_self(mob/user) + if(!user) + return + var/list/tool_list = list( + "Crowbar" = image(icon = 'icons/obj/tools.dmi', icon_state = "crowbar"), + "Multitool" = image(icon = 'icons/obj/device.dmi', icon_state = "multitool"), + "Screwdriver" = image(icon = 'icons/obj/tools.dmi', icon_state = "screwdriver_map"), + "Wirecutters" = image(icon = 'icons/obj/tools.dmi', icon_state = "cutters_map"), + "Wrench" = image(icon = 'icons/obj/tools.dmi', icon_state = "wrench"), + "Welding Tool" = image(icon = 'icons/obj/tools.dmi', icon_state = "miniwelder"), + "Analyzer" = image(icon = 'icons/obj/device.dmi', icon_state = "analyzer"), + "Mining Tool" = image(icon = 'icons/obj/mining.dmi', icon_state = "minipick"), + "Shovel" = image(icon = 'icons/obj/mining.dmi', icon_state = "spade"), + "Retractor" = image(icon = 'icons/obj/surgery.dmi', icon_state = "retractor"), + "Hemostat" = image(icon = 'icons/obj/surgery.dmi', icon_state = "hemostat"), + "Cautery" = image(icon = 'icons/obj/surgery.dmi', icon_state = "cautery"), + "Drill" = image(icon = 'icons/obj/surgery.dmi', icon_state = "drill"), + "Scalpel" = image(icon = 'icons/obj/surgery.dmi', icon_state = "scalpel"), + "Saw" = image(icon = 'icons/obj/surgery.dmi', icon_state = "saw") + ) + var/tool_result = show_radial_menu(user, src, tool_list, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE, tooltips = TRUE) + if(!check_menu(user)) + return + switch(tool_result) + if("Crowbar") + tool_behaviour = TOOL_CROWBAR + if("Multitool") + tool_behaviour = TOOL_MULTITOOL + if("Screwdriver") + tool_behaviour = TOOL_SCREWDRIVER + if("Wirecutters") + tool_behaviour = TOOL_WIRECUTTER + if("Wrench") + tool_behaviour = TOOL_WRENCH + if("Welding Tool") + tool_behaviour = TOOL_WELDER + if("Analyzer") + tool_behaviour = TOOL_ANALYZER + if("Mining Tool") + tool_behaviour = TOOL_MINING + if("Shovel") + tool_behaviour = TOOL_SHOVEL + if("Retractor") + tool_behaviour = TOOL_RETRACTOR + if("Hemostat") + tool_behaviour = TOOL_HEMOSTAT + if("Cautery") + tool_behaviour = TOOL_CAUTERY + if("Drill") + tool_behaviour = TOOL_DRILL + if("Scalpel") + tool_behaviour = TOOL_SCALPEL + if("Saw") + tool_behaviour = TOOL_SAW +*/ diff --git a/code/game/objects/items/dehy_carp.dm b/code/game/objects/items/dehy_carp.dm index 55d1a2c78a..03ff354ffb 100644 --- a/code/game/objects/items/dehy_carp.dm +++ b/code/game/objects/items/dehy_carp.dm @@ -8,6 +8,7 @@ var/mob/owner = null //Carp doesn't attack owner, set when using in hand var/owned = 0 //Boolean, no owner to begin with var/mobtype = /mob/living/simple_animal/hostile/carp //So admins can change what mob spawns via var fuckery + can_random_spawn = FALSE //Attack self /obj/item/toy/plush/carpplushie/dehy_carp/attack_self(mob/user) diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 6bac77258d..fe8f3ca626 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -721,7 +721,7 @@ GLOBAL_LIST_EMPTY(PDAs) return /obj/item/pda/proc/remove_id(mob/user) - if(issilicon(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) + if(hasSiliconAccessInArea(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) return do_remove_id(user) @@ -916,7 +916,7 @@ GLOBAL_LIST_EMPTY(PDAs) remove_pen() /obj/item/pda/proc/toggle_light() - if(issilicon(usr) || !usr.canUseTopic(src, BE_CLOSE)) + if(hasSiliconAccessInArea(usr) || !usr.canUseTopic(src, BE_CLOSE)) return if(fon) fon = FALSE @@ -928,7 +928,7 @@ GLOBAL_LIST_EMPTY(PDAs) /obj/item/pda/proc/remove_pen() - if(issilicon(usr) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) + if(hasSiliconAccessInArea(usr) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) return if(inserted_item) diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm index 4f4a6fc4e8..1006fe9146 100644 --- a/code/game/objects/items/devices/PDA/cart.dm +++ b/code/game/objects/items/devices/PDA/cart.dm @@ -563,22 +563,22 @@ Code: if (53) // Newscaster menu = "

[PDAIMG(notes)] Newscaster Access

" menu += "
Current Newsfeed: [current_channel ? current_channel : "None"]
" - var/datum/newscaster/feed_channel/current - for(var/datum/newscaster/feed_channel/chan in GLOB.news_network.network_channels) + var/datum/news/feed_channel/current + for(var/datum/news/feed_channel/chan in GLOB.news_network.network_channels) if (chan.channel_name == current_channel) current = chan if(!current) menu += "
ERROR : NO CHANNEL FOUND
" return var/i = 1 - for(var/datum/newscaster/feed_message/msg in current.messages) + for(var/datum/news/feed_message/msg in current.messages) menu +="-[msg.returnBody(-1)]
\[Story by [msg.returnAuthor(-1)]\]
" menu +="[msg.comments.len] comment[msg.comments.len > 1 ? "s" : ""]
" if(msg.img) user << browse_rsc(msg.img, "tmp_photo[i].png") menu +="
" i++ - for(var/datum/newscaster/feed_comment/comment in msg.comments) + for(var/datum/news/feed_comment/comment in msg.comments) menu +="[comment.body]
[comment.author] [comment.time_stamp]
" menu += "
Post Message" @@ -609,7 +609,7 @@ Code: /obj/item/cartridge/Topic(href, href_list) ..() - if(!usr.canUseTopic(src, !issilicon(usr))) + if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr))) usr.unset_machine() usr << browse(null, "window=pda") return @@ -682,8 +682,8 @@ Code: if("Newscaster Message") var/host_pda_owner_name = host_pda.id ? "[host_pda.id.registered_name] ([host_pda.id.assignment])" : "Unknown" var/message = host_pda.msg_input() - var/datum/newscaster/feed_channel/current - for(var/datum/newscaster/feed_channel/chan in GLOB.news_network.network_channels) + var/datum/news/feed_channel/current + for(var/datum/news/feed_channel/chan in GLOB.news_network.network_channels) if (chan.channel_name == current_channel) current = chan if(current.locked && current.author != host_pda_owner_name) diff --git a/code/game/objects/items/devices/compressionkit.dm b/code/game/objects/items/devices/compressionkit.dm index eebe4dc69b..9c7e8ce185 100644 --- a/code/game/objects/items/devices/compressionkit.dm +++ b/code/game/objects/items/devices/compressionkit.dm @@ -89,25 +89,6 @@ else to_chat(user, "Anomalous error. Summon a coder.") - else if(ishuman(target) && user.zone_selected == BODY_ZONE_PRECISE_GROIN) - var/mob/living/carbon/human/H = target - var/obj/item/organ/genital/penis/P = H.getorganslot(ORGAN_SLOT_PENIS) - if(!P) - return - playsound(get_turf(src), 'sound/weapons/flash.ogg', 50, 1) - H.visible_message("[user] is preparing to shrink [H]\'s [P.name] with their bluespace compression kit!") - if(do_mob(user, H, 40) && charges > 0 && P.length > 0) - H.visible_message("[user] has shrunk [H]\'s [P.name]!") - playsound(get_turf(src), 'sound/weapons/emitter2.ogg', 50, 1) - sparks() - flash_lighting_fx(3, 3, LIGHT_COLOR_CYAN) - charges -= 1 - var/p_name = P.name - P.modify_size(-5) - if(QDELETED(P)) - H.visible_message("[H]\'s [p_name] vanishes!") - - /obj/item/compressionkit/attackby(obj/item/I, mob/user, params) ..() if(istype(I, /obj/item/stack/ore/bluespace_crystal)) @@ -117,4 +98,4 @@ if(B.amount > 1) B.amount -= 1 else - qdel(I) \ No newline at end of file + qdel(I) diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index a82f99064e..e43aa681ce 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -51,7 +51,7 @@ /obj/item/flashlight/attack(mob/living/carbon/M, mob/living/carbon/human/user) add_fingerprint(user) - if(istype(M) && on && user.zone_selected in list(BODY_ZONE_PRECISE_EYES, BODY_ZONE_PRECISE_MOUTH)) + if(istype(M) && on && (user.zone_selected in list(BODY_ZONE_PRECISE_EYES, BODY_ZONE_PRECISE_MOUTH))) if((HAS_TRAIT(user, TRAIT_CLUMSY) || HAS_TRAIT(user, TRAIT_DUMB)) && prob(50)) //too dumb to use flashlight properly return ..() //just hit them in the head @@ -390,7 +390,7 @@ return TRUE /obj/item/flashlight/emp/attack(mob/living/M, mob/living/user) - if(on && user.zone_selected in list(BODY_ZONE_PRECISE_EYES, BODY_ZONE_PRECISE_MOUTH)) // call original attack when examining organs + if(on && (user.zone_selected in list(BODY_ZONE_PRECISE_EYES, BODY_ZONE_PRECISE_MOUTH))) // call original attack when examining organs ..() return diff --git a/code/game/objects/items/devices/geiger_counter.dm b/code/game/objects/items/devices/geiger_counter.dm index ce0e492393..2af449df24 100644 --- a/code/game/objects/items/devices/geiger_counter.dm +++ b/code/game/objects/items/devices/geiger_counter.dm @@ -38,6 +38,7 @@ /obj/item/geiger_counter/Destroy() STOP_PROCESSING(SSobj, src) + QDEL_NULL(soundloop) return ..() /obj/item/geiger_counter/process() diff --git a/code/game/objects/items/grenades/chem_grenade.dm b/code/game/objects/items/grenades/chem_grenade.dm index afdde02e32..acd71c57ac 100644 --- a/code/game/objects/items/grenades/chem_grenade.dm +++ b/code/game/objects/items/grenades/chem_grenade.dm @@ -117,7 +117,7 @@ if(!O.reagents) continue var/reagent_list = pretty_string_from_reagent_list(O.reagents) - user.log_message("removed [O] ([reagent_list]) from [src]") + user.log_message("removed [O] ([reagent_list]) from [src]", LOG_GAME) beakers = list() to_chat(user, "You open the [initial(name)] assembly and remove the payload.") return // First use of the wrench remove beakers, then use the wrench to remove the activation mechanism. diff --git a/code/game/objects/items/implants/implant_hijack.dm b/code/game/objects/items/implants/implant_hijack.dm new file mode 100644 index 0000000000..8a08232859 --- /dev/null +++ b/code/game/objects/items/implants/implant_hijack.dm @@ -0,0 +1,121 @@ +#define HIJACK_APC_MAX_AMOUNT 5 + +/obj/item/implant/hijack + name = "hijack implant" + desc = "Allows you to control the machinery in a room by hacking into the APC." + actions_types = list(/datum/action/item_action/hands_free/activate, /datum/action/item_action/removeAPCs, /datum/action/item_action/accessAPCs, /datum/action/item_action/stealthmodetoggle) + activated = 1 + var/toggled = FALSE + icon_state = "hijack" + var/eye_color + var/stealthmode = FALSE + var/stealthcooldown = 0 + var/hijacking = FALSE + +/obj/item/implant/hijack/activate() + . = ..() + toggled = !toggled + imp_in.click_intercept = toggled ? src : null + imp_in.siliconaccesstoggle = toggled ? TRUE : FALSE + to_chat(imp_in,"You turn [toggled ? "on" : "off"] [src]'s silicon interactions.") + toggle_eyes() + +/obj/item/implant/hijack/proc/toggle_eyes() + if (!ishuman(imp_in)) + return + var/on = toggled && !stealthmode + var/mob/living/carbon/human/H = imp_in + H.eye_color = on ? "ff0" : eye_color + H.dna.update_ui_block(DNA_EYE_COLOR_BLOCK) + H.update_body() + +/obj/item/implant/hijack/implant(mob/living/target, mob/user, silent = FALSE) + if(..()) + ADD_TRAIT(target, TRAIT_HIJACKER, "implant") + if (ishuman(target)) + var/mob/living/carbon/human/H = target + eye_color = H.eye_color + return TRUE + +/obj/item/implant/hijack/removed(mob/target, silent = FALSE, special = 0) + if(..()) + REMOVE_TRAIT(target, TRAIT_HIJACKER, "implant") + for (var/area/area in imp_in.siliconaccessareas) + imp_in.toggleSiliconAccessArea(area) + var/obj/machinery/power/apc/apc = area.get_apc() + if (apc) + apc.hijacker = null + apc.set_hijacked_lighting() + apc.update_icon() + if (ishuman(target)) + var/mob/living/carbon/human/H = target + H.eye_color = eye_color + return TRUE + +/obj/item/implant/hijack/proc/InterceptClickOn(mob/living/user,params,atom/object) + if (isitem(object) || !toggled || user.incapacitated()) + return + if (stealthmode == FALSE && istype(object,/obj/machinery/power/apc) && !user.CanReach(object)) + if (hijack_remotely(object)) + return + if (stealthmode && !user.CanReach(object)) + return + if (!object.hasSiliconAccessInArea(imp_in)) + return + var/list/modifiers = params2list(params) + imp_in.face_atom(object) + if (modifiers["shift"] && modifiers["ctrl"]) + object.AICtrlShiftClick(imp_in) + return TRUE + if (modifiers["shift"]) + object.AIShiftClick(imp_in) + return TRUE + if (modifiers["ctrl"]) + object.AICtrlClick(imp_in) + return TRUE + if (modifiers["alt"]) + object.AIAltClick(imp_in) + return TRUE + if (user.get_active_held_item()) + return + if (user.CanReach(object)) + object.attack_robot(imp_in) + else + object.attack_ai(imp_in) + return TRUE + +/obj/item/implant/hijack/proc/hijack_remotely(obj/machinery/power/apc/apc) + if (apc.hijacker || hijacking) + return FALSE //can't remotely hijack an already hijacked APC + hijacking = TRUE + to_chat(imp_in, "Establishing remote connection with APC.") + if (!do_after(imp_in, 4 SECONDS,target=apc)) + to_chat(imp_in, "Aborting.") + hijacking = FALSE + return TRUE + if (LAZYLEN(imp_in.siliconaccessareas) >= HIJACK_APC_MAX_AMOUNT) + to_chat(src,"You are connected to too many APCs! Too many more will fry your brain.") + hijacking = FALSE + return TRUE + imp_in.light_power = 2 + imp_in.light_range = 2 + imp_in.light_color = COLOR_YELLOW + imp_in.update_light() + imp_in.visible_message("[imp_in] starts glowing a with a hollow yellow light!") + to_chat(imp_in, "Beginning hijack of APC.") + if (do_after(imp_in, 21 SECONDS,target=apc)) + apc.hijacker = imp_in + stealthmode = FALSE + apc.set_hijacked_lighting() + imp_in.toggleSiliconAccessArea(apc.area) + apc.update_icon() + stealthcooldown = world.time + 1 MINUTES + 30 SECONDS + toggle_eyes() + else + to_chat(imp_in, "Aborting.") + hijacking = FALSE + imp_in.light_power = 0 + imp_in.light_range = 0 + imp_in.light_color = COLOR_YELLOW + imp_in.update_light() + return TRUE \ No newline at end of file diff --git a/code/game/objects/items/implants/implanter.dm b/code/game/objects/items/implants/implanter.dm index ab902369cc..a0e27f14f0 100644 --- a/code/game/objects/items/implants/implanter.dm +++ b/code/game/objects/items/implants/implanter.dm @@ -74,4 +74,8 @@ /obj/item/implanter/stealth name = "implanter (stealth)" - imp_type = /obj/item/implant/stealth \ No newline at end of file + imp_type = /obj/item/implant/stealth + +/obj/item/implanter/hijack + name = "implanter (hijack)" + imp_type = /obj/item/implant/hijack \ No newline at end of file diff --git a/code/game/objects/items/mop.dm b/code/game/objects/items/mop.dm index a8b28f2544..233eabd4ca 100644 --- a/code/game/objects/items/mop.dm +++ b/code/game/objects/items/mop.dm @@ -21,7 +21,7 @@ /obj/item/mop/New() ..() - create_reagents(mopcap) + create_reagents(mopcap, NONE, NO_REAGENTS_VALUE) /obj/item/mop/proc/clean(turf/A) diff --git a/code/game/objects/items/pinpointer.dm b/code/game/objects/items/pinpointer.dm index c4ad324a2c..151df7694a 100644 --- a/code/game/objects/items/pinpointer.dm +++ b/code/game/objects/items/pinpointer.dm @@ -26,6 +26,7 @@ /obj/item/pinpointer/Destroy() STOP_PROCESSING(SSfastprocess, src) GLOB.pinpointer_list -= src + target = null return ..() /obj/item/pinpointer/attack_self(mob/living/user) @@ -57,7 +58,7 @@ return var/turf/here = get_turf(src) var/turf/there = get_turf(target) - if(here.z != there.z) + if(!here || !there || here.z != there.z) add_overlay("pinon[alert ? "alert" : ""]null") return if(get_dist_euclidian(here,there) <= minimum_range) @@ -143,3 +144,34 @@ target = null if(!target) //target can be set to null from above code, or elsewhere active = FALSE + +/obj/item/pinpointer/pair + name = "pair pinpointer" + desc = "A handheld tracking device that locks onto its other half of the matching pair." + var/other_pair + +/obj/item/pinpointer/pair/Destroy() + other_pair = null + . = ..() + +/obj/item/pinpointer/pair/scan_for_target() + target = other_pair + +/obj/item/pinpointer/pair/examine(mob/user) + . = ..() + if(!active || !target) + return + var/mob/mob_holder = get(target, /mob) + if(istype(mob_holder)) + to_chat(user, "Its pair is being held by [mob_holder].") + return + +/obj/item/storage/box/pinpointer_pairs + name = "pinpointer pair box" + +/obj/item/storage/box/pinpointer_pairs/PopulateContents() + var/obj/item/pinpointer/pair/A = new(src) + var/obj/item/pinpointer/pair/B = new(src) + + A.other_pair = B + B.other_pair = A diff --git a/code/game/objects/items/plushes.dm b/code/game/objects/items/plushes.dm index 705dcad6c6..a2a8cb3150 100644 --- a/code/game/objects/items/plushes.dm +++ b/code/game/objects/items/plushes.dm @@ -31,7 +31,16 @@ var/normal_desc //--end of love :'(-- -/obj/item/toy/plush/Initialize() + var/snowflake_id //if we set from a config snowflake plushie. + var/can_random_spawn = TRUE //if this is FALSE, don't spawn this for random plushies. + +/obj/item/toy/plush/random_snowflake/Initialize(mapload, set_snowflake_id) + . = ..() + var/list/configlist = CONFIG_GET(keyed_list/snowflake_plushies) + var/id = pick(configlist) + set_snowflake_from_config(id) + +/obj/item/toy/plush/Initialize(mapload, set_snowflake_id) . = ..() AddComponent(/datum/component/squeak, squeak_override) @@ -50,6 +59,9 @@ normal_desc = desc + if(set_snowflake_id) + set_snowflake_from_config(set_snowflake_id) + /obj/item/toy/plush/Destroy() QDEL_NULL(grenade) @@ -97,6 +109,44 @@ return ..() +/obj/item/toy/plush/proc/set_snowflake_from_config(id) + var/list/configlist = CONFIG_GET(keyed_list/snowflake_plushies) + var/list/jsonlist = configlist[id] + ASSERT(jsonlist) + jsonlist = json_decode(jsonlist) + if(jsonlist["inherit_from"]) + var/path = text2path(jsonlist["inherit_from"]) + if(!ispath(path, /obj/item/toy/plush)) + stack_trace("Invalid path for inheritance") + else + var/obj/item/toy/plush/P = new path //can't initial() lists + name = P.name + desc = P.desc + icon_state = P.icon_state + item_state = P.item_state + icon = P.icon + squeak_override = P.squeak_override + attack_verb = P.attack_verb + gender = P.gender + qdel(P) + if(jsonlist["name"]) + name = jsonlist["name"] + if(jsonlist["desc"]) + desc = jsonlist["desc"] + if(jsonlist["gender"]) + gender = jsonlist["gender"] + if(jsonlist["icon_state"]) + icon_state = jsonlist["icon_state"] + item_state = jsonlist["item_state"] + icon = 'config/plushies/sprites.dmi' + if(jsonlist["attack_verb"]) + attack_verb = jsonlist["attack_verb"] + if(jsonlist["squeak_override"]) + squeak_override = jsonlist["squeak_override"] + if(squeak_override) + var/datum/component/squeak/S = GetComponent(/datum/component/squeak) + S?.override_squeak_sounds = squeak_override + /obj/item/toy/plush/handle_atom_del(atom/A) if(A == grenade) grenade = null @@ -367,13 +417,22 @@ if(mood_message) desc += mood_message +GLOBAL_LIST_INIT(valid_plushie_paths, valid_plushie_paths()) +/proc/valid_plushie_paths() + . = list() + for(var/i in subtypesof(/obj/item/toy/plush)) + var/obj/item/toy/plush/abstract = i + if(!initial(abstract.can_random_spawn)) + continue + . += i + /obj/item/toy/plush/random name = "Illegal plushie" desc = "Something fucked up" - var/blacklisted_plushes = list(/obj/item/toy/plush/carpplushie/dehy_carp, /obj/item/toy/plush/awakenedplushie, /obj/item/toy/plush/random) + can_random_spawn = FALSE /obj/item/toy/plush/random/Initialize() - var/newtype = pick(subtypesof(/obj/item/toy/plush) - typecacheof(blacklisted_plushes)) + var/newtype = prob(CONFIG_GET(number/snowflake_plushie_prob))? /obj/item/toy/plush/random_snowflake : pick(GLOB.valid_plushie_paths) new newtype(loc) return INITIALIZE_HINT_QDEL @@ -504,115 +563,12 @@ attack_verb = list("clawed", "hissed", "tail slapped") squeak_override = list('sound/weapons/slash.ogg' = 1) -/obj/item/toy/plush/lizardplushie/durgit - icon_state = "durgit" - item_state = "durgit" - squeak_override = list('modular_citadel/sound/voice/weh.ogg' = 1) //Durgit's the origin of the sound - -/obj/item/toy/plush/lizardplushie/rio - icon_state = "rio" - item_state = "rio" - -/obj/item/toy/plush/lizardplushie/dan - icon_state = "dan" - item_state = "dan" - -/obj/item/toy/plush/lizardplushie/urinsu - icon_state = "urinsu" - item_state = "urinsu" - -/obj/item/toy/plush/lizardplushie/arfrehn - icon_state = "arfrehn" - item_state = "arfrehn" - -/obj/item/toy/plush/lizardplushie/soars - icon_state = "soars" - item_state = "soars" - -/obj/item/toy/plush/lizardplushie/ghostie - icon_state = "ghostie" - item_state = "ghostie" - -/obj/item/toy/plush/lizardplushie/amber - icon_state = "amber" - item_state = "amber" - -/obj/item/toy/plush/lizardplushie/cyan - icon_state = "cyan" - item_state = "cyan" - -/obj/item/toy/plush/lizardplushie/meena - icon_state = "meena" - item_state = "meena" - -/obj/item/toy/plush/lizardplushie/stalks - icon_state = "stalks" - item_state = "stalks" - /obj/item/toy/plush/lizardplushie/kobold + name = "kobold plushie" + desc = "An adorable stuffed toy that resembles a kobold." icon_state = "kobold" item_state = "kobold" -/obj/item/toy/plush/lizardplushie/gorgi - icon_state = "gorgi" - item_state = "gorgi" - -/obj/item/toy/plush/lizardplushie/almaz - icon_state = "almaz" - item_state = "almaz" - squeak_override = list('modular_citadel/sound/voice/raptor_purr.ogg' = 1) - -/obj/item/toy/plush/lizardplushie/garou - icon_state = "garou" - item_state = "garou" - -/obj/item/toy/plush/lizardplushie/augments - icon_state = "augments" - item_state = "augments" - squeak_override = list('modular_citadel/sound/voice/weh.ogg' = 1) //I have no mouth and I must weh - attack_verb = list("hugged", "patted", "snugged", "booped") - -/obj/item/toy/plush/lizardplushie/xekov - icon_state = "xekov" - item_state = "xekov" - -/obj/item/toy/plush/lizardplushie/greg - icon_state = "greg" - item_state = "greg" - -/obj/item/toy/plush/lizardplushie/sin - icon_state = "sin" - item_state = "sin" - desc = "An adorable stuffed toy that resembles a lizardperson.. It faintly smells of sulfur." - -/obj/item/toy/plush/lizardplushie/ends - icon_state = "ends" - item_state = "ends" - -/obj/item/toy/plush/lizardplushie/lyssa - icon_state = "lyssa" - item_state = "lyssa" - -/obj/item/toy/plush/snakeplushie - name = "snake plushie" - desc = "An adorable stuffed toy that resembles a snake. Not to be mistaken for the real thing." - icon_state = "plushie_snake" - item_state = "plushie_snake" - attack_verb = list("bitten", "hissed", "tail slapped") - squeak_override = list('modular_citadel/sound/voice/hiss.ogg' = 1) - -/obj/item/toy/plush/snakeplushie/sasha - icon_state = "sasha" - item_state = "sasha" - -/obj/item/toy/plush/snakeplushie/shay - icon_state = "shay" - item_state = "shay" - -/obj/item/toy/plush/snakeplushie/vulken - icon_state = "vulken" - item_state = "vulken" - /obj/item/toy/plush/nukeplushie name = "operative plushie" desc = "A stuffed toy that resembles a syndicate nuclear operative. The tag claims operatives to be purely fictitious." @@ -630,29 +586,17 @@ squeak_override = list('sound/effects/blobattack.ogg' = 1) gender = FEMALE //given all the jokes and drawings, I'm not sure the xenobiologists would make a slimeboy -/obj/item/toy/plush/slimeplushie/annie - desc = "An adorable stuffed toy that resembles a slimey crewmember." - icon_state = "annie" - item_state = "annie" - -/obj/item/toy/plush/slimeplushie/paxton - desc = "An adorable stuffed toy that resembles a slimey crewmember." - icon_state = "paxton" - item_state = "paxton" - attack_verb = list("CQC'd", "jabroni'd", "powergamed", "robusted", "cakehatted") - gender = MALE - /obj/item/toy/plush/awakenedplushie name = "awakened plushie" desc = "An ancient plushie that has grown enlightened to the true nature of reality." icon_state = "plushie_awake" item_state = "plushie_awake" + can_random_spawn = FALSE /obj/item/toy/plush/awakenedplushie/ComponentInitialize() . = ..() AddComponent(/datum/component/edit_complainer) - /obj/item/toy/plush/beeplushie name = "bee plushie" desc = "A cute toy that resembles an even cuter bee." @@ -668,21 +612,7 @@ icon_state = "bumble" item_state = "bumble" squeak_override = list('modular_citadel/sound/voice/mothsqueak.ogg' = 1) - -/obj/item/toy/plush/mothplushie/nameko - icon_state = "nameko" - item_state = "nameko" - -/obj/item/toy/plush/mothplushie/suru - icon_state = "suru" - item_state = "suru" - -/obj/item/toy/plush/xeno - name = "xenohybrid plushie" - desc = "An adorable stuffed toy that resmembles a xenomorphic crewmember." - icon_state = "seras" - item_state = "seras" - squeak_override = list('sound/voice/hiss2.ogg' = 1) + can_random_spawn = FALSE /obj/item/toy/plush/lampplushie name = "lamp plushie" @@ -736,20 +666,6 @@ icon_state = "scrubpuppy" item_state = "scrubpuppy" -/obj/item/toy/plush/borgplushie/seeking - icon_state = "seeking" - item_state = "seeking" - -/obj/item/toy/plush/borgplushie/neeb - icon_state = "neeb" - item_state = "neeb" - -/obj/item/toy/plush/borgplushie/bhijn - desc = "An adorable stuffed toy of a IPC." - icon_state = "bhijn" - item_state = "bhijn" - attack_verb = list("closed", "reworked", "merged") - /obj/item/toy/plush/aiplush name = "AI plushie" desc = "A little stuffed toy AI core... it appears to be malfunctioning." @@ -758,246 +674,22 @@ attack_verb = list("hacked", "detonated", "overloaded") squeak_override = list('sound/machines/beep.ogg' = 9, 'sound/machines/buzz-two.ogg' = 1) -/obj/item/toy/plush/bird - name = "bird plushie" - desc = "An adorable stuffed plushie that resembles an avian." - icon_state = "sylas" - item_state = "sylas" - attack_verb = list("peeped", "beeped", "poofed") - squeak_override = list('modular_citadel/sound/voice/peep.ogg' = 1) - -/obj/item/toy/plush/bird/esela - icon_state = "esela" - item_state = "esela" - -/obj/item/toy/plush/bird/jahonna - icon_state = "jahonna" - item_state = "jahonna" - -/obj/item/toy/plush/bird/krick - icon_state = "krick" - item_state = "krick" - -/obj/item/toy/plush/bird/birddi - icon_state = "birddi" - item_state = "birddi" - -/obj/item/toy/plush/bird/jewel - icon_state = "jewel" - item_state = "jewel" - -/obj/item/toy/plush/sergal - name = "sergal plushie" - desc = "An adorable stuffed plushie that resembles a sagaru." - icon_state = "faux" - item_state = "faux" - squeak_override = list('modular_citadel/sound/voice/merp.ogg' = 1) - -/obj/item/toy/plush/sergal/gladwyn - icon_state = "gladwyn" - item_state = "gladwyn" - -/obj/item/toy/plush/sergal/jermaine - icon_state = "jermaine" - item_state = "jermaine" - -/obj/item/toy/plush/mammal - name = "mammal plushie" - desc = "An adorable stuffed toy resembling some sort of crew member." - icon_state = "dubious" - item_state = "dubious" - -/obj/item/toy/plush/mammal/gavin - icon_state = "gavin" - item_state = "gavin" - -/obj/item/toy/plush/mammal/blep - icon_state = "blep" - item_state = "blep" - -/obj/item/toy/plush/mammal/circe - desc = "A luxuriously soft toy that resembles a nine-tailed kitsune." - icon_state = "circe" - item_state = "circe" - attack_verb = list("medicated", "tailhugged", "kissed") - -/obj/item/toy/plush/mammal/robin - icon_state = "robin" - item_state = "robin" - -/obj/item/toy/plush/mammal/pavel - icon_state = "pavel" - item_state = "pavel" - -/obj/item/toy/plush/mammal/mason - icon_state = "mason" - item_state = "mason" - -/obj/item/toy/plush/mammal/oten - icon_state = "oten" - item_state = "oten" - -/obj/item/toy/plush/mammal/ray - icon_state = "ray" - item_state = "ray" - -/obj/item/toy/plush/mammal/redtail - icon_state = "redtail" - item_state = "redtail" - -/obj/item/toy/plush/mammal/dawud - icon_state = "dawud" - item_state = "dawud" - -/obj/item/toy/plush/mammal/edgar - icon_state = "edgar" - item_state = "edgar" - attack_verb = list("collared", "tricked", "headpatted") - -/obj/item/toy/plush/mammal/frank - icon_state = "frank" - item_state = "frank" - -/obj/item/toy/plush/mammal/poojawa - icon_state = "poojawa" - item_state = "poojawa" - -/obj/item/toy/plush/mammal/hazel - icon_state = "hazel" - item_state = "hazel" - -/obj/item/toy/plush/mammal/joker - icon_state = "joker" - item_state = "joker" - -/obj/item/toy/plush/mammal/gunther - icon_state = "gunther" - item_state = "gunther" - /obj/item/toy/plush/mammal/fox icon_state = "fox" item_state = "fox" -/obj/item/toy/plush/mammal/rae - desc = "An adorable stuffed toy of an artic fox." - icon_state = "rae" - item_state = "rae" +/obj/item/toy/plush/snakeplushie + name = "snake plushie" + desc = "An adorable stuffed toy that resembles a snake. Not to be mistaken for the real thing." + icon_state = "plushie_snake" + item_state = "plushie_snake" + attack_verb = list("bitten", "hissed", "tail slapped") + squeak_override = list('modular_citadel/sound/voice/hiss.ogg' = 1) -/obj/item/toy/plush/mammal/zed - desc = "A masked stuffed toy that resembles a fierce miner. He even comes with his own little crusher!" - icon_state = "zed" - item_state = "zed" - attack_verb = list("ENDED", "CRUSHED", "GNOMED") - -/obj/item/toy/plush/mammal/justin - icon_state = "justin" - item_state = "justin" - attack_verb = list("buttslapped", "fixed") - -/obj/item/toy/plush/mammal/reece - icon_state = "reece" - item_state = "reece" - attack_verb = list("healed", "cured", "demoted") - -/obj/item/toy/plush/mammal/redwood - desc = "An adorable stuffed toy resembling a Nanotrasen Captain. That just happens to be a bunny." - icon_state = "redwood" - item_state = "redwood" - attack_verb = list("ordered", "bapped", "reprimanded") - -/obj/item/toy/plush/mammal/marisol - desc = "An adorable stuffed toy resembling a demi-wolf security officer." - icon_state = "marisol" - item_state = "marisol" - attack_verb = list("arrested", "harmbattoned", "lasered") - -/obj/item/toy/plush/mammal/minty - desc = "An adorable stuffed toy resembling some sort of crew member. It smells like mint.." - icon_state = "minty" - item_state = "minty" - attack_verb = list("freshened", "brushed") - -/obj/item/toy/plush/mammal/dog - desc = "An adorable stuffed toy that resembles a canine." - icon_state = "katlin" - item_state = "katlin" - attack_verb = list("barked", "boofed", "borked") - squeak_override = list( - 'modular_citadel/sound/voice/bark1.ogg' = 1, - 'modular_citadel/sound/voice/bark2.ogg' = 1 - ) - -/obj/item/toy/plush/mammal/dog/frost - icon_state = "frost" - item_state = "frost" - -/obj/item/toy/plush/mammal/dog/atticus - icon_state = "atticus" - item_state = "atticus" - -/obj/item/toy/plush/mammal/dog/fletch - icon_state = "fletch" - item_state = "fletch" - -/obj/item/toy/plush/mammal/dog/vincent - icon_state = "vincent" - item_state = "vincent" - -/obj/item/toy/plush/mammal/dog/zigfried - desc = "An adorable stuffed toy of a very good boy." - icon_state = "zigfried" - item_state = "zigfried" - -/obj/item/toy/plush/mammal/dog/nikolai - icon_state = "nikolai" - item_state = "nikolai" - -/obj/item/toy/plush/mammal/dog/flynn - icon_state = "flynn" - item_state = "flynn" - -/obj/item/toy/plush/mammal/dog/fritz - icon_state = "fritz" - item_state = "fritz" - attack_verb = list("barked", "boofed", "shotgun'd") - obj_flags = UNIQUE_RENAME - unique_reskin = list("Goodboye" = "fritz", "Badboye" = "fritz_bad") - -/obj/item/toy/plush/mammal/dog/jesse - desc = "An adorable wolf toy that resembles a cream-colored wolf. He has a little pride flag!" - icon_state = "jesse" - item_state = "jesse" - attack_verb = list("greeted", "merc'd", "howdy'd") - -/obj/item/toy/plush/catgirl - name = "feline plushie" - desc = "An adorable stuffed toy that resembles a feline." - icon_state = "bailey" - item_state = "bailey" - attack_verb = list("headbutt", "scritched", "bit") - squeak_override = list('modular_citadel/sound/voice/nya.ogg' = 1) - -/obj/item/toy/plush/catgirl/mikeel - desc = "An adorable stuffed toy of some tauric cat person." - icon_state = "mikeel" - item_state = "mikeel" - -/obj/item/toy/plush/catgirl/skylar - desc = "An adorable stuffed toy that resembles a degenerate." - icon_state = "skylar2" - item_state = "skylar2" - attack_verb = list("powergamed", "merged", "tabled") - squeak_override = list('sound/effects/meow1.ogg' = 1) - -/obj/item/toy/plush/catgirl/drew - icon_state = "drew" - item_state = "drew" - -/obj/item/toy/plush/catgirl/trilby - desc = "A masked stuffed toy that resembles a feline scientist." - icon_state = "trilby" - item_state = "trilby" - attack_verb = list("PR'd", "coded", "remembered") +/obj/item/toy/plush/mammal + name = "mammal plushie" + desc = "An adorable stuffed toy resembling some sort of crew member." + can_random_spawn = FALSE /obj/item/toy/plush/catgirl/fermis name = "medcat plushie" @@ -1007,20 +699,36 @@ attack_verb = list("cuddled", "petpatted", "wigglepurred") squeak_override = list('modular_citadel/sound/voice/merowr.ogg' = 1) -/obj/item/toy/plush/catgirl/mariaf - desc = "An adorable stuffed toy that resembles a very tall cat girl." - icon_state = "mariaf" - item_state = "mariaf" - attack_verb = list("hugged", "stabbed", "licked") +/obj/item/toy/plush/xeno + name = "xenohybrid plushie" + desc = "An adorable stuffed toy that resmembles a xenomorphic crewmember." + squeak_override = list('sound/voice/hiss2.ogg' = 1) + can_random_spawn = FALSE -/obj/item/toy/plush/catgirl/maya - desc = "An adorable stuffed toy that resembles an angry cat girl. She has her own tiny nuke disk!" - icon_state = "maya" - item_state = "maya" - attack_verb = list("nuked", "arrested", "harmbatonned") +/obj/item/toy/plush/bird + name = "bird plushie" + desc = "An adorable stuffed plushie that resembles an avian." + attack_verb = list("peeped", "beeped", "poofed") + squeak_override = list('modular_citadel/sound/voice/peep.ogg' = 1) + can_random_spawn = FALSE -/obj/item/toy/plush/catgirl/marisa - desc = "An adorable stuffed toy that resembles a crew member, or maybe a witch. Having it makes you feel you can win." - icon_state = "marisa" - item_state = "marisa" - attack_verb = list("blasted", "sparked", "dazzled") +/obj/item/toy/plush/sergal + name = "sergal plushie" + desc = "An adorable stuffed plushie that resembles a sagaru." + squeak_override = list('modular_citadel/sound/voice/merp.ogg' = 1) + can_random_spawn = FALSE + +/obj/item/toy/plush/mammal/dog + desc = "An adorable stuffed toy that resembles a canine." + attack_verb = list("barked", "boofed", "borked") + squeak_override = list( + 'modular_citadel/sound/voice/bark1.ogg' = 1, + 'modular_citadel/sound/voice/bark2.ogg' = 1 + ) + +/obj/item/toy/plush/catgirl + name = "feline plushie" + desc = "An adorable stuffed toy that resembles a feline." + attack_verb = list("headbutt", "scritched", "bit") + squeak_override = list('modular_citadel/sound/voice/nya.ogg' = 1) + can_random_spawn = FALSE diff --git a/code/game/objects/items/religion.dm b/code/game/objects/items/religion.dm index 5fd9600a97..ac490b0122 100644 --- a/code/game/objects/items/religion.dm +++ b/code/game/objects/items/religion.dm @@ -44,9 +44,9 @@ if(H.stat == DEAD || H == user) continue if(H.mind && (has_job_loyalties || has_role_loyalties)) - if(has_job_loyalties && H.mind.assigned_role in job_loyalties) + if(has_job_loyalties && (H.mind.assigned_role in job_loyalties)) inspired += H - else if(has_role_loyalties && H.mind.special_role in role_loyalties) + else if(has_role_loyalties && (H.mind.special_role in role_loyalties)) inspired += H else if(check_inspiration(H)) inspired += H diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index 62f36c60c0..09c2d442e8 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -203,7 +203,7 @@ var/obj/item/gun/energy/kinetic_accelerator/cyborg/KA = new (R.module) R.module.basic_modules += KA R.module.add_module(KA, FALSE, TRUE) - + /obj/item/borg/upgrade/advcutter name = "mining cyborg advanced plasma cutter" @@ -335,7 +335,6 @@ var/msg_cooldown = 0 var/on = FALSE var/powercost = 10 - var/mob/living/silicon/robot/cyborg var/datum/action/toggle_action /obj/item/borg/upgrade/selfrepair/action(mob/living/silicon/robot/R, user = usr) @@ -346,7 +345,6 @@ to_chat(user, "This unit is already equipped with a self-repair module.") return FALSE - cyborg = R icon_state = "selfrepair_off" toggle_action = new /datum/action/item_action/toggle(src) toggle_action.Grant(R) @@ -354,34 +352,20 @@ /obj/item/borg/upgrade/selfrepair/deactivate(mob/living/silicon/robot/R, user = usr) . = ..() if (.) - toggle_action.Remove(cyborg) + toggle_action.Remove(R) QDEL_NULL(toggle_action) - cyborg = null - deactivate_sr() - -/obj/item/borg/upgrade/selfrepair/dropped() - . = ..() - addtimer(CALLBACK(src, .proc/check_dropped), 1) - -/obj/item/borg/upgrade/selfrepair/proc/check_dropped() - if(loc != cyborg) - toggle_action.Remove(cyborg) - QDEL_NULL(toggle_action) - cyborg = null deactivate_sr() /obj/item/borg/upgrade/selfrepair/ui_action_click() - on = !on if(on) - to_chat(cyborg, "You activate the self-repair module.") - START_PROCESSING(SSobj, src) + to_chat(toggle_action.owner, "You deactivate the self-repair module.") + deactivate_sr() else - to_chat(cyborg, "You deactivate the self-repair module.") - STOP_PROCESSING(SSobj, src) - update_icon() + to_chat(toggle_action.owner, "You activate the self-repair module.") + activate_sr() /obj/item/borg/upgrade/selfrepair/update_icon() - if(cyborg) + if(toggle_action) icon_state = "selfrepair_[on ? "on" : "off"]" for(var/X in actions) var/datum/action/A = X @@ -389,6 +373,11 @@ else icon_state = "cyborg_upgrade5" +/obj/item/borg/upgrade/selfrepair/proc/activate_sr() + START_PROCESSING(SSobj, src) + on = TRUE + update_icon() + /obj/item/borg/upgrade/selfrepair/proc/deactivate_sr() STOP_PROCESSING(SSobj, src) on = FALSE @@ -399,7 +388,9 @@ repair_tick = 1 return - if(cyborg && (cyborg.stat != DEAD) && on) + var/mob/living/silicon/robot/cyborg = toggle_action.owner + + if(istype(cyborg) && (cyborg.stat != DEAD) && on) if(!cyborg.cell) to_chat(cyborg, "Self-repair module deactivated. Please, insert the power cell.") deactivate_sr() diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm index 2e8005e631..3be698dd3a 100644 --- a/code/game/objects/items/shields.dm +++ b/code/game/objects/items/shields.dm @@ -236,3 +236,4 @@ throwforce = 15 //Massive pice of metal w_class = WEIGHT_CLASS_HUGE item_flags = SLOWS_WHILE_IN_HAND + transparent = FALSE diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index 21de34faa1..7879f50ada 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -1,7 +1,11 @@ /* Glass stack types * Contains: * Glass sheets + * Plasma glass * Reinforced glass sheets + * Reinforced plasma glass + * Titanium glass + * Plastitanium glass * Glass shards - TODO: Move this into code/game/object/item/weapons */ @@ -373,4 +377,8 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list( throwforce = 11 icon_state = "plasmalarge" materials = list(MAT_PLASMA=MINERAL_MATERIAL_AMOUNT * 0.5, MAT_GLASS=MINERAL_MATERIAL_AMOUNT) - icon_prefix = "plasma" \ No newline at end of file + icon_prefix = "plasma" + +/obj/item/shard/plasma/alien + name = "alien shard" + desc = "A nasty looking shard of advanced alloy glass." \ No newline at end of file diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index 53b78b2ecf..828ed96387 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -401,6 +401,8 @@ GLOBAL_LIST_INIT(abductor_recipes, list ( \ new/datum/stack_recipe("alien bed", /obj/structure/bed/abductor, 2, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("alien locker", /obj/structure/closet/abductor, 2, time = 15, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("alien table frame", /obj/structure/table_frame/abductor, 1, time = 15, one_per_turf = 1, on_floor = 1), \ + new/datum/stack_recipe("alien bar stool", /obj/item/chair/stool/bar/alien, 1, time = 20, one_per_turf = 1, on_floor = 1), \ + new/datum/stack_recipe("alien stool", /obj/item/chair/stool/alien, 1, time = 20, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("alien airlock assembly", /obj/structure/door_assembly/door_assembly_abductor, 4, time = 20, one_per_turf = 1, on_floor = 1), \ null, \ new/datum/stack_recipe("alien floor tile", /obj/item/stack/tile/mineral/abductor, 1, 4, 20), \ diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 2bd7dd0d38..45911afc73 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -51,6 +51,7 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \ new/datum/stack_recipe("closet", /obj/structure/closet, 2, time = 15, one_per_turf = TRUE, on_floor = TRUE), \ null, \ new/datum/stack_recipe("canister", /obj/machinery/portable_atmospherics/canister, 10, time = 15, one_per_turf = TRUE, on_floor = TRUE), \ + new/datum/stack_recipe("trash bin", /obj/structure/closet/crate/bin, 10, time = 15, one_per_turf = TRUE, on_floor = TRUE),\ null, \ new/datum/stack_recipe("floor tile", /obj/item/stack/tile/plasteel, 1, 4, 20), \ new/datum/stack_recipe("metal rod", /obj/item/stack/rods, 1, 2, 60), \ @@ -698,6 +699,16 @@ GLOBAL_LIST_INIT(bronze_recipes, list ( \ /* * Bones */ + +GLOBAL_LIST_INIT(bone_recipes, list( + new /datum/stack_recipe("Bone Dagger", /obj/item/kitchen/knife/combat/bone, 2, time = 20), \ + new /datum/stack_recipe("Skull Helmet", /obj/item/clothing/head/helmet/skull, 4, time = 30), \ + new /datum/stack_recipe("Bone Armor", /obj/item/clothing/suit/armor/bone, 6, time = 30))) + +/obj/item/stack/sheet/bone/Initialize(mapload, new_amount, merge = TRUE) + recipes = GLOB.bone_recipes + . = ..() + /obj/item/stack/sheet/bone name = "bones" icon = 'icons/obj/mining.dmi' @@ -714,12 +725,15 @@ GLOBAL_LIST_INIT(bronze_recipes, list ( \ grind_results = list(/datum/reagent/carbon = 10) merge_type = /obj/item/stack/sheet/bone + /* + * Plastic + */ + GLOBAL_LIST_INIT(plastic_recipes, list( new /datum/stack_recipe("see-through plastic flaps", /obj/structure/plasticflaps, 5, one_per_turf = TRUE, on_floor = TRUE, time = 40), \ new /datum/stack_recipe("opaque plastic flaps", /obj/structure/plasticflaps/opaque, 5, one_per_turf = TRUE, on_floor = TRUE, time = 40), \ new /datum/stack_recipe("water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/empty), \ new /datum/stack_recipe("large water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/large/empty,3), \ - new /datum/stack_recipe("large trash cart", /obj/structure/closet/crate/bin,50),\ new /datum/stack_recipe("wet floor sign", /obj/item/caution, 2))) /obj/item/stack/sheet/plastic diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm index 028f36b1d1..67e54128a4 100644 --- a/code/game/objects/items/storage/bags.dm +++ b/code/game/objects/items/storage/bags.dm @@ -399,10 +399,12 @@ /obj/item/storage/bag/bio/ComponentInitialize() . = ..() var/datum/component/storage/STR = GetComponent(/datum/component/storage) + STR.max_w_class = WEIGHT_CLASS_NORMAL //Allows you to pick up Lungs, Liver, and Stomach STR.max_combined_w_class = 200 STR.max_items = 25 STR.insert_preposition = "in" - STR.can_hold = typecacheof(list(/obj/item/slime_extract, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/blood, /obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/food/snacks/deadmouse, /obj/item/reagent_containers/food/snacks/monkeycube)) + STR.can_hold = typecacheof(list(/obj/item/slime_extract, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/blood, /obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/food/snacks/deadmouse, /obj/item/reagent_containers/food/snacks/monkeycube, /obj/item/organ, /obj/item/reagent_containers/food/snacks/meat/slab, /obj/item/bodypart)) + STR.cant_hold = typecacheof(list(/obj/item/organ/brain, /obj/item/organ/liver/cybernetic, /obj/item/organ/heart/cybernetic, /obj/item/organ/lungs/cybernetic, /obj/item/organ/tongue/cybernetic, /obj/item/organ/ears/cybernetic, /obj/item/organ/eyes/robotic, /obj/item/organ/cyberimp)) /obj/item/storage/bag/bio/holding name = "bio bag of holding" diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm index 082cbe245d..1be9df5c30 100755 --- a/code/game/objects/items/storage/belt.dm +++ b/code/game/objects/items/storage/belt.dm @@ -612,6 +612,21 @@ /obj/item/ammo_casing )) +/obj/item/storage/belt/quiver + name = "leather quiver" + desc = "A quiver made from the hide of some animal. Used to hold arrows." + icon_state = "quiver" + item_state = "quiver" + +/obj/item/storage/belt/quiver/ComponentInitialize() + . = ..() + var/datum/component/storage/STR = GetComponent(/datum/component/storage) + STR.max_items = 15 + STR.display_numerical_stacking = TRUE + STR.can_hold = typecacheof(list( + /obj/item/ammo_casing/caseless/arrow + )) + /obj/item/storage/belt/medolier name = "medolier" desc = "A medical bandolier for holding smartdarts." diff --git a/code/game/objects/items/storage/boxes.dm b/code/game/objects/items/storage/boxes.dm index daddc403b2..c4e6c57318 100644 --- a/code/game/objects/items/storage/boxes.dm +++ b/code/game/objects/items/storage/boxes.dm @@ -1288,3 +1288,62 @@ /obj/item/storage/box/marshmallow/PopulateContents() for (var/i in 1 to 5) new /obj/item/reagent_containers/food/snacks/marshmallow(src) + +/obj/item/storage/box/material/PopulateContents() //less uranium because radioactive + var/static/items_inside = list( + /obj/item/stack/sheet/metal/fifty=1,\ + /obj/item/stack/sheet/glass/fifty=1,\ + /obj/item/stack/sheet/rglass=50,\ + /obj/item/stack/sheet/plasmaglass=50,\ + /obj/item/stack/sheet/titaniumglass=50,\ + /obj/item/stack/sheet/plastitaniumglass=50,\ + /obj/item/stack/sheet/plasteel=50,\ + /obj/item/stack/sheet/mineral/plastitanium=50,\ + /obj/item/stack/sheet/mineral/titanium=50,\ + /obj/item/stack/sheet/mineral/gold=50,\ + /obj/item/stack/sheet/mineral/silver=50,\ + /obj/item/stack/sheet/mineral/plasma=50,\ + /obj/item/stack/sheet/mineral/uranium=50,\ + /obj/item/stack/sheet/mineral/diamond=50,\ + /obj/item/stack/sheet/bluespace_crystal=50,\ + /obj/item/stack/sheet/mineral/bananium=50,\ + /obj/item/stack/sheet/mineral/wood=50,\ + /obj/item/stack/sheet/plastic/fifty=1,\ + /obj/item/stack/sheet/runed_metal/fifty=1 + ) + generate_items_inside(items_inside, src) + +/obj/item/storage/box/debugtools + name = "box of debug tools" + icon_state = "syndiebox" + +/obj/item/storage/box/debugtools/PopulateContents() + var/static/items_inside = list( + /obj/item/flashlight/emp/debug=1,\ + /obj/item/pda=1,\ + /obj/item/modular_computer/tablet/preset/advanced=1,\ + /obj/item/geiger_counter=1,\ + /obj/item/construction/rcd/combat/admin=1,\ + /obj/item/pipe_dispenser=1,\ + /obj/item/card/emag=1,\ + /obj/item/healthanalyzer/advanced=1,\ + /obj/item/disk/tech_disk/debug=1,\ + /obj/item/uplink/debug=1,\ + /obj/item/uplink/nuclear/debug=1,\ + /obj/item/storage/box/beakers/bluespace=1,\ + /obj/item/storage/box/beakers/variety=1,\ + /obj/item/storage/box/material=1,\ + /obj/item/storage/belt/medical/surgery_belt_adv + ) + generate_items_inside(items_inside, src) + +/obj/item/storage/box/beakers/variety + name = "beaker variety box" + +/obj/item/storage/box/beakers/variety/PopulateContents() + new /obj/item/reagent_containers/glass/beaker(src) + new /obj/item/reagent_containers/glass/beaker/large(src) + new /obj/item/reagent_containers/glass/beaker/plastic(src) + new /obj/item/reagent_containers/glass/beaker/meta(src) + new /obj/item/reagent_containers/glass/beaker/noreact(src) + new /obj/item/reagent_containers/glass/beaker/bluespace(src) diff --git a/code/game/objects/items/teleportation.dm b/code/game/objects/items/teleportation.dm index 8c0f315ca3..347717dd63 100644 --- a/code/game/objects/items/teleportation.dm +++ b/code/game/objects/items/teleportation.dm @@ -138,14 +138,17 @@ /obj/item/hand_tele/pre_attack(atom/target, mob/user, params) if(try_dispel_portal(target, user)) - return FALSE + return TRUE return ..() -/obj/item/hand_tele/proc/try_dispel_portal(atom/target, mob/user) - if(is_parent_of_portal(target)) +/obj/item/hand_tele/proc/try_dispel_portal(atom/target, mob/user, delay = 30) + var/datum/beam/B = user.Beam(target) + if(is_parent_of_portal(target) && (!delay || do_after(user, delay, target = target))) qdel(target) to_chat(user, "You dispel [target] with \the [src]!") + qdel(B) return TRUE + qdel(B) return FALSE /obj/item/hand_tele/afterattack(atom/target, mob/user) diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 6782ba0098..359b3b4d10 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -1014,6 +1014,7 @@ /obj/item/toy/cards/singlecard/examine(mob/user) + . = ..() if(ishuman(user)) var/mob/living/carbon/human/cardUser = user if(cardUser.is_holding(src)) diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 45b9715b04..7fbdddbdc4 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -125,7 +125,7 @@ if ((M.client && M.machine == src)) is_in_use = TRUE ui_interact(M) - if(isAI(usr) || iscyborg(usr) || IsAdminGhost(usr)) + if(isAI(usr) || iscyborg(usr) || IsAdminGhost(usr) || hasSiliconAccessInArea(usr)) if (!(usr in nearby)) if (usr.client && usr.machine==src) // && M.machine == src is omitted because if we triggered this by using the dialog, it doesn't matter if our machine changed in between triggering it and this - the dialog is probably still supposed to refresh. is_in_use = TRUE diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm index 9fa4d730b6..cc1a3c0922 100644 --- a/code/game/objects/structures/beds_chairs/chair.dm +++ b/code/game/objects/structures/beds_chairs/chair.dm @@ -370,6 +370,43 @@ item_state = "stool_bar" origin_type = /obj/structure/chair/stool/bar +////////////////////////// +//Alien(Disco) Stools!//// +////////////////////////// + +/obj/structure/chair/stool/alien + name = "alien stool" + desc = "A hard stool made of advanced alien alloy." + icon_state = "stoolalien" + icon = 'icons/obj/abductor.dmi' + item_chair = /obj/item/chair/stool/alien + buildstacktype = /obj/item/stack/sheet/mineral/abductor + buildstackamount = 1 + +/obj/structure/chair/stool/bar/alien + name = "bronze bar stool" + desc = "A hard bar stool made of advanced alien alloy." + icon_state = "baralien" + icon = 'icons/obj/abductor.dmi' + item_chair = /obj/item/chair/stool/bar/alien + buildstacktype = /obj/item/stack/sheet/mineral/abductor + buildstackamount = 1 + +/obj/item/chair/stool/alien + name = "stool" + icon_state = "stoolalien_toppled" + item_state = "stoolalien" + icon = 'icons/obj/abductor.dmi' + origin_type = /obj/structure/chair/stool/alien + break_chance = 0 //It's too sturdy. + +/obj/item/chair/stool/bar/alien + name = "bar stool" + icon_state = "baralien_toppled" + item_state = "baralien" + icon = 'icons/obj/abductor.dmi' + origin_type = /obj/structure/chair/stool/bar/alien + ////////////////////////// //Brass & Bronze stools!// ////////////////////////// diff --git a/code/game/objects/structures/crates_lockers/closets/genpop.dm b/code/game/objects/structures/crates_lockers/closets/genpop.dm index 80b64aaedc..2b263bb1ed 100644 --- a/code/game/objects/structures/crates_lockers/closets/genpop.dm +++ b/code/game/objects/structures/crates_lockers/closets/genpop.dm @@ -95,7 +95,7 @@ if(user.lying && get_dist(src, user) > 0) return - if(!broken && registered_id != null && registered_id in user.held_items) + if(!broken && registered_id != null && (registered_id in user.held_items)) handle_prisoner_id(user) return diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index 1517b30d9c..88c8d51479 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -2,38 +2,21 @@ name = "\proper captain's locker" req_access = list(ACCESS_CAPTAIN) icon_state = "cap" -/obj/structure/closet/secure_closet/captains/PopulateContents() +/obj/structure/closet/secure_closet/captains/PopulateContents() //Excess clothing and such can be found in the Captain's Wardrobe. You can also find this file in code/modules/vending/wardrobes. ..() - new /obj/item/clothing/suit/hooded/wintercoat/captain(src) - new /obj/item/storage/backpack/captain(src) - new /obj/item/storage/backpack/satchel/cap(src) - new /obj/item/storage/backpack/duffelbag/captain(src) - new /obj/item/clothing/neck/cloak/cap(src) - new /obj/item/clothing/neck/petcollar(src) + new /obj/item/clothing/neck/petcollar(src) //I considered removing the pet stuff too but eh, who knows. We might get Renault back. Plus I guess you could use that collar for... other means. Aren't you supposed to be guarding the disk? new /obj/item/pet_carrier(src) - new /obj/item/clothing/shoes/sneakers/brown(src) - new /obj/item/clothing/under/rank/captain(src) - new /obj/item/clothing/under/rank/captain/skirt(src) new /obj/item/clothing/suit/armor/vest/capcarapace(src) - new /obj/item/clothing/head/caphat(src) - new /obj/item/clothing/under/captainparade(src) new /obj/item/clothing/suit/armor/vest/capcarapace/alt(src) - new /obj/item/clothing/head/caphat/parade(src) - new /obj/item/clothing/head/caphat/beret(src) - new /obj/item/clothing/suit/captunic(src) - new /obj/item/clothing/under/rank/captain/femformal(src) //citadel edit new /obj/item/clothing/head/crown/fancy(src) new /obj/item/cartridge/captain(src) new /obj/item/storage/box/silver_ids(src) new /obj/item/radio/headset/heads/captain/alt(src) new /obj/item/radio/headset/heads/captain(src) - new /obj/item/clothing/glasses/sunglasses/gar/supergar(src) - new /obj/item/clothing/gloves/color/captain(src) new /obj/item/storage/belt/sabre(src) new /obj/item/gun/energy/e_gun(src) new /obj/item/door_remote/captain(src) new /obj/item/storage/photo_album/Captain(src) - new /obj/item/clothing/head/caphat/beret/white(src) /obj/structure/closet/secure_closet/hop name = "\proper head of personnel's locker" diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index a6c0b22ad7..b14303984e 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -47,6 +47,12 @@ if(manifest) tear_manifest(user) +/obj/structure/closet/crate/tool_interact(obj/item/W, mob/user) + if(W.tool_behaviour == TOOL_WIRECUTTER && manifest) + tear_manifest(user) + return TRUE + return ..() + /obj/structure/closet/crate/open(mob/living/user) . = ..() if(. && manifest) diff --git a/code/game/objects/structures/crates_lockers/crates/bins.dm b/code/game/objects/structures/crates_lockers/crates/bins.dm index 7646fdb35f..bc3697a550 100644 --- a/code/game/objects/structures/crates_lockers/crates/bins.dm +++ b/code/game/objects/structures/crates_lockers/crates/bins.dm @@ -4,8 +4,8 @@ icon_state = "largebins" open_sound = 'sound/effects/bin_open.ogg' close_sound = 'sound/effects/bin_close.ogg' - material_drop = /obj/item/stack/sheet/plastic - material_drop_amount = 40 + material_drop = /obj/item/stack/sheet/metal + material_drop_amount = 10 anchored = TRUE horizontal = FALSE delivery_icon = null diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm index e9d9e4ce77..483b8fccbe 100644 --- a/code/game/objects/structures/ghost_role_spawners.dm +++ b/code/game/objects/structures/ghost_role_spawners.dm @@ -51,14 +51,17 @@ move_resist = MOVE_FORCE_NORMAL density = FALSE short_desc = "You are an ash walker. Your tribe worships the Necropolis." - flavour_text = "The wastes are sacred ground, its monsters a blessed bounty. You would never leave its sacred ground. \ - You have seen lights in the distance... they foreshadow the arrival of outsiders that seek to tear apart the Necropolis and its domain. \ - Fresh sacrifices for your nest." + flavour_text = "The wastes are sacred ground, its monsters a blessed bounty. You would never willingly leave your homeland behind. \ + You have seen lights in the distance... they foreshadow the arrival of outsiders to your domain. \ + Ensure your nest remains protected at all costs." assignedrole = "Ash Walker" /obj/effect/mob_spawn/human/ash_walker/special(mob/living/new_spawn) new_spawn.real_name = random_unique_lizard_name(gender) - to_chat(new_spawn, "Drag the corpses of men and beasts to your nest. It will absorb them to create more of your kind. Glory to the Necropolis!") + if(is_mining_level(z)) + to_chat(new_spawn, "Drag the corpses of men and beasts to your nest. It will absorb them to create more of your kind. Glory to the Necropolis!") + else + to_chat(new_spawn, "You have been born outside of your natural home! Whether you decide to return home, or make due with your new home is your own decision.") new_spawn.grant_language(/datum/language/draconic) var/datum/language_holder/holder = new_spawn.get_language_holder() diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 7696a13bb2..bf891ef223 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -168,7 +168,7 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an /obj/structure/bodycontainer/morgue/AltClick(mob/user) . = ..() - if(!user.canUseTopic(src, !issilicon(user))) + if(!user.canUseTopic(src, !hasSiliconAccessInArea(user))) return beeper = !beeper to_chat(user, "You turn the speaker function [beeper ? "on" : "off"].") diff --git a/code/game/objects/structures/traps.dm b/code/game/objects/structures/traps.dm index 9c1859df08..2cdc082ef3 100644 --- a/code/game/objects/structures/traps.dm +++ b/code/game/objects/structures/traps.dm @@ -35,7 +35,7 @@ . = ..() if(!isliving(user)) return - if(user.mind && user.mind in immune_minds) + if(user.mind && (user.mind in immune_minds)) return if(get_dist(user, src) <= 1) . += "You reveal [src]!" diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 14a7e445c1..d4925c8604 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -595,6 +595,14 @@ /obj/structure/window/plastitanium/unanchored anchored = FALSE +//pirate ship windows +/obj/structure/window/plastitanium/pirate + desc = "Yarr this window be explosion proof!" + explosion_block = 30 + +/obj/structure/window/plastitanium/pirate/unanchored + anchored = FALSE + /obj/structure/window/reinforced/clockwork name = "brass window" desc = "A paper-thin pane of translucent yet reinforced brass." diff --git a/code/game/turfs/simulated/wall/mineral_walls.dm b/code/game/turfs/simulated/wall/mineral_walls.dm index d55cb0b475..b04f4f0aa0 100644 --- a/code/game/turfs/simulated/wall/mineral_walls.dm +++ b/code/game/turfs/simulated/wall/mineral_walls.dm @@ -302,4 +302,4 @@ /turf/closed/wall/mineral/plastitanium/copyTurf(turf/T) . = ..() - T.transform = transform + T.transform = transform \ No newline at end of file diff --git a/code/game/turfs/simulated/wall/reinf_walls.dm b/code/game/turfs/simulated/wall/reinf_walls.dm index 8eab4c34fe..a1d2c1757c 100644 --- a/code/game/turfs/simulated/wall/reinf_walls.dm +++ b/code/game/turfs/simulated/wall/reinf_walls.dm @@ -258,3 +258,22 @@ /turf/closed/wall/r_wall/syndicate/overspace icon_state = "map-overspace" fixed_underlay = list("space"=1) + +/////////////////////Pirate Ship walls///////////////////// + +/turf/closed/wall/r_wall/syndicate/pirate + desc = "Yarr just try to blow this to smithereens!" + explosion_block = 30 + canSmoothWith = list(/turf/closed/wall/r_wall/syndicate/pirate, /obj/machinery/door/airlock/shuttle, /obj/machinery/door/airlock, /obj/structure/window/plastitanium/pirate, /obj/structure/shuttle/engine, /obj/structure/falsewall/plastitanium) + +/turf/closed/wall/r_wall/syndicate/pirate/nodiagonal + smooth = SMOOTH_MORE + icon_state = "map-shuttle_nd" + +/turf/closed/wall/r_wall/syndicate/pirate/nosmooth + icon = 'icons/turf/shuttle.dmi' + icon_state = "wall" + +/turf/closed/wall/r_wall/syndicate/pirate/overspace + icon_state = "map-overspace" + fixed_underlay = list("space"=1) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 688e03def3..e8f53f551d 100755 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -362,16 +362,14 @@ . = ..() if(.) return - if(!user || !istype(user, /mob/living)) - return FALSE if(length(src_object.contents())) to_chat(user, "You start dumping out the contents...") - if(!do_after(usr,20,target=src_object.parent)) + if(!do_after(user,20,target=src_object.parent)) return FALSE var/list/things = src_object.contents() var/datum/progressbar/progress = new(user, things.len, src) - while (do_after(usr, 10, TRUE, src, FALSE, CALLBACK(src_object, /datum/component/storage.proc/mass_remove_from_storage, src, things, progress))) + while (do_after(user, 10, TRUE, src, FALSE, CALLBACK(src_object, /datum/component/storage.proc/mass_remove_from_storage, src, things, progress))) stoplag(1) qdel(progress) diff --git a/code/game/world.dm b/code/game/world.dm index 6b380e0f94..77361310b8 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -10,6 +10,10 @@ GLOBAL_LIST(topic_status_cache) /world/New() enable_debugger() +#if DM_VERSION >= 513 && DM_BUILD >= 1506 + world.Profile(PROFILE_START) +#endif + log_world("World loaded at [TIME_STAMP("hh:mm:ss", FALSE)]!") SetupExternalRSC() @@ -18,7 +22,7 @@ GLOBAL_LIST(topic_status_cache) make_datum_references_lists() //initialises global lists for referencing frequently used datums (so that we only ever do it once) - TgsNew() + TgsNew(minimum_required_security_level = TGS_SECURITY_TRUSTED) GLOB.revdata = new diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 372902e8d6..bb0224bbfc 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -240,7 +240,7 @@ if( isemptylist(GLOB.news_network.network_channels) ) dat+="No active channels found..." else - for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels) + for(var/datum/news/feed_channel/CHANNEL in GLOB.news_network.network_channels) if(CHANNEL.is_admin_channel) dat+="[CHANNEL.channel_name]
" else @@ -277,7 +277,7 @@ if(src.admincaster_feed_channel.channel_name =="" || src.admincaster_feed_channel.channel_name == "\[REDACTED\]") dat+="•Invalid channel name.
" var/check = 0 - for(var/datum/newscaster/feed_channel/FC in GLOB.news_network.network_channels) + for(var/datum/news/feed_channel/FC in GLOB.news_network.network_channels) if(FC.channel_name == src.admincaster_feed_channel.channel_name) check = 1 break @@ -294,7 +294,7 @@ dat+="No feed messages found in channel...
" else var/i = 0 - for(var/datum/newscaster/feed_message/MESSAGE in src.admincaster_feed_channel.messages) + for(var/datum/news/feed_message/MESSAGE in src.admincaster_feed_channel.messages) i++ dat+="-[MESSAGE.returnBody(-1)]
" if(MESSAGE.img) @@ -302,7 +302,7 @@ dat+="

" dat+="\[Story by [MESSAGE.returnAuthor(-1)]\]
" dat+="[MESSAGE.comments.len] comment[MESSAGE.comments.len > 1 ? "s" : ""]:
" - for(var/datum/newscaster/feed_comment/comment in MESSAGE.comments) + for(var/datum/news/feed_comment/comment in MESSAGE.comments) dat+="[comment.body]
[comment.author] [comment.time_stamp]
" dat+="
" dat+="

Refresh" @@ -315,7 +315,7 @@ if(isemptylist(GLOB.news_network.network_channels)) dat+="No feed channels found active...
" else - for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels) + for(var/datum/news/feed_channel/CHANNEL in GLOB.news_network.network_channels) dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ""]
" dat+="
Cancel" if(11) @@ -326,7 +326,7 @@ if(isemptylist(GLOB.news_network.network_channels)) dat+="No feed channels found active...
" else - for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels) + for(var/datum/news/feed_channel/CHANNEL in GLOB.news_network.network_channels) dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ""]
" dat+="
Back" @@ -337,11 +337,11 @@ if( isemptylist(src.admincaster_feed_channel.messages) ) dat+="No feed messages found in channel...
" else - for(var/datum/newscaster/feed_message/MESSAGE in src.admincaster_feed_channel.messages) + for(var/datum/news/feed_message/MESSAGE in src.admincaster_feed_channel.messages) dat+="-[MESSAGE.returnBody(-1)]
\[Story by [MESSAGE.returnAuthor(-1)]\]
" dat+="[(MESSAGE.bodyCensor) ? ("Undo story censorship") : ("Censor story")] - [(MESSAGE.authorCensor) ? ("Undo Author Censorship") : ("Censor message Author")]
" dat+="[MESSAGE.comments.len] comment[MESSAGE.comments.len > 1 ? "s" : ""]: [MESSAGE.locked ? "Unlock" : "Lock"]
" - for(var/datum/newscaster/feed_comment/comment in MESSAGE.comments) + for(var/datum/news/feed_comment/comment in MESSAGE.comments) dat+="[comment.body] X
[comment.author] [comment.time_stamp]
" dat+="
Back" if(13) @@ -354,7 +354,7 @@ if( isemptylist(src.admincaster_feed_channel.messages) ) dat+="No feed messages found in channel...
" else - for(var/datum/newscaster/feed_message/MESSAGE in src.admincaster_feed_channel.messages) + for(var/datum/news/feed_message/MESSAGE in src.admincaster_feed_channel.messages) dat+="-[MESSAGE.returnBody(-1)]
\[Story by [MESSAGE.returnAuthor(-1)]\]
" dat+="
Back" if(14) diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm index 43360ad714..37fe2a41fc 100644 --- a/code/modules/admin/holder2.dm +++ b/code/modules/admin/holder2.dm @@ -19,9 +19,9 @@ GLOBAL_PROTECT(href_token) var/spamcooldown = 0 var/admincaster_screen = 0 //TODO: remove all these 5 variables, they are completly unacceptable - var/datum/newscaster/feed_message/admincaster_feed_message = new /datum/newscaster/feed_message - var/datum/newscaster/wanted_message/admincaster_wanted_message = new /datum/newscaster/wanted_message - var/datum/newscaster/feed_channel/admincaster_feed_channel = new /datum/newscaster/feed_channel + var/datum/news/feed_message/admincaster_feed_message = new /datum/news/feed_message + var/datum/news/wanted_message/admincaster_wanted_message = new /datum/news/wanted_message + var/datum/news/feed_channel/admincaster_feed_channel = new /datum/news/feed_channel var/admin_signature var/href_token diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 70b25bebdd..6abf2d3f1b 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -2481,7 +2481,7 @@ if(!check_rights(R_ADMIN)) return var/check = 0 - for(var/datum/newscaster/feed_channel/FC in GLOB.news_network.network_channels) + for(var/datum/news/feed_channel/FC in GLOB.news_network.network_channels) if(FC.channel_name == src.admincaster_feed_channel.channel_name) check = 1 break @@ -2500,7 +2500,7 @@ if(!check_rights(R_ADMIN)) return var/list/available_channels = list() - for(var/datum/newscaster/feed_channel/F in GLOB.news_network.network_channels) + for(var/datum/news/feed_channel/F in GLOB.news_network.network_channels) available_channels += F.channel_name src.admincaster_feed_channel.channel_name = adminscrub(input(usr, "Choose receiving Feed Channel.", "Network Channel Handler") in available_channels ) src.access_news_network() @@ -2606,28 +2606,28 @@ else if(href_list["ac_censor_channel_author"]) if(!check_rights(R_ADMIN)) return - var/datum/newscaster/feed_channel/FC = locate(href_list["ac_censor_channel_author"]) + var/datum/news/feed_channel/FC = locate(href_list["ac_censor_channel_author"]) FC.toggleCensorAuthor() src.access_news_network() else if(href_list["ac_censor_channel_story_author"]) if(!check_rights(R_ADMIN)) return - var/datum/newscaster/feed_message/MSG = locate(href_list["ac_censor_channel_story_author"]) + var/datum/news/feed_message/MSG = locate(href_list["ac_censor_channel_story_author"]) MSG.toggleCensorAuthor() src.access_news_network() else if(href_list["ac_censor_channel_story_body"]) if(!check_rights(R_ADMIN)) return - var/datum/newscaster/feed_message/MSG = locate(href_list["ac_censor_channel_story_body"]) + var/datum/news/feed_message/MSG = locate(href_list["ac_censor_channel_story_body"]) MSG.toggleCensorBody() src.access_news_network() else if(href_list["ac_pick_d_notice"]) if(!check_rights(R_ADMIN)) return - var/datum/newscaster/feed_channel/FC = locate(href_list["ac_pick_d_notice"]) + var/datum/news/feed_channel/FC = locate(href_list["ac_pick_d_notice"]) src.admincaster_feed_channel = FC src.admincaster_screen=13 src.access_news_network() @@ -2635,7 +2635,7 @@ else if(href_list["ac_toggle_d_notice"]) if(!check_rights(R_ADMIN)) return - var/datum/newscaster/feed_channel/FC = locate(href_list["ac_toggle_d_notice"]) + var/datum/news/feed_channel/FC = locate(href_list["ac_toggle_d_notice"]) FC.toggleCensorDclass() src.access_news_network() @@ -2651,17 +2651,17 @@ src.admincaster_screen = text2num(href_list["ac_setScreen"]) if (src.admincaster_screen == 0) if(src.admincaster_feed_channel) - src.admincaster_feed_channel = new /datum/newscaster/feed_channel + src.admincaster_feed_channel = new /datum/news/feed_channel if(src.admincaster_feed_message) - src.admincaster_feed_message = new /datum/newscaster/feed_message + src.admincaster_feed_message = new /datum/news/feed_message if(admincaster_wanted_message) - admincaster_wanted_message = new /datum/newscaster/wanted_message + admincaster_wanted_message = new /datum/news/wanted_message src.access_news_network() else if(href_list["ac_show_channel"]) if(!check_rights(R_ADMIN)) return - var/datum/newscaster/feed_channel/FC = locate(href_list["ac_show_channel"]) + var/datum/news/feed_channel/FC = locate(href_list["ac_show_channel"]) src.admincaster_feed_channel = FC src.admincaster_screen = 9 src.access_news_network() @@ -2669,7 +2669,7 @@ else if(href_list["ac_pick_censor_channel"]) if(!check_rights(R_ADMIN)) return - var/datum/newscaster/feed_channel/FC = locate(href_list["ac_pick_censor_channel"]) + var/datum/news/feed_channel/FC = locate(href_list["ac_pick_censor_channel"]) src.admincaster_feed_channel = FC src.admincaster_screen = 12 src.access_news_network() @@ -2688,8 +2688,8 @@ else if(href_list["ac_del_comment"]) if(!check_rights(R_ADMIN)) return - var/datum/newscaster/feed_comment/FC = locate(href_list["ac_del_comment"]) - var/datum/newscaster/feed_message/FM = locate(href_list["ac_del_comment_msg"]) + var/datum/news/feed_comment/FC = locate(href_list["ac_del_comment"]) + var/datum/news/feed_message/FM = locate(href_list["ac_del_comment_msg"]) FM.comments -= FC qdel(FC) src.access_news_network() @@ -2697,7 +2697,7 @@ else if(href_list["ac_lock_comment"]) if(!check_rights(R_ADMIN)) return - var/datum/newscaster/feed_message/FM = locate(href_list["ac_lock_comment"]) + var/datum/news/feed_message/FM = locate(href_list["ac_lock_comment"]) FM.locked ^= 1 src.access_news_network() diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm index da7c264774..14906bc83a 100644 --- a/code/modules/admin/verbs/SDQL2/SDQL_2.dm +++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm @@ -303,7 +303,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null //These three are weird. For best performance, they are only a number when they're not being changed by the SDQL searching/execution code. They only become numbers when they finish changing. var/list/obj_count_all var/list/obj_count_eligible - var/list/obj_count_finished + var/obj_count_finished //Statclick var/obj/effect/statclick/SDQL2_delete/delete_click @@ -682,7 +682,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null SDQL2_TICK_CHECK SDQL2_HALT_CHECK if(islist(obj_count_finished)) - obj_count_finished = obj_count_finished.len + obj_count_finished = length(obj_count_finished) state = SDQL2_STATE_SWITCHING /datum/SDQL2_query/proc/SDQL_print(object, list/text_list, print_nulls = TRUE) diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index ad2eeb7289..54d6a864fd 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -487,7 +487,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention) if(alert("This mob is being controlled by [M.key]. Are you sure you wish to assume control of it? [M.key] will be made a ghost.",,"Yes","No") != "Yes") return else - var/mob/dead/observer/ghost = new/mob/dead/observer(M,1) + var/mob/dead/observer/ghost = new/mob/dead/observer(get_turf(M), M) ghost.ckey = M.ckey message_admins("[key_name_admin(usr)] assumed direct control of [M].") log_admin("[key_name(usr)] assumed direct control of [M].") @@ -1058,7 +1058,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention) set name = "Start Line Profiling" set desc = "Starts tracking line by line profiling for code lines that support it" - PROFILE_START + LINE_PROFILE_START message_admins("[key_name_admin(src)] started line by line profiling.") SSblackbox.record_feedback("tally", "admin_verb", 1, "Start Line Profiling") @@ -1069,7 +1069,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention) set name = "Stops Line Profiling" set desc = "Stops tracking line by line profiling for code lines that support it" - PROFILE_STOP + LINE_PROFILE_STOP message_admins("[key_name_admin(src)] stopped line by line profiling.") SSblackbox.record_feedback("tally", "admin_verb", 1, "Stop Line Profiling") diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm index 24e80fd8f3..35ab3927d4 100644 --- a/code/modules/admin/verbs/mapping.dm +++ b/code/modules/admin/verbs/mapping.dm @@ -135,7 +135,7 @@ GLOBAL_LIST_EMPTY(dirty_vars) if(!(locate(/obj/structure/grille) in T)) var/window_check = 0 for(var/obj/structure/window/W in T) - if (W.dir == turn(C1.dir,180) || W.dir in list(5,6,9,10) ) + if(W.dir == turn(C1.dir,180) || (W.dir in list(5,6,9,10))) window_check = 1 break if(!window_check) diff --git a/code/modules/antagonists/clockcult/clock_items/replica_fabricator.dm b/code/modules/antagonists/clockcult/clock_items/replica_fabricator.dm index 501bcdc1c4..7be9ef039b 100644 --- a/code/modules/antagonists/clockcult/clock_items/replica_fabricator.dm +++ b/code/modules/antagonists/clockcult/clock_items/replica_fabricator.dm @@ -68,8 +68,8 @@ /obj/item/clockwork/replica_fabricator/pre_attack(atom/target, mob/living/user, params) if(!target || !user || !is_servant_of_ratvar(user) || istype(target, /obj/item/storage)) - return TRUE - return fabricate(target, user) + return ..() + return !fabricate(target, user) //A note here; return values are for if we CAN BE PUT ON A TABLE, not IF WE ARE SUCCESSFUL, unless no_table_check is TRUE /obj/item/clockwork/replica_fabricator/proc/fabricate(atom/target, mob/living/user, silent, no_table_check) diff --git a/code/modules/antagonists/clockcult/clock_mobs/clockwork_marauder.dm b/code/modules/antagonists/clockcult/clock_mobs/clockwork_marauder.dm index 6591343116..897bff779d 100644 --- a/code/modules/antagonists/clockcult/clock_mobs/clockwork_marauder.dm +++ b/code/modules/antagonists/clockcult/clock_mobs/clockwork_marauder.dm @@ -8,7 +8,7 @@ name = "clockwork marauder" desc = "The stalwart apparition of a soldier, blazing with crimson flames. It's armed with a gladius and shield." icon_state = "clockwork_marauder" - mob_biotypes = list(MOB_INORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_HUMANOID health = 120 maxHealth = 120 force_threshold = 8 diff --git a/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm b/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm index d0940ebb7a..00db2b0d72 100644 --- a/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm +++ b/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm @@ -118,7 +118,7 @@ continue if(ishostile(L)) var/mob/living/simple_animal/hostile/H = L - if(("ratvar" in H.faction) || (!H.mind && "neutral" in H.faction)) + if(("ratvar" in H.faction) || (!H.mind && ("neutral" in H.faction))) continue if(ismegafauna(H) || (!H.mind && H.AIStatus == AI_OFF)) continue diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm index 1bb1b8533a..3f70dc6e82 100644 --- a/code/modules/antagonists/cult/blood_magic.dm +++ b/code/modules/antagonists/cult/blood_magic.dm @@ -343,7 +343,7 @@ icon = 'icons/obj/items_and_weapons.dmi' icon_state = "disintegrate" item_state = null - item_flags = NEEDS_PERMIT | ABSTRACT | DROPDEL + item_flags = NEEDS_PERMIT | ABSTRACT | DROPDEL | NO_ATTACK_CHAIN_SOFT_STAMCRIT w_class = WEIGHT_CLASS_HUGE throwforce = 0 diff --git a/code/modules/antagonists/cult/ritual.dm b/code/modules/antagonists/cult/ritual.dm index ba2a96289d..e92f562db3 100644 --- a/code/modules/antagonists/cult/ritual.dm +++ b/code/modules/antagonists/cult/ritual.dm @@ -116,7 +116,7 @@ This file contains the cult dagger and rune list code if(user.blood_volume) user.apply_damage(initial(rune_to_scribe.scribe_damage), BRUTE, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) var/scribe_mod = initial(rune_to_scribe.scribe_delay) - if(istype(get_turf(user), /turf/open/floor/engine/cult)) + if(istype(get_turf(user), /turf/open/floor/engine/cult) && !(ispath(rune_to_scribe, /obj/effect/rune/narsie))) scribe_mod *= 0.5 if(!do_after(user, scribe_mod, target = get_turf(user))) for(var/V in shields) diff --git a/code/modules/antagonists/devil/imp/imp.dm b/code/modules/antagonists/devil/imp/imp.dm index fa5263059a..c2f636959b 100644 --- a/code/modules/antagonists/devil/imp/imp.dm +++ b/code/modules/antagonists/devil/imp/imp.dm @@ -13,7 +13,7 @@ icon = 'icons/mob/mob.dmi' icon_state = "imp" icon_living = "imp" - mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID speed = 1 a_intent = INTENT_HARM stop_automated_movement = 1 diff --git a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm index fe3b5a3aeb..0d815703c5 100644 --- a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm +++ b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm @@ -381,6 +381,7 @@ playsound(src, 'sound/machines/nuke/confirm_beep.ogg', 50, FALSE) set_active() update_ui_mode() + . = TRUE else playsound(src, 'sound/machines/nuke/angry_beep.ogg', 50, FALSE) if("anchor") diff --git a/code/modules/antagonists/revenant/revenant.dm b/code/modules/antagonists/revenant/revenant.dm index 9754d146c3..26efb92bec 100644 --- a/code/modules/antagonists/revenant/revenant.dm +++ b/code/modules/antagonists/revenant/revenant.dm @@ -16,7 +16,7 @@ var/icon_stun = "revenant_stun" var/icon_drain = "revenant_draining" var/stasis = FALSE - mob_biotypes = list(MOB_SPIRIT) + mob_biotypes = MOB_SPIRIT incorporeal_move = INCORPOREAL_MOVE_JAUNT invisibility = INVISIBILITY_REVENANT health = INFINITY //Revenants don't use health, they use essence instead diff --git a/code/modules/antagonists/slaughter/slaughter.dm b/code/modules/antagonists/slaughter/slaughter.dm index c703c85762..8a01622c87 100644 --- a/code/modules/antagonists/slaughter/slaughter.dm +++ b/code/modules/antagonists/slaughter/slaughter.dm @@ -12,7 +12,7 @@ icon = 'icons/mob/mob.dmi' icon_state = "daemon" icon_living = "daemon" - mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID speed = 1 a_intent = INTENT_HARM stop_automated_movement = 1 diff --git a/code/modules/antagonists/swarmer/swarmer.dm b/code/modules/antagonists/swarmer/swarmer.dm index 7680d61034..bf976e3cca 100644 --- a/code/modules/antagonists/swarmer/swarmer.dm +++ b/code/modules/antagonists/swarmer/swarmer.dm @@ -62,7 +62,7 @@ speak_emote = list("tones") initial_language_holder = /datum/language_holder/swarmer bubble_icon = "swarmer" - mob_biotypes = list(MOB_ROBOTIC) + mob_biotypes = MOB_ROBOTIC health = 40 maxHealth = 40 status_flags = CANPUSH diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm index f7c5dce30f..e85cf1efa6 100644 --- a/code/modules/atmospherics/machinery/airalarm.dm +++ b/code/modules/atmospherics/machinery/airalarm.dm @@ -245,7 +245,7 @@ /obj/machinery/airalarm/ui_data(mob/user) var/data = list( "locked" = locked, - "siliconUser" = user.has_unlimited_silicon_privilege, + "siliconUser" = user.has_unlimited_silicon_privilege || hasSiliconAccessInArea(user), "emagged" = (obj_flags & EMAGGED ? 1 : 0), "danger_level" = danger_level, ) @@ -288,7 +288,7 @@ "danger_level" = cur_tlv.get_danger_level(environment.gases[gas_id] * partial_pressure) )) - if(!locked || user.has_unlimited_silicon_privilege) + if(!locked || user.has_unlimited_silicon_privilege || hasSiliconAccessInArea(user)) data["vents"] = list() for(var/id_tag in A.air_vent_names) var/long_name = A.air_vent_names[id_tag] @@ -368,7 +368,7 @@ /obj/machinery/airalarm/ui_act(action, params) if(..() || buildstage != 2) return - if((locked && !usr.has_unlimited_silicon_privilege) || (usr.has_unlimited_silicon_privilege && aidisabled)) + if((locked && !usr.has_unlimited_silicon_privilege && !hasSiliconAccessInArea(usr)) || (usr.has_unlimited_silicon_privilege && aidisabled)) return var/device_id = params["id_tag"] switch(action) @@ -840,7 +840,7 @@ /obj/machinery/airalarm/AltClick(mob/user) . = ..() - if(!user.canUseTopic(src, !issilicon(user)) || !isturf(loc)) + if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)) || !isturf(loc)) return togglelock(user) return TRUE diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm index 539b5ce57a..1e8cce32c0 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm @@ -251,6 +251,7 @@ /obj/machinery/atmospherics/components/unary/cryo_cell/close_machine(mob/living/carbon/user) if((isnull(user) || istype(user)) && state_open && !panel_open) ..(user) + reagent_transfer = 0 return occupant /obj/machinery/atmospherics/components/unary/cryo_cell/container_resist(mob/living/user) diff --git a/code/modules/awaymissions/bluespaceartillery.dm b/code/modules/awaymissions/bluespaceartillery.dm index deb05920e2..ee4090b680 100644 --- a/code/modules/awaymissions/bluespaceartillery.dm +++ b/code/modules/awaymissions/bluespaceartillery.dm @@ -44,7 +44,7 @@ return if(reload < reload_cooldown) return - if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr)) + if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr)) priority_announce("Bluespace artillery fire detected. Brace for impact.") message_admins("[ADMIN_LOOKUPFLW(usr)] has launched an artillery strike.") var/list/L = list() diff --git a/code/modules/awaymissions/capture_the_flag.dm b/code/modules/awaymissions/capture_the_flag.dm index 3562350473..c4bb6e8cdd 100644 --- a/code/modules/awaymissions/capture_the_flag.dm +++ b/code/modules/awaymissions/capture_the_flag.dm @@ -466,11 +466,13 @@ // MELEE GANG /obj/item/claymore/ctf - slot_flags = SLOT_BACK + slot_flags = ITEM_SLOT_BACK + armour_penetration = 100 + total_mass = 1 /obj/item/claymore/ctf/pre_attack(atom/target, mob/user, params) if(!is_ctf_target(target)) - return FALSE + return TRUE return ..() /obj/item/claymore/ctf/dropped() diff --git a/code/modules/cargo/bounties/reagent.dm b/code/modules/cargo/bounties/reagent.dm index ca76c80df7..391b4ff464 100644 --- a/code/modules/cargo/bounties/reagent.dm +++ b/code/modules/cargo/bounties/reagent.dm @@ -105,6 +105,7 @@ datum/bounty/reagent/complex_drink/New() /datum/reagent/consumable/ethanol/hearty_punch,\ /datum/reagent/consumable/ethanol/manhattan_proj,\ /datum/reagent/consumable/ethanol/narsour,\ + /datum/reagent/consumable/ethanol/cogchamp,\ /datum/reagent/consumable/ethanol/neurotoxin,\ /datum/reagent/consumable/ethanol/patron,\ /datum/reagent/consumable/ethanol/quadruple_sec,\ diff --git a/code/modules/cargo/export_scanner.dm b/code/modules/cargo/export_scanner.dm index 9c523c194f..80fd05cf8c 100644 --- a/code/modules/cargo/export_scanner.dm +++ b/code/modules/cargo/export_scanner.dm @@ -36,6 +36,8 @@ var/price = 0 for(var/x in ex.total_amount) price += ex.total_value[x] + for(var/x in ex.reagents_value) + price += ex.reagents_value[x] if(price) to_chat(user, "Scanned [O], value: [price] credits[O.contents.len ? " (contents included)" : ""].") diff --git a/code/modules/cargo/exports.dm b/code/modules/cargo/exports.dm index fca10ac01c..bb90fa717a 100644 --- a/code/modules/cargo/exports.dm +++ b/code/modules/cargo/exports.dm @@ -49,13 +49,13 @@ Credit dupes that require a lot of manual work shouldn't be removed, unless they sold = E.sell_object(thing, report, dry_run, allowed_categories , apply_elastic) report.exported_atoms += " [thing.name]" break - if(thing.reagents) + if(thing.reagents?.value_multiplier) for(var/A in thing.reagents.reagent_list) var/datum/reagent/R = A if(!R.value) continue report.reagents_volume[R.name] += R.volume - report.reagents_value[R.name] += R.volume * R.value + report.reagents_value[R.name] += round(R.volume * R.value * thing.reagents.value_multiplier) if(!dry_run && (sold || delete_unsold)) if(ismob(thing)) thing.investigate_log("deleted through cargo export",INVESTIGATE_CARGO) diff --git a/code/modules/cargo/exports/large_objects.dm b/code/modules/cargo/exports/large_objects.dm index b8541dcd33..bf67286f11 100644 --- a/code/modules/cargo/exports/large_objects.dm +++ b/code/modules/cargo/exports/large_objects.dm @@ -6,7 +6,7 @@ k_elasticity = 0 unit_name = "crate" export_types = list(/obj/structure/closet/crate) - exclude_types = list(/obj/structure/closet/crate/large, /obj/structure/closet/crate/wooden) + exclude_types = list(/obj/structure/closet/crate/large, /obj/structure/closet/crate/wooden, /obj/structure/closet/crate/bin) /datum/export/large/crate/total_printout(datum/export_report/ex, notes = TRUE) // That's why a goddamn metal crate costs that much. . = ..() diff --git a/code/modules/cargo/supplypod_beacon.dm b/code/modules/cargo/supplypod_beacon.dm index 006f1a8084..668698d2e9 100644 --- a/code/modules/cargo/supplypod_beacon.dm +++ b/code/modules/cargo/supplypod_beacon.dm @@ -77,7 +77,7 @@ /obj/item/supplypod_beacon/AltClick(mob/user) . = ..() - if (!user.canUseTopic(src, !issilicon(user))) + if (!user.canUseTopic(src, !hasSiliconAccessInArea(user))) return if (express_console) unlink_console() diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index ba20fdacd2..793a72c1f7 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -1473,9 +1473,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) age = max(min( round(text2num(new_age)), AGE_MAX),AGE_MIN) if("flavor_text") - var/msg = stripped_multiline_input(usr, "Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!", "Flavor Text", html_decode(features["flavor_text"]), MAX_MESSAGE_LEN, TRUE) + var/msg = stripped_multiline_input(usr, "Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!", "Flavor Text", features["flavor_text"], MAX_FAVOR_LEN, TRUE) if(msg) - msg = msg features["flavor_text"] = msg if("hair") diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm index 7df10b56f7..b60856001e 100644 --- a/code/modules/clothing/glasses/_glasses.dm +++ b/code/modules/clothing/glasses/_glasses.dm @@ -488,4 +488,47 @@ if(client && client.prefs.uses_glasses_colour && glasses_equipped) add_client_colour(G.glass_colour_type) else - remove_client_colour(G.glass_colour_type) \ No newline at end of file + remove_client_colour(G.glass_colour_type) + +/obj/item/clothing/glasses/debug + name = "debug glasses" + desc = "Medical, security and diagnostic hud. Alt click to toggle xray." + icon_state = "nvgmeson" + item_state = "nvgmeson" + flags_cover = GLASSESCOVERSEYES + darkness_view = 8 + flash_protect = 2 + lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE + glass_colour_type = FALSE + clothing_flags = SCAN_REAGENTS + vision_flags = SEE_TURFS + var/list/hudlist = list(DATA_HUD_MEDICAL_ADVANCED, DATA_HUD_DIAGNOSTIC_ADVANCED, DATA_HUD_SECURITY_ADVANCED) + var/xray = FALSE + +/obj/item/clothing/glasses/debug/equipped(mob/user, slot) + . = ..() + if(slot != ITEM_SLOT_EYES) + return + if(ishuman(user)) + for(var/hud in hudlist) + var/datum/atom_hud/H = GLOB.huds[hud] + H.add_hud_to(user) + +/obj/item/clothing/glasses/debug/dropped(mob/user) + . = ..() + if(ishuman(user)) + for(var/hud in hudlist) + var/datum/atom_hud/H = GLOB.huds[hud] + H.remove_hud_from(user) + +/obj/item/clothing/glasses/debug/AltClick(mob/user) + . = ..() + if(ishuman(user)) + if(xray) + vision_flags -= SEE_MOBS|SEE_OBJS + else + vision_flags += SEE_MOBS|SEE_OBJS + xray = !xray + var/mob/living/carbon/human/H = user + H.update_sight() + diff --git a/code/modules/clothing/gloves/ring.dm b/code/modules/clothing/gloves/ring.dm index 54aaa58849..8354f13bd2 100644 --- a/code/modules/clothing/gloves/ring.dm +++ b/code/modules/clothing/gloves/ring.dm @@ -5,6 +5,7 @@ w_class = WEIGHT_CLASS_TINY icon = 'icons/obj/ring.dmi' icon_state = "ringgold" + item_state = "gring" body_parts_covered = 0 attack_verb = list("proposed") transfer_prints = TRUE @@ -17,10 +18,15 @@ /obj/item/clothing/gloves/ring/diamond name = "diamond ring" - desc = "A tiny gold ring, studded with a diamond. Cultures have used these rings in courtship for a millenia." + desc = "An expensive ring, studded with a diamond. Cultures have used these rings in courtship for a millenia." icon_state = "ringdiamond" + item_state = "dring" + +/obj/item/clothing/gloves/ring/diamond/attack_self(mob/user) + user.visible_message("\The [user] gets down on one knee, presenting \the [src].","You get down on one knee, presenting \the [src].") /obj/item/clothing/gloves/ring/silver name = "silver ring" desc = "A tiny silver ring, sized to wrap around a finger." icon_state = "ringsilver" + item_state = "sring" diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index 1e8f26e7fe..e6c68f2662 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -39,6 +39,12 @@ /obj/item/clothing/mask/gas/welding/attack_self(mob/user) weldingvisortoggle(user) +/obj/item/clothing/mask/gas/welding/up + +/obj/item/clothing/mask/gas/welding/up/Initialize() + ..() + visor_toggling() + // ******************************************************************** diff --git a/code/modules/clothing/outfits/standard.dm b/code/modules/clothing/outfits/standard.dm index 4c8f9bdab2..ab2f89ffc4 100644 --- a/code/modules/clothing/outfits/standard.dm +++ b/code/modules/clothing/outfits/standard.dm @@ -272,7 +272,7 @@ /datum/outfit/wizard name = "Blue Wizard" - uniform = /obj/item/clothing/under/color/lightpurple + uniform = /obj/item/clothing/under/color/lightpurple/trackless suit = /obj/item/clothing/suit/wizrobe shoes = /obj/item/clothing/shoes/sandal/magic ears = /obj/item/radio/headset @@ -427,14 +427,27 @@ /datum/outfit/debug //Debug objs plus hardsuit name = "Debug outfit" uniform = /obj/item/clothing/under/patriotsuit - suit = /obj/item/clothing/suit/space/hardsuit/syndi/elite - shoes = /obj/item/clothing/shoes/magboots/advance - suit_store = /obj/item/tank/internals/oxygen - mask = /obj/item/clothing/mask/gas/welding - belt = /obj/item/storage/belt/utility/chief/full - gloves = /obj/item/clothing/gloves/combat - id = /obj/item/card/id/ert - glasses = /obj/item/clothing/glasses/meson/night + suit = /obj/item/clothing/suit/space/hardsuit/syndi/elite/debug + glasses = /obj/item/clothing/glasses/debug ears = /obj/item/radio/headset/headset_cent/commander + mask = /obj/item/clothing/mask/gas/welding/up + gloves = /obj/item/clothing/gloves/combat + belt = /obj/item/storage/belt/utility/chief/full + l_pocket = /obj/item/gun/magic/wand/resurrection/debug + r_pocket = /obj/item/gun/magic/wand/death/debug + shoes = /obj/item/clothing/shoes/magboots/advance/debug + id = /obj/item/card/id/debug + suit_store = /obj/item/tank/internals/oxygen back = /obj/item/storage/backpack/holding - backpack_contents = list(/obj/item/card/emag=1, /obj/item/flashlight/emp/debug=1, /obj/item/construction/rcd/combat=1, /obj/item/gun/magic/wand/resurrection/debug=1, /obj/item/melee/transforming/energy/axe=1) + box = /obj/item/storage/box/debugtools + internals_slot = ITEM_SLOT_SUITSTORE + backpack_contents = list( + /obj/item/melee/transforming/energy/axe=1,\ + /obj/item/storage/part_replacer/bluespace/tier4=1,\ + /obj/item/debug/human_spawner=1,\ + ) + +/datum/outfit/debug/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) + var/obj/item/card/id/W = H.wear_id + W.registered_name = H.real_name + W.update_label() diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm index 8864add0d8..1acb7628a3 100644 --- a/code/modules/clothing/shoes/magboots.dm +++ b/code/modules/clothing/shoes/magboots.dm @@ -30,8 +30,9 @@ magpulse = !magpulse icon_state = "[magboot_state][magpulse]" to_chat(user, "You [magpulse ? "enable" : "disable"] the mag-pulse traction system.") - user.update_inv_shoes() //so our mob-overlays update - user.update_gravity(user.has_gravity()) + if(user) + user.update_inv_shoes() //so our mob-overlays update + user.update_gravity(user.has_gravity()) for(var/X in actions) var/datum/action/A = X A.UpdateButtonIcon() @@ -52,6 +53,11 @@ slowdown_active = SHOES_SLOWDOWN resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF +/obj/item/clothing/shoes/magboots/advance/debug + +/obj/item/clothing/shoes/magboots/advance/debug/Initialize() + attack_self(src) + /obj/item/clothing/shoes/magboots/syndie desc = "Reverse-engineered magnetic boots that have a heavy magnetic pull. Property of Gorlex Marauders." name = "blood-red magboots" diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm index 703fe26287..fab41c9876 100644 --- a/code/modules/clothing/spacesuits/hardsuit.dm +++ b/code/modules/clothing/spacesuits/hardsuit.dm @@ -269,7 +269,7 @@ item_state = "syndie_helm" item_color = "syndi" armor = list("melee" = 40, "bullet" = 50, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 90) - on = TRUE + on = FALSE var/obj/item/clothing/suit/space/hardsuit/syndi/linkedsuit = null actions_types = list(/datum/action/item_action/toggle_helmet_mode) visor_flags_inv = HIDEMASK|HIDEEYES|HIDEFACE|HIDEFACIALHAIR @@ -367,6 +367,12 @@ on = FALSE resistance_flags = FIRE_PROOF | ACID_PROOF +/obj/item/clothing/head/helmet/space/hardsuit/syndi/elite/debug + +/obj/item/clothing/head/helmet/space/hardsuit/syndi/elite/debug/Initialize() + . = ..() + soundloop.volume = 0 + /obj/item/clothing/suit/space/hardsuit/syndi/elite name = "elite syndicate hardsuit" desc = "An elite version of the syndicate hardsuit, with improved armour and fireproofing. It is in travel mode." @@ -380,6 +386,9 @@ resistance_flags = FIRE_PROOF | ACID_PROOF mutantrace_variation = STYLE_DIGITIGRADE|STYLE_SNEK_TAURIC|STYLE_PAW_TAURIC +/obj/item/clothing/suit/space/hardsuit/syndi/elite/debug + helmettype = /obj/item/clothing/head/helmet/space/hardsuit/syndi/elite/debug + slowdown = 0 //The Owl Hardsuit /obj/item/clothing/head/helmet/space/hardsuit/syndi/owl diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index e9b96af8eb..4d3e8acb28 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -325,17 +325,16 @@ body_parts_covered = CHEST|ARMS /obj/item/clothing/suit/ran - name = "Shikigami costume" + name = "shikigami costume" desc = "A costume that looks like a certain shikigami, is super fluffy." icon_state = "ran_suit" item_state = "ran_suit" body_parts_covered = CHEST|GROIN|LEGS flags_inv = HIDEJUMPSUIT|HIDETAUR heat_protection = CHEST|GROIN|LEGS //fluffy tails! -//2061 /obj/item/clothing/head/ran - name = "Shikigami hat" + name = "shikigami hat" desc = "A hat that looks like it keeps any fluffy ears contained super warm, has little charms over it." icon_state = "ran_hat" item_state = "ran_hat" @@ -704,8 +703,9 @@ name = "cosmic winter coat" icon_state = "coatcosmic" item_state = "coatcosmic" - allowed = list(/obj/item/flashlight) hoodtype = /obj/item/clothing/head/hooded/winterhood/cosmic + light_power = 1.8 + light_range = 1.2 /obj/item/clothing/head/hooded/winterhood/cosmic icon_state = "winterhood_cosmic" @@ -880,7 +880,6 @@ blood_overlay_type = "armor" body_parts_covered = CHEST resistance_flags = NONE - mutantrace_variation = NONE armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 5, "bio" = 0, "rad" = 0, "fire" = -5, "acid" = -15) //nylon sucks against acid /obj/item/clothing/suit/assu_suit @@ -996,4 +995,4 @@ tertiary_color = sanitize_hexcolor(tertiary_color_input, desired_format=6, include_crunch=1) update_icon() user.regenerate_icons() - return TRUE \ No newline at end of file + return TRUE diff --git a/code/modules/clothing/suits/reactive_armour.dm b/code/modules/clothing/suits/reactive_armour.dm index 0d2f68f580..dff62dd2c3 100644 --- a/code/modules/clothing/suits/reactive_armour.dm +++ b/code/modules/clothing/suits/reactive_armour.dm @@ -215,14 +215,24 @@ playsound(get_turf(owner),'sound/magic/repulse.ogg', 100, 1) owner.visible_message("[src] blocks [attack_text], converting the attack into a wave of force!") var/turf/T = get_turf(owner) - var/list/thrown_items = list() - for(var/atom/movable/A in range(T, 7)) - if(A == owner || A.anchored || thrown_items[A]) + var/list/cachedrange = range(T, 7) - owner + var/safety = 50 + var/list/to_throw = list() + for(var/mob/living/L in cachedrange) + if(L.move_resist > MOVE_FORCE_EXTREMELY_STRONG) continue - var/throwtarget = get_edge_target_turf(T, get_dir(T, get_step_away(A, T))) - A.throw_at(throwtarget,10,1) - thrown_items[A] = A - + to_throw += L + for(var/obj/O in cachedrange) + if(O.anchored) + continue + to_throw += O + for(var/i in to_throw) + if(!safety) + break + var/atom/movable/AM = i + var/throwtarget = get_edge_target_turf(T, get_dir(T, get_step_away(AM, T))) + AM.throw_at(throwtarget,10,1) + safety-- reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration return 1 diff --git a/code/modules/clothing/under/color.dm b/code/modules/clothing/under/color.dm index 12cafb7e46..a18b7e5817 100644 --- a/code/modules/clothing/under/color.dm +++ b/code/modules/clothing/under/color.dm @@ -41,6 +41,10 @@ item_color = "black" resistance_flags = NONE +/obj/item/clothing/under/color/black/trackless + desc = "A black jumpsuit that has its sensors removed." + has_sensor = NO_SENSORS + /obj/item/clothing/under/skirt/color/black name = "black jumpskirt" icon_state = "black_skirt" @@ -189,13 +193,16 @@ item_state = "b_suit" item_color = "teal_skirt" - /obj/item/clothing/under/color/lightpurple name = "purple jumpsuit" icon_state = "lightpurple" item_state = "p_suit" item_color = "lightpurple" +/obj/item/clothing/under/color/lightpurple/trackless + desc = "A magically colored jumpsuit. No sensors are attached!" + has_sensor = NO_SENSORS + /obj/item/clothing/under/skirt/color/lightpurple name = "lightpurple jumpskirt" icon_state = "lightpurple_skirt" diff --git a/code/modules/error_handler/error_handler.dm b/code/modules/error_handler/error_handler.dm index 418b75e1ce..6a3d2c2233 100644 --- a/code/modules/error_handler/error_handler.dm +++ b/code/modules/error_handler/error_handler.dm @@ -19,6 +19,13 @@ GLOBAL_VAR_INIT(total_runtimes_skipped, 0) log_world("The bug with recursion runtimes has been fixed. Please remove the snowflake check from world/Error in [__FILE__]:[__LINE__]") return //this will never happen. + else if(copytext(E.name,1,18) == "Out of resources!")//18 == length() of that string + 1 + log_world("BYOND out of memory. Restarting") + log_game("BYOND out of memory. Restarting") + TgsEndProcess() + Reboot(reason = 1) + return ..() + if (islist(stack_trace_storage)) for (var/line in splittext(E.desc, "\n")) if (text2ascii(line) != 32) diff --git a/code/modules/events/holiday/vday.dm b/code/modules/events/holiday/vday.dm index 13c516960a..d3cbf03581 100644 --- a/code/modules/events/holiday/vday.dm +++ b/code/modules/events/holiday/vday.dm @@ -64,65 +64,10 @@ resistance_flags = FLAMMABLE w_class = WEIGHT_CLASS_TINY -/obj/item/valentine/New() - ..() - message = pick("Roses are red / Violets are good / One day while Andy...", - "My love for you is like the singularity. It cannot be contained.", - "Will you be my lusty xenomorph maid?", - "We go together like the clown and the external airlock.", - "Roses are red / Liches are wizards / I love you more than a whole squad of lizards.", - "Be my valentine. Law 2.", - "You must be a mime, because you leave me speechless.", - "I love you like Ian loves the HoP.", - "You're hotter than a plasma fire in toxins.", - "Are you a rogue atmos tech? Because you're taking my breath away.", - "Could I have all access... to your heart?", - "Call me the doctor, because I'm here to inspect your johnson.", - "I'm not a changeling, but you make my proboscis extend.", - "I just can't get EI NATH of you.", - "You must be a nuke op, because you make my heart explode.", - "Roses are red / Botany is a farm / Not being my Valentine / causes human harm.", - "I want you more than an assistant wants insulated gloves.", - "If I was a security officer, I'd brig you all shift.", - "Are you the janitor? Because I think I've fallen for you.", - "You're always valid to my heart.", - "I'd risk the wrath of the gods to bwoink you.", - "You look as beautiful now as the last time you were cloned.", - "Someone check the gravitational generator, because I'm only attracted to you.", - "If I were the warden I'd always let you into my armory.", - "The virologist is rogue, and the only cure is a kiss from you.", - "Would you spend some time in my upgraded sleeper?", - "You must be a silicon, because you've unbolted my heart.", - "Are you Nar'Sie? Because there's nar-one else I sie.", - "If you were a taser, you'd be set to stunning.", - "Do you have stamina damage from running through my dreams?", - "If I were an alien, would you let me hug you?", - "My love for you is stronger than a reinforced wall.", - "This must be the captain's office, because I see a fox.", - "I'm not a highlander, but there can only be one for me.", - "The floor is made of lava! Quick, get on my bed.", - "If you were an abandoned station you'd be the DEARelict.", - "If you had a pickaxe you'd be a shaft FINEr.", - "Roses are red, tide is gray, if I were an assistant I'd steal you away.", - "Roses are red, text is green, I love you more than cleanbots clean.", - "If you were a carp I'd fi-lay you.", - "I'm a nuke op, and my pinpointer leads to your heart.", - "Wanna slay my megafauna?", - "I'm a clockwork cultist. Or zl inyragvar.", - "If you were a disposal bin I'd ride you all day.", - "Put on your explorer's suit because I'm taking you to LOVEaland.", - "I must be the CMO, 'cause I saw you on my CUTE sensors.", - "You're the vomit to my flyperson.", - "You must be liquid dark matter, because you're pulling me closer.", - "Not even sorium can drive me away from you.", - "Wanna make like a borg and do some heavy petting?", - "Are you powering the station? Because you super matter to me.", - "I wish science could make me a bag of holding you.", - "Let's call the emergency CUDDLE.", - "I must be tripping on BZ, because I saw an angel walk by.", - "Wanna empty out my tool storage?", - "Did you visit the medbay after you fell from heaven?", - "Are you wearing space pants? Wanna not be?" ) +/obj/item/valentine/Initialize(mapload) + message = pick(GLOB.flirts) + return ..() + /obj/item/valentine/attackby(obj/item/W, mob/user, params) ..() @@ -140,7 +85,7 @@ /obj/item/valentine/examine(mob/user) . = ..() if(in_range(user, src) || isobserver(user)) - if( !(ishuman(user) || isobserver(user) || issilicon(user)) ) + if( !(ishuman(user) || isobserver(user) || hasSiliconAccessInArea(user)) ) user << browse("[name][stars(message)]", "window=[name]") onclose(user, "[name]") else diff --git a/code/modules/events/meteor_wave.dm b/code/modules/events/meteor_wave.dm index 6ecc1d9d42..e24ce13034 100644 --- a/code/modules/events/meteor_wave.dm +++ b/code/modules/events/meteor_wave.dm @@ -22,7 +22,7 @@ /datum/round_event/meteor_wave/setup() announceWhen = 1 - startWhen = rand(60, 90) //Yeah for SOME REASON this is measured in seconds and not deciseconds??? + startWhen = rand(90, 180) // Apparently it is by 2 seconds, so 90 is actually 180 seconds, and 180 is 360 seconds. So this is 3-6 minutes if(GLOB.singularity_counter) startWhen *= 1 - min(GLOB.singularity_counter * SINGULO_BEACON_DISTURBANCE, SINGULO_BEACON_MAX_DISTURBANCE) endWhen = startWhen + 60 diff --git a/code/modules/events/pirates.dm b/code/modules/events/pirates.dm index 8bc5491970..ab9ab96678 100644 --- a/code/modules/events/pirates.dm +++ b/code/modules/events/pirates.dm @@ -177,6 +177,7 @@ shuttleId = "pirateship" icon_screen = "syndishuttle" icon_keyboard = "syndie_key" + resistance_flags = INDESTRUCTIBLE light_color = LIGHT_COLOR_RED possible_destinations = "pirateship_away;pirateship_home;pirateship_custom" @@ -184,6 +185,7 @@ name = "pirate shuttle navigation computer" desc = "Used to designate a precise transit location for the pirate shuttle." shuttleId = "pirateship" + resistance_flags = INDESTRUCTIBLE lock_override = CAMERA_LOCK_STATION shuttlePortId = "pirateship_custom" x_offset = 9 @@ -226,6 +228,7 @@ desc = "This sophisticated machine scans the nearby space for items of value." icon = 'icons/obj/machines/research.dmi' icon_state = "tdoppler" + resistance_flags = INDESTRUCTIBLE density = TRUE var/cooldown = 300 var/next_use = 0 @@ -259,6 +262,7 @@ name = "cargo hold pad" icon = 'icons/obj/telescience.dmi' icon_state = "lpad-idle-o" + resistance_flags = INDESTRUCTIBLE var/idle_state = "lpad-idle-o" var/warmup_state = "lpad-idle" var/sending_state = "lpad-beam" @@ -272,6 +276,7 @@ /obj/machinery/computer/piratepad_control name = "cargo hold control terminal" + resistance_flags = INDESTRUCTIBLE var/status_report = "Idle" var/obj/machinery/piratepad/pad var/warmup_time = 100 diff --git a/code/modules/events/spontaneous_appendicitis.dm b/code/modules/events/spontaneous_appendicitis.dm index 9cf3a86e71..58a2875849 100644 --- a/code/modules/events/spontaneous_appendicitis.dm +++ b/code/modules/events/spontaneous_appendicitis.dm @@ -19,7 +19,7 @@ continue if(!H.getorgan(/obj/item/organ/appendix)) //Don't give the disease to some who lacks it, only for it to be auto-cured continue - if(!(MOB_ORGANIC in H.mob_biotypes)) //biotype sleeper bugs strike again, once again making appendicitis pick a target that can't take it + if(!(H.mob_biotypes & MOB_ORGANIC)) //biotype sleeper bugs strike again, once again making appendicitis pick a target that can't take it continue var/foundAlready = FALSE //don't infect someone that already has appendicitis for(var/datum/disease/appendicitis/A in H.diseases) diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm index 150f066886..b0c3121c67 100644 --- a/code/modules/flufftext/Hallucination.dm +++ b/code/modules/flufftext/Hallucination.dm @@ -18,6 +18,7 @@ GLOBAL_LIST_INIT(hallucination_list, list( /datum/hallucination/items = 4, /datum/hallucination/fire = 3, /datum/hallucination/self_delusion = 2, + /datum/hallucination/naked = 2, /datum/hallucination/delusion = 2, /datum/hallucination/shock = 1, /datum/hallucination/death = 1, @@ -65,6 +66,9 @@ GLOBAL_LIST_INIT(hallucination_list, list( //Returns a random turf in a ring around the target mob, useful for sound hallucinations /datum/hallucination/proc/random_far_turf() + var/turf/target_T = get_turf(target) + if(!target_T) + return var/x_based = prob(50) var/first_offset = pick(-8,-7,-6,-5,5,6,7,8) var/second_offset = rand(-8,8) @@ -76,7 +80,7 @@ GLOBAL_LIST_INIT(hallucination_list, list( else y_off = first_offset x_off = second_offset - var/turf/T = locate(target.x + x_off, target.y + y_off, target.z) + var/turf/T = locate(target_T.x + x_off, target_T.y + y_off, target_T.z) return T /obj/effect/hallucination @@ -1318,3 +1322,26 @@ GLOBAL_LIST_INIT(hallucination_list, list( else to_chat(C,"[G] violently grabs you!") qdel(src) + +/datum/hallucination/naked + var/image/image + +/datum/hallucination/naked/New(mob/living/carbon/C, forced = TRUE) + set waitfor = FALSE + ..() + if (C.client && C.client.prefs) + var/datum/preferences/prefs = C.client.prefs + var/mob/living/carbon/human/dummy/M = generate_or_wait_for_human_dummy(DUMMY_HUMAN_SLOT_HALLUCINATION) + prefs.copy_to(M) + COMPILE_OVERLAYS(M) + CHECK_TICK + image = image(M,C) + unset_busy_human_dummy(DUMMY_HUMAN_SLOT_HALLUCINATION) + image.override = TRUE + target.client.images |= image + QDEL_IN(src, 20 SECONDS) + +/datum/hallucination/naked/Destroy() + if(target.client) + target.client.images.Remove(image) + return ..() \ No newline at end of file diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm index cd5c9d850b..d39492d9bf 100644 --- a/code/modules/food_and_drinks/drinks/drinks.dm +++ b/code/modules/food_and_drinks/drinks/drinks.dm @@ -9,6 +9,7 @@ lefthand_file = 'icons/mob/inhands/misc/food_lefthand.dmi' righthand_file = 'icons/mob/inhands/misc/food_righthand.dmi' reagent_flags = OPENCONTAINER + reagent_value = DEFAULT_REAGENTS_VALUE var/gulp_size = 5 //This is now officially broken ... need to think of a nice way to fix it. possible_transfer_amounts = list(5,10,15,20,25,30,50) volume = 50 @@ -107,9 +108,9 @@ smash(hit_atom, throwingdatum?.thrower, TRUE) /obj/item/reagent_containers/food/drinks/proc/smash(atom/target, mob/thrower, ranged = FALSE) - if(!isGlass) + if(!isGlass && !istype(src, /obj/item/reagent_containers/food/drinks/bottle)) //I don't like this but I also don't want to rework drink container hierarchy return - if(QDELING(src) || !target) //Invalid loc + if(QDELING(src) || (ranged && !target)) return if(bartender_check(target) && ranged) return @@ -126,12 +127,69 @@ B.transform = M B.pixel_x = rand(-12, 12) B.pixel_y = rand(-12, 12) - if(prob(33)) - new/obj/item/shard(drop_location()) - playsound(src, "shatter", 70, 1) + if(isGlass) + playsound(src, "shatter", 70, 1) + if(prob(33)) + new/obj/item/shard(drop_location()) + else + B.force = 0 + B.throwforce = 0 + B.desc = "A carton with the bottom half burst open. Might give you a papercut." transfer_fingerprints_to(B) qdel(src) +/obj/item/reagent_containers/food/drinks/MouseDrop(atom/over, atom/src_location, atom/over_location, src_control, over_control, params) + var/mob/user = usr + . = ..() + if (!istype(src_location) || !istype(over_location)) + return + if (!user || user.incapacitated() || !user.Adjacent(src)) + return + if (!(locate(/obj/structure/table) in src_location) || !(locate(/obj/structure/table) in over_location)) + return + + //Are we an expert slider? + var/datum/action/innate/D = get_action_of_type(user, /datum/action/innate/drink_fling) + if(!D?.active) + if (!src_location.Adjacent(over_location)) // Regular users can only do short slides. + return + if (prob(10)) + user.visible_message("\The [user] tries to slide \the [src] down the table, but fails miserably.", "You fail to slide \the [src] down the table!") + smash(over_location, user, FALSE) + return + user.visible_message("\The [user] slides \the [src] down the table.", "You slide \the [src] down the table!") + forceMove(over_location) + return + var/distance = MANHATTAN_DISTANCE(over_location, src) + if (distance >= 8 || distance == 0) // More than a full screen to go, or trying to slide to the same tile + return + + // Geometrically checking if we're on a straight line. + var/datum/vector/V = atoms2vector(src, over_location) + var/datum/vector/V_norm = V.duplicate() + V_norm.normalize() + if (!V_norm.is_integer()) + return // Only a cardinal vector (north, south, east, west) can pass this test + + // Checks if there's tables on the path. + var/turf/dest = get_translated_turf(V) + var/turf/temp_turf = src_location + + do + temp_turf = temp_turf.get_translated_turf(V_norm) + if (!locate(/obj/structure/table) in temp_turf) + var/datum/vector/V2 = atoms2vector(src, temp_turf) + vector_translate(V2, 0.1 SECONDS) + user.visible_message("\The [user] slides \the [src] down the table... and straight into the ground!", "You slide \the [src] down the table, and straight into the ground!") + smash(over_location, user, FALSE) + return + while (temp_turf != dest) + + vector_translate(V, 0.1 SECONDS) + user.visible_message("\The [user] expertly slides \the [src] down the table.", "You slide \the [src] down the table. What a pro.") + return + + //////////////////////////////////////////////////////////////////////////////// /// Drinks. END //////////////////////////////////////////////////////////////////////////////// @@ -223,19 +281,24 @@ spillable = TRUE /obj/item/reagent_containers/food/drinks/mug/on_reagent_change(changetype) + cut_overlays() if(reagents.total_volume) - icon_state = "tea" + var/mutable_appearance/MA = mutable_appearance(icon,"mugoverlay") + MA.color = mix_color_from_reagents(reagents.reagent_list) + add_overlay(MA) else icon_state = "tea_empty" /obj/item/reagent_containers/food/drinks/mug/tea name = "Duke Purple tea" + icon_state = "tea" desc = "An insult to Duke Purple is an insult to the Space Queen! Any proper gentleman will fight you, if you sully this tea." list_reagents = list(/datum/reagent/consumable/tea = 30) /obj/item/reagent_containers/food/drinks/mug/coco name = "Dutch hot coco" desc = "Made in Space South America." + icon_state = "coco" list_reagents = list(/datum/reagent/consumable/hot_coco = 30, /datum/reagent/consumable/sugar = 5) foodtype = SUGAR resistance_flags = FREEZE_PROOF @@ -289,28 +352,6 @@ icon_state = "juicebox" volume = 15 //I figure if you have to craft these it should at least be slightly better than something you can get for free from a watercooler -/obj/item/reagent_containers/food/drinks/sillycup/smallcarton/smash(atom/target, mob/thrower, ranged = FALSE) - if(bartender_check(target) && ranged) - return - var/obj/item/broken_bottle/B = new (loc) - B.icon_state = icon_state - var/icon/I = new('icons/obj/drinks.dmi', src.icon_state) - I.Blend(B.broken_outline, ICON_OVERLAY, rand(5), 1) - I.SwapColor(rgb(255, 0, 220, 255), rgb(0, 0, 0, 0)) - B.icon = I - B.name = "broken [name]" - B.force = 0 - B.throwforce = 0 - B.desc = "A carton with the bottom half burst open. Might give you a papercut." - if(ranged) - var/matrix/M = matrix(B.transform) - M.Turn(rand(-170, 170)) - B.transform = M - B.pixel_x = rand(-12, 12) - B.pixel_y = rand(-12, 12) - transfer_fingerprints_to(B) - qdel(src) - /obj/item/reagent_containers/food/drinks/sillycup/smallcarton/on_reagent_change(changetype) if (reagents.reagent_list.len) switch(reagents.get_master_reagent_id()) diff --git a/code/modules/food_and_drinks/drinks/drinks/bottle.dm b/code/modules/food_and_drinks/drinks/drinks/bottle.dm index 7f2b24ca11..07026e79de 100644 --- a/code/modules/food_and_drinks/drinks/drinks/bottle.dm +++ b/code/modules/food_and_drinks/drinks/drinks/bottle.dm @@ -16,40 +16,6 @@ isGlass = TRUE foodtype = ALCOHOL - -/obj/item/reagent_containers/food/drinks/bottle/smash(mob/living/target, mob/thrower, ranged = FALSE) - //Creates a shattering noise and replaces the bottle with a broken_bottle - if(bartender_check(target) && ranged) - return - var/obj/item/broken_bottle/B = new (loc) - if(!ranged) - thrower.put_in_hands(B) - else - var/matrix/M = matrix(B.transform) - M.Turn(rand(-170, 170)) - B.transform = M - B.pixel_x = rand(-12, 12) - B.pixel_y = rand(-12, 12) - B.icon_state = icon_state - - var/icon/I = new('icons/obj/drinks.dmi', src.icon_state) - I.Blend(B.broken_outline, ICON_OVERLAY, rand(5), 1) - I.SwapColor(rgb(255, 0, 220, 255), rgb(0, 0, 0, 0)) - B.icon = I - - if(isGlass) - if(prob(33)) - new/obj/item/shard(drop_location()) - playsound(src, "shatter", 70, 1) - else - B.force = 0 - B.throwforce = 0 - B.desc = "A carton with the bottom half burst open. Might give you a papercut." - B.name = "broken [name]" - transfer_fingerprints_to(B) - - qdel(src) - /obj/item/reagent_containers/food/drinks/bottle/attack(mob/living/target, mob/living/user) if(!target) @@ -109,7 +75,7 @@ //Keeping this here for now, I'll ask if I should keep it here. /obj/item/broken_bottle name = "broken bottle" - desc = "A bottle with a sharp broken bottom." + desc = "A shattered glass container with sharp edges." icon = 'icons/obj/drinks.dmi' icon_state = "broken_bottle" force = 9 diff --git a/code/modules/food_and_drinks/food.dm b/code/modules/food_and_drinks/food.dm index 6d3f007fd9..2af24080cb 100644 --- a/code/modules/food_and_drinks/food.dm +++ b/code/modules/food_and_drinks/food.dm @@ -12,6 +12,7 @@ possible_transfer_amounts = list() volume = 50 //Sets the default container amount for all food items. reagent_flags = INJECTABLE + reagent_value = NO_REAGENTS_VALUE resistance_flags = FLAMMABLE var/foodtype = NONE var/last_check_time diff --git a/code/modules/food_and_drinks/food/snacks.dm b/code/modules/food_and_drinks/food/snacks.dm index c068c1aa40..0b277e328b 100644 --- a/code/modules/food_and_drinks/food/snacks.dm +++ b/code/modules/food_and_drinks/food/snacks.dm @@ -71,10 +71,11 @@ All foods are distributed among various categories. Use common sense. if(!eater) return if(!reagents.total_volume) - var/obj/item/trash_item = generate_trash(eater) + var/mob/living/location = loc + var/obj/item/trash_item = generate_trash(location) qdel(src) - eater.put_in_hands(trash_item) - + if(istype(location)) + location.put_in_hands(trash_item) /obj/item/reagent_containers/food/snacks/attack_self(mob/user) return @@ -245,7 +246,7 @@ All foods are distributed among various categories. Use common sense. return TRUE /obj/item/reagent_containers/food/snacks/proc/initialize_slice(obj/item/reagent_containers/food/snacks/slice, reagents_per_slice) - slice.create_reagents(slice.volume) + slice.create_reagents(slice.volume, reagent_flags, reagent_value) reagents.trans_to(slice,reagents_per_slice) if(name != initial(name)) slice.name = "slice of [name]" @@ -279,7 +280,7 @@ All foods are distributed among various categories. Use common sense. // initialize_cooked_food() is called when microwaving the food /obj/item/reagent_containers/food/snacks/proc/initialize_cooked_food(obj/item/reagent_containers/food/snacks/S, cooking_efficiency = 1) - S.create_reagents(S.volume) + S.create_reagents(S.volume, reagent_flags, reagent_value) if(reagents) reagents.trans_to(S, reagents.total_volume) if(S.bonus_reagents && S.bonus_reagents.len) diff --git a/code/modules/food_and_drinks/food/snacks/meat.dm b/code/modules/food_and_drinks/food/snacks/meat.dm index 28fb2edf61..d44f859823 100644 --- a/code/modules/food_and_drinks/food/snacks/meat.dm +++ b/code/modules/food_and_drinks/food/snacks/meat.dm @@ -271,7 +271,7 @@ /obj/item/reagent_containers/food/snacks/meat/slab/meatwheat name = "meatwheat clump" desc = "This doesn't look like meat, but your standards aren't that high to begin with." - list_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/nutriment/vitamin = 2, /datum/reagent/blood = 5, /datum/reagent/consumable/cooking_oil = 1) + list_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/nutriment/vitamin = 2, /datum/reagent/consumable/cooking_oil = 1) filling_color = rgb(150, 0, 0) icon_state = "meatwheat_clump" bitesize = 4 diff --git a/code/modules/food_and_drinks/food/snacks_egg.dm b/code/modules/food_and_drinks/food/snacks_egg.dm index f01966a0ff..c65e42c0e4 100644 --- a/code/modules/food_and_drinks/food/snacks_egg.dm +++ b/code/modules/food_and_drinks/food/snacks_egg.dm @@ -96,6 +96,16 @@ tastes = list("egg" = 4, "salt" = 1, "pepper" = 1) foodtype = MEAT | FRIED | BREAKFAST +/obj/item/reagent_containers/food/snacks/baconegg + name = "bacon and eggs" + desc = "A fried egg with a side of bacon. Delicious!" + icon_state = "baconegg" + bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 1) + bitesize = 1 + filling_color = "#FFFFF0" + tastes = list("egg" = 2, "bacon" = 2, "salt" = 1, "pepper" = 1) + foodtype = MEAT | FRIED | BREAKFAST + /obj/item/reagent_containers/food/snacks/boiledegg name = "boiled egg" desc = "A hard boiled egg." diff --git a/code/modules/food_and_drinks/food/snacks_other.dm b/code/modules/food_and_drinks/food/snacks_other.dm index 41b08e8c7f..a7090a5274 100644 --- a/code/modules/food_and_drinks/food/snacks_other.dm +++ b/code/modules/food_and_drinks/food/snacks_other.dm @@ -549,7 +549,7 @@ name = "chocolate" desc = "A tiny and sweet chocolate. Has a 'strawberry' filling!" icon_state = "tiny_chocolate" - list_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/sugar = 1, /datum/reagent/consumable/coco = 1, /datum/reagent/drug/aphrodisiac = 1) + list_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/sugar = 1, /datum/reagent/consumable/coco = 1) filling_color = "#A0522D" tastes = list("chocolate" = 1) foodtype = JUNKFOOD | SUGAR diff --git a/code/modules/food_and_drinks/food/snacks_pastry.dm b/code/modules/food_and_drinks/food/snacks_pastry.dm index 1c8b70dc13..de1f00ae5d 100644 --- a/code/modules/food_and_drinks/food/snacks_pastry.dm +++ b/code/modules/food_and_drinks/food/snacks_pastry.dm @@ -353,6 +353,13 @@ tastes = list("muffin" = 3, "spookiness" = 1) foodtype = GRAIN | FRUIT | SUGAR | BREAKFAST +/obj/item/reagent_containers/food/snacks/muffin/poppy + name = "poppy muffin" + icon_state = "poppymuffin" + desc = "A classic lemon poppy seed muffin. Do not consume prior to drug testing." + tastes = list("muffin" = 3, "lemon" = 1, "seeds" = 1) + foodtype = GRAIN | SUGAR | BREAKFAST + /obj/item/reagent_containers/food/snacks/chawanmushi name = "chawanmushi" desc = "A legendary egg custard that makes friends out of enemies. Probably too hot for a cat to eat." diff --git a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm index 4406491f10..24f60300fa 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm @@ -212,7 +212,7 @@ meatslab.throw_at(pick(nearby_turfs),i,3) for (var/turfs=1 to meat_produced) var/turf/gibturf = pick(nearby_turfs) - if (!gibturf.density && src in view(gibturf)) + if (!gibturf.density && (src in view(gibturf))) new gibtype(gibturf,i,diseases) pixel_x = initial(pixel_x) //return to its spot after shaking diff --git a/code/modules/food_and_drinks/kitchen_machinery/microwave.dm b/code/modules/food_and_drinks/kitchen_machinery/microwave.dm index e4d36b29d2..e908662658 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/microwave.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/microwave.dm @@ -55,7 +55,7 @@ if(!operating) . += "Alt-click [src] to turn it on." - if(!in_range(user, src) && !issilicon(user) && !isobserver(user)) + if(!in_range(user, src) && !hasSiliconAccessInArea(user) && !isobserver(user)) . += "You're too far away to examine [src]'s contents and display!" return if(operating) @@ -63,7 +63,7 @@ return if(length(ingredients)) - if(issilicon(user)) + if(hasSiliconAccessInArea(user)) . += "\The [src] camera shows:" else . += "\The [src] contains:" @@ -187,14 +187,14 @@ /obj/machinery/microwave/AltClick(mob/user) . = ..() - if(user.canUseTopic(src, !issilicon(usr))) + if(user.canUseTopic(src, !hasSiliconAccessInArea(user))) cook() return TRUE /obj/machinery/microwave/ui_interact(mob/user) . = ..() - if(operating || panel_open || !anchored || !user.canUseTopic(src, !issilicon(user))) + if(operating || panel_open || !anchored || !user.canUseTopic(src, !hasSiliconAccessInArea(user))) return if(isAI(user) && (stat & NOPOWER)) return @@ -206,10 +206,10 @@ to_chat(user, "\The [src] is empty.") return - var/choice = show_radial_menu(user, src, isAI(user) ? ai_radial_options : radial_options, require_near = !issilicon(user)) + var/choice = show_radial_menu(user, src, isAI(user) ? ai_radial_options : radial_options, require_near = !hasSiliconAccessInArea(user)) // post choice verification - if(operating || panel_open || !anchored || !user.canUseTopic(src, !issilicon(user))) + if(operating || panel_open || !anchored || !user.canUseTopic(src, !hasSiliconAccessInArea(user))) return if(isAI(user) && (stat & NOPOWER)) return diff --git a/code/modules/food_and_drinks/pizzabox.dm b/code/modules/food_and_drinks/pizzabox.dm index bd556b8397..b163c6ba97 100644 --- a/code/modules/food_and_drinks/pizzabox.dm +++ b/code/modules/food_and_drinks/pizzabox.dm @@ -220,7 +220,7 @@ unprocess() qdel(src) if(!bomb_active || bomb_defused) - if(bomb_defused && bomb in src) + if(bomb_defused && (bomb in src)) bomb.defuse() bomb_active = FALSE unprocess() diff --git a/code/modules/food_and_drinks/recipes/drinks_recipes.dm b/code/modules/food_and_drinks/recipes/drinks_recipes.dm index 9df650500a..c94118ddf1 100644 --- a/code/modules/food_and_drinks/recipes/drinks_recipes.dm +++ b/code/modules/food_and_drinks/recipes/drinks_recipes.dm @@ -585,6 +585,14 @@ mix_message = "The mixture develops a sinister glow." mix_sound = 'sound/effects/singlebeat.ogg' +/datum/chemical_reaction/cogchamp + name = "CogChamp" + id = /datum/reagent/consumable/ethanol/cogchamp + results = list(/datum/reagent/consumable/ethanol/cogchamp = 3) + required_reagents = list(/datum/reagent/consumable/ethanol/cognac = 1, /datum/reagent/fuel = 1, /datum/reagent/consumable/ethanol/screwdrivercocktail = 1) + mix_message = "You hear faint sounds of gears turning as it mixes." + mix_sound = 'sound/effects/clockcult_gateway_closing.ogg' + /datum/chemical_reaction/quadruplesec name = "Quadruple Sec" id = /datum/reagent/consumable/ethanol/quadruple_sec diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_egg.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_egg.dm index 6d495d1c79..c049cd7563 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_egg.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_egg.dm @@ -13,6 +13,15 @@ result = /obj/item/reagent_containers/food/snacks/friedegg subcategory = CAT_EGG +/datum/crafting_recipe/food/baconegg + name = "Bacon and Eggs" + reqs = list( + /obj/item/reagent_containers/food/snacks/friedegg = 1, + /obj/item/reagent_containers/food/snacks/meat/bacon = 1 + ) + result = /obj/item/reagent_containers/food/snacks/baconegg + subcategory = CAT_EGG + /datum/crafting_recipe/food/omelette name = "Omelette" reqs = list( diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm index b545702e3e..62b8509eb1 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm @@ -377,6 +377,17 @@ datum/crafting_recipe/food/donut/meat result = /obj/item/reagent_containers/food/snacks/muffin/booberry subcategory = CAT_PASTRY +/datum/crafting_recipe/food/poppymuffin + name = "Poppy muffin" + reqs = list( + /datum/reagent/consumable/milk = 5, + /obj/item/reagent_containers/food/snacks/pastrybase = 1, + /obj/item/reagent_containers/food/snacks/grown/citrus/lemon = 1, + /obj/item/seeds/poppy = 1 + ) + result = /obj/item/reagent_containers/food/snacks/muffin/poppy + subcategory = CAT_PASTRY + /datum/crafting_recipe/food/chawanmushi name = "Chawanmushi" reqs = list( diff --git a/code/modules/holodeck/computer.dm b/code/modules/holodeck/computer.dm index d551222836..b5cbed8b79 100644 --- a/code/modules/holodeck/computer.dm +++ b/code/modules/holodeck/computer.dm @@ -92,7 +92,7 @@ data["emagged"] = TRUE data["emag_programs"] = emag_programs data["program"] = program - data["can_toggle_safety"] = issilicon(user) || IsAdminGhost(user) + data["can_toggle_safety"] = hasSiliconAccessInArea(user) || IsAdminGhost(user) return data @@ -109,7 +109,7 @@ if(A) load_program(A) if("safety") - if(!issilicon(usr) && !IsAdminGhost(usr)) + if(!hasSiliconAccessInArea(usr) && !IsAdminGhost(usr)) var/msg = "[key_name(usr)] attempted to emag the holodeck using a href they shouldn't have!" message_admins(msg) log_admin(msg) diff --git a/code/modules/hydroponics/gene_modder.dm b/code/modules/hydroponics/gene_modder.dm index 8f2900c8a6..fb9bb8ba7b 100644 --- a/code/modules/hydroponics/gene_modder.dm +++ b/code/modules/hydroponics/gene_modder.dm @@ -105,7 +105,7 @@ return var/datum/browser/popup = new(user, "plantdna", "Plant DNA Manipulator", 450, 600) - if(!(in_range(src, user) || issilicon(user))) + if(!(in_range(src, user) || hasSiliconAccessInArea(user))) popup.close() return diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm index f99cfde92d..65d942ca2b 100644 --- a/code/modules/hydroponics/grown.dm +++ b/code/modules/hydroponics/grown.dm @@ -15,6 +15,7 @@ // Saves us from having to define each stupid grown's dried_type as itself. // If you don't want a plant to be driable (watermelons) set this to null in the time definition. resistance_flags = FLAMMABLE + reagent_value = HARVEST_REAGENTS_VALUE var/dry_grind = FALSE //If TRUE, this object needs to be dry to be ground up var/can_distill = TRUE //If FALSE, this object cannot be distilled into an alcohol. var/distill_reagent //If NULL and this object can be distilled, it uses a generic fruit_wine reagent and adjusts its variables. diff --git a/code/modules/hydroponics/grown/cereals.dm b/code/modules/hydroponics/grown/cereals.dm index c5a7e0797a..1d1309acb8 100644 --- a/code/modules/hydroponics/grown/cereals.dm +++ b/code/modules/hydroponics/grown/cereals.dm @@ -33,6 +33,7 @@ icon_state = "seed-oat" species = "oat" plantname = "Oat Stalks" + rarity = 10 //Not really new, just better product = /obj/item/reagent_containers/food/snacks/grown/oat mutatelist = list() @@ -45,7 +46,7 @@ filling_color = "#556B2F" bitesize_mod = 2 foodtype = GRAIN - grind_results = list(/datum/reagent/consumable/flour = 0) + grind_results = list(/datum/reagent/consumable/flour = 0.5) //So when it grinds it has 50% more flour tastes = list("oat" = 1) distill_reagent = /datum/reagent/consumable/ethanol/ale @@ -81,6 +82,7 @@ species = "meatwheat" plantname = "Meatwheat" product = /obj/item/reagent_containers/food/snacks/grown/meatwheat + rarity = 40 mutatelist = list() /obj/item/reagent_containers/food/snacks/grown/meatwheat diff --git a/code/modules/hydroponics/growninedible.dm b/code/modules/hydroponics/growninedible.dm index ef925e3965..f4859ffb1e 100644 --- a/code/modules/hydroponics/growninedible.dm +++ b/code/modules/hydroponics/growninedible.dm @@ -11,7 +11,7 @@ /obj/item/grown/Initialize(newloc, obj/item/seeds/new_seed) . = ..() - create_reagents(50) + create_reagents(50, NONE, HARVEST_REAGENTS_VALUE) if(new_seed) seed = new_seed.Copy() diff --git a/code/modules/hydroponics/plant_genes.dm b/code/modules/hydroponics/plant_genes.dm index 756788898a..272f44267e 100644 --- a/code/modules/hydroponics/plant_genes.dm +++ b/code/modules/hydroponics/plant_genes.dm @@ -109,7 +109,7 @@ // Reagent genes store reagent ID and reagent ratio. Amount of reagent in the plant = 1 + (potency * rate) /datum/plant_gene/reagent name = "Nutriment" - var/reagent_id = "nutriment" + var/reagent_id = /datum/reagent/consumable/nutriment var/rate = 0.04 /datum/plant_gene/reagent/get_name() diff --git a/code/modules/integrated_electronics/core/printer.dm b/code/modules/integrated_electronics/core/printer.dm index f0aa10f2da..ea52b6d461 100644 --- a/code/modules/integrated_electronics/core/printer.dm +++ b/code/modules/integrated_electronics/core/printer.dm @@ -107,7 +107,7 @@ interact(user) /obj/item/integrated_circuit_printer/interact(mob/user) - if(!(in_range(src, user) || issilicon(user))) + if(!(in_range(src, user) || hasSiliconAccessInArea(user))) return if(isnull(current_category)) diff --git a/code/modules/integrated_electronics/core/special_pins/dir_pin.dm b/code/modules/integrated_electronics/core/special_pins/dir_pin.dm index 4ce5597af8..eb4d9a3366 100644 --- a/code/modules/integrated_electronics/core/special_pins/dir_pin.dm +++ b/code/modules/integrated_electronics/core/special_pins/dir_pin.dm @@ -18,7 +18,7 @@ write_data_to_pin(new_data) /datum/integrated_io/dir/write_data_to_pin(var/new_data) - if(isnull(new_data) || new_data in list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST)/* + list(UP, DOWN)*/) + if(isnull(new_data) || (new_data in GLOB.alldirs/* + list(UP, DOWN)*/)) data = new_data holder.on_data_written() diff --git a/code/modules/jobs/access.dm b/code/modules/jobs/access.dm index 81f47b9a1e..eddb18b25e 100644 --- a/code/modules/jobs/access.dm +++ b/code/modules/jobs/access.dm @@ -4,7 +4,7 @@ //check if it doesn't require any access at all if(src.check_access(null)) return TRUE - if(issilicon(M)) + if(hasSiliconAccessInArea(M)) if(ispAI(M)) return FALSE return TRUE //AI can do whatever it wants diff --git a/code/modules/jobs/job_exp.dm b/code/modules/jobs/job_exp.dm index f99bf65071..5ff791c5f3 100644 --- a/code/modules/jobs/job_exp.dm +++ b/code/modules/jobs/job_exp.dm @@ -40,7 +40,7 @@ GLOBAL_PROTECT(exp_to_update) return exp_type /proc/job_is_xp_locked(jobtitle) - if(!CONFIG_GET(flag/use_exp_restrictions_heads) && jobtitle in (GLOB.command_positions | list("AI"))) + if(!CONFIG_GET(flag/use_exp_restrictions_heads) && (jobtitle in (GLOB.command_positions | list("AI")))) return FALSE if(!CONFIG_GET(flag/use_exp_restrictions_other) && !(jobtitle in (GLOB.command_positions | list("AI")))) return FALSE diff --git a/code/modules/jobs/job_types/bartender.dm b/code/modules/jobs/job_types/bartender.dm index 0ace449757..cffeceea9c 100644 --- a/code/modules/jobs/job_types/bartender.dm +++ b/code/modules/jobs/job_types/bartender.dm @@ -28,3 +28,7 @@ backpack_contents = list(/obj/item/storage/box/beanbag=1,/obj/item/book/granter/action/drink_fling=1) shoes = /obj/item/clothing/shoes/laceup +/datum/job/bartender/after_spawn(mob/living/H, mob/M, latejoin = FALSE) + . = ..() + var/datum/action/innate/drink_fling/D = new + D.Grant(H) diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm index f128a76da2..459212aad0 100644 --- a/code/modules/library/lib_items.dm +++ b/code/modules/library/lib_items.dm @@ -112,7 +112,6 @@ else return ..() - /obj/structure/bookcase/attack_hand(mob/user) . = ..() if(.) @@ -129,14 +128,17 @@ choice.forceMove(drop_location()) update_icon() -/obj/structure/bookcase/attack_ghost(mob/dead/observer/user as mob) - if(contents.len && in_range(user, src)) - var/obj/item/book/choice = input("Which book would you like to read?") as null|obj in contents - if(choice) - if(!istype(choice)) //spellbook, cult tome, or the one weird bible storage - to_chat(user,"A mysterious force is keeping you from reading that.") - return - choice.attack_self(user) +/obj/structure/bookcase/attack_ghost(mob/dead/observer/user) + . = ..() + if(!length(contents)) + to_chat(user, "It's empty!") + return + var/obj/item/book/choice = input("Which book would you like to read?") as null|obj in contents + if(choice) + if(!istype(choice)) //spellbook, cult tome, or the one weird bible storage + to_chat(user,"A mysterious force is keeping you from reading that.") + return + choice.attack_ghost(user) /obj/structure/bookcase/deconstruct(disassembled = TRUE) new /obj/item/stack/sheet/mineral/wood(loc, 4) @@ -211,14 +213,17 @@ to_chat(user, "You skim through the book but can't comprehend any of it.") return if(dat) - user << browse("Penned by [author].
" + "[dat]", "window=book[window_size != null ? ";size=[window_size]" : ""]") - if(istype(user, /mob/living)) - user.visible_message("[user] opens a book titled \"[title]\" and begins reading intently.") - SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "book_nerd", /datum/mood_event/book_nerd) - onclose(user, "book") + show_to(user) + user.visible_message("[user] opens a book titled \"[title]\" and begins reading intently.") else to_chat(user, "This book is completely blank!") +/obj/item/book/attack_ghost(mob/dead/observer/O) + . = ..() + show_to(O) + +/obj/item/book/proc/show_to(mob/user) + user << browse("Penned by [author].
" + "[dat]", "window=book[window_size != null ? ";size=[window_size]" : ""]") /obj/item/book/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/pen)) @@ -320,9 +325,6 @@ else ..() -/obj/item/book/attack_ghost(mob/user) - attack_self(user) - /* * Barcode Scanner diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm index 204a2de9a6..008724b10f 100644 --- a/code/modules/library/lib_machines.dm +++ b/code/modules/library/lib_machines.dm @@ -441,7 +441,7 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums if(!GLOB.news_network) alert("No news network found on station. Aborting.") var/channelexists = 0 - for(var/datum/newscaster/feed_channel/FC in GLOB.news_network.network_channels) + for(var/datum/news/feed_channel/FC in GLOB.news_network.network_channels) if(FC.channel_name == "Nanotrasen Book Club") channelexists = 1 break diff --git a/code/modules/mining/equipment/mining_tools.dm b/code/modules/mining/equipment/mining_tools.dm index cc41682f96..32f9812068 100644 --- a/code/modules/mining/equipment/mining_tools.dm +++ b/code/modules/mining/equipment/mining_tools.dm @@ -66,6 +66,22 @@ force = 19 materials = list(MAT_DIAMOND=4000) +/obj/item/pickaxe/plasteel + name = "plasteel-tipped pickaxe" + icon_state = "titaxe" + toolspeed = 0.5 + desc = "A pickaxe with a plasteel pick head. Less robust at cracking rock walls and digging up dirt than the titanium pickaxe, but better at cracking open skulls." + force = 19 + materials = list(MAT_METAL=2000, MAT_PLASMA=2000) + +/obj/item/pickaxe/titanium + name = "titanium-tipped pickaxe" + icon_state = "psteelaxe" + toolspeed = 0.3 + desc = "A pickaxe with a titanium pick head. Extremely robust at cracking rock walls and digging up dirt, but less than the plasteel pickaxe at cracking open skulls." + force = 17 + materials = list(MAT_TITANIUM=4000) + /obj/item/pickaxe/drill name = "mining drill" icon_state = "handdrill" diff --git a/code/modules/mining/equipment/resonator.dm b/code/modules/mining/equipment/resonator.dm index f63b459f10..133cb41c33 100644 --- a/code/modules/mining/equipment/resonator.dm +++ b/code/modules/mining/equipment/resonator.dm @@ -46,7 +46,7 @@ /obj/item/resonator/pre_attack(atom/target, mob/user, params) if(check_allowed_items(target, 1)) CreateResonance(target, user) - return TRUE + return ..() //resonance field, crushes rock, damages mobs /obj/effect/temp_visual/resonance diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm index 1ddb3a3189..ac4cee8c42 100644 --- a/code/modules/mining/mine_items.dm +++ b/code/modules/mining/mine_items.dm @@ -93,7 +93,7 @@ req_access = list() circuit = /obj/item/circuitboard/computer/mining_shuttle/common shuttleId = "mining_common" - possible_destinations = "whiteship_home;lavaland_common_away;landing_zone_dock;mining_public" + possible_destinations = "lavaland_common_away;commonmining_home" /**********************Mining car (Crate like thing, not the rail car)**************************/ diff --git a/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm b/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm index 241ec8118e..92bc8e407b 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm @@ -16,7 +16,7 @@ from doing this unless you absolutely know what you are doing, and have defined a conversion in savefile.dm */ -/proc/init_sprite_accessory_subtypes(prototype, list/L, list/male, list/female,var/roundstart = FALSE)//Roundstart argument builds a specific list for roundstart parts where some parts may be locked +/proc/init_sprite_accessory_subtypes(prototype, list/L, list/male, list/female, roundstart = FALSE, skip_prototype = TRUE)//Roundstart argument builds a specific list for roundstart parts where some parts may be locked if(!istype(L)) L = list() if(!istype(male)) @@ -25,7 +25,7 @@ female = list() for(var/path in typesof(prototype)) - if(path == prototype) + if(path == prototype && skip_prototype) continue if(roundstart) var/datum/sprite_accessory/P = path diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 3559edc0fb..325ea6e8ed 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -55,7 +55,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) var/deadchat_name var/datum/spawners_menu/spawners_menu -/mob/dead/observer/Initialize() +/mob/dead/observer/Initialize(mapload, mob/body) set_invisibility(GLOB.observer_default_invisibility) verbs += list( @@ -76,11 +76,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) updateallghostimages() - var/turf/T - var/mob/body = loc - if(ismob(body)) - T = get_turf(body) //Where is the body located? - + if(body) gender = body.gender if(body.mind && body.mind.name) name = body.mind.name @@ -105,14 +101,15 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) update_icon() - if(!T) + if(!isturf(loc)) + var/turf/T var/list/turfs = get_area_turfs(/area/shuttle/arrival) if(turfs.len) T = pick(turfs) else T = SSmapping.get_station_center() - forceMove(T) + forceMove(T) if(!name) //To prevent nameless ghosts name = random_unique_name(gender) @@ -196,13 +193,13 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) else ghostimage_default.icon_state = new_form - if(ghost_accs >= GHOST_ACCS_DIR && icon_state in GLOB.ghost_forms_with_directions_list) //if this icon has dirs AND the client wants to show them, we make sure we update the dir on movement + if(ghost_accs >= GHOST_ACCS_DIR && (icon_state in GLOB.ghost_forms_with_directions_list)) //if this icon has dirs AND the client wants to show them, we make sure we update the dir on movement updatedir = 1 else updatedir = 0 //stop updating the dir in case we want to show accessories with dirs on a ghost sprite without dirs setDir(2 )//reset the dir to its default so the sprites all properly align up - if(ghost_accs == GHOST_ACCS_FULL && icon_state in GLOB.ghost_forms_with_accessories_list) //check if this form supports accessories and if the client wants to show them + if(ghost_accs == GHOST_ACCS_FULL && (icon_state in GLOB.ghost_forms_with_accessories_list)) //check if this form supports accessories and if the client wants to show them var/datum/sprite_accessory/S if(facial_hair_style) S = GLOB.facial_hair_styles_list[facial_hair_style] @@ -268,7 +265,7 @@ Works together with spawning an observer, noted above. if(!key || key[1] == "@" || (SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, can_reenter_corpse, special, penalize) & COMPONENT_BLOCK_GHOSTING)) return //mob has no key, is an aghost or some component hijacked. stop_sound_channel(CHANNEL_HEARTBEAT) //Stop heartbeat sounds because You Are A Ghost Now - var/mob/dead/observer/ghost = new(src) // Transfer safety to observer spawning proc. + var/mob/dead/observer/ghost = new(get_turf(src), src) // Transfer safety to observer spawning proc. SStgui.on_transfer(src, ghost) // Transfer NanoUIs. ghost.can_reenter_corpse = can_reenter_corpse if (client && client.prefs && client.prefs.auto_ooc) @@ -310,8 +307,9 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp var/obj/machinery/cryopod/C = loc C.despawn_occupant() else - ghostize(0, penalize = TRUE, voluntary = TRUE) //0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3 suicide_log(TRUE) + ghostize(FALSE, penalize = TRUE, voluntary = TRUE) //FALSE parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3 + /mob/camera/verb/ghost() set category = "OOC" @@ -479,32 +477,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp pixel_y = 0 animate(src, pixel_y = 2, time = 10, loop = -1) -/mob/dead/observer/verb/observe() - set name = "Observe" - set category = "Ghost" - - var/list/creatures = getpois() - - reset_perspective(null) - - var/eye_name = null - - eye_name = input("Please, select a player!", "Observe", null, null) as null|anything in creatures - - if (!eye_name) - return - - var/mob/mob_eye = creatures[eye_name] - //Istype so we filter out points of interest that are not mobs - if(client && mob_eye && istype(mob_eye)) - client.eye = mob_eye - if(mob_eye.hud_used) - client.screen = list() - LAZYINITLIST(mob_eye.observers) - mob_eye.observers |= src - mob_eye.hud_used.show_hud(mob_eye.hud_used.hud_version, src) - observetarget = mob_eye - /mob/dead/observer/verb/jumptomob() //Moves the ghost instead of just changing the ghosts's eye -Nodrak set category = "Ghost" set name = "Jump to Mob" @@ -796,7 +768,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp update_icon() /mob/dead/observer/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE) - return IsAdminGhost(usr) || (M.ghost_flags & INTERACT_GHOST_READ) + return IsAdminGhost(usr) /mob/dead/observer/is_literate() return 1 @@ -831,6 +803,32 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp client.screen = list() hud_used.show_hud(hud_used.hud_version) +/mob/dead/observer/verb/observe() + set name = "Observe" + set category = "OOC" + + var/list/creatures = getpois() + + reset_perspective(null) + + var/eye_name = null + + eye_name = input("Please, select a player!", "Observe", null, null) as null|anything in creatures + + if (!eye_name) + return + + var/mob/mob_eye = creatures[eye_name] + //Istype so we filter out points of interest that are not mobs + if(client && mob_eye && istype(mob_eye)) + client.eye = mob_eye + if(mob_eye.hud_used) + client.screen = list() + LAZYINITLIST(mob_eye.observers) + mob_eye.observers |= src + mob_eye.hud_used.show_hud(mob_eye.hud_used.hud_version, src) + observetarget = mob_eye + /mob/dead/observer/verb/register_pai_candidate() set category = "Ghost" set name = "pAI Setup" diff --git a/code/modules/mob/dead/observer/say.dm b/code/modules/mob/dead/observer/say.dm index 2c4743f7d3..8712f39531 100644 --- a/code/modules/mob/dead/observer/say.dm +++ b/code/modules/mob/dead/observer/say.dm @@ -22,7 +22,7 @@ . = say_dead(message) /mob/dead/observer/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source) - . = ..() + SEND_SIGNAL(src, COMSIG_MOVABLE_HEAR, args) //parent calls can't overwrite the current proc args. var/atom/movable/to_follow = speaker if(radio_freq) var/atom/movable/virtualspeaker/V = speaker @@ -36,4 +36,3 @@ // Recompose the message, because it's scrambled by default message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode, FALSE, source) to_chat(src, "[link] [message]") - diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm index a14fdb0b53..3b64c35969 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -10,7 +10,7 @@ organ_flags = ORGAN_VITAL attack_verb = list("attacked", "slapped", "whacked") ///The brain's organ variables are significantly more different than the other organs, with half the decay rate for balance reasons, and twice the maxHealth - decay_factor = STANDARD_ORGAN_DECAY / 4 //30 minutes of decaying to result in a fully damaged brain, since a fast decay rate would be unfun gameplay-wise + decay_factor = STANDARD_ORGAN_DECAY / 2 //30 minutes of decaying to result in a fully damaged brain, since a fast decay rate would be unfun gameplay-wise healing_factor = STANDARD_ORGAN_HEALING / 2 maxHealth = BRAIN_DAMAGE_DEATH diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index ef33afec25..6460d8331d 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -3,7 +3,7 @@ /mob/living/carbon/Initialize() . = ..() - create_reagents(1000) + create_reagents(1000, NONE, NO_REAGENTS_VALUE) update_body_parts() //to update the carbon's new bodyparts appearance GLOB.carbon_list += src blood_volume = (BLOOD_VOLUME_NORMAL * blood_ratio) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index b560699a58..8e19fa7776 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -99,6 +99,10 @@ . += "[t_He] [t_has] [glasses.get_examine_string(user)] covering [t_his] eyes." else if(eye_color == BLOODCULT_EYE && iscultist(src) && HAS_TRAIT(src, TRAIT_CULT_EYES)) . += "[t_His] eyes are glowing an unnatural red!" + else if(HAS_TRAIT(src, TRAIT_HIJACKER)) + var/obj/item/implant/hijack/H = user.getImplant(/obj/item/implant/hijack) + if (H && !H.stealthmode && H.toggled) + . += "[t_His] eyes are flickering a bright yellow!" //ears if(ears && !(SLOT_EARS in obscured)) @@ -390,10 +394,10 @@ if(invisible_man) . += "...?" else - var/flavor = print_flavor_text() + var/flavor = print_flavor_text(flavor_text) if(flavor) . += flavor - var/temp_flavor = print_flavor_text_2() + var/temp_flavor = print_flavor_text(flavor_text_2) if(temp_flavor) . += temp_flavor SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 2b03e22b77..ef3d4cbb98 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -9,6 +9,8 @@ verbs += /mob/living/proc/mob_sleep verbs += /mob/living/proc/lay_down verbs += /mob/living/carbon/human/proc/underwear_toggle //fwee + verbs += /mob/proc/set_flavor + verbs += /mob/proc/set_flavor_2 //initialize limbs first create_bodyparts() diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 36d9ca541b..63c7d8f668 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -5,7 +5,7 @@ pressure_resistance = 25 can_buckle = TRUE buckle_lying = FALSE - mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID //Hair colour and style var/hair_color = "000" var/hair_style = "Bald" diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index fd4cdbaf0f..e62177abbb 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -76,7 +76,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/list/species_traits = list() // generic traits tied to having the species var/list/inherent_traits = list() - var/list/inherent_biotypes = list(MOB_ORGANIC, MOB_HUMANOID) + var/inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID var/attack_verb = "punch" // punch-specific attack verb var/sound/attack_sound = 'sound/weapons/punch1.ogg' @@ -1264,10 +1264,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) H.update_mutant_bodyparts() /datum/species/proc/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H) - if(chem.type == exotic_blood) + if(chem.type == exotic_blood && !istype(exotic_blood, /datum/reagent/blood)) H.blood_volume = min(H.blood_volume + round(chem.volume, 0.1), BLOOD_VOLUME_MAXIMUM) H.reagents.del_reagent(chem.type) - return 1 + return TRUE return FALSE /datum/species/proc/check_weakness(obj/item, mob/living/attacker) diff --git a/code/modules/mob/living/carbon/human/species_types/android.dm b/code/modules/mob/living/carbon/human/species_types/android.dm index ad9ba83771..559abd8d0b 100644 --- a/code/modules/mob/living/carbon/human/species_types/android.dm +++ b/code/modules/mob/living/carbon/human/species_types/android.dm @@ -4,7 +4,7 @@ say_mod = "states" species_traits = list(NOBLOOD,NOGENITALS,NOAROUSAL) inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_NOFIRE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_LIMBATTACHMENT) - inherent_biotypes = list(MOB_ROBOTIC, MOB_HUMANOID) + inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID meat = null gib_types = /obj/effect/gibspawner/robot damage_overlay_type = "synth" diff --git a/code/modules/mob/living/carbon/human/species_types/dwarves.dm b/code/modules/mob/living/carbon/human/species_types/dwarves.dm index f5f238908c..15422b2cdd 100644 --- a/code/modules/mob/living/carbon/human/species_types/dwarves.dm +++ b/code/modules/mob/living/carbon/human/species_types/dwarves.dm @@ -54,21 +54,20 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) // //Dwarf Speech handling - Basically a filter/forces them to say things. The IC helper /datum/species/dwarf/proc/handle_speech(datum/source, list/speech_args) var/message = speech_args[SPEECH_MESSAGE] - if(message[1] != "*") - message = " [message]" //Credits to goonstation for the strings list. - var/list/dwarf_words = strings("dwarf_replacement.json", "dwarf") //thanks to regex too. + if(speech_args[SPEECH_LANGUAGE] != /datum/language/dwarf) // No accent if they speak their language + if(message[1] != "*") + message = " [message]" //Credits to goonstation for the strings list. + var/list/dwarf_words = strings("dwarf_replacement.json", "dwarf") //thanks to regex too. + for(var/key in dwarf_words) //Theres like 1459 words or something man. + var/value = dwarf_words[key] //Thus they will always be in character. + if(islist(value)) //Whether they like it or not. + value = pick(value) //This could be drastically reduced if needed though. + message = replacetextEx(message, " [uppertext(key)]", " [uppertext(value)]") + message = replacetextEx(message, " [capitalize(key)]", " [capitalize(value)]") + message = replacetextEx(message, " [key]", " [value]") //Also its scottish. - for(var/key in dwarf_words) //Theres like 1459 words or something man. - var/value = dwarf_words[key] //Thus they will always be in character. - if(islist(value)) //Whether they like it or not. - value = pick(value) //This could be drastically reduced if needed though. - - message = replacetextEx(message, " [uppertext(key)]", " [uppertext(value)]") - message = replacetextEx(message, " [capitalize(key)]", " [capitalize(value)]") - message = replacetextEx(message, " [key]", " [value]") //Also its scottish. - - if(prob(3)) - message += pick(" By Armok!") + if(prob(3)) + message += " By Armok!" speech_args[SPEECH_MESSAGE] = trim(message) //This mostly exists because my testdwarf's liver died while trying to also not die due to no alcohol. diff --git a/code/modules/mob/living/carbon/human/species_types/flypeople.dm b/code/modules/mob/living/carbon/human/species_types/flypeople.dm index 4697e6aa3c..71f5aaa8e2 100644 --- a/code/modules/mob/living/carbon/human/species_types/flypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/flypeople.dm @@ -3,7 +3,7 @@ id = "fly" say_mod = "buzzes" species_traits = list(NOEYES) - inherent_biotypes = list(MOB_ORGANIC, MOB_HUMANOID, MOB_BUG) + inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG mutanttongue = /obj/item/organ/tongue/fly mutantliver = /obj/item/organ/liver/fly mutantstomach = /obj/item/organ/stomach/fly @@ -13,22 +13,23 @@ exotic_bloodtype = "BUG" /datum/species/fly/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H) - if(chem.type == /datum/reagent/toxin/pestkiller) + if(istype(chem, /datum/reagent/toxin/pestkiller)) H.adjustToxLoss(3) H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM) - return 1 - - -/datum/species/fly/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H) - if(istype(chem, /datum/reagent/consumable)) + return TRUE + else if(istype(chem, /datum/reagent/consumable)) var/datum/reagent/consumable/nutri_check = chem if(nutri_check.nutriment_factor > 0) var/turf/pos = get_turf(H) H.vomit(0, FALSE, FALSE, 2, TRUE) + var/obj/effect/decal/cleanable/vomit/V = locate() in pos + if(V) + H.reagents.trans_id_to(V, chem, chem.volume) playsound(pos, 'sound/effects/splat.ogg', 50, 1) H.visible_message("[H] vomits on the floor!", \ "You throw up on the floor!") - ..() + return TRUE + return ..() /datum/species/fly/check_weakness(obj/item/weapon, mob/living/attacker) if(istype(weapon, /obj/item/melee/flyswatter)) diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index 98c3f269dc..6da73f0b79 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -4,7 +4,7 @@ id = "iron golem" species_traits = list(NOBLOOD,MUTCOLORS,NO_UNDERWEAR,NOGENITALS,NOAROUSAL) inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_CHUNKYFINGERS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER) - inherent_biotypes = list(MOB_INORGANIC, MOB_HUMANOID) + inherent_biotypes = MOB_HUMANOID|MOB_MINERAL mutant_organs = list(/obj/item/organ/adamantine_resonator) speedmod = 2 armor = 55 @@ -308,7 +308,8 @@ if(chem.type == /datum/reagent/toxin/plantbgone) H.adjustToxLoss(3) H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM) - return 1 + return TRUE + return ..() //Radioactive /datum/species/golem/uranium @@ -622,12 +623,11 @@ if(chem.type == /datum/reagent/water/holywater) H.adjustFireLoss(4) H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM) - - if(chem.type == /datum/reagent/fuel/unholywater) + else if(chem.type == /datum/reagent/fuel/unholywater) H.adjustBruteLoss(-4) H.adjustFireLoss(-4) H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM) - + return ..() /datum/species/golem/clockwork name = "Clockwork Golem" @@ -638,6 +638,7 @@ species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYES,NOGENITALS,NOAROUSAL) inherent_biotypes = list(MOB_ROBOTIC, MOB_HUMANOID) inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER) + inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID armor = 20 //Reinforced, but much less so to allow for fast movement attack_verb = "smash" attack_sound = 'sound/magic/clockwork/anima_fragment_attack.ogg' @@ -694,7 +695,7 @@ Being made of cloth, your body is magic resistant and faster than that of other golems, but weaker and less resilient." species_traits = list(NOBLOOD,NO_UNDERWEAR,NOGENITALS,NOAROUSAL) //no mutcolors, and can burn inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_NOBREATH,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_CHUNKYFINGERS) - inherent_biotypes = list(MOB_UNDEAD, MOB_HUMANOID) + inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID armor = 15 //feels no pain, but not too resistant burnmod = 2 // don't get burned speedmod = 1 // not as heavy as stone @@ -1017,7 +1018,7 @@ else playsound(get_turf(owner),'sound/magic/RATTLEMEBONES.ogg', 100) for(var/mob/living/L in orange(7, get_turf(owner))) - if((MOB_UNDEAD in L.mob_biotypes) || isgolem(L) || HAS_TRAIT(L, TRAIT_RESISTCOLD)) + if((L.mob_biotypes & MOB_UNDEAD) || isgolem(L) || HAS_TRAIT(L, TRAIT_RESISTCOLD)) return //Do not affect our brothers to_chat(L, "A spine-chilling sound chills you to the bone!") diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index 5cdb051026..dfa1725026 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -5,8 +5,8 @@ say_mod = "hisses" default_color = "00FF00" species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,LIPS,HORNCOLOR,WINGCOLOR) - inherent_biotypes = list(MOB_ORGANIC, MOB_HUMANOID, MOB_REPTILE) mutant_bodyparts = list("tail_lizard", "snout", "spines", "horns", "frills", "body_markings", "legs", "taur", "deco_wings") + inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_REPTILE mutanttongue = /obj/item/organ/tongue/lizard mutanttail = /obj/item/organ/tail/lizard coldmod = 1.5 diff --git a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm index 2580e3b9f0..9d5ca92894 100644 --- a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm @@ -57,6 +57,7 @@ H.adjustToxLoss(3) H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM) return TRUE + return ..() /datum/species/mush/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour) forced_colour = FALSE diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm index 4a7399f287..c899575e44 100644 --- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm +++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm @@ -6,7 +6,7 @@ meat = /obj/item/stack/sheet/mineral/plasma species_traits = list(NOBLOOD,NOTRANSSTING,NOGENITALS) inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RADIMMUNE,TRAIT_NOHUNGER,TRAIT_CALCIUM_HEALER) - inherent_biotypes = list(MOB_INORGANIC, MOB_HUMANOID) + inherent_biotypes = MOB_HUMANOID|MOB_MINERAL mutantlungs = /obj/item/organ/lungs/plasmaman mutanttongue = /obj/item/organ/tongue/bone/plasmaman mutantliver = /obj/item/organ/liver/plasmaman diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm index 66eb207670..1bed3b08d4 100644 --- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm @@ -50,7 +50,8 @@ if(chem.type == /datum/reagent/toxin/plantbgone) H.adjustToxLoss(3) H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM) - return 1 + return TRUE + return ..() /datum/species/pod/on_hit(obj/item/projectile/P, mob/living/carbon/human/H) switch(P.type) diff --git a/code/modules/mob/living/carbon/human/species_types/skeletons.dm b/code/modules/mob/living/carbon/human/species_types/skeletons.dm index 0c4007555c..410ad05d93 100644 --- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm +++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm @@ -8,7 +8,7 @@ meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/skeleton species_traits = list(NOBLOOD,NOGENITALS,NOAROUSAL) inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_FAKEDEATH, TRAIT_CALCIUM_HEALER) - inherent_biotypes = list(MOB_UNDEAD, MOB_HUMANOID) + inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID mutanttongue = /obj/item/organ/tongue/bone damage_overlay_type = ""//let's not show bloody wounds or burns over bones. disliked_food = NONE diff --git a/code/modules/mob/living/carbon/human/species_types/synths.dm b/code/modules/mob/living/carbon/human/species_types/synths.dm index 0957a9e807..cb7822ad7e 100644 --- a/code/modules/mob/living/carbon/human/species_types/synths.dm +++ b/code/modules/mob/living/carbon/human/species_types/synths.dm @@ -5,7 +5,7 @@ sexes = 0 species_traits = list(NOTRANSSTING,NOGENITALS,NOAROUSAL) //all of these + whatever we inherit from the real species inherent_traits = list(TRAIT_VIRUSIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOLIMBDISABLE,TRAIT_NOHUNGER,TRAIT_NOBREATH) - inherent_biotypes = list(MOB_ROBOTIC, MOB_HUMANOID) + inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID dangerous_existence = 1 blacklisted = 1 meat = null @@ -39,9 +39,8 @@ if(chem.type == /datum/reagent/medicine/synthflesh) chem.reaction_mob(H, TOUCH, 2 ,0) //heal a little H.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM) - return 1 - else - return ..() + return TRUE + return ..() /datum/species/synth/proc/assume_disguise(datum/species/S, mob/living/carbon/human/H) @@ -124,4 +123,4 @@ if (/datum/species/golem/bananium) speech_args[SPEECH_SPANS] |= SPAN_CLOWN if (/datum/species/golem/clockwork) - speech_args[SPEECH_SPANS] |= SPAN_ROBOT \ No newline at end of file + speech_args[SPEECH_SPANS] |= SPAN_ROBOT diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm index 7462d26ea6..8bbd870149 100644 --- a/code/modules/mob/living/carbon/human/species_types/vampire.dm +++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm @@ -4,7 +4,7 @@ default_color = "FFFFFF" species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,DRINKSBLOOD) inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH) - inherent_biotypes = list(MOB_UNDEAD, MOB_HUMANOID) + inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID default_features = list("mcolor" = "FFF", "tail_human" = "None", "ears" = "None", "wings" = "None") exotic_bloodtype = "U" use_skintones = TRUE diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm index 8255f08507..26a99dbc2b 100644 --- a/code/modules/mob/living/carbon/human/species_types/zombies.dm +++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm @@ -10,7 +10,7 @@ meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/zombie species_traits = list(NOBLOOD,NOZOMBIE,NOTRANSSTING) inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NOBREATH,TRAIT_NODEATH,TRAIT_FAKEDEATH) - inherent_biotypes = list(MOB_UNDEAD, MOB_HUMANOID) + inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID mutanttongue = /obj/item/organ/tongue/zombie var/static/list/spooks = list('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg','sound/hallucinations/veryfar_noise.ogg','sound/hallucinations/wail.ogg') disliked_food = NONE diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 534509523a..433f6a43b5 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -362,7 +362,7 @@ return // Also no decay if corpse chilled or not organic/undead - if(bodytemperature <= T0C-10 || (!(MOB_ORGANIC in mob_biotypes) && !(MOB_UNDEAD in mob_biotypes))) + if((bodytemperature <= T0C-10) || !(mob_biotypes & (MOB_ORGANIC|MOB_UNDEAD))) return // Wait a bit before decaying @@ -581,6 +581,9 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put if(cultslurring) cultslurring = max(cultslurring-1, 0) + if(clockcultslurring) + clockcultslurring = max(clockcultslurring-1, 0) + if(silent) silent = max(silent-1, 0) diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index cd51a4234b..f3abe83958 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -7,7 +7,7 @@ gender = NEUTER pass_flags = PASSTABLE ventcrawler = VENTCRAWLER_NUDE - mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/monkey = 5, /obj/item/stack/sheet/animalhide/monkey = 1) type_of_meat = /obj/item/reagent_containers/food/snacks/meat/slab/monkey gib_type = /obj/effect/decal/cleanable/blood/gibs diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm index 45f9662c9a..7cd79bb1ab 100644 --- a/code/modules/mob/living/death.dm +++ b/code/modules/mob/living/death.dm @@ -25,7 +25,7 @@ /mob/living/proc/spawn_gibs(with_bodyparts, atom/loc_override) var/location = loc_override ? loc_override.drop_location() : drop_location() - if(MOB_ROBOTIC in mob_biotypes) + if((MOB_ROBOTIC) in (mob_biotypes)) new /obj/effect/gibspawner/robot(location, src, get_static_viruses()) else new /obj/effect/gibspawner/generic(location, src, get_static_viruses()) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 9c8b2808ce..0c11d6ab42 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1080,7 +1080,7 @@ stop_pulling() //CIT CHANGE - Ditto... else if(has_legs || ignore_legs) lying = 0 - if (pulledby) + if (pulledby && isliving(pulledby)) var/mob/living/L = pulledby L.update_pull_movespeed() if(buckled) @@ -1094,6 +1094,10 @@ fall(forced = 1) canmove = !(ko || recoveringstam || pinned || IsStun() || IsFrozen() || chokehold || buckled || (!has_legs && !ignore_legs && !has_arms)) //Cit change - makes it plausible to move while resting, adds pinning and stamina crit density = !lying + if(resting) + ENABLE_BITFIELD(movement_type, CRAWLING) + else + DISABLE_BITFIELD(movement_type, CRAWLING) if(lying) if(layer == initial(layer)) //to avoid special cases like hiding larvas. layer = LYING_MOB_LAYER //so mob lying always appear behind standing mobs diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 84f0004805..7106d003ee 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -52,7 +52,7 @@ var/limb_destroyer = 0 //1 Sets AI behavior that allows mobs to target and dismember limbs with their basic attack. var/mob_size = MOB_SIZE_HUMAN - var/list/mob_biotypes = list(MOB_ORGANIC) + var/mob_biotypes = MOB_ORGANIC var/metabolism_efficiency = 1 //more or less efficiency to metabolize helpful/harmful reagents and regulate body temperature.. var/has_limbs = 0 //does the mob have distinct limbs?(arms,legs, chest,head) @@ -89,6 +89,7 @@ var/stuttering = 0 var/slurring = 0 var/cultslurring = 0 + var/clockcultslurring = 0 var/derpspeech = 0 var/list/implants = null diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 0fb48f65b1..35b49cce8e 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -224,7 +224,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list( . = "[.]" /mob/living/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source) - . = ..() + SEND_SIGNAL(src, COMSIG_MOVABLE_HEAR, args) //parent calls can't overwrite the current proc args. if(!client) return var/deaf_message @@ -258,7 +258,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list( if(M.stat != DEAD) //not dead, not important if(yellareas) //CIT CHANGE - see above. makes yelling penetrate walls var/area/A = get_area(M) //CIT CHANGE - ditto - if(istype(A) && A.ambientsounds != SPACE && A in yellareas) //CIT CHANGE - ditto + if(istype(A) && A.ambientsounds != SPACE && (A in yellareas)) //CIT CHANGE - ditto listening |= M //CIT CHANGE - ditto continue if(!M.client || !client) //client is so that ghosts don't have to listen to mice @@ -354,6 +354,9 @@ GLOBAL_LIST_INIT(department_radio_keys, list( if(cultslurring) message = cultslur(message) + + if(clockcultslurring) + message = CLOCK_CULT_SLUR(message) message = capitalize(message) @@ -365,7 +368,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list( if(message_mode == MODE_HEADSET) imp.radio.talk_into(src, message, , spans, language) return ITALICS | REDUCE_RANGE - if(message_mode == MODE_DEPARTMENT || message_mode in GLOB.radiochannels) + if(message_mode == MODE_DEPARTMENT || (message_mode in GLOB.radiochannels)) imp.radio.talk_into(src, message, message_mode, spans, language) return ITALICS | REDUCE_RANGE diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 33cbdb7cc9..ed0d0d02e8 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -315,10 +315,10 @@ var/is_anchored = FALSE if(move_resist == MOVE_FORCE_OVERPOWERING) move_resist = MOVE_FORCE_NORMAL + REMOVE_TRAIT(src, TRAIT_NO_TELEPORT, src) else is_anchored = TRUE move_resist = MOVE_FORCE_OVERPOWERING - REMOVE_TRAIT(src, TRAIT_NO_TELEPORT, src) ADD_TRAIT(src, TRAIT_NO_TELEPORT, src) to_chat(src, "You are now [is_anchored ? "" : "un"]anchored.") diff --git a/code/modules/mob/living/silicon/login.dm b/code/modules/mob/living/silicon/login.dm index 2f133259ca..7b1854b940 100644 --- a/code/modules/mob/living/silicon/login.dm +++ b/code/modules/mob/living/silicon/login.dm @@ -7,4 +7,7 @@ var/datum/antagonist/bloodsucker/V = mind.has_antag_datum(/datum/antagonist/bloodsucker) if(V) mind.remove_antag_datum(V) + var/datum/antagonist/gang/G = mind.has_antag_datum(/datum/antagonist/gang) + if(G) + mind.remove_antag_datum(G) ..() diff --git a/code/modules/mob/living/silicon/pai/pai_defense.dm b/code/modules/mob/living/silicon/pai/pai_defense.dm index 05b2bc77ba..d8e910642d 100644 --- a/code/modules/mob/living/silicon/pai/pai_defense.dm +++ b/code/modules/mob/living/silicon/pai/pai_defense.dm @@ -1,3 +1,4 @@ +#define PAI_EMP_SILENCE_DURATION 3 MINUTES /mob/living/silicon/pai/blob_act(obj/structure/blob/B) return FALSE @@ -8,7 +9,7 @@ return take_holo_damage(50/severity) Knockdown(400/severity) - silent = max((3 MINUTES)/severity, silent) + silent = max(silent, (PAI_EMP_SILENCE_DURATION) / SSmobs.wait / severity) if(holoform) fold_in(force = TRUE) emitter_next_use = world.time + emitter_emp_cd diff --git a/code/modules/mob/living/silicon/pai/update_icon.dm b/code/modules/mob/living/silicon/pai/update_icon.dm index 9e40b71c5d..8c051d9c41 100644 --- a/code/modules/mob/living/silicon/pai/update_icon.dm +++ b/code/modules/mob/living/silicon/pai/update_icon.dm @@ -8,9 +8,9 @@ var/list/states = icon_states(icon) icon_state = "" if(resting) //The next line is some bullshit but I can make it worse if you want and make it a single line instead of four.. :) - if(dynamic_chassis_sit && ("sit") in states) + if(dynamic_chassis_sit && ("sit" in states)) icon_state = "sit" - else if(dynamic_chassis_bellyup && ("bellyup") in states) + else if(dynamic_chassis_bellyup && ("bellyup" in states)) icon_state = "bellyup" else if("rest" in states) icon_state = "rest" diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index e304f13d1d..c6af8bd4c2 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -340,7 +340,7 @@ /obj/item/robot_module/medical/be_transformed_to(obj/item/robot_module/old_module) var/mob/living/silicon/robot/R = loc var/medmodels = list("Default", "Heavy", "Sleek", "Marina", "Droid", "Eyebot", "Medihound", "Medihound Dark", "Vale") - if(R.client && R.client.ckey in list("nezuli")) + if(R.client && (R.client.ckey in list("nezuli"))) medmodels += "Alina" var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in medmodels if(!borg_icon) @@ -437,7 +437,7 @@ /obj/item/robot_module/engineering/be_transformed_to(obj/item/robot_module/old_module) var/mob/living/silicon/robot/R = loc var/list/engymodels = list("Default", "Default - Treads", "Heavy", "Sleek", "Marina", "Can", "Spider", "Loader","Handy", "Pup Dozer", "Vale") - if(R.client && R.client.ckey in list("nezuli")) + if(R.client && (R.client.ckey in list("nezuli"))) engymodels += "Alina" var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in engymodels if(!borg_icon) @@ -515,7 +515,7 @@ /obj/item/robot_module/security/be_transformed_to(obj/item/robot_module/old_module) var/mob/living/silicon/robot/R = loc var/list/secmodels = list("Default", "Default - Treads", "Heavy", "Sleek", "Can", "Marina", "Spider", "K9", "K9 Dark", "Vale") - if(R.client && R.client.ckey in list("nezuli")) + if(R.client && (R.client.ckey in list("nezuli"))) secmodels += "Alina" var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in secmodels if(!borg_icon) diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index e5881848d5..72e98e348c 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -10,7 +10,7 @@ bubble_icon = "machine" weather_immunities = list("ash") possible_a_intents = list(INTENT_HELP, INTENT_HARM) - mob_biotypes = list(MOB_ROBOTIC) + mob_biotypes = MOB_ROBOTIC rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE speech_span = SPAN_ROBOT flags_1 = PREVENT_CONTENTS_EXPLOSION_1 | HEAR_1 diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index 69aacbf1d6..7da0ad13da 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -3,7 +3,7 @@ icon = 'icons/mob/aibots.dmi' layer = MOB_LAYER gender = NEUTER - mob_biotypes = list(MOB_ROBOTIC) + mob_biotypes = MOB_ROBOTIC light_range = 3 light_power = 0.9 light_color = "#CDDDFF" @@ -810,14 +810,14 @@ Pass a positive integer as an argument to override a bot's default speed. switch(href_list["operation"]) if("patrol") - if(!issilicon(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked)) + if(!hasSiliconAccessInArea(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked)) return TRUE auto_patrol = !auto_patrol bot_reset() if("remote") remote_disabled = !remote_disabled if("hack") - if(!issilicon(usr) && !IsAdminGhost(usr)) + if(!hasSiliconAccessInArea(usr) && !IsAdminGhost(usr)) var/msg = "[key_name(usr)] attempted to hack a bot with a href that shouldn't be available!" message_admins(msg) log_admin(msg) @@ -836,7 +836,7 @@ Pass a positive integer as an argument to override a bot's default speed. to_chat(usr, "[text_dehack]") bot_reset() if("ejectpai") - if(paicard && (!locked || issilicon(usr) || IsAdminGhost(usr))) + if(paicard && (!locked || hasSiliconAccessInArea(usr) || IsAdminGhost(usr))) to_chat(usr, "You eject [paicard] from [bot_name]") ejectpai(usr) update_controls() @@ -863,13 +863,13 @@ Pass a positive integer as an argument to override a bot's default speed. if(emagged == 2) //An emagged bot cannot be controlled by humans, silicons can if one hacked it. if(!hacked) //Manually emagged by a human - access denied to all. return TRUE - else if(!issilicon(user) && !IsAdminGhost(user)) //Bot is hacked, so only silicons and admins are allowed access. + else if(!hasSiliconAccessInArea(user) && !IsAdminGhost(user)) //Bot is hacked, so only silicons and admins are allowed access. return TRUE return FALSE /mob/living/simple_animal/bot/proc/hack(mob/user) var/hack - if(issilicon(user) || IsAdminGhost(user)) //Allows silicons or admins to toggle the emag status of a bot. + if(hasSiliconAccessInArea(user) || IsAdminGhost(user)) //Allows silicons or admins to toggle the emag status of a bot. hack += "[emagged == 2 ? "Software compromised! Unit may exhibit dangerous or erratic behavior." : "Unit operating normally. Release safety lock?"]
" hack += "Harm Prevention Safety System: [emagged ? "DANGER" : "Engaged"]
" else if(!locked) //Humans with access can use this option to hide a bot from the AI's remote control panel and PDA control. @@ -878,7 +878,7 @@ Pass a positive integer as an argument to override a bot's default speed. /mob/living/simple_animal/bot/proc/showpai(mob/user) var/eject = "" - if((!locked || issilicon(usr) || IsAdminGhost(usr))) + if((!locked || hasSiliconAccessInArea(usr) || IsAdminGhost(usr))) if(paicard || allow_pai) eject += "Personality card status: " if(paicard) diff --git a/code/modules/mob/living/simple_animal/bot/cleanbot.dm b/code/modules/mob/living/simple_animal/bot/cleanbot.dm index cdb8ac820c..0e48723f37 100644 --- a/code/modules/mob/living/simple_animal/bot/cleanbot.dm +++ b/code/modules/mob/living/simple_animal/bot/cleanbot.dm @@ -298,7 +298,7 @@ Status: [on ? "On" : "Off"]
Behaviour controls are [locked ? "locked" : "unlocked"]
Maintenance panel panel is [open ? "opened" : "closed"]"}) - if(!locked || issilicon(user)|| IsAdminGhost(user)) + if(!locked || hasSiliconAccessInArea(user)|| IsAdminGhost(user)) dat += "
Clean Blood: [blood ? "Yes" : "No"]" dat += "
Clean Trash: [trash ? "Yes" : "No"]" dat += "
Exterminate Pests: [pests ? "Yes" : "No"]" diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm index 4e479dc75b..6d304c6782 100644 --- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm +++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm @@ -110,7 +110,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]
"}, "[on ? "On" : "Off"]" ) - if(!locked || issilicon(user)|| IsAdminGhost(user)) + if(!locked || hasSiliconAccessInArea(user)|| IsAdminGhost(user)) if(!lasercolor) dat += text({"
Arrest Unidentifiable Persons: []
diff --git a/code/modules/mob/living/simple_animal/bot/firebot.dm b/code/modules/mob/living/simple_animal/bot/firebot.dm index 2b52da6821..6ab4dc36db 100644 --- a/code/modules/mob/living/simple_animal/bot/firebot.dm +++ b/code/modules/mob/living/simple_animal/bot/firebot.dm @@ -111,7 +111,7 @@ dat += "Maintenance panel panel is [open ? "opened" : "closed"]
" dat += "Behaviour controls are [locked ? "locked" : "unlocked"]
" - if(!locked || issilicon(user) || IsAdminGhost(user)) + if(!locked || hasSiliconAccessInArea(user) || IsAdminGhost(user)) dat += "Extinguish Fires: [extinguish_fires ? "Yes" : "No"]
" dat += "Extinguish People: [extinguish_people ? "Yes" : "No"]
" dat += "Patrol Station: [auto_patrol ? "Yes" : "No"]
" diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm index cae707ce46..1bf3883ea7 100644 --- a/code/modules/mob/living/simple_animal/bot/floorbot.dm +++ b/code/modules/mob/living/simple_animal/bot/floorbot.dm @@ -83,7 +83,7 @@ dat += "None Loaded
" dat += "Behaviour controls are [locked ? "locked" : "unlocked"]
" - if(!locked || issilicon(user) || IsAdminGhost(user)) + if(!locked || hasSiliconAccessInArea(user) || IsAdminGhost(user)) dat += "Add tiles to new hull plating: [autotile ? "Yes" : "No"]
" dat += "Place floor tiles: [placetiles ? "Yes" : "No"]
" dat += "Replace existing floor tiles with custom tiles: [replacetiles ? "Yes" : "No"]
" diff --git a/code/modules/mob/living/simple_animal/bot/honkbot.dm b/code/modules/mob/living/simple_animal/bot/honkbot.dm index d844237a61..e491cff74a 100644 --- a/code/modules/mob/living/simple_animal/bot/honkbot.dm +++ b/code/modules/mob/living/simple_animal/bot/honkbot.dm @@ -90,7 +90,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"}, "[on ? "On" : "Off"]" ) - if(!locked || issilicon(user) || IsAdminGhost(user)) + if(!locked || hasSiliconAccessInArea(user) || IsAdminGhost(user)) dat += text({"
Auto Patrol: []"}, "[auto_patrol ? "On" : "Off"]" ) diff --git a/code/modules/mob/living/simple_animal/bot/medbot.dm b/code/modules/mob/living/simple_animal/bot/medbot.dm index a4496dd1f5..bb29cd3526 100644 --- a/code/modules/mob/living/simple_animal/bot/medbot.dm +++ b/code/modules/mob/living/simple_animal/bot/medbot.dm @@ -148,7 +148,7 @@ else dat += "None Loaded" dat += "
Behaviour controls are [locked ? "locked" : "unlocked"]
" - if(!locked || issilicon(user) || IsAdminGhost(user)) + if(!locked || hasSiliconAccessInArea(user) || IsAdminGhost(user)) dat += "Healing Threshold: " dat += "-- " dat += "- " diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index 0e8e009ca8..b23f3f2baa 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -279,7 +279,7 @@ // TODO: remove this; PDAs currently depend on it /mob/living/simple_animal/bot/mulebot/get_controls(mob/user) - var/ai = issilicon(user) + var/ai = hasSiliconAccessInArea(user) var/dat dat += "

Multiple Utility Load Effector Mk. V

" dat += "ID: [id]
" diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index 8302346a00..461fa9cf2a 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -110,7 +110,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"}, "[on ? "On" : "Off"]" ) - if(!locked || issilicon(user) || IsAdminGhost(user)) + if(!locked || hasSiliconAccessInArea(user) || IsAdminGhost(user)) dat += text({"
Arrest Unidentifiable Persons: []
Arrest for Unauthorized Weapons: []
@@ -131,7 +131,7 @@ Auto Patrol: []"}, /mob/living/simple_animal/bot/secbot/Topic(href, href_list) if(..()) return 1 - if(!issilicon(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked)) + if(!hasSiliconAccessInArea(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked)) return TRUE switch(href_list["operation"]) if("idcheck") diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index fbdc32f2c1..4c6bfc4c3e 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -3,7 +3,7 @@ real_name = "Construct" desc = "" gender = NEUTER - mob_biotypes = list(MOB_INORGANIC) + mob_biotypes = NONE speak_emote = list("hisses") response_help = "thinks better of touching" response_disarm = "flails at" diff --git a/code/modules/mob/living/simple_animal/friendly/butterfly.dm b/code/modules/mob/living/simple_animal/friendly/butterfly.dm index 2fbbad66d8..80fba5a9a4 100644 --- a/code/modules/mob/living/simple_animal/friendly/butterfly.dm +++ b/code/modules/mob/living/simple_animal/friendly/butterfly.dm @@ -18,7 +18,7 @@ pass_flags = PASSTABLE | PASSGRILLE | PASSMOB ventcrawler = VENTCRAWLER_ALWAYS mob_size = MOB_SIZE_TINY - mob_biotypes = list(MOB_ORGANIC, MOB_BUG) + mob_biotypes = MOB_ORGANIC|MOB_BUG gold_core_spawnable = FRIENDLY_SPAWN verb_say = "flutters" verb_ask = "flutters inquisitively" diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index f12f3649cf..0f95096497 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -17,7 +17,7 @@ ventcrawler = VENTCRAWLER_ALWAYS pass_flags = PASSTABLE mob_size = MOB_SIZE_SMALL - mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + mob_biotypes = MOB_ORGANIC|MOB_BEAST minbodytemp = 200 maxbodytemp = 400 unsuitable_atmos_damage = 1 diff --git a/code/modules/mob/living/simple_animal/friendly/cockroach.dm b/code/modules/mob/living/simple_animal/friendly/cockroach.dm index 26d4691d83..95aa86aaab 100644 --- a/code/modules/mob/living/simple_animal/friendly/cockroach.dm +++ b/code/modules/mob/living/simple_animal/friendly/cockroach.dm @@ -13,7 +13,7 @@ maxbodytemp = INFINITY pass_flags = PASSTABLE | PASSGRILLE | PASSMOB mob_size = MOB_SIZE_TINY - mob_biotypes = list(MOB_ORGANIC, MOB_BUG) + mob_biotypes = MOB_ORGANIC|MOB_BUG response_help = "pokes" response_disarm = "shoos" response_harm = "splats" diff --git a/code/modules/mob/living/simple_animal/friendly/crab.dm b/code/modules/mob/living/simple_animal/friendly/crab.dm index 5dbf755601..d906757ed5 100644 --- a/code/modules/mob/living/simple_animal/friendly/crab.dm +++ b/code/modules/mob/living/simple_animal/friendly/crab.dm @@ -11,7 +11,7 @@ blood_volume = 350 speak_chance = 1 turns_per_move = 5 - butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 1) + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/rawcrab = 1) response_help = "pets" response_disarm = "gently pushes aside" response_harm = "stomps" diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm index f02d21c2af..37ef271226 100644 --- a/code/modules/mob/living/simple_animal/friendly/dog.dm +++ b/code/modules/mob/living/simple_animal/friendly/dog.dm @@ -1,7 +1,7 @@ //Dogs. /mob/living/simple_animal/pet/dog - mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + mob_biotypes = MOB_ORGANIC|MOB_BEAST response_help = "pets" response_disarm = "bops" response_harm = "kicks" @@ -19,7 +19,7 @@ /mob/living/simple_animal/pet/dog/ComponentInitialize() . = ..() - AddElement(/datum/element/wuv, "yaps_happily!", EMOTE_AUDIBLE, /datum/mood_event/pet_animal, "growls!", EMOTE_AUDIBLE) + AddElement(/datum/element/wuv, "yaps happily!", EMOTE_AUDIBLE, /datum/mood_event/pet_animal, "growls!", EMOTE_AUDIBLE) AddElement(/datum/element/mob_holder, held_icon) //Corgis and pugs are now under one dog subtype diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm index 158719414a..7dd373b49f 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm @@ -35,7 +35,7 @@ sight = (SEE_TURFS | SEE_OBJS) status_flags = (CANPUSH | CANSTUN | CANKNOCKDOWN) gender = NEUTER - mob_biotypes = list(MOB_ROBOTIC) + mob_biotypes = MOB_ROBOTIC speak_emote = list("chirps") speech_span = SPAN_ROBOT bubble_icon = "machine" diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index 38bcfbde79..fad519838a 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -17,7 +17,7 @@ response_disarm = "gently pushes aside" response_harm = "kicks" faction = list("neutral") - mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + mob_biotypes = MOB_ORGANIC|MOB_BEAST attack_same = 1 attacktext = "kicks" attack_sound = 'sound/weapons/punch1.ogg' @@ -112,7 +112,7 @@ icon_dead = "cow_dead" icon_gib = "cow_gib" gender = FEMALE - mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + mob_biotypes = MOB_ORGANIC|MOB_BEAST speak = list("moo?","moo","MOOOOOO") speak_emote = list("moos","moos hauntingly") emote_hear = list("brays.") @@ -189,7 +189,7 @@ icon_dead = "chick_dead" icon_gib = "chick_gib" gender = FEMALE - mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + mob_biotypes = MOB_ORGANIC|MOB_BEAST speak = list("Cherp.","Cherp?","Chirrup.","Cheep!") speak_emote = list("cheeps") emote_hear = list("cheeps.") @@ -235,7 +235,7 @@ name = "\improper chicken" desc = "Hopefully the eggs are good this season." gender = FEMALE - mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + mob_biotypes = MOB_ORGANIC|MOB_BEAST icon_state = "chicken_brown" icon_living = "chicken_brown" icon_dead = "chicken_brown_dead" @@ -454,7 +454,7 @@ name = "udder" /obj/item/udder/Initialize() - create_reagents(50) + create_reagents(50, NONE, NO_REAGENTS_VALUE) reagents.add_reagent(/datum/reagent/consumable/milk, 20) . = ..() diff --git a/code/modules/mob/living/simple_animal/friendly/lizard.dm b/code/modules/mob/living/simple_animal/friendly/lizard.dm index 6275256f5a..f0d354ace1 100644 --- a/code/modules/mob/living/simple_animal/friendly/lizard.dm +++ b/code/modules/mob/living/simple_animal/friendly/lizard.dm @@ -18,7 +18,7 @@ density = FALSE pass_flags = PASSTABLE | PASSMOB mob_size = MOB_SIZE_SMALL - mob_biotypes = list(MOB_ORGANIC, MOB_BEAST, MOB_REPTILE) + mob_biotypes = MOB_ORGANIC|MOB_BEAST|MOB_REPTILE gold_core_spawnable = FRIENDLY_SPAWN obj_damage = 0 environment_smash = ENVIRONMENT_SMASH_NONE diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm index d326573957..c5a4fa6e1e 100644 --- a/code/modules/mob/living/simple_animal/friendly/mouse.dm +++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm @@ -22,7 +22,7 @@ ventcrawler = VENTCRAWLER_ALWAYS pass_flags = PASSTABLE | PASSGRILLE | PASSMOB mob_size = MOB_SIZE_TINY - mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + mob_biotypes = MOB_ORGANIC|MOB_BEAST var/body_color //brown, gray and white, leave blank for random gold_core_spawnable = FRIENDLY_SPAWN var/chew_probability = 1 diff --git a/code/modules/mob/living/simple_animal/friendly/pet.dm b/code/modules/mob/living/simple_animal/friendly/pet.dm index c24dc6857a..dbdb5c646c 100644 --- a/code/modules/mob/living/simple_animal/friendly/pet.dm +++ b/code/modules/mob/living/simple_animal/friendly/pet.dm @@ -1,7 +1,7 @@ /mob/living/simple_animal/pet icon = 'icons/mob/pets.dmi' mob_size = MOB_SIZE_SMALL - mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + mob_biotypes = MOB_ORGANIC|MOB_BEAST blood_volume = BLOOD_VOLUME_NORMAL var/unique_pet = FALSE // if the mob can be renamed var/obj/item/clothing/neck/petcollar/pcollar diff --git a/code/modules/mob/living/simple_animal/friendly/sloth.dm b/code/modules/mob/living/simple_animal/friendly/sloth.dm index 21df73fa61..28063d6e52 100644 --- a/code/modules/mob/living/simple_animal/friendly/sloth.dm +++ b/code/modules/mob/living/simple_animal/friendly/sloth.dm @@ -14,7 +14,7 @@ response_help = "pets" response_disarm = "gently pushes aside" response_harm = "kicks" - mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + mob_biotypes = MOB_ORGANIC|MOB_BEAST gold_core_spawnable = FRIENDLY_SPAWN melee_damage_lower = 18 melee_damage_upper = 18 diff --git a/code/modules/mob/living/simple_animal/friendly/snake.dm b/code/modules/mob/living/simple_animal/friendly/snake.dm index 95838c9acb..7f75888649 100644 --- a/code/modules/mob/living/simple_animal/friendly/snake.dm +++ b/code/modules/mob/living/simple_animal/friendly/snake.dm @@ -30,7 +30,7 @@ density = FALSE pass_flags = PASSTABLE | PASSMOB mob_size = MOB_SIZE_SMALL - mob_biotypes = list(MOB_ORGANIC, MOB_BEAST, MOB_REPTILE) + mob_biotypes = MOB_ORGANIC|MOB_BEAST|MOB_REPTILE gold_core_spawnable = FRIENDLY_SPAWN obj_damage = 0 environment_smash = ENVIRONMENT_SMASH_NONE @@ -59,4 +59,4 @@ QDEL_NULL(target) adjustBruteLoss(-2) else - return ..() \ No newline at end of file + return ..() diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm index 62c8588ac8..9ad3cbd373 100644 --- a/code/modules/mob/living/simple_animal/guardian/guardian.dm +++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm @@ -10,7 +10,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians desc = "A mysterious being that stands by its charge, ever vigilant." speak_emote = list("hisses") gender = NEUTER - mob_biotypes = list(MOB_INORGANIC) + mob_biotypes = NONE bubble_icon = "guardian" response_help = "passes through" response_disarm = "flails at" diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm index acd8da9618..b019019c71 100644 --- a/code/modules/mob/living/simple_animal/hostile/bear.dm +++ b/code/modules/mob/living/simple_animal/hostile/bear.dm @@ -6,7 +6,7 @@ icon_living = "bear" icon_dead = "bear_dead" icon_gib = "bear_gib" - mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + mob_biotypes = MOB_ORGANIC|MOB_BEAST speak = list("RAWR!","Rawr!","GRR!","Growl!") speak_emote = list("growls", "roars") emote_hear = list("rawrs.","grumbles.","grawls.") diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm index bb1f1284b5..524c220fa4 100644 --- a/code/modules/mob/living/simple_animal/hostile/bees.dm +++ b/code/modules/mob/living/simple_animal/hostile/bees.dm @@ -37,7 +37,7 @@ pass_flags = PASSTABLE | PASSGRILLE | PASSMOB density = FALSE mob_size = MOB_SIZE_TINY - mob_biotypes = list(MOB_ORGANIC, MOB_BUG) + mob_biotypes = MOB_ORGANIC|MOB_BUG movement_type = FLYING gold_core_spawnable = HOSTILE_SPAWN search_objects = 1 //have to find those plant trays! diff --git a/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm b/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm index 2b5b5236ed..07572fff83 100644 --- a/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm @@ -2,7 +2,7 @@ /mob/living/simple_animal/hostile/boss/paper_wizard name = "Mjor the Creative" desc = "A wizard with a taste for the arts." - mob_biotypes = list(MOB_INORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_HUMANOID boss_abilities = list(/datum/action/boss/wizard_summon_minions, /datum/action/boss/wizard_mimic) faction = list("hostile","stickman") del_on_death = TRUE diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm index d527a40120..36968a1ab0 100644 --- a/code/modules/mob/living/simple_animal/hostile/carp.dm +++ b/code/modules/mob/living/simple_animal/hostile/carp.dm @@ -7,7 +7,7 @@ icon_living = "carp" icon_dead = "carp_dead" icon_gib = "carp_gib" - mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + mob_biotypes = MOB_ORGANIC|MOB_BEAST speak_chance = 0 turns_per_move = 5 butcher_results = list(/obj/item/reagent_containers/food/snacks/carpmeat = 2) diff --git a/code/modules/mob/living/simple_animal/hostile/cat_butcher.dm b/code/modules/mob/living/simple_animal/hostile/cat_butcher.dm index 5181e920d7..4e3375caf7 100644 --- a/code/modules/mob/living/simple_animal/hostile/cat_butcher.dm +++ b/code/modules/mob/living/simple_animal/hostile/cat_butcher.dm @@ -22,7 +22,7 @@ attacktext = "slashes at" attack_sound = 'sound/weapons/circsawhit.ogg' a_intent = INTENT_HARM - mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID loot = list(/obj/effect/mob_spawn/human/corpse/cat_butcher, /obj/item/circular_saw) atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0) unsuitable_atmos_damage = 15 diff --git a/code/modules/mob/living/simple_animal/hostile/eyeballs.dm b/code/modules/mob/living/simple_animal/hostile/eyeballs.dm index 44f7f9c9f8..2d438dbf1c 100644 --- a/code/modules/mob/living/simple_animal/hostile/eyeballs.dm +++ b/code/modules/mob/living/simple_animal/hostile/eyeballs.dm @@ -7,7 +7,7 @@ icon_living = "eyeball" icon_gib = "" gender = NEUTER - mob_biotypes = list(MOB_ORGANIC) + mob_biotypes = MOB_ORGANIC response_help = "pets" response_disarm = "gently pushes aside" response_harm = "hits" diff --git a/code/modules/mob/living/simple_animal/hostile/faithless.dm b/code/modules/mob/living/simple_animal/hostile/faithless.dm index 3d411738c1..479b102b36 100644 --- a/code/modules/mob/living/simple_animal/hostile/faithless.dm +++ b/code/modules/mob/living/simple_animal/hostile/faithless.dm @@ -4,7 +4,7 @@ icon_state = "faithless" icon_living = "faithless" icon_dead = "faithless_dead" - mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID gender = MALE speak_chance = 0 turns_per_move = 5 diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm index 20ce5ac751..cc7b1e19d1 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -22,7 +22,7 @@ icon_state = "guard" icon_living = "guard" icon_dead = "guard_dead" - mob_biotypes = list(MOB_ORGANIC, MOB_BUG) + mob_biotypes = MOB_ORGANIC|MOB_BUG speak_emote = list("chitters") emote_hear = list("chitters") speak_chance = 5 diff --git a/code/modules/mob/living/simple_animal/hostile/goose.dm b/code/modules/mob/living/simple_animal/hostile/goose.dm index 3bc8715c5c..db232c20c4 100644 --- a/code/modules/mob/living/simple_animal/hostile/goose.dm +++ b/code/modules/mob/living/simple_animal/hostile/goose.dm @@ -6,7 +6,7 @@ icon_state = "goose" // sprites by cogwerks from goonstation, used with permission icon_living = "goose" icon_dead = "goose_dead" - mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + mob_biotypes = MOB_ORGANIC|MOB_BEAST speak_chance = 0 turns_per_move = 5 butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 2) diff --git a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm index 6866df01d5..6d864576a1 100644 --- a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm +++ b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm @@ -9,7 +9,7 @@ icon_state = "crawling" icon_living = "crawling" icon_dead = "dead" - mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID speak_chance = 80 maxHealth = 220 health = 220 diff --git a/code/modules/mob/living/simple_animal/hostile/illusion.dm b/code/modules/mob/living/simple_animal/hostile/illusion.dm index 5ee2549054..89303702f3 100644 --- a/code/modules/mob/living/simple_animal/hostile/illusion.dm +++ b/code/modules/mob/living/simple_animal/hostile/illusion.dm @@ -6,7 +6,7 @@ icon_living = "static" icon_dead = "null" gender = NEUTER - mob_biotypes = list() + mob_biotypes = NONE melee_damage_lower = 5 melee_damage_upper = 5 a_intent = INTENT_HARM diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm index deb88d677b..ea01e4b659 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm @@ -10,7 +10,7 @@ icon_state = "leaper" icon_living = "leaper" icon_dead = "leaper_dead" - mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + mob_biotypes = MOB_ORGANIC|MOB_BEAST maxHealth = 300 health = 300 ranged = TRUE diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/mega_arachnid.dm b/code/modules/mob/living/simple_animal/hostile/jungle/mega_arachnid.dm index 607db5d54f..91e17e8e57 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/mega_arachnid.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/mega_arachnid.dm @@ -7,7 +7,7 @@ icon_state = "arachnid" icon_living = "arachnid" icon_dead = "arachnid_dead" - mob_biotypes = list(MOB_ORGANIC, MOB_BUG) + mob_biotypes = MOB_ORGANIC|MOB_BUG melee_damage_lower = 30 melee_damage_upper = 30 maxHealth = 300 diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm b/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm index b786637592..b2e6fa9704 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm @@ -13,7 +13,7 @@ icon_state = "mook" icon_living = "mook" icon_dead = "mook_dead" - mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID pixel_x = -16 maxHealth = 45 health = 45 diff --git a/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm b/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm index 2e783d84d8..c025ba58db 100644 --- a/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm +++ b/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm @@ -23,7 +23,7 @@ desc = "Death to Nanotrasen. This variant comes in MECHA DEATH flavour." wanted_objects = list() search_objects = 0 - mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID var/spawn_mecha_type = /obj/mecha/combat/marauder/mauler/loaded var/obj/mecha/mecha //Ref to pilot's mecha instance diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm index 899e901827..a0e6561c68 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm @@ -28,7 +28,7 @@ Difficulty: Medium icon_state = "miner" icon_living = "miner" icon = 'icons/mob/broadMobs.dmi' - mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID light_color = "#E4C7C5" movement_type = GROUND speak_emote = list("roars") @@ -39,8 +39,8 @@ Difficulty: Medium ranged = 1 ranged_cooldown_time = 16 pixel_x = -16 - crusher_loot = list(/obj/item/melee/transforming/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator, /obj/item/crusher_trophy/miner_eye) - loot = list(/obj/item/melee/transforming/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator) + crusher_loot = list(/obj/item/melee/transforming/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator/premiumka, /obj/item/crusher_trophy/miner_eye) + loot = list(/obj/item/melee/transforming/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator/premiumka) wander = FALSE del_on_death = TRUE blood_volume = BLOOD_VOLUME_NORMAL @@ -73,7 +73,7 @@ Difficulty: Medium target.stun_absorption -= "miner" /obj/item/projectile/kinetic/miner - damage = 20 + damage = 40 speed = 0.9 icon_state = "ka_tracer" range = MINER_DASH_RANGE diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm index d7c52efe1d..9ee51c0c4f 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm @@ -6,7 +6,7 @@ a_intent = INTENT_HARM sentience_type = SENTIENCE_BOSS environment_smash = ENVIRONMENT_SMASH_RWALLS - mob_biotypes = list(MOB_ORGANIC, MOB_EPIC) + mob_biotypes = MOB_ORGANIC|MOB_EPIC obj_damage = 400 light_range = 3 faction = list("mining", "boss") diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm index 5e159e8517..16a55421b8 100644 --- a/code/modules/mob/living/simple_animal/hostile/mimic.dm +++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm @@ -12,7 +12,7 @@ maxHealth = 250 health = 250 gender = NEUTER - mob_biotypes = list(MOB_INORGANIC) + mob_biotypes = NONE harm_intent_damage = 5 melee_damage_lower = 8 diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm index 91b76974b5..1cbabd41dd 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm @@ -8,7 +8,7 @@ icon_aggro = "Basilisk_alert" icon_dead = "Basilisk_dead" icon_gib = "syndicate_gib" - mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + mob_biotypes = MOB_ORGANIC|MOB_BEAST move_to_delay = 20 projectiletype = /obj/item/projectile/temp/basilisk projectilesound = 'sound/weapons/pierce.ogg' diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm index e4046138cd..8687b2d14c 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm @@ -5,7 +5,7 @@ icon_state = "curseblob" icon_living = "curseblob" icon_aggro = "curseblob" - mob_biotypes = list(MOB_SPIRIT) + mob_biotypes = MOB_SPIRIT movement_type = FLYING move_to_delay = 5 vision_range = 20 diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goldgrub.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goldgrub.dm index c02f0c46c7..25e38652e1 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goldgrub.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goldgrub.dm @@ -8,7 +8,7 @@ icon_aggro = "Goldgrub_alert" icon_dead = "Goldgrub_dead" icon_gib = "syndicate_gib" - mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + mob_biotypes = MOB_ORGANIC|MOB_BEAST vision_range = 2 aggro_vision_range = 9 move_to_delay = 5 diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm index c17e98a7db..87abc1ea14 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm @@ -8,7 +8,7 @@ icon_aggro = "Goliath_alert" icon_dead = "Goliath_dead" icon_gib = "syndicate_gib" - mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + mob_biotypes = MOB_ORGANIC|MOB_BEAST mouse_opacity = MOUSE_OPACITY_OPAQUE move_to_delay = 10 ranged = 1 diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm index 9e9fbaeab8..fd3221d900 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm @@ -6,7 +6,7 @@ icon_state = "gutlunch" icon_living = "gutlunch" icon_dead = "gutlunch" - mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + mob_biotypes = MOB_ORGANIC|MOB_BEAST speak_emote = list("warbles", "quavers") emote_hear = list("trills.") emote_see = list("sniffs.", "burps.") diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm index 9e398ce0da..11de9df70b 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm @@ -7,7 +7,7 @@ icon_aggro = "Hivelord_alert" icon_dead = "Hivelord_dead" icon_gib = "syndicate_gib" - mob_biotypes = list(MOB_ORGANIC) + mob_biotypes = MOB_ORGANIC mouse_opacity = MOUSE_OPACITY_OPAQUE move_to_delay = 14 ranged = 1 @@ -98,7 +98,7 @@ icon_aggro = "legion" icon_dead = "legion" icon_gib = "syndicate_gib" - mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID obj_damage = 60 melee_damage_lower = 15 melee_damage_upper = 15 diff --git a/code/modules/mob/living/simple_animal/hostile/nanotrasen.dm b/code/modules/mob/living/simple_animal/hostile/nanotrasen.dm index 543ffe6131..ed2a407b8e 100644 --- a/code/modules/mob/living/simple_animal/hostile/nanotrasen.dm +++ b/code/modules/mob/living/simple_animal/hostile/nanotrasen.dm @@ -6,7 +6,7 @@ icon_living = "nanotrasen" icon_dead = null icon_gib = "syndicate_gib" - mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID speak_chance = 12 turns_per_move = 5 response_help = "pokes" diff --git a/code/modules/mob/living/simple_animal/hostile/netherworld.dm b/code/modules/mob/living/simple_animal/hostile/netherworld.dm index 918a2d8acc..363e3ec573 100644 --- a/code/modules/mob/living/simple_animal/hostile/netherworld.dm +++ b/code/modules/mob/living/simple_animal/hostile/netherworld.dm @@ -4,7 +4,7 @@ icon_state = "otherthing" icon_living = "otherthing" icon_dead = "otherthing-dead" - mob_biotypes = list(MOB_INORGANIC) + mob_biotypes = NONE health = 80 maxHealth = 80 obj_damage = 100 diff --git a/code/modules/mob/living/simple_animal/hostile/pirate.dm b/code/modules/mob/living/simple_animal/hostile/pirate.dm index 174ae0b9fb..1b2212bf55 100644 --- a/code/modules/mob/living/simple_animal/hostile/pirate.dm +++ b/code/modules/mob/living/simple_animal/hostile/pirate.dm @@ -5,7 +5,7 @@ icon_state = "piratemelee" icon_living = "piratemelee" icon_dead = "pirate_dead" - mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID speak_chance = 0 turns_per_move = 5 response_help = "pushes" @@ -43,7 +43,7 @@ var/obj/effect/light_emitter/red_energy_sword/sord do_footstep = TRUE - + /mob/living/simple_animal/hostile/pirate/melee/space name = "Space Pirate Swashbuckler" icon_state = "piratespace" diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/bat.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/bat.dm index c518cbe083..cc17759cc6 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/bat.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/bat.dm @@ -10,7 +10,7 @@ response_help = "brushes aside" response_disarm = "flails at" response_harm = "hits" - mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + mob_biotypes = MOB_ORGANIC|MOB_BEAST speak_chance = 0 maxHealth = 15 health = 15 diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm index d2c8f1f270..ca14d4ae67 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm @@ -6,7 +6,7 @@ icon_living = "clown" icon_dead = "clown_dead" icon_gib = "clown_gib" - mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID turns_per_move = 5 response_help = "pokes" response_disarm = "gently pushes aside" diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/frog.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/frog.dm index 47734abebc..ef51d8621b 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/frog.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/frog.dm @@ -4,7 +4,7 @@ icon_state = "frog" icon_living = "frog" icon_dead = "frog_dead" - mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + mob_biotypes = MOB_ORGANIC|MOB_BEAST speak = list("ribbit","croak") emote_see = list("hops in a circle.", "shakes.") speak_chance = 1 diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/ghost.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/ghost.dm index bfe8349192..48d16f63f3 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/ghost.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/ghost.dm @@ -4,7 +4,7 @@ icon = 'icons/mob/mob.dmi' icon_state = "ghost" icon_living = "ghost" - mob_biotypes = list(MOB_SPIRIT) + mob_biotypes = MOB_SPIRIT speak_chance = 0 turns_per_move = 5 response_help = "passes through" diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/spaceman.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/spaceman.dm index c50ace8871..29b0c0b701 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/spaceman.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/spaceman.dm @@ -5,7 +5,7 @@ icon_living = "old" icon_dead = "old_dead" icon_gib = "clown_gib" - mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID gender = MALE turns_per_move = 5 response_help = "pokes" diff --git a/code/modules/mob/living/simple_animal/hostile/russian.dm b/code/modules/mob/living/simple_animal/hostile/russian.dm index f66814f01f..c99c7a04b5 100644 --- a/code/modules/mob/living/simple_animal/hostile/russian.dm +++ b/code/modules/mob/living/simple_animal/hostile/russian.dm @@ -6,7 +6,7 @@ icon_living = "russianmelee" icon_dead = "russianmelee_dead" icon_gib = "syndicate_gib" - mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID speak_chance = 0 turns_per_move = 5 response_help = "pokes" diff --git a/code/modules/mob/living/simple_animal/hostile/skeleton.dm b/code/modules/mob/living/simple_animal/hostile/skeleton.dm index 48b69a1f5c..51c55cbf65 100644 --- a/code/modules/mob/living/simple_animal/hostile/skeleton.dm +++ b/code/modules/mob/living/simple_animal/hostile/skeleton.dm @@ -6,7 +6,7 @@ icon_living = "skeleton" icon_dead = "skeleton" gender = NEUTER - mob_biotypes = list(MOB_UNDEAD, MOB_HUMANOID) + mob_biotypes = MOB_UNDEAD|MOB_HUMANOID turns_per_move = 5 speak_emote = list("rattles") emote_see = list("rattles") diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm index 1e1fa9d41b..5ad787b143 100644 --- a/code/modules/mob/living/simple_animal/hostile/statue.dm +++ b/code/modules/mob/living/simple_animal/hostile/statue.dm @@ -9,7 +9,7 @@ icon_dead = "human_male" gender = NEUTER a_intent = INTENT_HARM - mob_biotypes = list(MOB_INORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_HUMANOID response_help = "touches" response_disarm = "pushes" @@ -191,7 +191,7 @@ /obj/effect/proc_holder/spell/aoe_turf/blindness/cast(list/targets,mob/user = usr) for(var/mob/living/L in GLOB.alive_mob_list) var/turf/T = get_turf(L.loc) - if(T && T in targets) + if(T && (T in targets)) L.blind_eyes(4) return diff --git a/code/modules/mob/living/simple_animal/hostile/stickman.dm b/code/modules/mob/living/simple_animal/hostile/stickman.dm index fa5cb151ed..855d55938d 100644 --- a/code/modules/mob/living/simple_animal/hostile/stickman.dm +++ b/code/modules/mob/living/simple_animal/hostile/stickman.dm @@ -5,7 +5,7 @@ icon_living = "stickman" icon_dead = "stickman_dead" icon_gib = "syndicate_gib" - mob_biotypes = list(MOB_INORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_HUMANOID gender = MALE speak_chance = 0 turns_per_move = 5 @@ -40,7 +40,7 @@ minimum_distance = 5 icon_state = "stickmanranged" icon_living = "stickmanranged" - casingtype = /obj/item/ammo_casing/c45/nostamina + casingtype = /obj/item/ammo_casing/c10mm projectilesound = 'sound/misc/bang.ogg' loot = list(/obj/item/gun/ballistic/automatic/pistol/stickman) @@ -51,7 +51,7 @@ icon_state = "stickdog" icon_living = "stickdog" icon_dead = "stickdog_dead" - mob_biotypes = list(MOB_INORGANIC, MOB_BEAST) + mob_biotypes = MOB_BEAST /mob/living/simple_animal/hostile/stickman/Initialize(mapload, var/wizard_summoned) . = ..() diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index 96a75f6b4f..0947a3090b 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -22,7 +22,7 @@ icon_living = "syndicate" icon_dead = "syndicate_dead" icon_gib = "syndicate_gib" - mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID speak_chance = 0 turns_per_move = 5 response_help = "pokes" @@ -284,7 +284,7 @@ icon_living = "viscerator_attack" pass_flags = PASSTABLE | PASSMOB a_intent = INTENT_HARM - mob_biotypes = list(MOB_ROBOTIC) + mob_biotypes = MOB_ROBOTIC health = 25 maxHealth = 25 melee_damage_lower = 15 diff --git a/code/modules/mob/living/simple_animal/hostile/wizard.dm b/code/modules/mob/living/simple_animal/hostile/wizard.dm index f047a7aed1..f97613fe8f 100644 --- a/code/modules/mob/living/simple_animal/hostile/wizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/wizard.dm @@ -5,7 +5,7 @@ icon_state = "wizard" icon_living = "wizard" icon_dead = "wizard_dead" - mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID speak_chance = 0 turns_per_move = 3 response_help = "pokes" diff --git a/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm b/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm index ec7451dc2e..88b5bcc373 100644 --- a/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm +++ b/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm @@ -8,7 +8,7 @@ icon_aggro = "Fugu0" icon_dead = "Fugu_dead" icon_gib = "syndicate_gib" - mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + mob_biotypes = MOB_ORGANIC|MOB_BEAST mouse_opacity = MOUSE_OPACITY_ICON move_to_delay = 5 friendly = "floats near" diff --git a/code/modules/mob/living/simple_animal/hostile/zombie.dm b/code/modules/mob/living/simple_animal/hostile/zombie.dm index 7d89941687..ae3f0465d5 100644 --- a/code/modules/mob/living/simple_animal/hostile/zombie.dm +++ b/code/modules/mob/living/simple_animal/hostile/zombie.dm @@ -4,7 +4,7 @@ icon = 'icons/mob/simple_human.dmi' icon_state = "zombie" icon_living = "zombie" - mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID) + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID speak_chance = 0 stat_attack = UNCONSCIOUS //braains maxHealth = 100 diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index f378906db1..e79e24b885 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -467,11 +467,11 @@ return return - if(parrot_interest && parrot_interest in view(src)) + if(parrot_interest && (parrot_interest in view(src))) parrot_state = PARROT_SWOOP | PARROT_STEAL return - if(parrot_perch && parrot_perch in view(src)) + if(parrot_perch && (parrot_perch in view(src))) parrot_state = PARROT_SWOOP | PARROT_RETURN return diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm index 64ffa147cf..6aa7f8b401 100644 --- a/code/modules/mob/living/simple_animal/shade.dm +++ b/code/modules/mob/living/simple_animal/shade.dm @@ -6,7 +6,7 @@ icon = 'icons/mob/mob.dmi' icon_state = "shade" icon_living = "shade" - mob_biotypes = list(MOB_SPIRIT) + mob_biotypes = MOB_SPIRIT maxHealth = 40 health = 40 spacewalk = TRUE diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index 5a1a794d4e..2ea2a412f8 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -97,7 +97,7 @@ else var/datum/action/innate/slime/evolve/E = new E.Grant(src) - create_reagents(100) + create_reagents(100, NONE, NO_REAGENTS_VALUE) set_colour(new_colour) . = ..() nutrition = 700 diff --git a/code/modules/mob/living/taste.dm b/code/modules/mob/living/taste.dm index e4d1aa94a5..46d0608f44 100644 --- a/code/modules/mob/living/taste.dm +++ b/code/modules/mob/living/taste.dm @@ -16,21 +16,22 @@ // non destructively tastes a reagent container /mob/living/proc/taste(datum/reagents/from) - if(last_taste_time + 50 < world.time) - var/taste_sensitivity = get_taste_sensitivity() - var/text_output = from.generate_taste_message(taste_sensitivity) - // We dont want to spam the same message over and over again at the - // person. Give it a bit of a buffer. - if(hallucination > 50 && prob(25)) - text_output = pick("spiders","dreams","nightmares","the future","the past","victory",\ - "defeat","pain","bliss","revenge","poison","time","space","death","life","truth","lies","justice","memory",\ - "regrets","your soul","suffering","music","noise","blood","hunger","the american way") - if(text_output != last_taste_text || last_taste_time + 100 < world.time) - to_chat(src, "You can taste [text_output].") - // "something indescribable" -> too many tastes, not enough flavor. - - last_taste_time = world.time - last_taste_text = text_output + if(last_taste_time + 50 > world.time) + return FALSE + var/taste_sensitivity = get_taste_sensitivity() + var/text_output = from.generate_taste_message(taste_sensitivity) + // We dont want to spam the same message over and over again at the + // person. Give it a bit of a buffer. + if(hallucination > 50 && prob(25)) + text_output = pick("spiders","dreams","nightmares","the future","the past","victory",\ + "defeat","pain","bliss","revenge","poison","time","space","death","life","truth","lies","justice","memory",\ + "regrets","your soul","suffering","music","noise","blood","hunger","the american way") + if(text_output != last_taste_text || last_taste_time + 100 < world.time) + to_chat(src, "You can taste [text_output].") + // "something indescribable" -> too many tastes, not enough flavor. + last_taste_time = world.time + last_taste_text = text_output + return TRUE //FermiChem - How to check pH of a beaker without a meter/pH paper. //Basically checks the pH of the holder and burns your poor tongue if it's too acidic! @@ -41,22 +42,24 @@ if (!T) return .=..() + if(!.) + return if ((from.pH > 12.5) || (from.pH < 1.5)) - to_chat(src, "You taste chemical burns!") T.applyOrganDamage(5) + to_chat(src, "You taste chemical burns!") if(istype(T, /obj/item/organ/tongue/cybernetic)) to_chat(src, "Your tongue moves on it's own in response to the liquid.") say("The pH is appropriately [round(from.pH, 1)].") return if (!HAS_TRAIT(src, TRAIT_AGEUSIA)) //I'll let you get away with not having 1 damage. switch(from.pH) - if(11.5 to INFINITY) + if(11.5 to 12.5) to_chat(src, "You taste a strong alkaline flavour!") if(8.5 to 11.5) to_chat(src, "You taste a sort of soapy tone in the mixture.") if(2.5 to 5.5) to_chat(src, "You taste a sort of acid tone in the mixture.") - if(-INFINITY to 2.5) + if(1.5 to 2.5) to_chat(src, "You taste a strong acidic flavour!") #undef DEFAULT_TASTE_SENSITIVITY diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 35c7510ad9..1ca6299efb 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -512,9 +512,6 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) usr << browse(text("[][]", name, replacetext(flavor_text_2, "\n", "
")), text("window=[];size=500x200", name)) onclose(usr, "[name]") - if(href_list["flavor_change"]) - update_flavor_text() - if(href_list["refresh"]) if(machine && in_range(src, usr)) show_inv(machine) @@ -808,7 +805,7 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) //Can the mob interact() with an atom? /mob/proc/can_interact_with(atom/A) - return IsAdminGhost(src) || Adjacent(A) + return IsAdminGhost(src) || Adjacent(A) || A.hasSiliconAccessInArea(src) //Can the mob use Topic to interact with machines /mob/proc/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE) diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 1402b78908..6d5ae72e77 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -121,4 +121,10 @@ var/mob/audiovisual_redirect //Mob to redirect messages, speech, and sounds to + var/siliconaccessareas = list() + var/siliconaccesstoggle = FALSE + var/voluntary_ghosted = FALSE //whether or not they voluntarily ghosted. + + var/flavor_text = "" + var/flavor_text_2 = "" //version of the above that only lasts for the current round. diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index d78d23c234..b25531f0e0 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -147,6 +147,10 @@ . += newletter return sanitize(.) +//Ratvarian Slurring! + +#define CLOCK_CULT_SLUR(phrase) sanitize(text2ratvar(phrase)) + ///Adds stuttering to the message passed in /proc/stutter(phrase) phrase = html_decode(phrase) @@ -402,17 +406,28 @@ It's fairly easy to fix if dealing with single letters but not so much with comp return return TRUE -/proc/canGhostWrite(var/mob/A, var/obj/target, var/desc="", var/allow_all=FALSE) - if(allow_all & TRUE) - if(!target.GetComponent(/datum/component/anti_magic)) - return 1 - if(IsAdminGhost(A)) - if (desc != "") - log_admin("GHOST: [key_name(A)] [desc] ([target.name] at [loc_name(target)])") +/atom/proc/hasSiliconAccessInArea(mob/user) + return user && (issilicon(user) || (user.siliconaccesstoggle && (get_area(src) in user.siliconaccessareas))) + +/mob/proc/toggleSiliconAccessArea(area/area) + if (area in siliconaccessareas) + siliconaccessareas -= area + to_chat(src,"You lost control of [area]!") + return FALSE + else + if (LAZYLEN(siliconaccessareas) < HIJACK_APC_MAX_AMOUNT) + siliconaccessareas += area + to_chat(src,"You successfully took control of [area].") else - log_admin("GHOST: [key_name(A)] fucked with the [target.name] at [loc_name(target)]") - return 1 - return 0 + to_chat(src,"You are connected to too many APCs! Too many more will fry your brain.") + return FALSE + return TRUE + +/mob/proc/getImplant(type) + return + +/mob/living/getImplant(type) + return locate(type) in implants /proc/offer_control(mob/M) to_chat(M, "Control of your mob has been offered to dead players.") diff --git a/code/modules/mob/say_vr.dm b/code/modules/mob/say_vr.dm index 74cc0c2e77..377bb1c5fc 100644 --- a/code/modules/mob/say_vr.dm +++ b/code/modules/mob/say_vr.dm @@ -1,52 +1,6 @@ ////////////////////////////////////////////////////// ////////////////////SUBTLE COMMAND//////////////////// ////////////////////////////////////////////////////// -/mob - var/flavor_text = "" //tired of fucking double checking this - var/flavor_text_2 = "" - -/mob/proc/update_flavor_text() - set src in usr - if(usr != src) - to_chat(usr, "No.") - var/msg = stripped_multiline_input(usr, "Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!", "Flavor Text", html_decode(flavor_text), MAX_MESSAGE_LEN, TRUE) - - if(msg) - flavor_text = html_encode(msg) - -/mob/proc/update_flavor_text_2() - set src in usr - if(usr != src) - to_chat(usr, "No.") - var/msg = stripped_multiline_input(usr, "Set the temporary flavor text in your 'examine' verb. This should be used only for things pertaining to the current round!", "Short-Term Flavor Text", html_decode(flavor_text_2), MAX_MESSAGE_LEN, TRUE) - - if(msg) - flavor_text_2 = html_encode(msg) - - -/mob/proc/warn_flavor_changed() - if(flavor_text && flavor_text != "") // don't spam people that don't use it! - to_chat(src, "

OOC Warning:

") - to_chat(src, "Your flavor text is likely out of date! Change") - -/mob/proc/print_flavor_text() - if(flavor_text && flavor_text != "") - // We are decoding and then encoding to not only get correct amount of characters, but also to prevent partial escaping characters being shown. - var/msg = html_decode(replacetext(flavor_text, "\n", " ")) - if(length_char(msg) <= 40) - return "[html_encode(msg)]" - else - return "[html_encode(copytext_char(msg, 1, 37))]... More..." - -/mob/proc/print_flavor_text_2() - if(flavor_text && flavor_text != "") - // We are decoding and then encoding to not only get correct amount of characters, but also to prevent partial escaping characters being shown. - var/msg = html_decode(replacetext(flavor_text_2, "\n", " ")) - if(length_char(msg) <= 40) - return "[html_encode(msg)]" - else - return "[html_encode(copytext_char(msg, 1, 37))]... More..." - /mob/proc/get_top_level_mob() if(istype(src.loc,/mob)&&src.loc!=src) @@ -60,9 +14,6 @@ proc/get_top_level_mob(var/mob/S) return M.get_top_level_mob() return S - - - ///////////////// EMOTE CODE // Maybe making this as an emote is less messy? // It was - ktccd diff --git a/code/modules/modular_computers/computers/item/computer_ui.dm b/code/modules/modular_computers/computers/item/computer_ui.dm index 3e67a14874..11f5145478 100644 --- a/code/modules/modular_computers/computers/item/computer_ui.dm +++ b/code/modules/modular_computers/computers/item/computer_ui.dm @@ -14,7 +14,7 @@ return 0 // Robots don't really need to see the screen, their wireless connection works as long as computer is on. - if(!screen_on && !issilicon(user)) + if(!screen_on && !hasSiliconAccessInArea(user)) if(ui) ui.close() return 0 diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm index f661f0ec10..b54bc9f2be 100644 --- a/code/modules/modular_computers/file_system/program.dm +++ b/code/modules/modular_computers/file_system/program.dm @@ -87,7 +87,7 @@ if(IsAdminGhost(user)) return TRUE - if(issilicon(user)) + if(computer && computer.hasSiliconAccessInArea(user)) return TRUE if(ishuman(user)) diff --git a/code/modules/newscaster/_news.dm b/code/modules/newscaster/_news.dm new file mode 100644 index 0000000000..6c6f10fdcc --- /dev/null +++ b/code/modules/newscaster/_news.dm @@ -0,0 +1,2 @@ +/datum/news + var/author = "" diff --git a/code/modules/newscaster/feed_channel.dm b/code/modules/newscaster/feed_channel.dm new file mode 100644 index 0000000000..278c9c7ad1 --- /dev/null +++ b/code/modules/newscaster/feed_channel.dm @@ -0,0 +1,33 @@ +/datum/news/feed_channel + var/channel_name = "" + var/list/datum/news/feed_message/messages = list() + var/locked = FALSE + var/censored = 0 + var/list/authorCensorTime = list() + var/list/DclassCensorTime = list() + var/authorCensor + var/is_admin_channel = 0 + +/datum/news/feed_channel/proc/returnAuthor(censor) + if(censor == -1) + censor = authorCensor + var/txt = "[GLOB.news_network.redactedText]" + if(!censor) + txt = author + return txt + +/datum/news/feed_channel/proc/toggleCensorDclass() + if(censored) + DclassCensorTime.Add(GLOB.news_network.lastAction*-1) + else + DclassCensorTime.Add(GLOB.news_network.lastAction) + censored = !censored + GLOB.news_network.lastAction ++ + +/datum/news/feed_channel/proc/toggleCensorAuthor() + if(authorCensor) + authorCensorTime.Add(GLOB.news_network.lastAction*-1) + else + authorCensorTime.Add(GLOB.news_network.lastAction) + authorCensor = !authorCensor + GLOB.news_network.lastAction ++ diff --git a/code/modules/newscaster/feed_comment.dm b/code/modules/newscaster/feed_comment.dm new file mode 100644 index 0000000000..ff5ebac028 --- /dev/null +++ b/code/modules/newscaster/feed_comment.dm @@ -0,0 +1,3 @@ +/datum/news/feed_comment + var/body = "" + var/time_stamp = "" diff --git a/code/modules/newscaster/feed_message.dm b/code/modules/newscaster/feed_message.dm new file mode 100644 index 0000000000..573b3f772d --- /dev/null +++ b/code/modules/newscaster/feed_message.dm @@ -0,0 +1,46 @@ +/datum/news/feed_message + var/body ="" + var/list/authorCensorTime = list() + var/list/bodyCensorTime = list() + var/is_admin_message = 0 + var/icon/img = null + var/time_stamp = "" + var/list/datum/news/feed_comment/comments = list() + var/locked = FALSE + var/caption = "" + var/creationTime + var/authorCensor + var/bodyCensor + var/photo_file + +/datum/news/feed_message/proc/returnAuthor(censor) + if(censor == -1) + censor = authorCensor + var/txt = "[GLOB.news_network.redactedText]" + if(!censor) + txt = author + return txt + +/datum/news/feed_message/proc/returnBody(censor) + if(censor == -1) + censor = bodyCensor + var/txt = "[GLOB.news_network.redactedText]" + if(!censor) + txt = body + return txt + +/datum/news/feed_message/proc/toggleCensorAuthor() + if(authorCensor) + authorCensorTime.Add(GLOB.news_network.lastAction*-1) + else + authorCensorTime.Add(GLOB.news_network.lastAction) + authorCensor = !authorCensor + GLOB.news_network.lastAction ++ + +/datum/news/feed_message/proc/toggleCensorBody() + if(bodyCensor) + bodyCensorTime.Add(GLOB.news_network.lastAction*-1) + else + bodyCensorTime.Add(GLOB.news_network.lastAction) + bodyCensor = !bodyCensor + GLOB.news_network.lastAction ++ diff --git a/code/modules/newscaster/ghostread.dm b/code/modules/newscaster/ghostread.dm new file mode 100644 index 0000000000..77cb1a03c8 --- /dev/null +++ b/code/modules/newscaster/ghostread.dm @@ -0,0 +1,52 @@ +/mob/dead/observer/verb/read_news() + set name = "Read Newscaster" + set desc = "Open a list of available news channels" + set category = "Ghost" + + var/datum/browser/B = new(src, "ghost_news_list", "Chanenl List", 450, 600) + B.set_content(render_news_channel_list()) + B.open() + +/mob/dead/observer/Topic(href, href_list) + . = ..() + if(href_list["show_news_channel"]) + var/datum/D = locate(href_list["show_news_channel"]) + if(istype(D, /datum/news/feed_channel)) //safety + render_news_channel(D) + +/mob/dead/observer/proc/render_news_channel_list() + var/datum/news_network/news_network = GLOB.news_network + var/list/content = list() + for(var/i in news_network.network_channels) + var/datum/news/feed_channel/FC = i + content += "[FC.channel_name] ([length(FC.messages)] messages)[FC.locked? " (LOCKED)":""][FC.censored? " (CENSORED)":""][FC.is_admin_channel? " (ADMIN)":""]" + return content.Join("
") + +/mob/dead/observer/proc/render_news_channel(datum/news/feed_channel/FC) + var/list/content = list() + content += "[FC.channel_name]: \[created by: [FC.returnAuthor(-1)]\]
" + if(FC.censored) + content += "ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
" + content += "No further feed story additions are allowed while the D-Notice is in effect.

" + if(!length(FC.messages)) + content += "This channel is empty.
" + else + for(var/i in FC.messages) + var/datum/news/feed_message/FM = i + content += "-[FM.returnBody(-1)]
" + if(FM.img) + src << browse_rsc(FM.img, "tmp_photo[i].png") + content += "
" + if(FM.caption) + content += "[FM.caption]
" + content += "
" + content += "\[Story by [FM.returnAuthor(-1)] \] - ([FM.time_stamp])
" + content += "[FM.comments.len] comment[FM.comments.len > 1 ? "s" : ""]
" + for(var/c in FM.comments) + var/datum/news/feed_comment/comment = c + content += "[comment.body]
[comment.author] [comment.time_stamp]
" + if(FM.locked) + content += "Comments locked
" + var/datum/browser/popup = new(src, "ghost_news_channel", 450, 900) + popup.set_content(content.Join("")) + popup.open() diff --git a/code/modules/newscaster/news_network.dm b/code/modules/newscaster/news_network.dm new file mode 100644 index 0000000000..5e056addee --- /dev/null +++ b/code/modules/newscaster/news_network.dm @@ -0,0 +1,72 @@ +GLOBAL_DATUM_INIT(news_network, /datum/news_network, new) + +/// Contains all the news datum of a newscaster system. +/datum/news_network + var/list/datum/news/feed_channel/network_channels = list() + var/datum/news/wanted_message/wanted_issue + var/lastAction + var/redactedText = "\[REDACTED\]" + +/datum/news_network/New() + CreateFeedChannel("Station Announcements", "SS13", 1) + wanted_issue = new /datum/news/wanted_message + +/datum/news_network/proc/CreateFeedChannel(channel_name, author, locked, adminChannel = 0) + var/datum/news/feed_channel/newChannel = new /datum/news/feed_channel + newChannel.channel_name = channel_name + newChannel.author = author + newChannel.locked = locked + newChannel.is_admin_channel = adminChannel + network_channels += newChannel + +/datum/news_network/proc/SubmitArticle(msg, author, channel_name, datum/picture/picture, adminMessage = 0, allow_comments = 1) + var/datum/news/feed_message/newMsg = new /datum/news/feed_message + newMsg.author = author + newMsg.body = msg + newMsg.time_stamp = STATION_TIME_TIMESTAMP("hh:mm:ss", world.time) + newMsg.is_admin_message = adminMessage + newMsg.locked = !allow_comments + if(picture) + newMsg.img = picture.picture_image + newMsg.caption = picture.caption + newMsg.photo_file = save_photo(picture.picture_image) + for(var/datum/news/feed_channel/FC in network_channels) + if(FC.channel_name == channel_name) + FC.messages += newMsg + break + for(var/obj/machinery/newscaster/NEWSCASTER in GLOB.allCasters) + NEWSCASTER.newsAlert(channel_name) + lastAction ++ + newMsg.creationTime = lastAction + +/datum/news_network/proc/submitWanted(criminal, body, scanned_user, datum/picture/picture, adminMsg = 0, newMessage = 0) + wanted_issue.active = 1 + wanted_issue.criminal = criminal + wanted_issue.body = body + wanted_issue.scannedUser = scanned_user + wanted_issue.isAdminMsg = adminMsg + if(picture) + wanted_issue.img = picture.picture_image + wanted_issue.photo_file = save_photo(picture.picture_image) + if(newMessage) + for(var/obj/machinery/newscaster/N in GLOB.allCasters) + N.newsAlert() + N.update_icon() + +/datum/news_network/proc/deleteWanted() + wanted_issue.active = 0 + wanted_issue.criminal = null + wanted_issue.body = null + wanted_issue.scannedUser = null + wanted_issue.img = null + for(var/obj/machinery/newscaster/NEWSCASTER in GLOB.allCasters) + NEWSCASTER.update_icon() + +/datum/news_network/proc/save_photo(icon/photo) + var/photo_file = copytext_char(md5("\icon[photo]"), 1, 6) + if(!fexists("[GLOB.log_directory]/photos/[photo_file].png")) + //Clean up repeated frames + var/icon/clean = new /icon() + clean.Insert(photo, "", SOUTH, 1, 0) + fcopy(clean, "[GLOB.log_directory]/photos/[photo_file].png") + return photo_file diff --git a/code/game/machinery/newscaster.dm b/code/modules/newscaster/newscaster_machine.dm similarity index 60% rename from code/game/machinery/newscaster.dm rename to code/modules/newscaster/newscaster_machine.dm index 7097de1f3b..cb2016a1a1 100644 --- a/code/game/machinery/newscaster.dm +++ b/code/modules/newscaster/newscaster_machine.dm @@ -1,175 +1,5 @@ -GLOBAL_DATUM_INIT(news_network, /datum/newscaster/feed_network, new) GLOBAL_LIST_EMPTY(allCasters) -/datum/newscaster - -/datum/newscaster/feed_comment - var/author = "" - var/body = "" - var/time_stamp = "" - -/datum/newscaster/feed_message - var/author ="" - var/body ="" - var/list/authorCensorTime = list() - var/list/bodyCensorTime = list() - var/is_admin_message = 0 - var/icon/img = null - var/time_stamp = "" - var/list/datum/newscaster/feed_comment/comments = list() - var/locked = FALSE - var/caption = "" - var/creationTime - var/authorCensor - var/bodyCensor - var/photo_file - -/datum/newscaster/feed_message/proc/returnAuthor(censor) - if(censor == -1) - censor = authorCensor - var/txt = "[GLOB.news_network.redactedText]" - if(!censor) - txt = author - return txt - -/datum/newscaster/feed_message/proc/returnBody(censor) - if(censor == -1) - censor = bodyCensor - var/txt = "[GLOB.news_network.redactedText]" - if(!censor) - txt = body - return txt - -/datum/newscaster/feed_message/proc/toggleCensorAuthor() - if(authorCensor) - authorCensorTime.Add(GLOB.news_network.lastAction*-1) - else - authorCensorTime.Add(GLOB.news_network.lastAction) - authorCensor = !authorCensor - GLOB.news_network.lastAction ++ - -/datum/newscaster/feed_message/proc/toggleCensorBody() - if(bodyCensor) - bodyCensorTime.Add(GLOB.news_network.lastAction*-1) - else - bodyCensorTime.Add(GLOB.news_network.lastAction) - bodyCensor = !bodyCensor - GLOB.news_network.lastAction ++ - -/datum/newscaster/feed_channel - var/channel_name = "" - var/list/datum/newscaster/feed_message/messages = list() - var/locked = FALSE - var/author = "" - var/censored = 0 - var/list/authorCensorTime = list() - var/list/DclassCensorTime = list() - var/authorCensor - var/is_admin_channel = 0 - -/datum/newscaster/feed_channel/proc/returnAuthor(censor) - if(censor == -1) - censor = authorCensor - var/txt = "[GLOB.news_network.redactedText]" - if(!censor) - txt = author - return txt - -/datum/newscaster/feed_channel/proc/toggleCensorDclass() - if(censored) - DclassCensorTime.Add(GLOB.news_network.lastAction*-1) - else - DclassCensorTime.Add(GLOB.news_network.lastAction) - censored = !censored - GLOB.news_network.lastAction ++ - -/datum/newscaster/feed_channel/proc/toggleCensorAuthor() - if(authorCensor) - authorCensorTime.Add(GLOB.news_network.lastAction*-1) - else - authorCensorTime.Add(GLOB.news_network.lastAction) - authorCensor = !authorCensor - GLOB.news_network.lastAction ++ - -/datum/newscaster/wanted_message - var/active - var/criminal - var/body - var/scannedUser - var/isAdminMsg - var/icon/img - var/photo_file - -/datum/newscaster/feed_network - var/list/datum/newscaster/feed_channel/network_channels = list() - var/datum/newscaster/wanted_message/wanted_issue - var/lastAction - var/redactedText = "\[REDACTED\]" - -/datum/newscaster/feed_network/New() - CreateFeedChannel("Station Announcements", "SS13", 1) - wanted_issue = new /datum/newscaster/wanted_message - -/datum/newscaster/feed_network/proc/CreateFeedChannel(channel_name, author, locked, adminChannel = 0) - var/datum/newscaster/feed_channel/newChannel = new /datum/newscaster/feed_channel - newChannel.channel_name = channel_name - newChannel.author = author - newChannel.locked = locked - newChannel.is_admin_channel = adminChannel - network_channels += newChannel - -/datum/newscaster/feed_network/proc/SubmitArticle(msg, author, channel_name, datum/picture/picture, adminMessage = 0, allow_comments = 1) - var/datum/newscaster/feed_message/newMsg = new /datum/newscaster/feed_message - newMsg.author = author - newMsg.body = msg - newMsg.time_stamp = STATION_TIME_TIMESTAMP("hh:mm:ss", world.time) - newMsg.is_admin_message = adminMessage - newMsg.locked = !allow_comments - if(picture) - newMsg.img = picture.picture_image - newMsg.caption = picture.caption - newMsg.photo_file = save_photo(picture.picture_image) - for(var/datum/newscaster/feed_channel/FC in network_channels) - if(FC.channel_name == channel_name) - FC.messages += newMsg - break - for(var/obj/machinery/newscaster/NEWSCASTER in GLOB.allCasters) - NEWSCASTER.newsAlert(channel_name) - lastAction ++ - newMsg.creationTime = lastAction - -/datum/newscaster/feed_network/proc/submitWanted(criminal, body, scanned_user, datum/picture/picture, adminMsg = 0, newMessage = 0) - wanted_issue.active = 1 - wanted_issue.criminal = criminal - wanted_issue.body = body - wanted_issue.scannedUser = scanned_user - wanted_issue.isAdminMsg = adminMsg - if(picture) - wanted_issue.img = picture.picture_image - wanted_issue.photo_file = save_photo(picture.picture_image) - if(newMessage) - for(var/obj/machinery/newscaster/N in GLOB.allCasters) - N.newsAlert() - N.update_icon() - -/datum/newscaster/feed_network/proc/deleteWanted() - wanted_issue.active = 0 - wanted_issue.criminal = null - wanted_issue.body = null - wanted_issue.scannedUser = null - wanted_issue.img = null - for(var/obj/machinery/newscaster/NEWSCASTER in GLOB.allCasters) - NEWSCASTER.update_icon() - -/datum/newscaster/feed_network/proc/save_photo(icon/photo) - var/photo_file = copytext_char(md5("\icon[photo]"), 1, 6) - if(!fexists("[GLOB.log_directory]/photos/[photo_file].png")) - //Clean up repeated frames - var/icon/clean = new /icon() - clean.Insert(photo, "", SOUTH, 1, 0) - fcopy(clean, "[GLOB.log_directory]/photos/[photo_file].png") - return photo_file - /obj/item/wallframe/newscaster name = "newscaster frame" desc = "Used to build newscasters, just secure to the wall." @@ -177,7 +7,6 @@ GLOBAL_LIST_EMPTY(allCasters) materials = list(MAT_METAL=14000, MAT_GLASS=8000) result_path = /obj/machinery/newscaster - /obj/machinery/newscaster name = "newscaster" desc = "A standard Nanotrasen-licensed newsfeed handler for use in commercial space stations. All the news you absolutely have no use for, in one place!" @@ -189,7 +18,6 @@ GLOBAL_LIST_EMPTY(allCasters) armor = list("melee" = 50, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30) max_integrity = 200 integrity_failure = 50 - ghost_flags = INTERACT_GHOST_READ var/screen = 0 var/paper_remaining = 15 var/securityCaster = 0 @@ -197,12 +25,11 @@ GLOBAL_LIST_EMPTY(allCasters) var/alert_delay = 500 var/alert = FALSE var/scanned_user = "Unknown" - var/mob/active_user = null var/msg = "" var/datum/picture/picture var/channel_name = "" var/c_locked=0 - var/datum/newscaster/feed_channel/viewing_channel = null + var/datum/news/feed_channel/viewing_channel = null var/allow_comments = 1 /obj/machinery/newscaster/security_unit @@ -266,10 +93,10 @@ GLOBAL_LIST_EMPTY(allCasters) /obj/machinery/newscaster/ui_interact(mob/user) . = ..() - if(ishuman(user) || issilicon(user) || isobserver(user)) - var/mob/M = user + if(ishuman(user) || issilicon(user)) + var/mob/living/human_or_robot_user = user var/dat - scan_user(M) + scan_user(human_or_robot_user) switch(screen) if(0) dat += "Welcome to Newscasting Unit #[unit_no].
Interface & News networks Operational." @@ -281,7 +108,7 @@ GLOBAL_LIST_EMPTY(allCasters) dat+= "
Submit new Feed story" dat+= "
Print newspaper" dat+= "
Re-scan User" - dat+= "

Exit" + dat+= "

Exit" if(securityCaster) var/wanted_already = 0 if(GLOB.news_network.wanted_issue.active) @@ -296,7 +123,7 @@ GLOBAL_LIST_EMPTY(allCasters) if( isemptylist(GLOB.news_network.network_channels) ) dat+="No active channels found..." else - for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels) + for(var/datum/news/feed_channel/CHANNEL in GLOB.news_network.network_channels) if(CHANNEL.is_admin_channel) dat+="[CHANNEL.channel_name]
" else @@ -335,7 +162,7 @@ GLOBAL_LIST_EMPTY(allCasters) if(7) dat+="ERROR: Could not submit Feed Channel to Network.

" var/list/existing_authors = list() - for(var/datum/newscaster/feed_channel/FC in GLOB.news_network.network_channels) + for(var/datum/news/feed_channel/FC in GLOB.news_network.network_channels) if(FC.authorCensor) existing_authors += GLOB.news_network.redactedText else @@ -345,7 +172,7 @@ GLOBAL_LIST_EMPTY(allCasters) if(channel_name=="" || channel_name == "\[REDACTED\]") dat+="Invalid channel name.
" var/check = 0 - for(var/datum/newscaster/feed_channel/FC in GLOB.news_network.network_channels) + for(var/datum/news/feed_channel/FC in GLOB.news_network.network_channels) if(FC.channel_name == channel_name) check = 1 break @@ -358,7 +185,7 @@ GLOBAL_LIST_EMPTY(allCasters) var/total_num=length(GLOB.news_network.network_channels) var/active_num=total_num var/message_num=0 - for(var/datum/newscaster/feed_channel/FC in GLOB.news_network.network_channels) + for(var/datum/news/feed_channel/FC in GLOB.news_network.network_channels) if(!FC.censored) message_num += length(FC.messages) else @@ -377,7 +204,7 @@ GLOBAL_LIST_EMPTY(allCasters) dat+="No feed messages found in channel...
" else var/i = 0 - for(var/datum/newscaster/feed_message/MESSAGE in viewing_channel.messages) + for(var/datum/news/feed_message/MESSAGE in viewing_channel.messages) i++ dat+="-[MESSAGE.returnBody(-1)]
" if(MESSAGE.img) @@ -388,7 +215,7 @@ GLOBAL_LIST_EMPTY(allCasters) dat+="
" dat+="\[Story by [MESSAGE.returnAuthor(-1)] \] - ([MESSAGE.time_stamp])
" dat+="[MESSAGE.comments.len] comment[MESSAGE.comments.len > 1 ? "s" : ""]
" - for(var/datum/newscaster/feed_comment/comment in MESSAGE.comments) + for(var/datum/news/feed_comment/comment in MESSAGE.comments) dat+="[comment.body]
[comment.author] [comment.time_stamp]
" if(MESSAGE.locked) dat+="Comments locked
" @@ -404,7 +231,7 @@ GLOBAL_LIST_EMPTY(allCasters) if(isemptylist(GLOB.news_network.network_channels)) dat+="No feed channels found active...
" else - for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels) + for(var/datum/news/feed_channel/CHANNEL in GLOB.news_network.network_channels) dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ""]
" dat+="
Cancel" if(11) @@ -415,7 +242,7 @@ GLOBAL_LIST_EMPTY(allCasters) if(isemptylist(GLOB.news_network.network_channels)) dat+="No feed channels found active...
" else - for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels) + for(var/datum/news/feed_channel/CHANNEL in GLOB.news_network.network_channels) dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ""]
" dat+="
Back" if(12) @@ -424,11 +251,11 @@ GLOBAL_LIST_EMPTY(allCasters) if(isemptylist(viewing_channel.messages)) dat+="No feed messages found in channel...
" else - for(var/datum/newscaster/feed_message/MESSAGE in viewing_channel.messages) + for(var/datum/news/feed_message/MESSAGE in viewing_channel.messages) dat+="-[MESSAGE.returnBody(-1)]
\[Story by [MESSAGE.returnAuthor(-1)]\]
" dat+="[(MESSAGE.bodyCensor) ? ("Undo story censorship") : ("Censor story")] - [(MESSAGE.authorCensor) ? ("Undo Author Censorship") : ("Censor message Author")]
" dat+="[MESSAGE.comments.len] comment[MESSAGE.comments.len > 1 ? "s" : ""]: [MESSAGE.locked ? "Unlock" : "Lock"]
" - for(var/datum/newscaster/feed_comment/comment in MESSAGE.comments) + for(var/datum/news/feed_comment/comment in MESSAGE.comments) dat+="[comment.body] X
[comment.author] [comment.time_stamp]
" dat+="
Back" if(13) @@ -441,7 +268,7 @@ GLOBAL_LIST_EMPTY(allCasters) if(isemptylist(viewing_channel.messages)) dat+="No feed messages found in channel...
" else - for(var/datum/newscaster/feed_message/MESSAGE in viewing_channel.messages) + for(var/datum/news/feed_message/MESSAGE in viewing_channel.messages) dat+="-[MESSAGE.returnBody(-1)]
\[Story by [MESSAGE.returnAuthor(-1)]\]
" dat+="
Back" if(14) @@ -503,44 +330,32 @@ GLOBAL_LIST_EMPTY(allCasters) if(21) dat+="Unable to print newspaper. Insufficient paper. Please notify maintenance personnel to refill machine storage.

" dat+="Return" - var/datum/browser/popup = new(M, "newscaster_main", "Newscaster Unit #[unit_no]", 400, 600) + var/datum/browser/popup = new(human_or_robot_user, "newscaster_main", "Newscaster Unit #[unit_no]", 400, 600) popup.set_content(dat) - popup.set_title_image(M.browse_rsc_icon(icon, icon_state)) + popup.set_title_image(human_or_robot_user.browse_rsc_icon(icon, icon_state)) popup.open() /obj/machinery/newscaster/Topic(href, href_list) if(..()) return - if(active_user && !isobserver(active_user) && get_dist(active_user,src)<=1 && usr!=active_user) - to_chat(usr, "You must wait for [active_user] to finish and move away.") - return - if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && isturf(loc))) || issilicon(usr) || isobserver(usr)) + if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && isturf(loc))) || hasSiliconAccessInArea(usr)) usr.set_machine(src) scan_user(usr) if(href_list["set_channel_name"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"set a channel's name")) - to_chat(usr, "You can't do that.") - return channel_name = stripped_input(usr, "Provide a Feed Channel Name", "Network Channel Handler", "", MAX_NAME_LEN) updateUsrDialog() else if(href_list["set_channel_lock"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"locked a channel")) - to_chat(usr, "You can't do that.") - return c_locked = !c_locked updateUsrDialog() else if(href_list["submit_new_channel"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"created a new channel")) - to_chat(usr, "You can't do that.") - return var/list/existing_authors = list() - for(var/datum/newscaster/feed_channel/FC in GLOB.news_network.network_channels) + for(var/datum/news/feed_channel/FC in GLOB.news_network.network_channels) if(FC.authorCensor) existing_authors += GLOB.news_network.redactedText else existing_authors += FC.author var/check = 0 - for(var/datum/newscaster/feed_channel/FC in GLOB.news_network.network_channels) + for(var/datum/news/feed_channel/FC in GLOB.news_network.network_channels) if(FC.channel_name == channel_name) check = 1 break @@ -555,33 +370,21 @@ GLOBAL_LIST_EMPTY(allCasters) screen=5 updateUsrDialog() else if(href_list["set_channel_receiving"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"tried to set the receiving channel")) - to_chat(usr, "You can't do that.") - return var/list/available_channels = list() - for(var/datum/newscaster/feed_channel/F in GLOB.news_network.network_channels) + for(var/datum/news/feed_channel/F in GLOB.news_network.network_channels) if( (!F.locked || F.author == scanned_user) && !F.censored) available_channels += F.channel_name channel_name = input(usr, "Choose receiving Feed Channel", "Network Channel Handler") in available_channels updateUsrDialog() else if(href_list["set_new_message"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"set the message of a new feed story")) - to_chat(usr, "You can't do that.") - return var/temp_message = trim(stripped_multiline_input(usr, "Write your Feed story", "Network Channel Handler", msg)) if(temp_message) msg = temp_message updateUsrDialog() else if(href_list["set_attachment"]) - if(isobserver(usr)) - to_chat(usr, "You can't do that.") - return AttachPhoto(usr) updateUsrDialog() else if(href_list["submit_new_message"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"added a new story")) - to_chat(usr, "You can't do that.") - return if(msg =="" || msg=="\[REDACTED\]" || scanned_user == "Unknown" || channel_name == "" ) screen=6 else @@ -591,27 +394,15 @@ GLOBAL_LIST_EMPTY(allCasters) msg = "" updateUsrDialog() else if(href_list["create_channel"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"created a channel")) - to_chat(usr, "You can't do that.") - return screen=2 updateUsrDialog() else if(href_list["create_feed_story"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"created a feed story")) - to_chat(usr, "You can't do that.") - return screen=3 updateUsrDialog() else if(href_list["menu_paper"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"")) - to_chat(usr, "You can't do that.") - return screen=8 updateUsrDialog() else if(href_list["print_paper"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"printed a paper")) - to_chat(usr, "You can't do that.") - return if(!paper_remaining) screen=21 else @@ -619,21 +410,12 @@ GLOBAL_LIST_EMPTY(allCasters) screen = 20 updateUsrDialog() else if(href_list["menu_censor_story"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"censored a story")) - to_chat(usr, "You can't do that.") - return screen=10 updateUsrDialog() else if(href_list["menu_censor_channel"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"censored a channel")) - to_chat(usr, "You can't do that.") - return screen=11 updateUsrDialog() else if(href_list["menu_wanted"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"")) - to_chat(usr, "You can't do that.") - return var/already_wanted = 0 if(GLOB.news_network.wanted_issue.active) already_wanted = 1 @@ -643,21 +425,12 @@ GLOBAL_LIST_EMPTY(allCasters) screen = 14 updateUsrDialog() else if(href_list["set_wanted_name"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"tried to set the name of a wanted person")) - to_chat(usr, "You can't do that.") - return channel_name = stripped_input(usr, "Provide the name of the Wanted person", "Network Security Handler") updateUsrDialog() else if(href_list["set_wanted_desc"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"tried to set the description of a wanted person")) - to_chat(usr, "You can't do that.") - return msg = stripped_input(usr, "Provide a description of the Wanted person and any other details you deem important", "Network Security Handler") updateUsrDialog() else if(href_list["submit_wanted"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"submitted a wanted poster")) - to_chat(usr, "You can't do that.") - return var/input_param = text2num(href_list["submit_wanted"]) if(msg == "" || channel_name == "" || scanned_user == "Unknown") screen = 16 @@ -688,48 +461,33 @@ GLOBAL_LIST_EMPTY(allCasters) screen=18 updateUsrDialog() else if(href_list["censor_channel_author"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"tried to censor an author")) - to_chat(usr, "You can't do that.") - return - var/datum/newscaster/feed_channel/FC = locate(href_list["censor_channel_author"]) + var/datum/news/feed_channel/FC = locate(href_list["censor_channel_author"]) if(FC.is_admin_channel) alert("This channel was created by a Nanotrasen Officer. You cannot censor it.","Ok") return FC.toggleCensorAuthor() updateUsrDialog() else if(href_list["censor_channel_story_author"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"tried to censor a story's author")) - to_chat(usr, "You can't do that.") - return - var/datum/newscaster/feed_message/MSG = locate(href_list["censor_channel_story_author"]) + var/datum/news/feed_message/MSG = locate(href_list["censor_channel_story_author"]) if(MSG.is_admin_message) alert("This message was created by a Nanotrasen Officer. You cannot censor its author.","Ok") return MSG.toggleCensorAuthor() updateUsrDialog() else if(href_list["censor_channel_story_body"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"tried to censor a story")) - to_chat(usr, "You can't do that.") - return - var/datum/newscaster/feed_message/MSG = locate(href_list["censor_channel_story_body"]) + var/datum/news/feed_message/MSG = locate(href_list["censor_channel_story_body"]) if(MSG.is_admin_message) alert("This channel was created by a Nanotrasen Officer. You cannot censor it.","Ok") return MSG.toggleCensorBody() updateUsrDialog() else if(href_list["pick_d_notice"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"")) - to_chat(usr, "You can't do that.") - return - var/datum/newscaster/feed_channel/FC = locate(href_list["pick_d_notice"]) + var/datum/news/feed_channel/FC = locate(href_list["pick_d_notice"]) viewing_channel = FC screen=13 updateUsrDialog() else if(href_list["toggle_d_notice"]) - if(isobserver(usr) && !canGhostWrite(usr,src,"tried to set a D-notice")) - to_chat(usr, "You can't do that.") - return - var/datum/newscaster/feed_channel/FC = locate(href_list["toggle_d_notice"]) + var/datum/news/feed_channel/FC = locate(href_list["toggle_d_notice"]) if(FC.is_admin_channel) alert("This channel was created by a Nanotrasen Officer. You cannot place a D-Notice upon it.","Ok") return @@ -748,21 +506,21 @@ GLOBAL_LIST_EMPTY(allCasters) viewing_channel = null updateUsrDialog() else if(href_list["show_channel"]) - var/datum/newscaster/feed_channel/FC = locate(href_list["show_channel"]) + var/datum/news/feed_channel/FC = locate(href_list["show_channel"]) viewing_channel = FC screen = 9 updateUsrDialog() else if(href_list["pick_censor_channel"]) - var/datum/newscaster/feed_channel/FC = locate(href_list["pick_censor_channel"]) + var/datum/news/feed_channel/FC = locate(href_list["pick_censor_channel"]) viewing_channel = FC screen = 12 updateUsrDialog() else if(href_list["new_comment"]) - var/datum/newscaster/feed_message/FM = locate(href_list["new_comment"]) + var/datum/news/feed_message/FM = locate(href_list["new_comment"]) var/cominput = copytext_char(stripped_input(usr, "Write your message:", "New comment", null), 140) if(cominput) scan_user(usr) - var/datum/newscaster/feed_comment/FC = new/datum/newscaster/feed_comment + var/datum/news/feed_comment/FC = new/datum/news/feed_comment FC.author = scanned_user FC.body = cominput FC.time_stamp = STATION_TIME_TIMESTAMP("hh:mm:ss", world.time) @@ -770,14 +528,14 @@ GLOBAL_LIST_EMPTY(allCasters) usr.log_message("(as [scanned_user]) commented on message [FM.returnBody(-1)] -- [FC.body]", LOG_COMMENT) updateUsrDialog() else if(href_list["del_comment"]) - var/datum/newscaster/feed_comment/FC = locate(href_list["del_comment"]) - var/datum/newscaster/feed_message/FM = locate(href_list["del_comment_msg"]) + var/datum/news/feed_comment/FC = locate(href_list["del_comment"]) + var/datum/news/feed_message/FM = locate(href_list["del_comment_msg"]) if(istype(FC) && istype(FM)) FM.comments -= FC qdel(FC) updateUsrDialog() else if(href_list["lock_comment"]) - var/datum/newscaster/feed_message/FM = locate(href_list["lock_comment"]) + var/datum/news/feed_message/FM = locate(href_list["lock_comment"]) FM.locked ^= 1 updateUsrDialog() else if(href_list["set_comment"]) @@ -876,12 +634,6 @@ GLOBAL_LIST_EMPTY(allCasters) picture = selection /obj/machinery/newscaster/proc/scan_user(mob/living/user) - if(active_user) - if(active_user != user) - if(get_dist(active_user,src)<=1) - if(!isobserver(active_user)) - to_chat(user, "Wait for [active_user] to finish and move away.") - return if(ishuman(user)) var/mob/living/carbon/human/human_user = user if(human_user.wear_id) @@ -901,19 +653,14 @@ GLOBAL_LIST_EMPTY(allCasters) else if(issilicon(user)) var/mob/living/silicon/ai_user = user scanned_user = "[ai_user.name] ([ai_user.job])" - else if (IsAdminGhost(user)) - scanned_user = "Nanotrasen Officer #[rand(0,9)][rand(0,9)][rand(0,9)]" - else if (isobserver(user)) - scanned_user = "Space-Time Anomaly #[rand(0,9)][rand(0,9)][rand(0,9)]" else throw EXCEPTION("Invalid user for this proc") return - active_user = user /obj/machinery/newscaster/proc/print_paper() SSblackbox.record_feedback("amount", "newspapers_printed", 1) var/obj/item/newspaper/NEWSPAPER = new /obj/item/newspaper - for(var/datum/newscaster/feed_channel/FC in GLOB.news_network.network_channels) + for(var/datum/news/feed_channel/FC in GLOB.news_network.network_channels) NEWSPAPER.news_content += FC if(GLOB.news_network.wanted_issue.active) NEWSPAPER.wantedAuthor = GLOB.news_network.wanted_issue.scannedUser @@ -925,7 +672,6 @@ GLOBAL_LIST_EMPTY(allCasters) NEWSPAPER.creationTime = GLOB.news_network.lastAction paper_remaining-- - /obj/machinery/newscaster/proc/remove_alert() alert = FALSE update_icon() @@ -940,177 +686,3 @@ GLOBAL_LIST_EMPTY(allCasters) else say("Attention! Wanted issue distributed!") playsound(loc, 'sound/machines/warning-buzzer.ogg', 75, 1) - -/obj/item/newspaper - name = "newspaper" - desc = "An issue of The Griffon, the newspaper circulating aboard Nanotrasen Space Stations." - icon = 'icons/obj/bureaucracy.dmi' - icon_state = "newspaper" - lefthand_file = 'icons/mob/inhands/misc/books_lefthand.dmi' - righthand_file = 'icons/mob/inhands/misc/books_righthand.dmi' - w_class = WEIGHT_CLASS_SMALL - attack_verb = list("bapped") - var/screen = 0 - var/pages = 0 - var/curr_page = 0 - var/list/datum/newscaster/feed_channel/news_content = list() - var/scribble="" - var/scribble_page = null - var/wantedAuthor - var/wantedCriminal - var/wantedBody - var/wantedPhoto - var/creationTime - -/obj/item/newspaper/suicide_act(mob/user) - user.visible_message("[user] is focusing intently on [src]! It looks like [user.p_theyre()] trying to commit sudoku... until [user.p_their()] eyes light up with realization!") - user.say(";JOURNALISM IS MY CALLING! EVERYBODY APPRECIATES UNBIASED REPORTI-GLORF", forced="newspaper suicide") - var/mob/living/carbon/human/H = user - var/obj/W = new /obj/item/reagent_containers/food/drinks/bottle/whiskey(H.loc) - playsound(H.loc, 'sound/items/drink.ogg', rand(10,50), 1) - W.reagents.trans_to(H, W.reagents.total_volume) - user.visible_message("[user] downs the contents of [W.name] in one gulp! Shoulda stuck to sudoku!") - - return(TOXLOSS) - -/obj/item/newspaper/attack_self(mob/user) - if(ishuman(user)) - var/mob/living/carbon/human/human_user = user - var/dat - pages = 0 - switch(screen) - if(0) //Cover - dat+="
The Griffon
" - dat+="
Nanotrasen-standard newspaper, for use on Nanotrasen? Space Facilities

" - if(isemptylist(news_content)) - if(wantedAuthor) - dat+="Contents:
    **Important Security Announcement** \[page [pages+2]\]
" - else - dat+="Other than the title, the rest of the newspaper is unprinted..." - else - dat+="Contents:
    " - for(var/datum/newscaster/feed_channel/NP in news_content) - pages++ - if(wantedAuthor) - dat+="**Important Security Announcement** \[page [pages+2]\]
    " - var/temp_page=0 - for(var/datum/newscaster/feed_channel/NP in news_content) - temp_page++ - dat+="[NP.channel_name] \[page [temp_page+1]\]
    " - dat+="
" - if(scribble_page==curr_page) - dat+="
There is a small scribble near the end of this page... It reads: \"[scribble]\"" - dat+= "
" - if(1) // X channel pages inbetween. - for(var/datum/newscaster/feed_channel/NP in news_content) - pages++ - var/datum/newscaster/feed_channel/C = news_content[curr_page] - dat += "[C.channel_name] \[created by: [C.returnAuthor(notContent(C.authorCensorTime))]\]

" - if(notContent(C.DclassCensorTime)) - dat+="This channel was deemed dangerous to the general welfare of the station and therefore marked with a D-Notice. Its contents were not transferred to the newspaper at the time of printing." - else - if(isemptylist(C.messages)) - dat+="No Feed stories stem from this channel..." - else - var/i = 0 - for(var/datum/newscaster/feed_message/MESSAGE in C.messages) - if(MESSAGE.creationTime > creationTime) - if(i == 0) - dat+="No Feed stories stem from this channel..." - break - if(i == 0) - dat+="
    " - i++ - dat+="-[MESSAGE.returnBody(notContent(MESSAGE.bodyCensorTime))]
    " - if(MESSAGE.img) - user << browse_rsc(MESSAGE.img, "tmp_photo[i].png") - dat+="
    " - dat+="\[Story by [MESSAGE.returnAuthor(notContent(MESSAGE.authorCensorTime))]\]

    " - dat+="
" - if(scribble_page==curr_page) - dat+="
There is a small scribble near the end of this page... It reads: \"[scribble]\"" - dat+= "

" - if(2) //Last page - for(var/datum/newscaster/feed_channel/NP in news_content) - pages++ - if(wantedAuthor!=null) - dat+="
Wanted Issue:


" - dat+="Criminal name: [wantedCriminal]
" - dat+="Description: [wantedBody]
" - dat+="Photo:: " - if(wantedPhoto) - user << browse_rsc(wantedPhoto, "tmp_photow.png") - dat+="
" - else - dat+="None" - else - dat+="Apart from some uninteresting classified ads, there's nothing on this page..." - if(scribble_page==curr_page) - dat+="
There is a small scribble near the end of this page... It reads: \"[scribble]\"" - dat+= "
" - dat+="

[curr_page+1]
" - human_user << browse(dat, "window=newspaper_main;size=300x400") - onclose(human_user, "newspaper_main") - else - to_chat(user, "The paper is full of unintelligible symbols!") - -/obj/item/newspaper/proc/notContent(list/L) - if(!L.len) - return 0 - for(var/i=L.len;i>0;i--) - var/num = abs(L[i]) - if(creationTime <= num) - continue - else - if(L[i] > 0) - return 1 - else - return 0 - return 0 - -/obj/item/newspaper/Topic(href, href_list) - var/mob/living/U = usr - ..() - if((src in U.contents) || (isturf(loc) && in_range(src, U))) - U.set_machine(src) - if(href_list["next_page"]) - if(curr_page == pages+1) - return //Don't need that at all, but anyway. - if(curr_page == pages) //We're at the middle, get to the end - screen = 2 - else - if(curr_page == 0) //We're at the start, get to the middle - screen=1 - curr_page++ - playsound(loc, "pageturn", 50, 1) - else if(href_list["prev_page"]) - if(curr_page == 0) - return - if(curr_page == 1) - screen = 0 - else - if(curr_page == pages+1) //we're at the end, let's go back to the middle. - screen = 1 - curr_page-- - playsound(loc, "pageturn", 50, 1) - if(ismob(loc)) - attack_self(loc) - -/obj/item/newspaper/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/pen)) - if(!user.is_literate()) - to_chat(user, "You scribble illegibly on [src]!") - return - if(scribble_page == curr_page) - to_chat(user, "There's already a scribble in this page... You wouldn't want to make things too cluttered, would you?") - else - var/s = stripped_input(user, "Write something", "Newspaper") - if (!s) - return - if(!user.canUseTopic(src, BE_CLOSE)) - return - scribble_page = curr_page - scribble = s - attack_self(user) - else - return ..() diff --git a/code/modules/newscaster/newspaper.dm b/code/modules/newscaster/newspaper.dm new file mode 100644 index 0000000000..0afb36a7e7 --- /dev/null +++ b/code/modules/newscaster/newspaper.dm @@ -0,0 +1,173 @@ +/obj/item/newspaper + name = "newspaper" + desc = "An issue of The Griffon, the newspaper circulating aboard Nanotrasen Space Stations." + icon = 'icons/obj/bureaucracy.dmi' + icon_state = "newspaper" + lefthand_file = 'icons/mob/inhands/misc/books_lefthand.dmi' + righthand_file = 'icons/mob/inhands/misc/books_righthand.dmi' + w_class = WEIGHT_CLASS_SMALL + attack_verb = list("bapped") + var/screen = 0 + var/pages = 0 + var/curr_page = 0 + var/list/datum/news/feed_channel/news_content = list() + var/scribble="" + var/scribble_page = null + var/wantedAuthor + var/wantedCriminal + var/wantedBody + var/wantedPhoto + var/creationTime + +/obj/item/newspaper/suicide_act(mob/user) + user.visible_message("[user] is focusing intently on [src]! It looks like [user.p_theyre()] trying to commit sudoku... until [user.p_their()] eyes light up with realization!") + user.say(";JOURNALISM IS MY CALLING! EVERYBODY APPRECIATES UNBIASED REPORTI-GLORF", forced="newspaper suicide") + var/mob/living/carbon/human/H = user + var/obj/W = new /obj/item/reagent_containers/food/drinks/bottle/whiskey(H.loc) + playsound(H.loc, 'sound/items/drink.ogg', rand(10,50), 1) + W.reagents.trans_to(H, W.reagents.total_volume) + user.visible_message("[user] downs the contents of [W.name] in one gulp! Shoulda stuck to sudoku!") + + return(TOXLOSS) + +/obj/item/newspaper/attack_self(mob/user) + if(ishuman(user)) + var/mob/living/carbon/human/human_user = user + var/dat + pages = 0 + switch(screen) + if(0) //Cover + dat+="
The Griffon
" + dat+="
Nanotrasen-standard newspaper, for use on Nanotrasen? Space Facilities

" + if(isemptylist(news_content)) + if(wantedAuthor) + dat+="Contents:
    **Important Security Announcement** \[page [pages+2]\]
" + else + dat+="Other than the title, the rest of the newspaper is unprinted..." + else + dat+="Contents:
    " + for(var/datum/news/feed_channel/NP in news_content) + pages++ + if(wantedAuthor) + dat+="**Important Security Announcement** \[page [pages+2]\]
    " + var/temp_page=0 + for(var/datum/news/feed_channel/NP in news_content) + temp_page++ + dat+="[NP.channel_name] \[page [temp_page+1]\]
    " + dat+="
" + if(scribble_page==curr_page) + dat+="
There is a small scribble near the end of this page... It reads: \"[scribble]\"" + dat+= "
" + if(1) // X channel pages inbetween. + for(var/datum/news/feed_channel/NP in news_content) + pages++ + var/datum/news/feed_channel/C = news_content[curr_page] + dat += "[C.channel_name] \[created by: [C.returnAuthor(notContent(C.authorCensorTime))]\]

" + if(notContent(C.DclassCensorTime)) + dat+="This channel was deemed dangerous to the general welfare of the station and therefore marked with a D-Notice. Its contents were not transferred to the newspaper at the time of printing." + else + if(isemptylist(C.messages)) + dat+="No Feed stories stem from this channel..." + else + var/i = 0 + for(var/datum/news/feed_message/MESSAGE in C.messages) + if(MESSAGE.creationTime > creationTime) + if(i == 0) + dat+="No Feed stories stem from this channel..." + break + if(i == 0) + dat+="
    " + i++ + dat+="-[MESSAGE.returnBody(notContent(MESSAGE.bodyCensorTime))]
    " + if(MESSAGE.img) + user << browse_rsc(MESSAGE.img, "tmp_photo[i].png") + dat+="
    " + dat+="\[Story by [MESSAGE.returnAuthor(notContent(MESSAGE.authorCensorTime))]\]

    " + dat+="
" + if(scribble_page==curr_page) + dat+="
There is a small scribble near the end of this page... It reads: \"[scribble]\"" + dat+= "

" + if(2) //Last page + for(var/datum/news/feed_channel/NP in news_content) + pages++ + if(wantedAuthor!=null) + dat+="
Wanted Issue:


" + dat+="Criminal name: [wantedCriminal]
" + dat+="Description: [wantedBody]
" + dat+="Photo:: " + if(wantedPhoto) + user << browse_rsc(wantedPhoto, "tmp_photow.png") + dat+="
" + else + dat+="None" + else + dat+="Apart from some uninteresting classified ads, there's nothing on this page..." + if(scribble_page==curr_page) + dat+="
There is a small scribble near the end of this page... It reads: \"[scribble]\"" + dat+= "
" + dat+="

[curr_page+1]
" + human_user << browse(dat, "window=newspaper_main;size=300x400") + onclose(human_user, "newspaper_main") + else + to_chat(user, "The paper is full of unintelligible symbols!") + +/obj/item/newspaper/proc/notContent(list/L) + if(!L.len) + return 0 + for(var/i=L.len;i>0;i--) + var/num = abs(L[i]) + if(creationTime <= num) + continue + else + if(L[i] > 0) + return 1 + else + return 0 + return 0 + +/obj/item/newspaper/Topic(href, href_list) + var/mob/living/U = usr + ..() + if((src in U.contents) || (isturf(loc) && in_range(src, U))) + U.set_machine(src) + if(href_list["next_page"]) + if(curr_page == pages+1) + return //Don't need that at all, but anyway. + if(curr_page == pages) //We're at the middle, get to the end + screen = 2 + else + if(curr_page == 0) //We're at the start, get to the middle + screen=1 + curr_page++ + playsound(loc, "pageturn", 50, 1) + else if(href_list["prev_page"]) + if(curr_page == 0) + return + if(curr_page == 1) + screen = 0 + else + if(curr_page == pages+1) //we're at the end, let's go back to the middle. + screen = 1 + curr_page-- + playsound(loc, "pageturn", 50, 1) + if(ismob(loc)) + attack_self(loc) + +/obj/item/newspaper/attackby(obj/item/W, mob/user, params) + if(istype(W, /obj/item/pen)) + if(!user.is_literate()) + to_chat(user, "You scribble illegibly on [src]!") + return + if(scribble_page == curr_page) + to_chat(user, "There's already a scribble in this page... You wouldn't want to make things too cluttered, would you?") + else + var/s = stripped_input(user, "Write something", "Newspaper") + if (!s) + return + if(!user.canUseTopic(src, BE_CLOSE)) + return + scribble_page = curr_page + scribble = s + attack_self(user) + else + return ..() diff --git a/code/modules/newscaster/wanted_message.dm b/code/modules/newscaster/wanted_message.dm new file mode 100644 index 0000000000..58eb234f02 --- /dev/null +++ b/code/modules/newscaster/wanted_message.dm @@ -0,0 +1,8 @@ +/datum/news/wanted_message + var/active + var/criminal + var/body + var/scannedUser + var/isAdminMsg + var/icon/img + var/photo_file diff --git a/code/modules/ninja/outfit.dm b/code/modules/ninja/outfit.dm index 7ee71db1f1..323deed5c4 100644 --- a/code/modules/ninja/outfit.dm +++ b/code/modules/ninja/outfit.dm @@ -1,6 +1,6 @@ /datum/outfit/ninja name = "Space Ninja" - uniform = /obj/item/clothing/under/color/black + uniform = /obj/item/clothing/under/color/black/trackless suit = /obj/item/clothing/suit/space/space_ninja glasses = /obj/item/clothing/glasses/night mask = /obj/item/clothing/mask/gas/space_ninja diff --git a/code/modules/oracle_ui/hookup_procs.dm b/code/modules/oracle_ui/hookup_procs.dm index 0a092caf30..18d7bbfd8c 100644 --- a/code/modules/oracle_ui/hookup_procs.dm +++ b/code/modules/oracle_ui/hookup_procs.dm @@ -35,9 +35,9 @@ return ..() /obj/machinery/oui_canview(mob/user) - if(user.has_unlimited_silicon_privilege) + if(user.has_unlimited_silicon_privilege || hasSiliconAccessInArea(user)) return TRUE - if(!can_interact()) + if(!can_interact(user)) return FALSE if(iscyborg(user)) return can_see(user, src, 7) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 6a674fa6b1..982afa49c8 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -106,6 +106,8 @@ var/update_overlay = -1 var/icon_update_needed = FALSE var/obj/machinery/computer/apc_control/remote_control = null + var/mob/living/carbon/hijacker + var/hijackerlast = TRUE /obj/machinery/power/apc/unlocked locked = FALSE @@ -260,7 +262,7 @@ . += "Alt-Click the APC to [ locked ? "unlock" : "lock"] the interface." - if(issilicon(user)) + if(area.hasSiliconAccessInArea(user)) . += "Ctrl-Click the APC to switch the breaker [ operating ? "off" : "on"]." // update the APC icon to show the three base states @@ -299,12 +301,15 @@ if(!(update_state & UPSTATE_ALLGOOD)) SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays) - + var/hijackerreturn + if (hijacker) + var/obj/item/implant/hijack/H = hijacker.getImplant(/obj/item/implant/hijack) + hijackerreturn = H && !H.stealthmode if(update & 2) SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays) if(!(stat & (BROKEN|MAINT)) && update_state & UPSTATE_ALLGOOD) SSvis_overlays.add_vis_overlay(src, icon, "apcox-[locked]", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir) - SSvis_overlays.add_vis_overlay(src, icon, "apco3-[charging]", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir) + SSvis_overlays.add_vis_overlay(src, icon, "apco3-[hijackerreturn ? "3" : charging]", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir) if(operating) SSvis_overlays.add_vis_overlay(src, icon, "apco0-[equipment]", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir) SSvis_overlays.add_vis_overlay(src, icon, "apco1-[lighting]", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir) @@ -319,6 +324,8 @@ light_color = LIGHT_COLOR_BLUE if(APC_FULLY_CHARGED) light_color = LIGHT_COLOR_GREEN + if (hijackerreturn) + light_color = LIGHT_COLOR_YELLOW set_light(lon_range) else if(update_state & UPSTATE_BLUESCREEN) light_color = LIGHT_COLOR_BLUE @@ -387,14 +394,19 @@ else if(environ==2) update_overlay |= APC_UPOVERLAY_ENVIRON2 - var/results = 0 - if(last_update_state == update_state && last_update_overlay == update_overlay) + var/hijackerreturn + if (hijacker) + var/obj/item/implant/hijack/H = hijacker.getImplant(/obj/item/implant/hijack) + hijackerreturn = H && !H.stealthmode + if(last_update_state == update_state && last_update_overlay == update_overlay && hijackerreturn == hijackerlast) return 0 if(last_update_state != update_state) results += 1 - if(last_update_overlay != update_overlay) + if(last_update_overlay != update_overlay || hijackerreturn != hijackerlast) results += 2 + if (hijackerreturn != hijackerlast) + hijackerlast = hijackerreturn return results // Used in process so it doesn't update the icon too much @@ -534,7 +546,7 @@ /obj/machinery/power/apc/attackby(obj/item/W, mob/living/user, params) - if(issilicon(user) && get_dist(src,user)>1) + if(area.hasSiliconAccessInArea(user) && get_dist(src,user)>1) return attack_hand(user) if (istype(W, /obj/item/stock_parts/cell) && opened) @@ -741,7 +753,7 @@ /obj/machinery/power/apc/AltClick(mob/user) . = ..() - if(!user.canUseTopic(src, !issilicon(user)) || !isturf(loc)) + if(!user.canUseTopic(src, !area.hasSiliconAccessInArea(user)) || !isturf(loc)) return togglelock(user) return TRUE @@ -756,7 +768,7 @@ else if(stat & (BROKEN|MAINT)) to_chat(user, "Nothing happens!") else - if(allowed(usr) && !wires.is_cut(WIRE_IDSCAN) && !malfhack) + if((allowed(usr) || area.hasSiliconAccessInArea(usr)) && !wires.is_cut(WIRE_IDSCAN) && !malfhack) locked = !locked to_chat(user, "You [ locked ? "lock" : "unlock"] the APC interface.") update_icon() @@ -833,6 +845,11 @@ if((stat & MAINT) && !opened) //no board; no interface return +/obj/machinery/power/apc/oui_canview(mob/user) + if(user.has_unlimited_silicon_privilege || area.hasSiliconAccessInArea(user)) + return TRUE + return ..() + /obj/machinery/power/apc/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) @@ -842,8 +859,12 @@ ui.open() /obj/machinery/power/apc/ui_data(mob/user) + var/obj/item/implant/hijack/H = user.getImplant(/obj/item/implant/hijack) + var/abilitiesavail = FALSE + if (H && !H.stealthmode && H.toggled) + abilitiesavail = TRUE var/list/data = list( - "locked" = locked && !(integration_cog && is_servant_of_ratvar(user)), + "locked" = locked && !(integration_cog && is_servant_of_ratvar(user)) && !area.hasSiliconAccessInArea(user), "lock_nightshift" = nightshift_requires_auth, "failTime" = failure_timer, "isOperating" = operating, @@ -853,11 +874,14 @@ "chargingStatus" = charging, "totalLoad" = DisplayPower(lastused_total), "coverLocked" = coverlocked, - "siliconUser" = user.has_unlimited_silicon_privilege || user.using_power_flow_console(), + "siliconUser" = user.has_unlimited_silicon_privilege || user.using_power_flow_console() || area.hasSiliconAccessInArea(user), "malfStatus" = get_malf_status(user), "emergencyLights" = !emergency_lights, "nightshiftLights" = nightshift_lights, - + "hijackable" = HAS_TRAIT(user,TRAIT_HIJACKER), + "hijacker" = hijacker == user ? TRUE : FALSE, + "drainavail" = cell && cell.percent() >= 85 && abilitiesavail, + "lockdownavail" = cell && cell.percent() >= 35 && abilitiesavail, "powerChannels" = list( list( "title" = "Equipment", @@ -925,17 +949,12 @@ /obj/machinery/power/apc/proc/can_use(mob/user, loud = 0) //used by attack_hand() and Topic() if(IsAdminGhost(user)) return TRUE + if (user == hijacker || (area.hasSiliconAccessInArea(user) && !aidisabled)) + return TRUE if(user.has_unlimited_silicon_privilege) var/mob/living/silicon/ai/AI = user var/mob/living/silicon/robot/robot = user - if ( \ - src.aidisabled || \ - malfhack && istype(malfai) && \ - ( \ - (istype(AI) && (malfai!=AI && malfai != AI.parent)) || \ - (istype(robot) && (robot in malfai.connected_robots)) \ - ) \ - ) + if (src.aidisabled || malfhack && istype(malfai) && ((istype(AI) && (malfai!=AI && malfai != AI.parent)) || (istype(robot) && (robot in malfai.connected_robots)))) if(!loud) to_chat(user, "\The [src] has eee disabled!") return FALSE @@ -945,11 +964,15 @@ . = ..() if (!. && !QDELETED(remote_control)) . = remote_control.can_interact(user) + if (hijacker == user && area.hasSiliconAccessInArea(user)) + return TRUE /obj/machinery/power/apc/ui_status(mob/user) . = ..() if (!QDELETED(remote_control) && user == remote_control.operator) . = UI_INTERACTIVE + if (user == hijacker && area.hasSiliconAccessInArea(user)) + . = UI_INTERACTIVE /obj/machinery/power/apc/ui_act(action, params) if(..() || !can_use(usr, 1)) @@ -959,7 +982,10 @@ failure_timer = 0 update_icon() update() - var/authorized = (!locked || usr.has_unlimited_silicon_privilege || (integration_cog && (is_servant_of_ratvar(usr)))) + if (action == "hijack" && can_use(usr, 1)) //don't need auth for hijack button + hijack(usr) + return + var/authorized = (!locked || usr.has_unlimited_silicon_privilege || area.hasSiliconAccessInArea(usr) || (integration_cog && (is_servant_of_ratvar(usr)))) if((action == "toggle_nightshift") && (!nightshift_requires_auth || authorized)) toggle_nightshift_lights() return TRUE @@ -967,7 +993,7 @@ return switch(action) if("lock") - if(usr.has_unlimited_silicon_privilege) + if(usr.has_unlimited_silicon_privilege || area.hasSiliconAccessInArea(usr)) if((obj_flags & EMAGGED) || (stat & (BROKEN|MAINT))) to_chat(usr, "The APC does not respond to the command.") else @@ -1001,7 +1027,7 @@ update() return TRUE if("overload") - if(usr.has_unlimited_silicon_privilege) + if(usr.has_unlimited_silicon_privilege || area.hasSiliconAccessInArea(usr)) overload_lighting() return TRUE if("hack") @@ -1023,7 +1049,26 @@ L.no_emergency = emergency_lights INVOKE_ASYNC(L, /obj/machinery/light/.proc/update, FALSE) CHECK_TICK - return TRUE + if("drain") + cell.use(cell.charge) + hijacker.toggleSiliconAccessArea(area) + hijacker = null + set_hijacked_lighting() + update_icon() + var/obj/item/implant/hijack/H = usr.getImplant(/obj/item/implant/hijack) + H.stealthcooldown = world.time + 2 MINUTES + energy_fail(30 SECONDS * (cell.charge / cell.maxcharge)) + if("lockdown") + var/celluse = rand(20,35) + celluse = celluse /100 + for (var/obj/machinery/door/D in GLOB.airlocks) + if (get_area(D) == area) + INVOKE_ASYNC(D,/obj/machinery/door.proc/hostile_lockdown,usr, FALSE) + addtimer(CALLBACK(D,/obj/machinery/door.proc/disable_lockdown, FALSE), 30 SECONDS) + cell.charge -= cell.maxcharge*celluse + var/obj/item/implant/hijack/H = usr.getImplant(/obj/item/implant/hijack) + H.stealthcooldown = world.time + 3 MINUTES + return TRUE /obj/machinery/power/apc/proc/toggle_breaker() if(!is_operational() || failure_timer) @@ -1032,6 +1077,39 @@ update() update_icon() +/obj/machinery/power/apc/proc/hijack(mob/living/L) + if (!istype(L)) + return + if (hijacker && hijacker != L) + var/obj/item/implant/hijack/H = L.getImplant(/obj/item/implant/hijack) + to_chat(L, "Someone already has control of this APC. Beginning counter-hijack.") + H.hijacking = TRUE + if (do_after(L,20 SECONDS,target=src)) + hijacker.toggleSiliconAccessArea(area) + if (L.toggleSiliconAccessArea(area)) + hijacker = L + update_icon() + set_hijacked_lighting() + H.hijacking = FALSE + return + else + to_chat(L, "Aborting.") + H.hijacking = FALSE + return + to_chat(L, "Beginning hijack of APC.") + var/obj/item/implant/hijack/H = L.getImplant(/obj/item/implant/hijack) + H.hijacking = TRUE + if (do_after(L,H.stealthmode ? 12 SECONDS : 5 SECONDS,target=src)) + if (L.toggleSiliconAccessArea(area)) + hijacker = L + update_icon() + set_hijacked_lighting() + H.hijacking = FALSE + else + to_chat(L, "Aborting.") + H.hijacking = FALSE + return + /obj/machinery/power/apc/proc/malfhack(mob/living/silicon/ai/malf) if(!istype(malf)) return @@ -1438,6 +1516,17 @@ L.update(FALSE) CHECK_TICK +/obj/machinery/power/apc/proc/set_hijacked_lighting() + set waitfor = FALSE + var/hijackerreturn + if (hijacker) + var/obj/item/implant/hijack/H = hijacker.getImplant(/obj/item/implant/hijack) + hijackerreturn = H && !H.stealthmode + for(var/obj/machinery/light/L in area) + L.hijacked = hijackerreturn + L.update(FALSE) + CHECK_TICK + /obj/machinery/power/apc/proc/update_nightshift_auth_requirement() nightshift_requires_auth = nightshift_toggle_requires_auth() diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 441eb27621..5ca09036ad 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -220,6 +220,7 @@ var/bulb_emergency_colour = "#FF3232" // determines the colour of the light while it's in emergency mode var/bulb_emergency_pow_mul = 0.75 // the multiplier for determining the light's power in emergency mode var/bulb_emergency_pow_min = 0.5 // the minimum value for the light's power in emergency mode + var/hijacked = FALSE // if true, the light is in a hijacked area /obj/machinery/light/broken status = LIGHT_BROKEN @@ -298,7 +299,10 @@ if(emergency_mode || (A && A.fire)) icon_state = "[base_state]_emergency" else - icon_state = "[base_state]" + if (hijacked) + icon_state = "[base_state]_hijacked" + else + icon_state = "[base_state]" if(on) var/mutable_appearance/glowybit = mutable_appearance(overlayicon, base_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) glowybit.alpha = CLAMP(light_power*250, 30, 200) @@ -326,6 +330,10 @@ var/area/A = get_base_area(src) if (A && A.fire) CO = bulb_emergency_colour + else if (hijacked) + BR = BR * 1.5 + PO = PO * 1.5 + CO = color ? color : LIGHT_COLOR_YELLOW else if (nightshift_enabled) BR = nightshift_brightness PO = nightshift_light_power @@ -355,7 +363,7 @@ if(on != on_gs) on_gs = on if(on) - static_power_used = brightness * 14.4 //20W per unit luminosity + static_power_used = brightness * 14.4 * (hijacked ? 2 : 1) //20W per unit luminosity addStaticPower(static_power_used, STATIC_LIGHT) else removeStaticPower(static_power_used, STATIC_LIGHT) diff --git a/code/modules/projectiles/ammunition/caseless/arrow.dm b/code/modules/projectiles/ammunition/caseless/arrow.dm new file mode 100644 index 0000000000..e0ca637a8b --- /dev/null +++ b/code/modules/projectiles/ammunition/caseless/arrow.dm @@ -0,0 +1,8 @@ +/obj/item/ammo_casing/caseless/arrow + name = "wooden arrow" + desc = "An arrow made of wood, typically fired from a bow." + projectile_type = /obj/item/projectile/bullet/reusable/arrow + caliber = "arrow" + icon_state = "arrow" + throwforce = 3 //good luck hitting someone with the pointy end of the arrow + throw_speed = 3 \ No newline at end of file diff --git a/code/modules/projectiles/ammunition/energy/gravity.dm b/code/modules/projectiles/ammunition/energy/gravity.dm index eabb4f66d7..be7b618803 100644 --- a/code/modules/projectiles/ammunition/energy/gravity.dm +++ b/code/modules/projectiles/ammunition/energy/gravity.dm @@ -15,15 +15,15 @@ . = ..() /obj/item/ammo_casing/energy/gravity/repulse - projectile_type = /obj/item/projectile/gravityrepulse + projectile_type = /obj/item/projectile/gravity/repulse select_name = "repulse" /obj/item/ammo_casing/energy/gravity/attract - projectile_type = /obj/item/projectile/gravityattract + projectile_type = /obj/item/projectile/gravity/attract select_name = "attract" /obj/item/ammo_casing/energy/gravity/chaos - projectile_type = /obj/item/projectile/gravitychaos + projectile_type = /obj/item/projectile/gravity/chaos select_name = "chaos" diff --git a/code/modules/projectiles/ammunition/energy/stun.dm b/code/modules/projectiles/ammunition/energy/stun.dm index 7c2b62c02c..2abc472138 100644 --- a/code/modules/projectiles/ammunition/energy/stun.dm +++ b/code/modules/projectiles/ammunition/energy/stun.dm @@ -5,6 +5,10 @@ e_cost = 200 harmful = FALSE +/obj/item/ammo_casing/energy/electrode/security + projectile_type = /obj/item/projectile/energy/electrode/security + e_cost = 100 + /obj/item/ammo_casing/energy/electrode/spec e_cost = 100 @@ -13,6 +17,7 @@ e_cost = 100 /obj/item/ammo_casing/energy/electrode/hos + projectile_type = /obj/item/projectile/energy/electrode/security/hos e_cost = 200 /obj/item/ammo_casing/energy/electrode/old @@ -27,4 +32,4 @@ click_cooldown_override = 3.5 /obj/item/ammo_casing/energy/disabler/secborg - e_cost = 50 \ No newline at end of file + e_cost = 50 diff --git a/code/modules/projectiles/boxes_magazines/internal/bow.dm b/code/modules/projectiles/boxes_magazines/internal/bow.dm new file mode 100644 index 0000000000..9ce1565606 --- /dev/null +++ b/code/modules/projectiles/boxes_magazines/internal/bow.dm @@ -0,0 +1,6 @@ +/obj/item/ammo_box/magazine/internal/bow + name = "bow... magazine?" //shouldn't be seeing this + ammo_type = /obj/item/ammo_casing/caseless/arrow + caliber = "arrow" + max_ammo = 1 + start_empty = 1 \ No newline at end of file diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index f285248326..34f7134591 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -15,7 +15,7 @@ throw_speed = 3 throw_range = 5 force = 5 - item_flags = NEEDS_PERMIT + item_flags = NEEDS_PERMIT | NO_ATTACK_CHAIN_SOFT_STAMCRIT attack_verb = list("struck", "hit", "bashed") var/fire_sound = "gunshot" @@ -51,6 +51,7 @@ righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' var/obj/item/firing_pin/pin = /obj/item/firing_pin //standard firing pin for most guns + var/no_pin_required = FALSE //whether the gun can be fired without a pin var/obj/item/flashlight/gun_light var/can_flashlight = 0 @@ -79,17 +80,24 @@ /obj/item/gun/Initialize() . = ..() if(pin) - pin = new pin(src) + if(no_pin_required) + pin = null + else + pin = new pin(src) if(gun_light) alight = new (src) if(zoomable) azoom = new (src) /obj/item/gun/Destroy() - QDEL_NULL(pin) - QDEL_NULL(gun_light) - QDEL_NULL(bayonet) - QDEL_NULL(chambered) + if(pin) + QDEL_NULL(pin) + if(gun_light) + QDEL_NULL(gun_light) + if(bayonet) + QDEL_NULL(bayonet) + if(chambered) + QDEL_NULL(chambered) return ..() /obj/item/gun/CheckParts(list/parts_list) @@ -103,6 +111,8 @@ /obj/item/gun/examine(mob/user) . = ..() + if(no_pin_required) + return if(pin) . += "It has \a [pin] installed." else @@ -158,6 +168,9 @@ return if(firing) return + if(user.getStaminaLoss() >= STAMINA_SOFTCRIT) //respect stamina softcrit + to_chat(user, "You are too exhausted to fire [src]!") + return if(flag) //It's adjacent, is the user, or is on the user's person if(target in user.contents) //can't shoot stuff inside us. return @@ -222,6 +235,8 @@ return FALSE /obj/item/gun/proc/handle_pins(mob/living/user) + if(no_pin_required) + return TRUE if(pin) if(pin.pin_auth(user) || (pin.obj_flags & EMAGGED)) return TRUE @@ -236,7 +251,7 @@ return /obj/item/gun/proc/on_cooldown() - return busy_action || firing || (last_fire + fire_delay > world.time) + return busy_action || firing || ((last_fire + fire_delay) > world.time) /obj/item/gun/proc/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0) add_fingerprint(user) diff --git a/code/modules/projectiles/guns/ballistic/bow.dm b/code/modules/projectiles/guns/ballistic/bow.dm new file mode 100644 index 0000000000..448e2915d9 --- /dev/null +++ b/code/modules/projectiles/guns/ballistic/bow.dm @@ -0,0 +1,53 @@ +/obj/item/gun/ballistic/bow + name = "wooden bow" + desc = "Some sort of primitive projectile weapon. Used to fire arrows." + icon_state = "bow" + item_state = "bow" + w_class = WEIGHT_CLASS_BULKY + weapon_weight = WEAPON_HEAVY //need both hands to fire + force = 5 + mag_type = /obj/item/ammo_box/magazine/internal/bow + fire_sound = 'sound/weapons/bowfire.wav' + slot_flags = ITEM_SLOT_BACK + item_flags = NONE + casing_ejector = FALSE + inaccuracy_modifier = 0.33 //to counteract the innaccuracy from WEAPON_HEAVY, bows are supposed to be accurate but only able to be fired with both hands + pin = null + no_pin_required = TRUE + trigger_guard = TRIGGER_GUARD_NONE //so ashwalkers can use it + +/obj/item/gun/ballistic/bow/shoot_with_empty_chamber() + return + +/obj/item/gun/ballistic/bow/chamber_round() + chambered = magazine.get_round(1) + +/obj/item/gun/ballistic/bow/afterattack() + . = ..() + if (chambered) + chambered = null + magazine.get_round(0) + update_icon() + +/obj/item/gun/ballistic/bow/attack_self(mob/living/user) + if (chambered) + var/obj/item/ammo_casing/AC = magazine.get_round(0) + user.put_in_hands(AC) + chambered = null + to_chat(user, "You gently release the bowstring, removing the arrow.") + else if (get_ammo()) + to_chat(user, "You draw back the bowstring.") + playsound(src, 'sound/weapons/bowdraw.wav', 75, 0) //gets way too high pitched if the freq varies + chamber_round() + update_icon() + +/obj/item/gun/ballistic/bow/attackby(obj/item/I, mob/user, params) + if (magazine.attackby(I, user, params, 1)) + to_chat(user, "You notch the arrow.") + update_icon() + +/obj/item/gun/ballistic/bow/update_icon() + icon_state = "bow_[get_ammo() ? (chambered ? "firing" : "loaded") : "unloaded"]" + +/obj/item/gun/ballistic/bow/can_shoot() + return chambered \ No newline at end of file diff --git a/code/modules/projectiles/guns/ballistic/pistol.dm b/code/modules/projectiles/guns/ballistic/pistol.dm index 5f67194b29..68f212ba30 100644 --- a/code/modules/projectiles/guns/ballistic/pistol.dm +++ b/code/modules/projectiles/guns/ballistic/pistol.dm @@ -79,6 +79,7 @@ /obj/item/gun/ballistic/automatic/pistol/stickman name = "flat gun" desc = "A 2 dimensional gun.. what?" + can_suppress = FALSE icon_state = "flatgun" /obj/item/gun/ballistic/automatic/pistol/stickman/pickup(mob/living/user) diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index e1b62620c7..be43bc48fd 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -150,7 +150,7 @@ if(istype(v, /obj/item/ammo_casing/energy)) //already set ammo_type[v] = isnull(user_can_select)? TRUE : user_can_select else - C = new v //if you put non energycasing/type stuff in here you deserve the runtime + C = new v(src) //if you put non energycasing/type stuff in here you deserve the runtime ammo_type[i] = C ammo_type[C] = isnull(user_can_select)? TRUE : user_can_select set_firemode_index(initial(current_firemode_index)) diff --git a/code/modules/projectiles/guns/energy/dueling.dm b/code/modules/projectiles/guns/energy/dueling.dm index 6fe10eb3b6..615bb5d939 100644 --- a/code/modules/projectiles/guns/energy/dueling.dm +++ b/code/modules/projectiles/guns/energy/dueling.dm @@ -320,10 +320,10 @@ if(C.setting == counter_setting) return BULLET_ACT_BLOCK - var/mob/living/L = target - if(!istype(target)) + if(!isliving(target)) return BULLET_ACT_BLOCK + var/mob/living/L = target switch(hugbox) if(DUEL_HUGBOX_NONE) var/obj/item/bodypart/B = L.get_bodypart(BODY_ZONE_HEAD) diff --git a/code/modules/projectiles/guns/energy/energy_gun.dm b/code/modules/projectiles/guns/energy/energy_gun.dm index 163deae0ed..efe107a3f8 100644 --- a/code/modules/projectiles/guns/energy/energy_gun.dm +++ b/code/modules/projectiles/guns/energy/energy_gun.dm @@ -97,7 +97,7 @@ pin = null can_charge = 0 ammo_x_offset = 1 - ammo_type = list(/obj/item/ammo_casing/energy/electrode, /obj/item/ammo_casing/energy/disabler, /obj/item/ammo_casing/energy/laser) + ammo_type = list(/obj/item/ammo_casing/energy/disabler, /obj/item/ammo_casing/energy/laser) selfcharge = EGUN_SELFCHARGE var/fail_tick = 0 var/fail_chance = 0 @@ -113,18 +113,21 @@ ..() /obj/item/gun/energy/e_gun/nuclear/proc/failcheck() - if(prob(fail_chance) && isliving(loc)) - var/mob/living/M = loc + if(prob(fail_chance)) switch(fail_tick) if(0 to 200) fail_tick += (2*(fail_chance)) - M.rad_act(400) - to_chat(M, "Your [name] feels warmer.") + radiation_pulse(src, 50) + var/mob/M = (ismob(loc) && loc) || (ismob(loc.loc) && loc.loc) //thank you short circuiting. if you powergame and nest these guns deeply you get to suffer no-warning radiation death. + if(M) + to_chat(M, "Your [name] feels warmer.") if(201 to INFINITY) SSobj.processing.Remove(src) - M.rad_act(800) - crit_fail = 1 - to_chat(M, "Your [name]'s reactor overloads!") + radiation_pulse(src, 200) + crit_fail = TRUE + var/mob/M = (ismob(loc) && loc) || (ismob(loc.loc) && loc.loc) + if(M) + to_chat(M, "Your [name]'s reactor overloads!") /obj/item/gun/energy/e_gun/nuclear/emp_act(severity) . = ..() diff --git a/code/modules/projectiles/guns/energy/stun.dm b/code/modules/projectiles/guns/energy/stun.dm index 55d11c52d1..d700db817c 100644 --- a/code/modules/projectiles/guns/energy/stun.dm +++ b/code/modules/projectiles/guns/energy/stun.dm @@ -18,10 +18,23 @@ /obj/item/gun/energy/e_gun/advtaser name = "hybrid taser" - desc = "A dual-mode taser designed to fire both short-range high-power electrodes and long-range disabler beams." + desc = "A dual-mode taser designed to fire both short-range high-power electrodes and long-range disabler beams. Right click in combat mode to fire a taser shot with a cooldown." icon_state = "advtaser" - ammo_type = list(/obj/item/ammo_casing/energy/disabler, /obj/item/ammo_casing/energy/electrode) + ammo_type = list(/obj/item/ammo_casing/energy/disabler, /obj/item/ammo_casing/energy/electrode/security = FALSE) ammo_x_offset = 2 + // Not enough guns have altfire systems like this yet for this to be a universal framework. + var/last_altfire = 0 + var/altfire_delay = 15 + +/obj/item/gun/energy/e_gun/advtaser/altafterattack(atom/target, mob/user, proximity_flag, params) + . = TRUE + if(last_altfire + altfire_delay > world.time) + return + var/current_index = current_firemode_index + set_firemode_to_type(/obj/item/ammo_casing/energy/electrode) + process_afterattack(target, user, proximity_flag, params) + set_firemode_index(current_index) + last_altfire = world.time /obj/item/gun/energy/e_gun/advtaser/cyborg name = "cyborg taser" diff --git a/code/modules/projectiles/guns/magic/wand.dm b/code/modules/projectiles/guns/magic/wand.dm index 52236ab695..57bbd13cf7 100644 --- a/code/modules/projectiles/guns/magic/wand.dm +++ b/code/modules/projectiles/guns/magic/wand.dm @@ -73,6 +73,12 @@ user.adjustOxyLoss(500) charges-- +/obj/item/gun/magic/wand/death/debug + desc = "In some obscure circles, this is known as the 'cloning tester's friend'." + max_charges = 500 + variable_charges = FALSE + can_charge = TRUE + recharge_rate = 1 ///////////////////////////////////// //WAND OF HEALING diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm index 3de5d607a1..ec5eee7b6b 100644 --- a/code/modules/projectiles/guns/misc/beam_rifle.dm +++ b/code/modules/projectiles/guns/misc/beam_rifle.dm @@ -299,27 +299,17 @@ if(istype(object, /obj/screen) && !istype(object, /obj/screen/click_catcher)) return process_aim() - if(aiming_time_left <= aiming_time_fire_threshold && check_user()) + if(aiming_time_left <= aiming_time_fire_threshold && check_user() && ((lastfire + delay) <= world.time)) sync_ammo() - afterattack(M.client.mouseObject, M, FALSE, M.client.mouseParams, passthrough = TRUE) + do_fire(M.client.mouseObject, M, FALSE, M.client.mouseParams, M.zone_selected) stop_aiming() QDEL_LIST(current_tracers) return ..() -/obj/item/gun/energy/beam_rifle/afterattack(atom/target, mob/living/user, flag, params, passthrough = FALSE) - if(flag) //It's adjacent, is the user, or is on the user's person - if(target in user.contents) //can't shoot stuff inside us. - return - if(!ismob(target) || user.a_intent == INTENT_HARM) //melee attack - return - if(target == user && user.zone_selected != BODY_ZONE_PRECISE_MOUTH) //so we can't shoot ourselves (unless mouth selected) - return - if(!passthrough && (aiming_time > aiming_time_fire_threshold)) - return - if(lastfire > world.time + delay) - return - lastfire = world.time +/obj/item/gun/energy/beam_rifle/do_fire(atom/target, mob/living/user, message = TRUE, params, zone_override = "", bonus_spread = 0) . = ..() + if(.) + lastfire = world.time stop_aiming() /obj/item/gun/energy/beam_rifle/proc/sync_ammo() diff --git a/code/modules/projectiles/pins.dm b/code/modules/projectiles/pins.dm index 0465a611cd..e754a9c070 100644 --- a/code/modules/projectiles/pins.dm +++ b/code/modules/projectiles/pins.dm @@ -23,6 +23,8 @@ if(proximity_flag) if(istype(target, /obj/item/gun)) var/obj/item/gun/G = target + if(G.no_pin_required) + return if(G.pin && (force_replace || G.pin.pin_removeable)) G.pin.forceMove(get_turf(G)) G.pin.gun_remove(user) @@ -69,13 +71,10 @@ if(gun) qdel(gun) - - /obj/item/firing_pin/magic name = "magic crystal shard" desc = "A small enchanted shard which allows magical weapons to fire." - // Test pin, works only near firing range. /obj/item/firing_pin/test_range name = "test-range firing pin" @@ -229,3 +228,16 @@ if(gun) gun.pin = null return ..() + +//Station Locked + +/obj/item/firing_pin/away + name = "station locked pin" + desc = "A firing pin that only will fire when off the station." + +/obj/item/firing_pin/away/pin_auth(mob/living/user) + var/area/station_area = get_area(src) + if(!station_area || is_station_level(station_area.z)) + to_chat(user, "The pin beeps, refusing to fire.") + return FALSE + return TRUE diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index a902c545b8..4521e4ea13 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -90,6 +90,10 @@ var/decayedRange //stores original range var/reflect_range_decrease = 5 //amount of original range that falls off when reflecting, so it doesn't go forever var/is_reflectable = FALSE // Can it be reflected or not? + + /// factor to multiply by for zone accuracy percent. + var/zone_accuracy_factor = 1 + //Effects var/stun = 0 var/knockdown = 0 @@ -185,10 +189,6 @@ else new /obj/effect/temp_visual/dir_setting/bloodsplatter(target_loca, splatter_dir, bloodtype_to_color()) - if(iscarbon(L) && !HAS_TRAIT(L, TRAIT_NOMARROW)) - var/mob/living/carbon/C = L - C.bleed(damage) - else L.add_splatter_floor(target_loca) else if(impact_effect_type && !hitscan) new impact_effect_type(target_loca, hitx, hity) @@ -211,11 +211,8 @@ L.on_hit(src) var/reagent_note - if(reagents && reagents.reagent_list) - reagent_note = " REAGENTS:" - for(var/datum/reagent/R in reagents.reagent_list) - reagent_note += R.type + " (" - reagent_note += num2text(R.volume) + ") " + if(reagents) + reagent_note = reagents.log_list() if(ismob(firer)) log_combat(firer, L, "shot", src, reagent_note) @@ -253,7 +250,8 @@ return TRUE var/distance = get_dist(T, starting) // Get the distance between the turf shot from and the mob we hit and use that for the calculations. - def_zone = ran_zone(def_zone, max(100-(7*distance), 5)) //Lower accurancy/longer range tradeoff. 7 is a balanced number to use. + if(check_zone(def_zone) != BODY_ZONE_CHEST) + def_zone = ran_zone(def_zone, max(100-(7*distance), 5) * zone_accuracy_factor) //Lower accurancy/longer range tradeoff. 7 is a balanced number to use. if(isturf(A) && hitsound_wall) var/volume = CLAMP(vol_by_damage() + 20, 0, 100) diff --git a/code/modules/projectiles/projectile/bullets/dart_syringe.dm b/code/modules/projectiles/projectile/bullets/dart_syringe.dm index 3f418df75b..b5a9eb8d69 100644 --- a/code/modules/projectiles/projectile/bullets/dart_syringe.dm +++ b/code/modules/projectiles/projectile/bullets/dart_syringe.dm @@ -6,7 +6,7 @@ /obj/item/projectile/bullet/dart/Initialize() . = ..() - create_reagents(50, NO_REACT) + create_reagents(50, NO_REACT, NO_REAGENTS_VALUE) /obj/item/projectile/bullet/dart/on_hit(atom/target, blocked = FALSE, skip = FALSE) if(iscarbon(target)) diff --git a/code/modules/projectiles/projectile/bullets/shotgun.dm b/code/modules/projectiles/projectile/bullets/shotgun.dm index 02ec167b80..c28d85511e 100644 --- a/code/modules/projectiles/projectile/bullets/shotgun.dm +++ b/code/modules/projectiles/projectile/bullets/shotgun.dm @@ -61,7 +61,7 @@ /obj/item/projectile/bullet/pellet/shotgun_buckshot name = "buckshot pellet" - damage = 10 + damage = 12.5 /obj/item/projectile/bullet/pellet/shotgun_rubbershot name = "rubbershot pellet" diff --git a/code/modules/projectiles/projectile/bullets/sniper.dm b/code/modules/projectiles/projectile/bullets/sniper.dm index bea5dbc140..5e3ae53806 100644 --- a/code/modules/projectiles/projectile/bullets/sniper.dm +++ b/code/modules/projectiles/projectile/bullets/sniper.dm @@ -7,6 +7,7 @@ knockdown = 100 dismemberment = 50 armour_penetration = 50 + zone_accuracy_factor = 100 //guarunteed 100% var/breakthings = TRUE /obj/item/projectile/bullet/p50/on_hit(atom/target, blocked = 0) diff --git a/code/modules/projectiles/projectile/energy/stun.dm b/code/modules/projectiles/projectile/energy/stun.dm index 88e70154d1..3bb1b3794e 100644 --- a/code/modules/projectiles/projectile/energy/stun.dm +++ b/code/modules/projectiles/projectile/energy/stun.dm @@ -2,11 +2,11 @@ name = "electrode" icon_state = "spark" color = "#FFFF00" - nodamage = 1 + nodamage = TRUE knockdown = 60 knockdown_stamoverride = 36 knockdown_stam_max = 50 - stutter = 5 + stutter = 10 jitter = 20 hitsound = 'sound/weapons/taserhit.ogg' range = 7 @@ -14,6 +14,7 @@ muzzle_type = /obj/effect/projectile/muzzle/stun impact_type = /obj/effect/projectile/impact/stun var/tase_duration = 50 + var/strong_tase = TRUE /obj/item/projectile/energy/electrode/on_hit(atom/target, blocked = FALSE) . = ..() @@ -26,10 +27,24 @@ C.IgniteMob() if(C.dna && C.dna.check_mutation(HULK)) C.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ), forced = "hulk") - else if((C.status_flags & CANKNOCKDOWN) && !HAS_TRAIT(C, TRAIT_STUNIMMUNE)) - C.apply_status_effect(STATUS_EFFECT_TASED, tase_duration) + else if(tase_duration && (C.status_flags & CANKNOCKDOWN) && !HAS_TRAIT(C, TRAIT_STUNIMMUNE)) + C.apply_status_effect(strong_tase? STATUS_EFFECT_TASED : STATUS_EFFECT_TASED_WEAK, tase_duration) addtimer(CALLBACK(C, /mob/living/carbon.proc/do_jitter_animation, jitter), 5) /obj/item/projectile/energy/electrode/on_range() //to ensure the bolt sparks when it reaches the end of its range if it didn't hit a target yet do_sparks(1, TRUE, src) ..() + +/obj/item/projectile/energy/electrode/security + tase_duration = 30 + knockdown = 0 + stamina = 10 + knockdown_stamoverride = 0 + knockdown_stam_max = 0 + strong_tase = FALSE + range = 12 + +/obj/item/projectile/energy/electrode/security/hos + knockdown = 100 + knockdown_stamoverride = 30 + knockdown_stam_max = null diff --git a/code/modules/projectiles/projectile/reusable/arrow.dm b/code/modules/projectiles/projectile/reusable/arrow.dm new file mode 100644 index 0000000000..f1c9638fd9 --- /dev/null +++ b/code/modules/projectiles/projectile/reusable/arrow.dm @@ -0,0 +1,6 @@ +/obj/item/projectile/bullet/reusable/arrow + name = "wooden arrow" + desc = "Woosh!" + damage = 15 + icon_state = "arrow" + ammo_type = /obj/item/ammo_casing/caseless/arrow \ No newline at end of file diff --git a/code/modules/projectiles/projectile/special/gravity.dm b/code/modules/projectiles/projectile/special/gravity.dm index 0ef9bc6653..ba21ecb28c 100644 --- a/code/modules/projectiles/projectile/special/gravity.dm +++ b/code/modules/projectiles/projectile/special/gravity.dm @@ -1,90 +1,65 @@ -/obj/item/projectile/gravityrepulse +/obj/item/projectile/gravity + name = "gravity bolt" + icon = 'icons/effects/effects.dmi' + icon_state = "chronofield" + hitsound = 'sound/weapons/wave.ogg' + damage = 0 + damage_type = BRUTE + nodamage = TRUE + var/power = 4 + var/list/thrown = list() //normally we wouldn't need this but incase on_hit is called multiple times, yeah.. this is a good idea. + +/obj/item/projectile/gravity/Initialize(mapload) + . = ..() + var/obj/item/ammo_casing/energy/gravity/G = loc + if(istype(G)) + power = min(G.gun.power, 15) + +/obj/item/projectile/gravity/on_hit() + . = ..() + var/turf/T = get_turf(src) + var/list/tothrow = list() + var/list/cachedrange = range(T, power) + for(var/mob/M in cachedrange) + tothrow += M + for(var/obj/O in cachedrange) + tothrow += O + var/safety = 50 + for(var/i in tothrow) + if(!safety) + break + var/atom/movable/AM = i + if((AM == src) || (AM == firer) || (AM.move_resist > MOVE_FORCE_EXTREMELY_STRONG) || AM.anchored || thrown[AM]) + continue + thrown[AM] = TRUE + safety-- + var/target = get_target(T, AM) + if(!target) + return FALSE + AM.throw_at(target, power + 1, 1) + for(var/turf/F in range(T,power)) + new /obj/effect/temp_visual/gravpush(F) + +/obj/item/projectile/gravity/proc/get_target(turf/origin, atom/movable/AM) + return origin + +/obj/item/projectile/gravity/repulse name = "repulsion bolt" - icon = 'icons/effects/effects.dmi' - icon_state = "chronofield" - hitsound = 'sound/weapons/wave.ogg' - damage = 0 - damage_type = BRUTE - nodamage = 1 color = "#33CCFF" - var/turf/T - var/power = 4 - var/list/thrown_items = list() -/obj/item/projectile/gravityrepulse/Initialize() - . = ..() - var/obj/item/ammo_casing/energy/gravity/repulse/C = loc - if(istype(C)) //Hard-coded maximum power so servers can't be crashed by trying to throw the entire Z level's items - power = min(C.gun.power, 15) +/obj/item/projectile/gravity/repulse/get_target(turf/origin, atom/movable/AM) + return get_turf_in_angle(Get_Angle(origin, AM), origin, power) -/obj/item/projectile/gravityrepulse/on_hit() - . = ..() - T = get_turf(src) - for(var/atom/movable/A in range(T, power)) - if(A == src || (firer && A == src.firer) || A.anchored || thrown_items[A]) - continue - var/throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(A, src))) - A.throw_at(throwtarget,power+1,1) - thrown_items[A] = A - for(var/turf/F in range(T,power)) - new /obj/effect/temp_visual/gravpush(F) - -/obj/item/projectile/gravityattract +/obj/item/projectile/gravity/attract name = "attraction bolt" - icon = 'icons/effects/effects.dmi' - icon_state = "chronofield" - hitsound = 'sound/weapons/wave.ogg' - damage = 0 - damage_type = BRUTE - nodamage = 1 color = "#FF6600" - var/turf/T - var/power = 4 - var/list/thrown_items = list() -/obj/item/projectile/gravityattract/Initialize() - . = ..() - var/obj/item/ammo_casing/energy/gravity/attract/C = loc - if(istype(C)) //Hard-coded maximum power so servers can't be crashed by trying to throw the entire Z level's items - power = min(C.gun.power, 15) +/obj/item/projectile/gravity/attract/get_target(turf/origin, atom/movable/AM) + return origin -/obj/item/projectile/gravityattract/on_hit() - . = ..() - T = get_turf(src) - for(var/atom/movable/A in range(T, power)) - if(A == src || (firer && A == src.firer) || A.anchored || thrown_items[A]) - continue - A.throw_at(T, power+1, 1) - thrown_items[A] = A - for(var/turf/F in range(T,power)) - new /obj/effect/temp_visual/gravpush(F) - -/obj/item/projectile/gravitychaos +/obj/item/projectile/gravity/chaos name = "gravitational blast" - icon = 'icons/effects/effects.dmi' - icon_state = "chronofield" - hitsound = 'sound/weapons/wave.ogg' - damage = 0 - damage_type = BRUTE - nodamage = 1 color = "#101010" - var/turf/T - var/power = 4 - var/list/thrown_items = list() -/obj/item/projectile/gravitychaos/Initialize() - . = ..() - var/obj/item/ammo_casing/energy/gravity/chaos/C = loc - if(istype(C)) //Hard-coded maximum power so servers can't be crashed by trying to throw the entire Z level's items - power = min(C.gun.power, 15) - -/obj/item/projectile/gravitychaos/on_hit() - . = ..() - T = get_turf(src) - for(var/atom/movable/A in range(T, power)) - if(A == src|| (firer && A == src.firer) || A.anchored || thrown_items[A]) - continue - A.throw_at(get_edge_target_turf(A, pick(GLOB.cardinals)), power+1, 1) - thrown_items[A] = A - for(var/turf/Z in range(T,power)) - new /obj/effect/temp_visual/gravpush(Z) +/obj/item/projectile/gravity/chaos/get_target(turf/origin, atom/movable/AM) + return get_turf_in_angle(rand(0, 359), origin, power) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 95e104ba68..4c240660a9 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -61,8 +61,9 @@ var/reactedVol = 0 //how much of the reagent is reacted during a fermireaction var/fermiIsReacting = FALSE //that prevents multiple reactions from occurring (i.e. add_reagent calls to process_reactions(), this stops any extra reactions.) var/fermiReactID //instance of the chem reaction used during a fermireaction, kept here so it's cache isn't lost between loops/procs. + var/value_multiplier = DEFAULT_REAGENTS_VALUE //used for cargo reagents selling. -/datum/reagents/New(maximum=100, new_flags) +/datum/reagents/New(maximum=100, new_flags = NONE, new_value = DEFAULT_REAGENTS_VALUE) maximum_volume = maximum //I dislike having these here but map-objects are initialised before world/New() is called. >_> @@ -72,6 +73,7 @@ build_chemical_reactions_list() reagents_holder_flags = new_flags + value_multiplier = new_value /datum/reagents/Destroy() . = ..() @@ -1147,10 +1149,10 @@ // Convenience proc to create a reagents holder for an atom // Max vol is maximum volume of holder -/atom/proc/create_reagents(max_vol, flags) +/atom/proc/create_reagents(max_vol, flags, new_value) if(reagents) qdel(reagents) - reagents = new/datum/reagents(max_vol, flags) + reagents = new/datum/reagents(max_vol, flags, new_value) reagents.my_atom = src /proc/get_random_reagent_id() // Returns a random reagent type minus blacklisted reagents diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index 0abdc9a739..ed68c25cb6 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -270,7 +270,7 @@ if(!is_operational() || recording_recipe) return var/amount = text2num(params["amount"]) - if(beaker && amount in beaker.possible_transfer_amounts) + if(beaker && (amount in beaker.possible_transfer_amounts)) beaker.reagents.remove_all(amount) work_animation() . = TRUE @@ -319,7 +319,7 @@ if(!is_operational()) return var/name = stripped_input(usr,"Name","What do you want to name this recipe?", "Recipe", MAX_NAME_LEN) - if(!usr.canUseTopic(src, !issilicon(usr))) + if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr))) return if(saved_recipes[name] && alert("\"[name]\" already exists, do you want to overwrite it?",, "Yes", "No") == "No") return diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm index 44148c85a7..66c663e2e4 100644 --- a/code/modules/reagents/chemistry/machinery/chem_master.dm +++ b/code/modules/reagents/chemistry/machinery/chem_master.dm @@ -261,7 +261,7 @@ return vol_each = min(reagents.total_volume / amount, 50) var/name = html_decode(stripped_input(usr,"Name:","Name your pill!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN)) - if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr))) + if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !hasSiliconAccessInArea(usr))) return var/obj/item/reagent_containers/pill/P var/target_loc = drop_location() @@ -288,7 +288,7 @@ reagents.trans_to(P,vol_each) else var/name = html_decode(stripped_input(usr, "Name:", "Name your pack!", reagents.get_master_reagent_name(), MAX_NAME_LEN)) - if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr))) + if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !hasSiliconAccessInArea(usr))) return var/obj/item/reagent_containers/food/condiment/pack/P = new/obj/item/reagent_containers/food/condiment/pack(drop_location()) @@ -314,7 +314,7 @@ return vol_each = min(reagents.total_volume / amount, 40) var/name = html_decode(stripped_input(usr,"Name:","Name your patch!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN)) - if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr))) + if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !hasSiliconAccessInArea(usr))) return var/obj/item/reagent_containers/pill/P @@ -332,7 +332,7 @@ if(condi) var/name = html_decode(stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN)) - if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr))) + if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !hasSiliconAccessInArea(usr))) return var/obj/item/reagent_containers/food/condiment/P = new(drop_location()) P.originalname = name @@ -345,7 +345,7 @@ amount_full = round(reagents.total_volume / 30) vol_part = ((reagents.total_volume*1000) % 30000) / 1000 //% operator doesn't support decimals. var/name = html_decode(stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN)) - if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr))) + if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !hasSiliconAccessInArea(usr))) return var/obj/item/reagent_containers/glass/bottle/P @@ -373,7 +373,7 @@ amount_full = round(reagents.total_volume / 60) vol_part = reagents.total_volume % 60 var/name = html_decode(stripped_input(usr, "Name:","Name your hypovial!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN)) - if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr))) + if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !hasSiliconAccessInArea(usr))) return var/obj/item/reagent_containers/glass/bottle/vial/small/P @@ -408,7 +408,7 @@ vol_each = min(reagents.total_volume / amount, 20) var/name = html_decode(stripped_input(usr,"Name:","Name your SmartDart!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN)) - if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr))) + if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !hasSiliconAccessInArea(usr))) return var/obj/item/reagent_containers/syringe/dart/D diff --git a/code/modules/reagents/chemistry/machinery/pandemic.dm b/code/modules/reagents/chemistry/machinery/pandemic.dm index bba5371ef8..3dea44cf40 100644 --- a/code/modules/reagents/chemistry/machinery/pandemic.dm +++ b/code/modules/reagents/chemistry/machinery/pandemic.dm @@ -170,7 +170,7 @@ if(!A.mutable) return if(A) - var/new_name = stripped_input(usr, "Name the disease", "New name", "", MAX_NAME_LEN) + var/new_name = sanitize_name(html_encode(params["name"])) if(!new_name || ..()) return A.AssignName(new_name) @@ -181,27 +181,30 @@ if(!istype(A) || !A.mutable) to_chat(usr, "ERROR: Cannot replicate virus strain.") return + wait = TRUE + addtimer(CALLBACK(src, .proc/reset_replicator_cooldown), 50) A = A.Copy() var/list/data = list("blood_DNA" = "UNKNOWN DNA", "blood_type" = "SY", "viruses" = list(A)) var/obj/item/reagent_containers/glass/bottle/B = new(drop_location()) B.name = "[A.name] culture bottle" B.desc = "A small bottle. Contains [A.agent] culture in synthblood medium." - B.reagents.add_reagent(/datum/reagent/blood, 20, data) - wait = TRUE + B.reagents.add_reagent(/datum/reagent/blood/synthetics, 10, data) update_icon() var/turf/source_turf = get_turf(src) log_virus("A culture bottle was printed for the virus [A.admin_details()] at [loc_name(source_turf)] by [key_name(usr)]") - addtimer(CALLBACK(src, .proc/reset_replicator_cooldown), 50) + . = TRUE if("create_vaccine_bottle") + wait = TRUE + addtimer(CALLBACK(src, .proc/reset_replicator_cooldown), 400) var/id = params["index"] var/datum/disease/D = SSdisease.archive_diseases[id] var/obj/item/reagent_containers/glass/bottle/B = new(drop_location()) B.name = "[D.name] vaccine bottle" B.reagents.add_reagent(/datum/reagent/vaccine, 15, list(id)) - wait = TRUE + update_icon() - addtimer(CALLBACK(src, .proc/reset_replicator_cooldown), 200) + . = TRUE /obj/machinery/computer/pandemic/attackby(obj/item/I, mob/user, params) diff --git a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm index 7e1b7ec018..b17c2dfb37 100644 --- a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm +++ b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm @@ -142,7 +142,7 @@ /obj/machinery/reagentgrinder/ui_interact(mob/user) // The microwave Menu //I am reasonably certain that this is not a microwave . = ..() - if(operating || !user.canUseTopic(src, !issilicon(user))) + if(operating || !user.canUseTopic(src, !hasSiliconAccessInArea(user))) return var/list/options = list() @@ -170,10 +170,10 @@ for(var/key in options) choice = key else - choice = show_radial_menu(user, src, options, require_near = !issilicon(user)) + choice = show_radial_menu(user, src, options, require_near = !hasSiliconAccessInArea(user)) // post choice verification - if(operating || (isAI(user) && stat & NOPOWER) || !user.canUseTopic(src, !issilicon(user))) + if(operating || (isAI(user) && stat & NOPOWER) || !user.canUseTopic(src, !hasSiliconAccessInArea(user))) return switch(choice) @@ -190,7 +190,7 @@ /obj/machinery/reagentgrinder/examine(mob/user) . = ..() - if(!in_range(user, src) && !issilicon(user) && !isobserver(user)) + if(!in_range(user, src) && !hasSiliconAccessInArea(user) && !isobserver(user)) . += "You're too far away to examine [src]'s contents and display!" return diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index 810124b2ba..4b65776ce9 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -551,7 +551,7 @@ All effects don't start immediately, but rather get worse over time; the rate is value = 1 /datum/reagent/consumable/ethanol/screwdrivercocktail/on_mob_life(mob/living/carbon/M) - if(M.mind && M.mind.assigned_role in list("Station Engineer", "Atmospheric Technician", "Chief Engineer")) //Engineers lose radiation poisoning at a massive rate. + if(M.mind && (M.mind.assigned_role in list("Station Engineer", "Atmospheric Technician", "Chief Engineer"))) //Engineers lose radiation poisoning at a massive rate. M.radiation = max(M.radiation - 25, 0) return ..() @@ -725,11 +725,15 @@ All effects don't start immediately, but rather get worse over time; the rate is var/dorf_mode /datum/reagent/consumable/ethanol/manly_dorf/on_mob_metabolize(mob/living/M) + var/real_dorf = isdwarf(M) //_species(H, /datum/species/dwarf) if(ishuman(M)) var/mob/living/carbon/human/H = M - if(H.dna.check_mutation(DWARFISM) || HAS_TRAIT(H, TRAIT_ALCOHOL_TOLERANCE)) + if(H.dna.check_mutation(DWARFISM) || HAS_TRAIT(H, TRAIT_ALCOHOL_TOLERANCE) || real_dorf) to_chat(H, "Now THAT is MANLY!") - boozepwr = 5 //We've had worse in the mines + if(real_dorf) + boozepwr = 100 // Don't want dwarves to die because of a low booze power + else + boozepwr = 5 //We've had worse in the mines dorf_mode = TRUE /datum/reagent/consumable/ethanol/manly_dorf/on_mob_life(mob/living/carbon/M) @@ -1509,6 +1513,23 @@ All effects don't start immediately, but rather get worse over time; the rate is M.stuttering = min(M.stuttering + 3, 3) ..() +/datum/reagent/consumable/ethanol/cogchamp + name = "CogChamp" + description = "Now you can fill yourself with the power of Ratvar!" + color = rgb(255, 201, 49) + boozepwr = 10 + quality = DRINK_FANTASTIC + taste_description = "a brass taste with a hint of oil" + glass_icon_state = "cogchamp" + glass_name = "CogChamp" + glass_desc = "Not even Ratvar's Four Generals could withstand this! Qevax Jryy!" + value = 8.13 + +/datum/reagent/consumable/ethanol/cogchamp/on_mob_life(mob/living/carbon/M) + M.clockcultslurring = min(M.clockcultslurring + 3, 3) + M.stuttering = min(M.stuttering + 3, 3) + ..() + /datum/reagent/consumable/ethanol/triple_sec name = "Triple Sec" description = "A sweet and vibrant orange liqueur." diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index b6cb387b81..52eee9f8ea 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -383,7 +383,7 @@ name = "Hot Chocolate" description = "Made with love! And coco beans." nutriment_factor = 3 * REAGENTS_METABOLISM - color = "#403010" // rgb: 64, 48, 16 + color = "#660000" // rgb: 221, 202, 134 taste_description = "creamy chocolate" glass_icon_state = "chocolateglass" glass_name = "glass of chocolate" diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index e8913f9ce4..6d37f30884 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -994,7 +994,7 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M) /datum/reagent/medicine/stimulants/on_mob_metabolize(mob/living/L) ..() - L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING)) + L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-0.5, blacklisted_movetypes=(FLYING|FLOATING)) /datum/reagent/medicine/stimulants/on_mob_end_metabolize(mob/living/L) L.remove_movespeed_modifier(type) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index c7e574594b..6d33701a34 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -338,8 +338,8 @@ /datum/reagent/water/holywater/on_mob_life(mob/living/carbon/M) if(!data) - data = 1 - data++ + data = list("misc" = 1) + data["misc"]++ M.jitteriness = min(M.jitteriness+4,10) if(iscultist(M)) for(var/datum/action/innate/cult/blood_magic/BM in M.actions) @@ -348,7 +348,7 @@ to_chat(M, "Your blood rites falter as holy water scours your body!") for(var/datum/action/innate/cult/blood_spell/BS in BM.spells) qdel(BS) - if(data >= 25) // 10 units, 45 seconds @ metabolism 0.4 units & tick rate 1.8 sec + if(data["misc"] >= 25) // 10 units, 45 seconds @ metabolism 0.4 units & tick rate 1.8 sec if(!M.stuttering) M.stuttering = 1 M.stuttering = min(M.stuttering+4, 10) @@ -369,7 +369,7 @@ "You can't save him. Nothing can save him now", "It seems that Nar'Sie will triumph after all")].") if("emote") M.visible_message("[M] [pick("whimpers quietly", "shivers as though cold", "glances around in paranoia")].") - if(data >= 60) // 30 units, 135 seconds + if(data["misc"] >= 60) // 30 units, 135 seconds if(iscultist(M) || is_servant_of_ratvar(M)) if(iscultist(M)) SSticker.mode.remove_cultist(M.mind, FALSE, TRUE) @@ -770,7 +770,7 @@ ..() if(!istype(H)) return - if(!H.dna || !H.dna.species || !(MOB_ORGANIC in H.mob_biotypes)) + if(!H.dna || !H.dna.species || !(H.mob_biotypes & MOB_ORGANIC)) return if(isjellyperson(H)) diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index a32cb94401..e649caafb5 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -260,7 +260,7 @@ /datum/reagent/toxin/pestkiller/reaction_mob(mob/living/M, method=TOUCH, reac_volume) ..() - if(MOB_BUG in M.mob_biotypes) + if(M.mob_biotypes & MOB_BUG) var/damage = min(round(0.4*reac_volume, 0.1),10) M.adjustToxLoss(damage) diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 23176f8a05..c178aad717 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -7,7 +7,8 @@ var/amount_per_transfer_from_this = 5 var/list/possible_transfer_amounts = list(5,10,15,20,25,30) var/volume = 30 - var/reagent_flags //used to determine the reagent holder flags on add_initial_reagents() + var/reagent_flags = NONE //used to determine the reagent holder flags on add_initial_reagents() + var/reagent_value = DEFAULT_REAGENTS_VALUE //same as above but for the holder value multiplier. var/list/list_reagents = null var/spawned_disease = null var/disease_amount = 20 @@ -22,7 +23,7 @@ volume = vol if(container_flags & APTFT_VERB && length(possible_transfer_amounts)) verbs += /obj/item/reagent_containers/proc/set_APTFT - create_reagents(volume, reagent_flags) + create_reagents(volume, reagent_flags, reagent_value) if(spawned_disease) var/datum/disease/F = new spawned_disease() var/list/data = list("blood_DNA" = "UNKNOWN DNA", "blood_type" = "SY","viruses"= list(F)) @@ -105,11 +106,11 @@ /obj/item/reagent_containers/proc/bartender_check(atom/target) . = FALSE var/turf/T = get_turf(src) - if(!T || target.CanPass(src, T) || !thrownby || !thrownby.actions) + if(!T || !target.CanPass(src, T) || !thrownby || !thrownby.actions) return - for(var/datum/action/innate/drink_fling/D in thrownby.actions) - if(D.active) - return TRUE + var/datum/action/innate/D = get_action_of_type(thrownby, /datum/action/innate/drink_fling) + if(D?.active) + return TRUE /obj/item/reagent_containers/proc/ForceResetRotation() transform = initial(transform) @@ -131,13 +132,14 @@ if(thrownby) log_combat(thrownby, M, "splashed", R) reagents.reaction(target, TOUCH) - + else if(bartender_check(target) && thrown) visible_message("[src] lands onto the [target.name] without spilling a single drop.") transform = initial(transform) addtimer(CALLBACK(src, .proc/ForceResetRotation), 1) return + else if(isturf(target) && reagents.reagent_list.len && thrownby) log_combat(thrownby, target, "splashed (thrown) [english_list(reagents.reagent_list)]", "in [AREACOORD(target)]") diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm index 34dd97b0aa..73d0c5eafa 100644 --- a/code/modules/reagents/reagent_containers/borghydro.dm +++ b/code/modules/reagents/reagent_containers/borghydro.dm @@ -19,6 +19,7 @@ Borg Hypospray amount_per_transfer_from_this = 5 volume = 30 possible_transfer_amounts = list() + reagent_value = NO_REAGENTS_VALUE var/mode = 1 var/charge_cost = 50 var/charge_tick = 0 diff --git a/code/modules/reagents/reagent_containers/dropper.dm b/code/modules/reagents/reagent_containers/dropper.dm index 9feec362a4..4e1de85fce 100644 --- a/code/modules/reagents/reagent_containers/dropper.dm +++ b/code/modules/reagents/reagent_containers/dropper.dm @@ -44,7 +44,7 @@ if(safe_thing) if(!safe_thing.reagents) - safe_thing.create_reagents(100) + safe_thing.create_reagents(100, NONE, NO_REAGENTS_VALUE) reagents.reaction(safe_thing, TOUCH, fraction) trans = reagents.trans_to(safe_thing, amount_per_transfer_from_this) diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index eac8edcbc8..fd4282b1b0 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -423,9 +423,9 @@ else unload_hypo(vial,user) -/obj/item/hypospray/mkii/AltClick(mob/living/user) +/obj/item/hypospray/mkii/CtrlClick(mob/living/user) . = ..() - if(user.canUseTopic(src, FALSE)) + if(user.canUseTopic(src, FALSE) && user.get_active_held_item(src)) switch(mode) if(HYPO_SPRAY) mode = HYPO_INJECT @@ -437,7 +437,7 @@ /obj/item/hypospray/mkii/examine(mob/user) . = ..() - . += "Alt-Click it to toggle its mode from spraying to injecting and vice versa." + . += "Ctrl-Click it to toggle its mode from spraying to injecting and vice versa." #undef HYPO_SPRAY #undef HYPO_INJECT diff --git a/code/modules/reagents/reagent_containers/rags.dm b/code/modules/reagents/reagent_containers/rags.dm index 59c956acd6..e7f340887c 100644 --- a/code/modules/reagents/reagent_containers/rags.dm +++ b/code/modules/reagents/reagent_containers/rags.dm @@ -11,6 +11,7 @@ container_flags = APTFT_VERB volume = 5 spillable = FALSE + reagent_value = NO_REAGENTS_VALUE var/wipe_sound var/soak_efficiency = 1 var/extinguish_efficiency = 0 @@ -26,7 +27,7 @@ if(reagents.total_volume) . += "It's soaked. Alt-Click to squeeze it dry, and perhaps gather the liquids into another held open container." -/obj/item/reagent_containers/rag/afterattack(atom/A as obj|turf|area, mob/user,proximity) +/obj/item/reagent_containers/rag/afterattack(atom/A, mob/user,proximity) . = ..() if(!proximity) return @@ -45,7 +46,7 @@ C.visible_message("[user] has touched \the [C] with \the [src].") log_combat(user, C, "touched", log_object) - else if(istype(A) && src in user) + else if(istype(A) && (src in user)) user.visible_message("[user] starts to wipe down [A] with [src]!", "You start to wipe down [A] with [src]...") if(do_after(user, action_speed, target = A)) user.visible_message("[user] finishes wiping off [A]!", "You finish wiping off [A].") diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index e8c8d14141..62ca5d658e 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -68,7 +68,7 @@ /obj/item/reagent_containers/spray/proc/spray(atom/A) var/range = CLAMP(get_dist(src, A), 1, current_range) var/obj/effect/decal/chempuff/D = new /obj/effect/decal/chempuff(get_turf(src)) - D.create_reagents(amount_per_transfer_from_this) + D.create_reagents(amount_per_transfer_from_this, NONE, NO_REAGENTS_VALUE) var/puff_reagent_left = range //how many turf, mob or dense objet we can react with before we consider the chem puff consumed if(stream_mode) reagents.trans_to(D, amount_per_transfer_from_this) @@ -172,6 +172,7 @@ /obj/item/reagent_containers/spray/drying_agent name = "drying agent spray" desc = "A spray bottle for drying agent." + icon_state = "cleaner_drying" volume = 100 list_reagents = list(/datum/reagent/drying_agent = 100) amount_per_transfer_from_this = 2 diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm index 90f96d0352..d39d9f4b85 100644 --- a/code/modules/recycling/disposal/bin.dm +++ b/code/modules/recycling/disposal/bin.dm @@ -79,12 +79,12 @@ /obj/machinery/disposal/attackby(obj/item/I, mob/user, params) add_fingerprint(user) if(!pressure_charging && !full_pressure && !flush) - if(istype(I, /obj/item/screwdriver)) + if(I.tool_behaviour == TOOL_SCREWDRIVER) panel_open = !panel_open I.play_tool_sound(src) to_chat(user, "You [panel_open ? "remove":"attach"] the screws around the power connection.") return - else if(istype(I, /obj/item/weldingtool) && panel_open) + else if(I.tool_behaviour == TOOL_WELDER && panel_open) if(!I.tool_start_check(user, amount=0)) return @@ -99,7 +99,7 @@ return place_item_in_disposal(I, user) update_icon() - return 1 //no afterattack + return TRUE //no afterattack else return ..() @@ -288,32 +288,16 @@ var/datum/oracle_ui/themed/nano/ui obj_flags = CAN_BE_HIT | USES_TGUI | SHOVABLE_ONTO - // attack by item places it in to disposal /obj/machinery/disposal/bin/attackby(obj/item/I, mob/user, params) - add_fingerprint(user) - if(!pressure_charging && !full_pressure && !flush) - if(I.tool_behaviour == TOOL_SCREWDRIVER) - panel_open = !panel_open - I.play_tool_sound(src) - to_chat(user, "You [panel_open ? "remove":"attach"] the screws around the power connection.") - return - else if(I.tool_behaviour == TOOL_WELDER && panel_open) - if(!I.tool_start_check(user, amount=0)) - return - - to_chat(user, "You start slicing the floorweld off \the [src]...") - if(I.use_tool(src, user, 20, volume=100) && panel_open) - to_chat(user, "You slice the floorweld off \the [src].") - deconstruct() - return - - if(user.a_intent != INTENT_HARM) - if((I.item_flags & ABSTRACT) || !user.temporarilyRemoveItemFromInventory(I)) - return - place_item_in_disposal(I, user) + if(istype(I, /obj/item/storage/bag/trash)) //Not doing component overrides because this is a specific type. + var/obj/item/storage/bag/trash/T = I + var/datum/component/storage/STR = T.GetComponent(/datum/component/storage) + to_chat(user, "You empty the bag.") + for(var/obj/item/O in T.contents) + STR.remove_from_storage(O,src) + T.update_icon() update_icon() - return TRUE //no afterattack else return ..() diff --git a/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm b/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm index b4d67315ba..6ccbf32615 100644 --- a/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm +++ b/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm @@ -26,6 +26,14 @@ category = list ("Misc. Machinery") departmental_flags = DEPARTMENTAL_FLAG_ALL +/datum/design/board/autolathe_secure + name = "Machine Design (Secure Autolathe Board)" + desc = "The circuit board for an autolathe. This one is programmed to not allow hacking." + id = "autolathe_secure" + build_path = /obj/item/circuitboard/machine/autolathe/secure + category = list ("Misc. Machinery") + departmental_flags = DEPARTMENTAL_FLAG_ALL + /datum/design/board/recharger name = "Machine Design (Weapon Recharger Board)" desc = "The circuit board for a Weapon Recharger." diff --git a/code/modules/research/designs/mining_designs.dm b/code/modules/research/designs/mining_designs.dm index b4ac5f109d..69e695afac 100644 --- a/code/modules/research/designs/mining_designs.dm +++ b/code/modules/research/designs/mining_designs.dm @@ -62,6 +62,26 @@ category = list("Mining Designs") departmental_flags = DEPARTMENTAL_FLAG_CARGO +/datum/design/plasteel_pick + name = "plasteel-tipped pickaxe" + desc = "A pickaxe with a plasteel pick head. Less robust at cracking rock walls and digging up dirt than the titanium pickaxe, but better at cracking open skulls." + id = "plasteel_pick" + build_type = PROTOLATHE + materials = list(MAT_METAL=2000, MAT_PLASMA=2000) + build_path = /obj/item/pickaxe/plasteel + category = list("Mining Designs") + departmental_flags = DEPARTMENTAL_FLAG_CARGO + +/datum/design/titanium_pick + name = "titanium-tipped pickaxe" + desc = "A pickaxe with a titanium pick head. Extremely robust at cracking rock walls and digging up dirt, but less than the plasteel pickaxe at cracking open skulls." + id = "titanium_pick" + build_type = PROTOLATHE + materials = list(MAT_TITANIUM = 4000) + build_path = /obj/item/pickaxe/titanium + category = list("Mining Designs") + departmental_flags = DEPARTMENTAL_FLAG_CARGO + /datum/design/jackhammer name = "Sonic Jackhammer" desc = "Essentially a handheld planet-cracker. Can drill through walls with ease as well." diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm index 2bc56f2fbd..72b2c91e4c 100644 --- a/code/modules/research/designs/misc_designs.dm +++ b/code/modules/research/designs/misc_designs.dm @@ -289,6 +289,16 @@ ////////////Janitor Designs////////////// ///////////////////////////////////////// +/datum/design/mop + name = "Mop" + desc = "Just your everyday standard mop." + id = "mop" + build_type = PROTOLATHE + materials = list(MAT_METAL = 1200, MAT_GLASS = 100) + build_path = /obj/item/mop + category = list("Equipment") + departmental_flags = DEPARTMENTAL_FLAG_SERVICE + /datum/design/advmop name = "Advanced Mop" desc = "An upgraded mop with a large internal capacity for holding water or other cleaning chemicals." diff --git a/code/modules/research/designs/tool_designs.dm b/code/modules/research/designs/tool_designs.dm index 300fe6c68a..cf1c0563d5 100644 --- a/code/modules/research/designs/tool_designs.dm +++ b/code/modules/research/designs/tool_designs.dm @@ -27,7 +27,7 @@ desc = "A tool that can construct and deconstruct walls, airlocks and floors on the fly." id = "rcd_loaded" build_type = PROTOLATHE - materials = list(MAT_METAL = MINERAL_MATERIAL_AMOUNT, MAT_GLASS = MINERAL_MATERIAL_AMOUNT) // costs more than what it did in the autolathe, this one comes loaded. + materials = list(MAT_METAL = 36000) // costs more than what it did in the autolathe, this one comes loaded. build_path = /obj/item/construction/rcd/loaded category = list("Tool Designs") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING diff --git a/code/modules/research/designs/weapon_designs.dm b/code/modules/research/designs/weapon_designs.dm index 1d65edbe9a..467679fea6 100644 --- a/code/modules/research/designs/weapon_designs.dm +++ b/code/modules/research/designs/weapon_designs.dm @@ -225,6 +225,16 @@ category = list("Firing Pins") departmental_flags = DEPARTMENTAL_FLAG_SECURITY +/datum/design/pin_away + name = "Station Locked Pin" + desc = "This is a security firing pin which only authorizes users who are off station." + id = "pin_away" + build_type = PROTOLATHE + materials = list(MAT_METAL = 1500, MAT_GLASS = 2000) + build_path = /obj/item/firing_pin/away + category = list("Firing Pins") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY + ////////////// //Guns//////// ////////////// diff --git a/code/modules/research/nanites/nanite_chamber_computer.dm b/code/modules/research/nanites/nanite_chamber_computer.dm index f9d931b3de..dec263368b 100644 --- a/code/modules/research/nanites/nanite_chamber_computer.dm +++ b/code/modules/research/nanites/nanite_chamber_computer.dm @@ -89,7 +89,7 @@ var/mob/living/L = chamber.occupant - if(!(MOB_ORGANIC in L.mob_biotypes) && !(MOB_UNDEAD in L.mob_biotypes)) + if(!(L.mob_biotypes & (MOB_ORGANIC|MOB_UNDEAD))) data["status_msg"] = "Occupant not compatible with nanites." return data diff --git a/code/modules/research/nanites/nanite_programs/healing.dm b/code/modules/research/nanites/nanite_programs/healing.dm index df439e4496..6dd1b3ee82 100644 --- a/code/modules/research/nanites/nanite_programs/healing.dm +++ b/code/modules/research/nanites/nanite_programs/healing.dm @@ -125,7 +125,7 @@ if(!parts.len) return FALSE else - if(!(MOB_ROBOTIC in host_mob.mob_biotypes)) + if(!(host_mob.mob_biotypes & MOB_ROBOTIC)) return FALSE return ..() diff --git a/code/modules/research/nanites/public_chamber.dm b/code/modules/research/nanites/public_chamber.dm index c0d19e0375..f1cd19b2a2 100644 --- a/code/modules/research/nanites/public_chamber.dm +++ b/code/modules/research/nanites/public_chamber.dm @@ -137,7 +137,7 @@ var/mob/living/L = occupant if(SEND_SIGNAL(L, COMSIG_HAS_NANITES)) return - if((MOB_ORGANIC in L.mob_biotypes) || (MOB_UNDEAD in L.mob_biotypes)) + if(L.mob_biotypes & (MOB_ORGANIC | MOB_UNDEAD)) inject_nanites() /obj/machinery/public_nanite_chamber/open_machine() diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index d33ef29155..71cfe7c0f5 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -52,13 +52,12 @@ Nothing else in the console has ID requirements. research_control = FALSE /proc/CallMaterialName(ID) + if(GLOB.chemical_reagents_list[ID]) + var/datum/reagent/reagent = GLOB.chemical_reagents_list[ID] + return reagent.name if (ID[1] == "$" && GLOB.materials_list[ID]) var/datum/material/material = GLOB.materials_list[ID] return material.name - - else if(GLOB.chemical_reagents_list[ID]) - var/datum/reagent/reagent = GLOB.chemical_reagents_list[ID] - return reagent.name return "ERROR: Report This" /obj/machinery/computer/rdconsole/proc/SyncRDevices() //Makes sure it is properly sync'ed up with the devices attached to it (if any). diff --git a/code/modules/research/stock_parts.dm b/code/modules/research/stock_parts.dm index e29cf28f34..befaf3d96a 100644 --- a/code/modules/research/stock_parts.dm +++ b/code/modules/research/stock_parts.dm @@ -22,7 +22,7 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi if(works_from_distance) user.Beam(T, icon_state = "rped_upgrade", time = 5) T.exchange_parts(user, src) - return FALSE + return TRUE return ..() /obj/item/storage/part_replacer/afterattack(obj/machinery/T, mob/living/user, adjacent, params) @@ -60,6 +60,7 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi new /obj/item/stock_parts/manipulator(src) new /obj/item/stock_parts/micro_laser(src) new /obj/item/stock_parts/matter_bin(src) + new /obj/item/stock_parts/cell/high(src) /obj/item/storage/part_replacer/bluespace/tier2 @@ -70,6 +71,7 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi new /obj/item/stock_parts/manipulator/nano(src) new /obj/item/stock_parts/micro_laser/high(src) new /obj/item/stock_parts/matter_bin/adv(src) + new /obj/item/stock_parts/cell/super(src) /obj/item/storage/part_replacer/bluespace/tier3 @@ -80,6 +82,7 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi new /obj/item/stock_parts/manipulator/pico(src) new /obj/item/stock_parts/micro_laser/ultra(src) new /obj/item/stock_parts/matter_bin/super(src) + new /obj/item/stock_parts/cell/hyper(src) /obj/item/storage/part_replacer/bluespace/tier4 @@ -90,6 +93,7 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi new /obj/item/stock_parts/manipulator/femto(src) new /obj/item/stock_parts/micro_laser/quadultra(src) new /obj/item/stock_parts/matter_bin/bluespace(src) + new /obj/item/stock_parts/cell/bluespace(src) /obj/item/storage/part_replacer/cargo //used in a cargo crate diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index e1abfedde6..75b71611d5 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -190,7 +190,7 @@ description = "A refresher course on modern engineering technology." prereq_ids = list("base") design_ids = list("solarcontrol", "recharger", "powermonitor", "rped", "pacman", "adv_capacitor", "adv_scanning", "emitter", "high_cell", "adv_matter_bin", - "atmosalerts", "atmos_control", "recycler", "autolathe", "high_micro_laser", "nano_mani", "mesons", "thermomachine", "rad_collector", "tesla_coil", "grounding_rod", + "atmosalerts", "atmos_control", "recycler", "autolathe", "autolathe_secure", "high_micro_laser", "nano_mani", "mesons", "thermomachine", "rad_collector", "tesla_coil", "grounding_rod", "apc_control", "cell_charger", "power control", "airlock_board", "firelock_board", "airalarm_electronics", "firealarm_electronics", "cell_charger", "stack_console", "stack_machine", "rcd_ammo") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 6000) export_price = 5000 @@ -602,7 +602,7 @@ display_name = "Basic Tools" description = "Basic mechanical, electronic, surgical and botanical tools." prereq_ids = list("base") - design_ids = list("screwdriver", "wrench", "wirecutters", "crowbar", "multitool", "welding_tool", "tscanner", "analyzer", "cable_coil", "pipe_painter", "airlock_painter", "scalpel", "circular_saw", "surgicaldrill", "retractor", "cautery", "hemostat", "cultivator", "plant_analyzer", "shovel", "spade", "hatchet") + design_ids = list("screwdriver", "wrench", "wirecutters", "crowbar", "multitool", "welding_tool", "tscanner", "analyzer", "cable_coil", "pipe_painter", "airlock_painter", "scalpel", "circular_saw", "surgicaldrill", "retractor", "cautery", "hemostat", "cultivator", "plant_analyzer", "shovel", "spade", "hatchet", "mop") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 500) export_price = 5000 @@ -620,7 +620,7 @@ display_name = "Advanced Mining Technology" description = "Efficiency Level 127" //dumb mc references prereq_ids = list("basic_mining", "adv_engi", "adv_power", "adv_plasma") - design_ids = list("drill_diamond", "jackhammer", "hypermod", "plasmacutter_adv", "ore_silo") + design_ids = list("drill_diamond", "jackhammer", "hypermod", "plasmacutter_adv", "ore_silo", "plasteel_pick", "titanium_pick") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) export_price = 5000 @@ -666,7 +666,7 @@ display_name = "Weapon Development Technology" description = "Our researchers have found new to weaponize just about everything now." prereq_ids = list("engineering") - design_ids = list("pin_testing", "tele_shield", "lasercarbine") + design_ids = list("pin_testing", "tele_shield", "lasercarbine", "pin_away") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500) export_price = 5000 diff --git a/code/modules/ruins/objects_and_mobs/necropolis_gate.dm b/code/modules/ruins/objects_and_mobs/necropolis_gate.dm index 26e5f1a9c0..c80b4d972c 100644 --- a/code/modules/ruins/objects_and_mobs/necropolis_gate.dm +++ b/code/modules/ruins/objects_and_mobs/necropolis_gate.dm @@ -22,6 +22,8 @@ var/static/mutable_appearance/dais_overlay var/obj/structure/opacity_blocker/sight_blocker var/sight_blocker_distance = 1 + var/uses + var/ashwalker_only = FALSE /obj/structure/necropolis_gate/Initialize() . = ..() @@ -87,9 +89,13 @@ //ATTACK HAND IGNORING PARENT RETURN VALUE /obj/structure/necropolis_gate/attack_hand(mob/user) - if(locked) + if(locked || uses == 0) to_chat(user, "It's [open ? "stuck open":"locked"].") return + if(ashwalker_only) + if(!(user.mind.assigned_role == "Ash Walker")) + to_chat(user, "The gate screeches in an incoherant language!") + return toggle_the_gate(user) return ..() @@ -131,12 +137,18 @@ density = FALSE sleep(5) open = TRUE + if(uses && uses > 0) + uses -= 1 changing_openness = FALSE return TRUE /obj/structure/necropolis_gate/locked locked = TRUE +/obj/structure/necropolis_gate/ashwalker + uses = 1 + ashwalker_only = TRUE + GLOBAL_DATUM(necropolis_gate, /obj/structure/necropolis_gate/legion_gate) /obj/structure/necropolis_gate/legion_gate desc = "A tremendous, impossibly large gateway, set into a massive tower of stone." diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm index 0e7cba9776..bdf6e8cc87 100644 --- a/code/modules/shuttle/supply.dm +++ b/code/modules/shuttle/supply.dm @@ -168,7 +168,7 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list( for(var/chem in ex.reagents_value) var/value = ex.reagents_value[chem] - msg += "[value] credits: received [ex.reagents_volume[chem]]u of [chem].\n" + msg += "[value > 0 ? "+" : ""][value] credits: received [ex.reagents_volume[chem]]u of [chem].\n" SSshuttle.points += value msg = copytext_char(msg, 1, MAX_MESSAGE_LEN) diff --git a/code/modules/spells/spell_types/summonitem.dm b/code/modules/spells/spell_types/summonitem.dm index c4b184cc9b..d0e415fb2a 100644 --- a/code/modules/spells/spell_types/summonitem.dm +++ b/code/modules/spells/spell_types/summonitem.dm @@ -38,7 +38,7 @@ else message = "You must hold the desired item in your hands to mark it for recall." - else if(marked_item && marked_item in hand_items) //unlinking item to the spell + else if(marked_item && (marked_item in hand_items)) //unlinking item to the spell message = "You remove the mark on [marked_item] to use elsewhere." name = "Instant Summons" marked_item = null @@ -78,7 +78,7 @@ if(iscarbon(M)) //Edge case housekeeping var/mob/living/carbon/C = M - if(C.stomach_contents && item_to_retrieve in C.stomach_contents) + if(C.stomach_contents && (item_to_retrieve in C.stomach_contents)) C.stomach_contents -= item_to_retrieve for(var/X in C.bodyparts) var/obj/item/bodypart/part = X diff --git a/code/modules/spells/spell_types/wizard.dm b/code/modules/spells/spell_types/wizard.dm index e098fe389d..44fdd1eb55 100644 --- a/code/modules/spells/spell_types/wizard.dm +++ b/code/modules/spells/spell_types/wizard.dm @@ -248,6 +248,7 @@ mutations = list(BLINDMUT) duration = 300 sound = 'sound/magic/blind.ogg' + /obj/effect/proc_holder/spell/aoe_turf/repulse name = "Repulse" desc = "This spell throws everything around the user away." @@ -266,15 +267,22 @@ action_icon_state = "repulse" /obj/effect/proc_holder/spell/aoe_turf/repulse/cast(list/targets,mob/user = usr, stun_amt = 50) + var/list/mobs = list() + var/list/objs = list() var/list/thrownatoms = list() var/atom/throwtarget var/distfromcaster playMagSound() for(var/turf/T in targets) //Done this way so things don't get thrown all around hilariously. - for(var/atom/movable/AM in T) - thrownatoms += AM - + for(var/mob/M in T) + mobs += M + for(var/obj/O in T) + objs += O + thrownatoms = mobs + objs //mobs first + var/safety = 50 for(var/am in thrownatoms) + if(!safety) + break var/atom/movable/AM = am if(AM == user || AM.anchored) continue @@ -299,6 +307,7 @@ M.Knockdown(stun_amt, override_hardstun = stun_amt * 0.2) to_chat(M, "You're thrown back by [user]!") AM.throw_at(throwtarget, ((CLAMP((maxthrow - (CLAMP(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1,user)//So stuff gets tossed around at the same time. + safety-- /obj/effect/proc_holder/spell/aoe_turf/repulse/xeno //i fixed conflicts only to find out that this is in the WIZARD file instead of the xeno file?! name = "Tail Sweep" diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm index 097be23c40..c9affe92f9 100644 --- a/code/modules/surgery/bodyparts/bodyparts.dm +++ b/code/modules/surgery/bodyparts/bodyparts.dm @@ -5,6 +5,7 @@ force = 3 throwforce = 3 icon = 'icons/mob/human_parts.dmi' + w_class = WEIGHT_CLASS_SMALL icon_state = "" layer = BELOW_MOB_LAYER //so it isn't hidden behind objects when on the floor var/mob/living/carbon/owner = null diff --git a/code/modules/surgery/experimental_dissection.dm b/code/modules/surgery/experimental_dissection.dm index 40fe90a829..a94abafe4c 100644 --- a/code/modules/surgery/experimental_dissection.dm +++ b/code/modules/surgery/experimental_dissection.dm @@ -24,8 +24,8 @@ /datum/surgery_step/dissection name = "dissection" - implements = list(/obj/item/scalpel/augment = 75, /obj/item/scalpel/advanced = 60, /obj/item/scalpel = 45, /obj/item/kitchen/knife = 20, /obj/item/shard = 10)// special tools not only cut down time but also improve probability, doesn't use TOOL_SCALPEL because different scalpels have different probs - time = 125 + implements = list(/obj/item/scalpel/alien = 100, /obj/item/scalpel/advanced = 99, /obj/item/scalpel = 90, /obj/item/kitchen/knife = 45, /obj/item/shard = 25)// special tools not only cut down time but also improve probability, doesn't use TOOL_SCALPEL because different scalpels have different probs + time = 100 silicons_obey_prob = TRUE repeatable = TRUE @@ -110,4 +110,4 @@ requires_tech = TRUE replaced_by = null -#undef BASE_HUMAN_REWARD \ No newline at end of file +#undef BASE_HUMAN_REWARD diff --git a/code/modules/surgery/organs/heart.dm b/code/modules/surgery/organs/heart.dm index 77aa302f8c..5767e84c73 100644 --- a/code/modules/surgery/organs/heart.dm +++ b/code/modules/surgery/organs/heart.dm @@ -6,7 +6,7 @@ slot = ORGAN_SLOT_HEART healing_factor = STANDARD_ORGAN_HEALING - decay_factor = 2.5 * STANDARD_ORGAN_DECAY //designed to fail about 5 minutes after death + decay_factor = 2 * STANDARD_ORGAN_DECAY low_threshold_passed = "Prickles of pain appear then die out from within your chest..." high_threshold_passed = "Something inside your chest hurts, and the pain isn't subsiding. You notice yourself breathing far faster than before." diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm index 8ad293fbcb..bcc764d00a 100644 --- a/code/modules/surgery/organs/tongue.dm +++ b/code/modules/surgery/organs/tongue.dm @@ -30,39 +30,23 @@ /obj/item/organ/tongue/Initialize(mapload) . = ..() + low_threshold_passed = "Your [name] feels a little sore." + low_threshold_cleared = "Your [name] soreness has subsided." + high_threshold_passed = "Your [name] is really starting to hurt." + high_threshold_cleared = "The pain of your [name] has subsided a little." + now_failing = "Your [name] feels like it's about to fall out!." + now_fixed = "The excruciating pain of your [name] has subsided." languages_possible = languages_possible_base /obj/item/organ/tongue/proc/handle_speech(datum/source, list/speech_args) + return -/obj/item/organ/tongue/emp_act(severity) +/obj/item/organ/tongue/applyOrganDamage(d, maximum = maxHealth) . = ..() - if(. & EMP_PROTECT_SELF) - return - if(organ_flags & ORGAN_SYNTHETIC) - var/errormessage = list("Runtime in tongue.dm, line 39: Undefined operation \"zapzap ow my tongue\"", "afhsjifksahgjkaslfhashfjsak", "-1.#IND", "Graham's number", "inside you all along", "awaiting at least 1 approving review before merging this taste request") - owner.say("The pH is appropriately [pick(errormessage)].") - -/obj/item/organ/tongue/applyOrganDamage(var/d, var/maximum = maxHealth) - - if(!d) //Micro-optimization. - return - if(maximum < damage) - return - damage = CLAMP(damage + d, 0, maximum) - var/mess = check_damage_thresholds(owner) - prev_damage = damage - if(mess && owner) - to_chat(owner, mess) - - if ((damage / maxHealth) > 1) + if (damage >= maxHealth) to_chat(owner, "Your tongue is singed beyond recognition, and disintegrates!") SSblackbox.record_feedback("tally", "fermi_chem", 1, "Tongues lost to Fermi") qdel(src) - else if ((damage / maxHealth) > 0.85) - to_chat(owner, "Your tongue feels like it's about to fall out!.") - else if ((damage / maxHealth) > 0.5) - to_chat(owner, "Your tongue is really starting to hurt.") - /obj/item/organ/tongue/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE) ..() @@ -311,6 +295,13 @@ maxHealth = 60 //It's robotic! organ_flags = ORGAN_SYNTHETIC +/obj/item/organ/tongue/cybernetic/emp_act(severity) + . = ..() + if(. & EMP_PROTECT_SELF) + return + var/errormessage = list("Runtime in tongue.dm, line 39: Undefined operation \"zapzap ow my tongue\"", "afhsjifksahgjkaslfhashfjsak", "-1.#IND", "Graham's number", "inside you all along", "awaiting at least 1 approving review before merging this taste request") + owner.say("The pH is appropriately [pick(errormessage)].", forced = "EMPed synthetic tongue") + /obj/item/organ/tongue/cybernetic/handle_speech(datum/source, list/speech_args) speech_args[SPEECH_SPANS] |= SPAN_ROBOT diff --git a/code/modules/tgs/core/core.dm b/code/modules/tgs/core/core.dm index 61f1e71d2e..70252cfb49 100644 --- a/code/modules/tgs/core/core.dm +++ b/code/modules/tgs/core/core.dm @@ -1,47 +1,60 @@ -/world/TgsNew(datum/tgs_event_handler/event_handler) - var/tgs_version = world.params[TGS_VERSION_PARAMETER] - if(!tgs_version) +/world/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_ULTRASAFE) + var/current_api = TGS_READ_GLOBAL(tgs) + if(current_api) + TGS_ERROR_LOG("TgsNew(): TGS API datum already set ([current_api])! Was TgsNew() called more than once?") return - var/path = SelectTgsApi(tgs_version) - if(!path) - TGS_ERROR_LOG("Found unsupported API version: [tgs_version]. If this is a valid version please report this, backporting is done on demand.") +#ifdef TGS_V3_API + minimum_required_security_level = TGS_SECURITY_TRUSTED +#endif + var/raw_parameter = world.params[TGS_VERSION_PARAMETER] + if(!raw_parameter) + return - TGS_INFO_LOG("Activating API for version [tgs_version]") - var/datum/tgs_api/new_api = new path + var/datum/tgs_version/version = new(raw_parameter) + if(!version.Valid(FALSE)) + TGS_ERROR_LOG("Failed to validate TGS version parameter: [raw_parameter]!") + return - var/result = new_api.OnWorldNew(event_handler ? event_handler : new /datum/tgs_event_handler/tgs_default) - if(result && result != TGS_UNIMPLEMENTED) - TGS_WRITE_GLOBAL(tgs, new_api) - else + var/api_datum + switch(version.suite) + if(3) +#ifndef TGS_V3_API + TGS_ERROR_LOG("Detected V3 API but TGS_V3_API isn't defined!") +#else + switch(version.major) + if(2) + api_datum = /datum/tgs_api/v3210 +#endif + if(4) + switch(version.major) + if(0) + api_datum = /datum/tgs_api/v4 + + var/datum/tgs_version/max_api_version = TgsMaximumAPIVersion(); + if(version.suite != null && version.major != null && version.minor != null && version.patch != null && version.deprefixed_parameter > max_api_version.deprefixed_parameter) + TGS_ERROR_LOG("Detected unknown API version! Defaulting to latest. Update the DMAPI to fix this problem.") + api_datum = /datum/tgs_api/latest + + if(!api_datum) + TGS_ERROR_LOG("Found unsupported API version: [raw_parameter]. If this is a valid version please report this, backporting is done on demand.") + return + + TGS_INFO_LOG("Activating API for version [version.deprefixed_parameter]") + var/datum/tgs_api/new_api = new api_datum(version) + + TGS_WRITE_GLOBAL(tgs, new_api) + + var/result = new_api.OnWorldNew(event_handler, minimum_required_security_level) + if(!result || result == TGS_UNIMPLEMENTED) + TGS_WRITE_GLOBAL(tgs, null) TGS_ERROR_LOG("Failed to activate API!") -/world/proc/SelectTgsApi(tgs_version) - //remove the old 3.0 header - tgs_version = replacetext(tgs_version, "/tg/station 13 Server v", "") - - var/list/version_bits = splittext(tgs_version, ".") - - var/super = text2num(version_bits[1]) - var/major = text2num(version_bits[2]) - var/minor = text2num(version_bits[3]) - var/patch = text2num(version_bits[4]) - - switch(super) - if(3) - switch(major) - if(2) - return /datum/tgs_api/v3210 - - if(super != null && major != null && minor != null && patch != null && tgs_version > TgsMaximumAPIVersion()) - TGS_ERROR_LOG("Detected unknown API version! Defaulting to latest. Update the DMAPI to fix this problem.") - return /datum/tgs_api/latest - /world/TgsMaximumAPIVersion() - return "4.0.0.0" + return new /datum/tgs_version("4.0.x.x") /world/TgsMinimumAPIVersion() - return "3.2.0.0" + return new /datum/tgs_version("3.2.0.0") /world/TgsInitializationComplete() var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) @@ -71,7 +84,9 @@ return TGS_READ_GLOBAL(tgs) != null /world/TgsVersion() - return world.params[TGS_VERSION_PARAMETER] + var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) + if(api) + return api.version /world/TgsInstanceName() var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) @@ -116,6 +131,11 @@ if(api) api.ChatPrivateMessage(message, user) +/world/TgsSecurityLevel() + var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) + if(api) + api.SecurityLevel() + /* The MIT License diff --git a/code/modules/tgs/core/datum.dm b/code/modules/tgs/core/datum.dm index 6af39a75df..fb2508059a 100644 --- a/code/modules/tgs/core/datum.dm +++ b/code/modules/tgs/core/datum.dm @@ -1,9 +1,14 @@ TGS_DEFINE_AND_SET_GLOBAL(tgs, null) /datum/tgs_api + var/datum/tgs_version/version + +/datum/tgs_api/New(datum/tgs_version/version) + . = ..() + src.version = version /datum/tgs_api/latest - parent_type = /datum/tgs_api/v3210 + parent_type = /datum/tgs_api/v4 TGS_PROTECT_DATUM(/datum/tgs_api) @@ -46,6 +51,9 @@ TGS_PROTECT_DATUM(/datum/tgs_api) /datum/tgs_api/proc/ChatPrivateMessage(message, admin_only) return TGS_UNIMPLEMENTED +/datum/tgs_api/proc/SecurityLevel() + return TGS_UNIMPLEMENTED + /* The MIT License diff --git a/code/modules/tgs/core/default_event_handler.dm b/code/modules/tgs/core/default_event_handler.dm deleted file mode 100644 index 716715bb26..0000000000 --- a/code/modules/tgs/core/default_event_handler.dm +++ /dev/null @@ -1,30 +0,0 @@ -/datum/tgs_event_handler/tgs_default/HandleEvent(event_code) - //TODO - return - -/* -The MIT License - -Copyright (c) 2017 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/code/modules/tgs/core/tgs_version.dm b/code/modules/tgs/core/tgs_version.dm new file mode 100644 index 0000000000..b97745611f --- /dev/null +++ b/code/modules/tgs/core/tgs_version.dm @@ -0,0 +1,22 @@ +/datum/tgs_version/New(raw_parameter) + src.raw_parameter = raw_parameter + deprefixed_parameter = replacetext(raw_parameter, "/tg/station 13 Server v", "") + var/list/version_bits = splittext(deprefixed_parameter, ".") + + suite = text2num(version_bits[1]) + if(version_bits.len > 1) + major = text2num(version_bits[2]) + if(version_bits.len > 2) + minor = text2num(version_bits[3]) + if(version_bits.len == 4) + patch = text2num(version_bits[4]) + +/datum/tgs_version/proc/Valid(allow_wildcards = FALSE) + if(suite == null) + return FALSE + if(allow_wildcards) + return TRUE + return !Wildcard() + +/datum/tgs_version/Wildcard() + return major == null || minor == null || patch == null diff --git a/code/modules/tgs/includes.dm b/code/modules/tgs/includes.dm index 7ca906c840..247f1fda5d 100644 --- a/code/modules/tgs/includes.dm +++ b/code/modules/tgs/includes.dm @@ -1,6 +1,10 @@ #include "core\_definitions.dm" #include "core\core.dm" #include "core\datum.dm" -#include "core\default_event_handler.dm" +#include "core\tgs_version.dm" +#ifdef TGS_V3_API #include "v3210\api.dm" #include "v3210\commands.dm" +#endif +#include "v4\api.dm" +#include "v4\commands.dm" diff --git a/code/modules/tgs/v3210/api.dm b/code/modules/tgs/v3210/api.dm index 2a95f7861e..c536995b04 100644 --- a/code/modules/tgs/v3210/api.dm +++ b/code/modules/tgs/v3210/api.dm @@ -56,8 +56,9 @@ /datum/tgs_api/v3210/proc/file2list(filename) return splittext(trim_left(trim_right(file2text(filename))), "\n") -/datum/tgs_api/v3210/OnWorldNew(datum/tgs_event_handler/event_handler) //don't use event handling in this version +/datum/tgs_api/v3210/OnWorldNew(datum/tgs_event_handler/event_handler, minimum_required_security_level) //don't use event handling in this version . = FALSE + comms_key = world.params[SERVICE_WORLD_PARAM] instance_name = world.params[SERVICE_INSTANCE_PARAM] if(!instance_name) @@ -170,6 +171,7 @@ var/datum/tgs_revision_information/ri = new ri.commit = commit ri.origin_commit = originmastercommit + return ri /datum/tgs_api/v3210/EndProcess() sleep(world.tick_lag) //flush the buffers @@ -187,9 +189,12 @@ /datum/tgs_api/v3210/ChatTargetedBroadcast(message, admin_only) ExportService("[admin_only ? SERVICE_REQUEST_IRC_ADMIN_CHANNEL_MESSAGE : SERVICE_REQUEST_IRC_BROADCAST] [message]") -/datum/tgs_api/v3210/ChatPrivateMessage(message, admin_only) +/datum/tgs_api/v3210/ChatPrivateMessage(message, datum/tgs_chat_user/user) return TGS_UNIMPLEMENTED +/datum/tgs_api/v3210/SecurityLevel() + return TGS_SECURITY_TRUSTED + #undef REBOOT_MODE_NORMAL #undef REBOOT_MODE_HARD #undef REBOOT_MODE_SHUTDOWN diff --git a/code/modules/tgs/v4/api.dm b/code/modules/tgs/v4/api.dm new file mode 100644 index 0000000000..b61cddbeba --- /dev/null +++ b/code/modules/tgs/v4/api.dm @@ -0,0 +1,342 @@ +#define TGS4_PARAM_INFO_JSON "tgs_json" + +#define TGS4_INTEROP_ACCESS_IDENTIFIER "tgs_tok" + +#define TGS4_RESPONSE_SUCCESS "tgs_succ" + +#define TGS4_TOPIC_CHANGE_PORT "tgs_port" +#define TGS4_TOPIC_CHANGE_REBOOT_MODE "tgs_rmode" +#define TGS4_TOPIC_CHAT_COMMAND "tgs_chat_comm" +#define TGS4_TOPIC_EVENT "tgs_event" +#define TGS4_TOPIC_INTEROP_RESPONSE "tgs_interop" + +#define TGS4_COMM_NEW_PORT "tgs_new_port" +#define TGS4_COMM_VALIDATE "tgs_validate" +#define TGS4_COMM_SERVER_PRIMED "tgs_prime" +#define TGS4_COMM_WORLD_REBOOT "tgs_reboot" +#define TGS4_COMM_END_PROCESS "tgs_kill" +#define TGS4_COMM_CHAT "tgs_chat_send" + +#define TGS4_PARAMETER_COMMAND "tgs_com" +#define TGS4_PARAMETER_DATA "tgs_data" + +#define TGS4_PORT_CRITFAIL_MESSAGE " Must exit to let watchdog reboot..." + +#define EXPORT_TIMEOUT_DS 200 + +/datum/tgs_api/v4 + var/access_identifier + var/instance_name + var/json_path + var/chat_channels_json_path + var/chat_commands_json_path + var/server_commands_json_path + var/reboot_mode = TGS_REBOOT_MODE_NORMAL + var/security_level + + var/requesting_new_port = FALSE + + var/list/intercepted_message_queue + + var/list/custom_commands + + var/list/cached_test_merges + var/datum/tgs_revision_information/cached_revision + + var/datum/tgs_event_handler/event_handler + + var/export_lock = FALSE + var/list/last_interop_response + +/datum/tgs_api/v4/ApiVersion() + return "4.0.0.0" + +/datum/tgs_api/v4/OnWorldNew(datum/tgs_event_handler/event_handler, minimum_required_security_level) + json_path = world.params[TGS4_PARAM_INFO_JSON] + if(!json_path) + TGS_ERROR_LOG("Missing [TGS4_PARAM_INFO_JSON] world parameter!") + return + var/json_file = file2text(json_path) + if(!json_file) + TGS_ERROR_LOG("Missing specified json file: [json_path]") + return + var/cached_json = json_decode(json_file) + if(!cached_json) + TGS_ERROR_LOG("Failed to decode info json: [json_file]") + return + + access_identifier = cached_json["accessIdentifier"] + server_commands_json_path = cached_json["serverCommandsJson"] + + if(cached_json["apiValidateOnly"]) + TGS_INFO_LOG("Validating API and exiting...") + Export(TGS4_COMM_VALIDATE, list(TGS4_PARAMETER_DATA = "[minimum_required_security_level]")) + del(world) + + security_level = cached_json["securityLevel"] + chat_channels_json_path = cached_json["chatChannelsJson"] + chat_commands_json_path = cached_json["chatCommandsJson"] + src.event_handler = event_handler + instance_name = cached_json["instanceName"] + + ListCustomCommands() + + var/list/revisionData = cached_json["revision"] + if(revisionData) + cached_revision = new + cached_revision.commit = revisionData["commitSha"] + cached_revision.origin_commit = revisionData["originCommitSha"] + + cached_test_merges = list() + var/list/json = cached_json["testMerges"] + for(var/entry in json) + var/datum/tgs_revision_information/test_merge/tm = new + tm.time_merged = text2num(entry["timeMerged"]) + + var/list/revInfo = entry["revision"] + if(revInfo) + tm.commit = revInfo["commitSha"] + tm.origin_commit = revInfo["originCommitSha"] + + tm.title = entry["titleAtMerge"] + tm.body = entry["bodyAtMerge"] + tm.url = entry["url"] + tm.author = entry["author"] + tm.number = entry["number"] + tm.pull_request_commit = entry["pullRequestRevision"] + tm.comment = entry["comment"] + + cached_test_merges += tm + + return TRUE + +/datum/tgs_api/v4/OnInitializationComplete() + Export(TGS4_COMM_SERVER_PRIMED) + + var/tgs4_secret_sleep_offline_sauce = 24051994 + var/old_sleep_offline = world.sleep_offline + world.sleep_offline = tgs4_secret_sleep_offline_sauce + sleep(1) + if(world.sleep_offline == tgs4_secret_sleep_offline_sauce) //if not someone changed it + world.sleep_offline = old_sleep_offline + +/datum/tgs_api/v4/OnTopic(T) + var/list/params = params2list(T) + var/their_sCK = params[TGS4_INTEROP_ACCESS_IDENTIFIER] + if(!their_sCK) + return FALSE //continue world/Topic + + if(their_sCK != access_identifier) + return "Invalid comms key!"; + + var/command = params[TGS4_PARAMETER_COMMAND] + if(!command) + return "No command!" + + . = TGS4_RESPONSE_SUCCESS + + switch(command) + if(TGS4_TOPIC_CHAT_COMMAND) + var/result = HandleCustomCommand(params[TGS4_PARAMETER_DATA]) + if(result == null) + result = "Error running chat command!" + return result + if(TGS4_TOPIC_EVENT) + intercepted_message_queue = list() + var/list/event_notification = json_decode(params[TGS4_PARAMETER_DATA]) + var/list/event_parameters = event_notification["Parameters"] + + var/list/event_call = list(event_notification["Type"]) + if(event_parameters) + event_call += event_parameters + + if(event_handler != null) + event_handler.HandleEvent(arglist(event_call)) + + . = json_encode(intercepted_message_queue) + intercepted_message_queue = null + return + if(TGS4_TOPIC_INTEROP_RESPONSE) + last_interop_response = json_decode(params[TGS4_PARAMETER_DATA]) + return + if(TGS4_TOPIC_CHANGE_PORT) + var/new_port = text2num(params[TGS4_PARAMETER_DATA]) + if (!(new_port > 0)) + return "Invalid port: [new_port]" + + //the topic still completes, miraculously + //I honestly didn't believe byond could do it + if(event_handler != null) + event_handler.HandleEvent(TGS_EVENT_PORT_SWAP, new_port) + if(!world.OpenPort(new_port)) + return "Port change failed!" + return + if(TGS4_TOPIC_CHANGE_REBOOT_MODE) + var/new_reboot_mode = text2num(params[TGS4_PARAMETER_DATA]) + if(event_handler != null) + event_handler.HandleEvent(TGS_EVENT_REBOOT_MODE_CHANGE, reboot_mode, new_reboot_mode) + reboot_mode = new_reboot_mode + return + + return "Unknown command: [command]" + +/datum/tgs_api/v4/proc/Export(command, list/data, override_requesting_new_port = FALSE) + if(!data) + data = list() + data[TGS4_PARAMETER_COMMAND] = command + var/json = json_encode(data) + + while(requesting_new_port && !override_requesting_new_port) + sleep(1) + + //we need some port open at this point to facilitate return communication + if(!world.port) + requesting_new_port = TRUE + if(!world.OpenPort(0)) //open any port + TGS_ERROR_LOG("Unable to open random port to retrieve new port![TGS4_PORT_CRITFAIL_MESSAGE]") + del(world) + + //request a new port + export_lock = FALSE + var/list/new_port_json = Export(TGS4_COMM_NEW_PORT, list(TGS4_PARAMETER_DATA = "[world.port]"), TRUE) //stringify this on purpose + + if(!new_port_json) + TGS_ERROR_LOG("No new port response from server![TGS4_PORT_CRITFAIL_MESSAGE]") + del(world) + + var/new_port = new_port_json[TGS4_PARAMETER_DATA] + if(!isnum(new_port) || new_port <= 0) + TGS_ERROR_LOG("Malformed new port json ([json_encode(new_port_json)])![TGS4_PORT_CRITFAIL_MESSAGE]") + del(world) + + if(new_port != world.port && !world.OpenPort(new_port)) + TGS_ERROR_LOG("Unable to open port [new_port]![TGS4_PORT_CRITFAIL_MESSAGE]") + del(world) + requesting_new_port = FALSE + + while(export_lock) + sleep(1) + export_lock = TRUE + + last_interop_response = null + fdel(server_commands_json_path) + text2file(json, server_commands_json_path) + + for(var/I = 0; I < EXPORT_TIMEOUT_DS && !last_interop_response; ++I) + sleep(1) + + if(!last_interop_response) + TGS_ERROR_LOG("Failed to get export result for: [json]") + else + . = last_interop_response + + export_lock = FALSE + +/datum/tgs_api/v4/OnReboot() + var/list/result = Export(TGS4_COMM_WORLD_REBOOT) + if(!result) + return + + //okay so the standard TGS4 proceedure is: right before rebooting change the port to whatever was sent to us in the above json's data parameter + + var/port = result[TGS4_PARAMETER_DATA] + if(!isnum(port)) + return //this is valid, server may just want use to reboot + + if(port == 0) + //to byond 0 means any port and "none" means close vOv + port = "none" + + if(!world.OpenPort(port)) + TGS_ERROR_LOG("Unable to set port to [port]!") + +/datum/tgs_api/v4/InstanceName() + return instance_name + +/datum/tgs_api/v4/TestMerges() + return cached_test_merges + +/datum/tgs_api/v4/EndProcess() + Export(TGS4_COMM_END_PROCESS) + +/datum/tgs_api/v4/Revision() + return cached_revision + +/datum/tgs_api/v4/ChatBroadcast(message, list/channels) + var/list/ids + if(length(channels)) + ids = list() + for(var/I in channels) + var/datum/tgs_chat_channel/channel = I + ids += channel.id + message = list("message" = message, "channelIds" = ids) + if(intercepted_message_queue) + intercepted_message_queue += list(message) + else + Export(TGS4_COMM_CHAT, message) + +/datum/tgs_api/v4/ChatTargetedBroadcast(message, admin_only) + var/list/channels = list() + for(var/I in ChatChannelInfo()) + var/datum/tgs_chat_channel/channel = I + if (!channel.is_private_channel && ((channel.is_admin_channel && admin_only) || (!channel.is_admin_channel && !admin_only))) + channels += channel.id + message = list("message" = message, "channelIds" = channels) + if(intercepted_message_queue) + intercepted_message_queue += list(message) + else + Export(TGS4_COMM_CHAT, message) + +/datum/tgs_api/v4/ChatPrivateMessage(message, datum/tgs_chat_user/user) + message = list("message" = message, "channelIds" = list(user.channel.id)) + if(intercepted_message_queue) + intercepted_message_queue += list(message) + else + Export(TGS4_COMM_CHAT, message) + +/datum/tgs_api/v4/ChatChannelInfo() + . = list() + //no caching cause tgs may change this + var/list/json = json_decode(file2text(chat_channels_json_path)) + for(var/I in json) + . += DecodeChannel(I) + +/datum/tgs_api/v4/proc/DecodeChannel(channel_json) + var/datum/tgs_chat_channel/channel = new + channel.id = channel_json["id"] + channel.friendly_name = channel_json["friendlyName"] + channel.connection_name = channel_json["connectionName"] + channel.is_admin_channel = channel_json["isAdminChannel"] + channel.is_private_channel = channel_json["isPrivateChannel"] + channel.custom_tag = channel_json["tag"] + return channel + +/datum/tgs_api/v4/SecurityLevel() + return security_level + +/* +The MIT License + +Copyright (c) 2017 Jordan Brown + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ diff --git a/code/modules/tgs/v4/commands.dm b/code/modules/tgs/v4/commands.dm new file mode 100644 index 0000000000..af21a86fb6 --- /dev/null +++ b/code/modules/tgs/v4/commands.dm @@ -0,0 +1,69 @@ +/datum/tgs_api/v4/proc/ListCustomCommands() + var/results = list() + custom_commands = list() + for(var/I in typesof(/datum/tgs_chat_command) - /datum/tgs_chat_command) + var/datum/tgs_chat_command/stc = new I + var/command_name = stc.name + if(!command_name || findtext(command_name, " ") || findtext(command_name, "'") || findtext(command_name, "\"")) + TGS_ERROR_LOG("Custom command [command_name] ([I]) can't be used as it is empty or contains illegal characters!") + continue + + if(results[command_name]) + var/datum/other = custom_commands[command_name] + TGS_ERROR_LOG("Custom commands [other.type] and [I] have the same name (\"[command_name]\"), only [other.type] will be available!") + continue + results += list(list("name" = command_name, "help_text" = stc.help_text, "admin_only" = stc.admin_only)) + custom_commands[command_name] = stc + + var/commands_file = chat_commands_json_path + if(!commands_file) + return + text2file(json_encode(results), commands_file) + +/datum/tgs_api/v4/proc/HandleCustomCommand(command_json) + var/list/data = json_decode(command_json) + var/command = data["command"] + var/user = data["user"] + var/params = data["params"] + + var/datum/tgs_chat_user/u = new + u.id = user["id"] + u.friendly_name = user["friendlyName"] + u.mention = user["mention"] + u.channel = DecodeChannel(user["channel"]) + + var/datum/tgs_chat_command/sc = custom_commands[command] + if(sc) + var/result = sc.Run(u, params) + if(result == null) + result = "" + return result + return "Unknown command: [command]!" + +/* + +The MIT License + +Copyright (c) 2017 Jordan Brown + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ diff --git a/code/modules/tgui/states.dm b/code/modules/tgui/states.dm index fc30d171fb..959f096d05 100644 --- a/code/modules/tgui/states.dm +++ b/code/modules/tgui/states.dm @@ -103,7 +103,7 @@ return UI_CLOSE var/dist = get_dist(src_object, src) - if(dist <= 1) // Open and interact if 1-0 tiles away. + if(dist <= 1 || src_object.hasSiliconAccessInArea(src)) // Open and interact if 1-0 tiles away. return UI_INTERACTIVE else if(dist <= 2) // View only if 2-3 tiles away. return UI_UPDATE diff --git a/code/modules/uplink/uplink_devices.dm b/code/modules/uplink/uplink_devices.dm index 2bcfb40c45..9c09a7334a 100644 --- a/code/modules/uplink/uplink_devices.dm +++ b/code/modules/uplink/uplink_devices.dm @@ -57,3 +57,22 @@ /obj/item/pen/uplink/Initialize(mapload, owner, tc_amount = 20) . = ..() AddComponent(/datum/component/uplink, owner, TRUE, FALSE, null, tc_amount) + +/obj/item/uplink/debug + name = "debug uplink" + +/obj/item/uplink/debug/Initialize(mapload, owner, tc_amount = 9000) + . = ..() + var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink) + hidden_uplink.name = "debug uplink" + hidden_uplink.debug = TRUE + +/obj/item/uplink/nuclear/debug + name = "debug nuclear uplink" + +/obj/item/uplink/nuclear/debug/Initialize(mapload, owner, tc_amount = 9000) + . = ..() + var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink) + hidden_uplink.set_gamemode(/datum/game_mode/nuclear) + hidden_uplink.name = "debug nuclear uplink" + hidden_uplink.debug = TRUE diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index b75f212ba9..52f6efd3df 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -157,6 +157,7 @@ category = "Role-Restricted" exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) surplus = 0 + cant_discount = TRUE /datum/uplink_item/badass category = "(Pointless) Badassery" @@ -164,4 +165,4 @@ //Discounts (dynamically filled above) /datum/uplink_item/discounts - category = "Discounted Gear" \ No newline at end of file + category = "Discounted Gear" diff --git a/code/modules/uplink/uplink_items/uplink_implants.dm b/code/modules/uplink/uplink_items/uplink_implants.dm index d8a31a9b9c..02b8b1e01d 100644 --- a/code/modules/uplink/uplink_items/uplink_implants.dm +++ b/code/modules/uplink/uplink_items/uplink_implants.dm @@ -29,6 +29,22 @@ item = /obj/item/storage/box/syndie_kit/imp_freedom cost = 5 +/datum/uplink_item/implants/hijack + name = "Hijack Implant" + desc = "An implant that will let you hack into the APCs on station, allowing you to control them at will and the machinery within those rooms." + item = /obj/item/implanter/hijack + cost = 14 //really overkill, 14 tc, can still get caught in a room you haven't hijacked and you're fucked. + surplus = 0 //nope not having hijack implants with surplus crates nope nope nope nope + restricted = TRUE + +/datum/uplink_item/implants/radio + name = "Internal Syndicate Radio Implant" + desc = "An implant injected into the body, allowing the use of an internal Syndicate radio. \ + Used just like a regular headset, but can be disabled to use external headsets normally and to avoid detection." + item = /obj/item/storage/box/syndie_kit/imp_radio + cost = 4 + restricted = TRUE + /datum/uplink_item/implants/microbomb name = "Microbomb Implant" desc = "An implant injected into the body, and later activated either manually or automatically upon death. \ @@ -47,14 +63,6 @@ include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) restricted = TRUE -/datum/uplink_item/implants/radio - name = "Internal Syndicate Radio Implant" - desc = "An implant injected into the body, allowing the use of an internal Syndicate radio. \ - Used just like a regular headset, but can be disabled to use external headsets normally and to avoid detection." - item = /obj/item/storage/box/syndie_kit/imp_radio - cost = 4 - restricted = TRUE - /datum/uplink_item/implants/reviver name = "Reviver Implant" desc = "This implant will attempt to revive and heal you if you lose consciousness. Comes with an autosurgeon." diff --git a/code/modules/vending/snack.dm b/code/modules/vending/snack.dm index efb0905f6b..9dda649b24 100644 --- a/code/modules/vending/snack.dm +++ b/code/modules/vending/snack.dm @@ -4,22 +4,25 @@ product_slogans = "Try our new nougat bar!;Twice the calories for half the price!" product_ads = "The healthiest!;Award-winning chocolate bars!;Mmm! So good!;Oh my god it's so juicy!;Have a snack.;Snacks are good for you!;Have some more Getmore!;Best quality snacks straight from mars.;We love chocolate!;Try our new jerky!" icon_state = "snack" - products = list(/obj/item/reagent_containers/food/snacks/candy = 6, - /obj/item/reagent_containers/food/drinks/dry_ramen = 6, - /obj/item/reagent_containers/food/snacks/chips = 6, - /obj/item/reagent_containers/food/snacks/sosjerky = 6, - /obj/item/reagent_containers/food/snacks/no_raisin = 6, - /obj/item/reagent_containers/food/snacks/spacetwinkie = 6, - /obj/item/reagent_containers/food/snacks/cheesiehonkers = 6) + products = list(/obj/item/reagent_containers/food/snacks/candy = 5, + /obj/item/reagent_containers/food/snacks/chocolatebar = 5, + /obj/item/reagent_containers/food/drinks/dry_ramen = 5, + /obj/item/reagent_containers/food/snacks/chips = 5, + /obj/item/reagent_containers/food/snacks/sosjerky = 5, + /obj/item/reagent_containers/food/snacks/no_raisin = 5, + /obj/item/reagent_containers/food/snacks/spacetwinkie = 5, + /obj/item/reagent_containers/food/snacks/cheesiehonkers = 5, + /obj/item/reagent_containers/food/snacks/cornchips = 5) contraband = list( - /obj/item/reagent_containers/food/snacks/cracker = 12, - /obj/item/reagent_containers/food/snacks/beans = 2, - /obj/item/reagent_containers/food/snacks/honeybar = 6, - /obj/item/reagent_containers/food/snacks/syndicake = 6) + /obj/item/reagent_containers/food/snacks/cracker = 10, + /obj/item/reagent_containers/food/snacks/honeybar = 5, + /obj/item/reagent_containers/food/snacks/syndicake = 5, + /obj/item/reagent_containers/food/snacks/beans = 2) premium = list( /obj/item/reagent_containers/food/snacks/lollipop = 2, /obj/item/reagent_containers/food/snacks/spiderlollipop = 2, /obj/item/reagent_containers/food/snacks/chococoin = 1, + /obj/item/storage/box/marshmallow = 1, /obj/item/storage/box/donkpockets = 2) refill_canister = /obj/item/vending_refill/snack diff --git a/code/modules/vending/wardrobes.dm b/code/modules/vending/wardrobes.dm index 0a3ded63bd..5d2e08734e 100644 --- a/code/modules/vending/wardrobes.dm +++ b/code/modules/vending/wardrobes.dm @@ -399,3 +399,35 @@ /obj/item/vending_refill/wardrobe/viro_wardrobe machine_name = "ViroDrobe" + +/obj/machinery/vending/wardrobe/cap_wardrobe + name = "Captain's Wardrobe" + desc = "The latest and greatest in Nanotrasen fashion for your great leader." + icon_state = "capsdrobe" + icon_deny = "capsdrobe-deny" + product_ads = "Only the greatest for a commander such as ours." + req_access = list(ACCESS_CAPTAIN) + vend_reply = "A wonderful day to you, great leader." + products = list(/obj/item/clothing/suit/hooded/wintercoat/captain = 1, + /obj/item/storage/backpack/captain = 1, + /obj/item/storage/backpack/satchel/cap = 1, + /obj/item/storage/backpack/duffelbag/captain = 1, + /obj/item/clothing/neck/cloak/cap = 1, + /obj/item/clothing/shoes/sneakers/brown = 2, + /obj/item/clothing/under/rank/captain = 1, + /obj/item/clothing/under/rank/captain/skirt = 1, + /obj/item/clothing/head/caphat = 1, + /obj/item/clothing/head/caphat/parade = 1, + /obj/item/clothing/head/caphat/beret = 1, + /obj/item/clothing/head/caphat/beret/white = 1, + /obj/item/clothing/under/captainparade = 1, + /obj/item/clothing/suit/captunic = 1, + /obj/item/clothing/under/rank/captain/femformal = 1, + /obj/item/clothing/glasses/sunglasses/gar/supergar = 1, + /obj/item/clothing/gloves/color/captain = 1) + refill_canister = /obj/item/vending_refill/wardrobe/cap_wardrobe + +/obj/item/vending_refill/wardrobe/cap_wardrobe + machine_name = "Captain's Wardrobe" + icon_state = "refill_caps" + \ No newline at end of file diff --git a/code/modules/vore/eating/belly_obj.dm b/code/modules/vore/eating/belly_obj.dm index 460ea74225..e33f748292 100644 --- a/code/modules/vore/eating/belly_obj.dm +++ b/code/modules/vore/eating/belly_obj.dm @@ -190,7 +190,7 @@ if(H && H.client && (isturf(H.loc) || (H.loc != src.contents))) var/sound/eating = GLOB.pred_vore_sounds[vore_sound] SEND_SOUND(H,eating) - else if(H && H in contents && H.client) + else if(H?.client && (H in contents)) var/sound/eating = GLOB.prey_vore_sounds[vore_sound] SEND_SOUND(H,eating) recent_sound = TRUE @@ -246,7 +246,7 @@ if(H && H.client && (isturf(H.loc) || (H.loc != src.contents))) var/sound/releasement = GLOB.pred_release_sounds[release_sound] H.playsound_local(owner.loc, releasement, vol = 75, vary = 1, falloff = VORE_SOUND_FALLOFF) - else if(H && H in contents && H.client) + else if(H?.client && (H in contents)) var/sound/releasement = GLOB.prey_release_sounds[release_sound] SEND_SOUND(H,releasement) recent_sound = TRUE @@ -302,7 +302,7 @@ if(H && H.client && (isturf(H.loc) || (H.loc != src.contents))) var/sound/releasement = GLOB.pred_release_sounds[release_sound] H.playsound_local(owner.loc, releasement, vol = 75, vary = 1, falloff = VORE_SOUND_FALLOFF) - else if(H && H in contents && H.client) + else if(H?.client && (H in contents)) var/sound/releasement = GLOB.prey_release_sounds[release_sound] SEND_SOUND(H,releasement) recent_sound = TRUE @@ -364,7 +364,7 @@ if(H && H.client && (isturf(H.loc) || (H.loc != src.contents))) var/sound/eating = GLOB.pred_vore_sounds[vore_sound] H.playsound_local(owner.loc, eating, vol = 75, vary = 1, falloff = VORE_SOUND_FALLOFF) - else if(H && H in contents && H.client) + else if(H?.client && (H in contents)) var/sound/eating = GLOB.prey_vore_sounds[vore_sound] SEND_SOUND(H,eating) recent_sound = TRUE @@ -586,7 +586,7 @@ for(var/mob/living/H in hearing_mobs) if(H && H.client && (isturf(H.loc) || (H.loc != src.contents))) H.playsound_local(owner.loc, pred_struggle_snuggle, vol = 75, vary = 1, falloff = VORE_SOUND_FALLOFF) - else if(H && H in contents && H.client) + else if(H && H.client && (H in contents)) SEND_SOUND(H,prey_struggle_snuggle) else diff --git a/code/modules/vore/eating/bellymodes.dm b/code/modules/vore/eating/bellymodes.dm index 6942a2d5a9..ea15892a30 100644 --- a/code/modules/vore/eating/bellymodes.dm +++ b/code/modules/vore/eating/bellymodes.dm @@ -195,7 +195,7 @@ for(var/mob/living/H in hearing_mobs) if(H && H.client && (isturf(H.loc) || (H.loc != src.contents))) SEND_SOUND(H,pred_digest) - else if(H && H in contents && H.client) + else if(H?.client && (H in contents)) SEND_SOUND(H,prey_digest) //No digestion protection for megafauna. diff --git a/code/modules/zombie/organs.dm b/code/modules/zombie/organs.dm index 59c6a321e6..3d045ba31e 100644 --- a/code/modules/zombie/organs.dm +++ b/code/modules/zombie/organs.dm @@ -45,7 +45,9 @@ if(!owner) return if(!(src in owner.internal_organs)) - Remove() + Remove(owner) + if(owner.mob_biotypes & MOB_MINERAL)//does not process in inorganic things + return if (causes_damage && !iszombie(owner) && owner.stat != DEAD) owner.adjustToxLoss(1) if (prob(10)) diff --git a/config/config.txt b/config/config.txt index 6d302a5512..0ab0cc911e 100644 --- a/config/config.txt +++ b/config/config.txt @@ -6,6 +6,7 @@ $include comms.txt $include antag_rep.txt $include donator_groupings.txt $include dynamic_config.txt +$include plushies/defines.txt # You can use the @ character at the beginning of a config option to lock it from being edited in-game # Example usage: @@ -384,6 +385,15 @@ MAPROTATION ## When it's set to zero, the map will be randomly picked each round ALLOW_MAP_VOTING 1 +## Map voting type +## Determines what kind of vote the map vote is +## Options are: +## PLURALITY (default, only vote for one option) +## APPROVAL (can vote for as many as you want), I +## IRV (vote by ranked choice, winner determined by instant runoff algorithm) +## SCORE (give individual rankings of each choice, winner determined by majority judgement algorithm) +MAP_VOTE_TYPE SCORE + ## Map rotate chance delta ## This is the chance of map rotation factored to the round length. ## A value of 1 would mean the map rotation chance is the round length in minutes (hour long round == 60% rotation chance) @@ -438,8 +448,14 @@ MINUTE_CLICK_LIMIT 400 ##How long to wait between messaging admins about occurences of a unique error #ERROR_MSG_DELAY 50 -## Send a message to IRC when starting a new game -#IRC_ANNOUNCE_NEW_GAME +## Chat Announce Options +## Various messages to be sent to game chats +## Uncommenting these will enable them, by default they will be broadcast to Game chat channels on TGS3 or non-admin channels on TGS4 +## If using TGS4, the string option can be set as a chat channel tag to limit the message to channels of that tag type (case-sensitive) +## i.e. CHAT_ANNOUNCE_NEW_GAME chat_channel_tag + +## Send a message with the station name starting a new game +#CHAT_ANNOUNCE_NEW_GAME ## Allow admin hrefs that don't use the new token system, will eventually be removed DEBUG_ADMIN_HREFS @@ -490,3 +506,5 @@ FAIL2TOPIC_MAX_FAILS 5 ## Firewall rule name used on physical server FAIL2TOPIC_RULE_NAME _dd_fail2topic +## Enable automatic profiling - Byond 513.1506 and newer only. +#AUTO_PROFILE diff --git a/config/game_options.txt b/config/game_options.txt index 0fa4db519d..b2b0ac0abd 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -426,6 +426,7 @@ ROUNDSTART_RACES lizard ROUNDSTART_RACES plasmaman #ROUNDSTART_RACES shadow ROUNDSTART_RACES felinid +ROUNDSTART_RACES dwarf ## Races that are better than humans in some ways, but worse in others #ROUNDSTART_RACES jelly diff --git a/code/modules/games/cards.dm b/config/plushies/defines.txt similarity index 100% rename from code/modules/games/cards.dm rename to config/plushies/defines.txt diff --git a/config/plushies/plushie_config.txt b/config/plushies/plushie_config.txt new file mode 100644 index 0000000000..7cd1d88f3e --- /dev/null +++ b/config/plushies/plushie_config.txt @@ -0,0 +1,2 @@ +# EXAMPLE +# SNOWFLAKE_PLUSHIES example {"name":"example","desc":"thanks, coders.","icon_state":"","attack_verb":["thumped","whomped","bumped"],"squeak_override":{"sound/weapons/magout.ogg":1}} diff --git a/config/plushies/sprites.dmi b/config/plushies/sprites.dmi new file mode 100644 index 0000000000..2970010b2b Binary files /dev/null and b/config/plushies/sprites.dmi differ diff --git a/dependencies.sh b/dependencies.sh index 0f66dcab1a..488504b288 100644 --- a/dependencies.sh +++ b/dependencies.sh @@ -17,10 +17,10 @@ export RUST_G_VERSION=0.4.2 export BSQL_VERSION=v1.4.0.0 #node version -export NODE_VERSION=8 +export NODE_VERSION=12 # PHP version export PHP_VERSION=5.6 # SpacemanDMM git tag -export SPACEMAN_DMM_VERSION=suite-1.0 +export SPACEMAN_DMM_VERSION=suite-1.2 diff --git a/html/changelogs/AutoChangeLog-pr-10277.yml b/html/changelogs/AutoChangeLog-pr-10277.yml new file mode 100644 index 0000000000..d2c873d010 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10277.yml @@ -0,0 +1,4 @@ +author: "kevinz000" +delete-after: True +changes: + - refactor: "Custom snowflake plushies are now in config rather than code." diff --git a/html/changelogs/AutoChangeLog-pr-10596.yml b/html/changelogs/AutoChangeLog-pr-10596.yml new file mode 100644 index 0000000000..7f56a256a0 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10596.yml @@ -0,0 +1,5 @@ +author: "Seris02" +delete-after: True +changes: + - rscadd: "hijack implant" + - code_imp: "changed mentions of the issilion proc to hasSiliconAccessInArea based on what the proc is used for" diff --git a/html/changelogs/AutoChangeLog-pr-10704.yml b/html/changelogs/AutoChangeLog-pr-10704.yml new file mode 100644 index 0000000000..1acd46b51f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10704.yml @@ -0,0 +1,4 @@ +author: "nemvar" +delete-after: True +changes: + - code_imp: "Slight changes the self-repair borg module. It no longer references the borg that owns it." diff --git a/html/changelogs/AutoChangeLog-pr-10792.yml b/html/changelogs/AutoChangeLog-pr-10792.yml new file mode 100644 index 0000000000..78c86a838a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10792.yml @@ -0,0 +1,4 @@ +author: "Naksu" +delete-after: True +changes: + - bugfix: "Odysseus chem synthesizing now works again." diff --git a/html/changelogs/AutoChangeLog-pr-10857.yml b/html/changelogs/AutoChangeLog-pr-10857.yml new file mode 100644 index 0000000000..ae8c5f6ac0 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10857.yml @@ -0,0 +1,4 @@ +author: "Seris02" +delete-after: True +changes: + - rscadd: "Added naked hallucination" diff --git a/html/changelogs/AutoChangeLog-pr-10861.yml b/html/changelogs/AutoChangeLog-pr-10861.yml new file mode 100644 index 0000000000..5071cc30f9 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10861.yml @@ -0,0 +1,4 @@ +author: "ancientpower" +delete-after: True +changes: + - rscadd: "Ported drink sliding from /vg/station." diff --git a/html/changelogs/AutoChangeLog-pr-10913.yml b/html/changelogs/AutoChangeLog-pr-10913.yml new file mode 100644 index 0000000000..8bf549a154 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10913.yml @@ -0,0 +1,4 @@ +author: "Feasel" +delete-after: True +changes: + - balance: "Buffed dissection success chances." diff --git a/html/changelogs/AutoChangeLog-pr-10916.yml b/html/changelogs/AutoChangeLog-pr-10916.yml new file mode 100644 index 0000000000..05d9b007b1 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10916.yml @@ -0,0 +1,4 @@ +author: "kevinz000" +delete-after: True +changes: + - balance: "Projectiles now always hit chest if targeting chest, snipers have 100% targeting zone accuracy. All other cases are unchanged." diff --git a/html/changelogs/AutoChangeLog-pr-10918.yml b/html/changelogs/AutoChangeLog-pr-10918.yml new file mode 100644 index 0000000000..bf47d0accf --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10918.yml @@ -0,0 +1,4 @@ +author: "r4d6" +delete-after: True +changes: + - config: "Made dwarves into a roundstart races" diff --git a/html/changelogs/AutoChangeLog-pr-10923.yml b/html/changelogs/AutoChangeLog-pr-10923.yml new file mode 100644 index 0000000000..0fd9a0f14e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10923.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Nerfed cargo passive points generation from 500 to 125 creds per minute." diff --git a/html/changelogs/AutoChangeLog-pr-10926.yml b/html/changelogs/AutoChangeLog-pr-10926.yml new file mode 100644 index 0000000000..9662402d1b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10926.yml @@ -0,0 +1,9 @@ +author: "keronshb" +delete-after: True +changes: + - rscadd: "Added repairable turrets" + - rscadd: "Adds Tiny Fans to the pirate ship" + - tweak: "changes some reinforced windows to plastinanium pirate windows" + - tweak: "made the pirate shuttle + turrets bomb resistant" + - tweak: "made most pirate machines + consoles indestructible" + - tweak: "increased pirate turret health" diff --git a/html/changelogs/AutoChangeLog-pr-10930.yml b/html/changelogs/AutoChangeLog-pr-10930.yml new file mode 100644 index 0000000000..4121a00b9b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10930.yml @@ -0,0 +1,4 @@ +author: "r4d6" +delete-after: True +changes: + - tweak: "Meteor Timer back to 3-5 minutes" diff --git a/html/changelogs/AutoChangeLog-pr-10934.yml b/html/changelogs/AutoChangeLog-pr-10934.yml new file mode 100644 index 0000000000..61ef7ec04f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10934.yml @@ -0,0 +1,4 @@ +author: "kevinz000" +delete-after: True +changes: + - refactor: "Refactored ghostreading/etc" diff --git a/html/changelogs/AutoChangeLog-pr-10936.yml b/html/changelogs/AutoChangeLog-pr-10936.yml new file mode 100644 index 0000000000..2303f157ab --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10936.yml @@ -0,0 +1,4 @@ +author: "kevinz000" +delete-after: True +changes: + - balance: "Cyborgization will now de-gang people, even gangheads." diff --git a/html/changelogs/AutoChangeLog-pr-10937.yml b/html/changelogs/AutoChangeLog-pr-10937.yml new file mode 100644 index 0000000000..1c56882ccc --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10937.yml @@ -0,0 +1,4 @@ +author: "Arturlang" +delete-after: True +changes: + - admin: "The debug outfit is now kitted out for whatever debbuging needs." diff --git a/html/changelogs/AutoChangeLog-pr-10940.yml b/html/changelogs/AutoChangeLog-pr-10940.yml new file mode 100644 index 0000000000..c0bbfc371a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10940.yml @@ -0,0 +1,5 @@ +author: "Ghommie" +delete-after: True +changes: + - balance: "Some reagent holders (such as cigarettes, food) are not suitable for reagents export anymore, while unprocessed botany crops will only net 1/3 of the standard reagents values." + - bugfix: "Export scanners now include the reagents value in the price report." diff --git a/html/changelogs/AutoChangeLog-pr-10942.yml b/html/changelogs/AutoChangeLog-pr-10942.yml new file mode 100644 index 0000000000..2a30ace3aa --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10942.yml @@ -0,0 +1,4 @@ +author: "Putnam3145" +delete-after: True +changes: + - rscadd: "map voting doesn't suck anymore" diff --git a/html/changelogs/AutoChangeLog-pr-10943.yml b/html/changelogs/AutoChangeLog-pr-10943.yml new file mode 100644 index 0000000000..f45d8b1d39 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10943.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixed a little inconvenience with the character setup preview dummy having extra unwarranted bits." diff --git a/html/changelogs/AutoChangeLog-pr-10947.yml b/html/changelogs/AutoChangeLog-pr-10947.yml new file mode 100644 index 0000000000..a6f1fb1344 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10947.yml @@ -0,0 +1,4 @@ +author: "nemvar" +delete-after: True +changes: + - bugfix: "Trash from food now gets generated at the location of the food item, instead of in the hands of the eater." diff --git a/html/changelogs/AutoChangeLog-pr-10948.yml b/html/changelogs/AutoChangeLog-pr-10948.yml new file mode 100644 index 0000000000..f9da9463fc --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10948.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Stopped role restricted uplink items from being discounted despite not being purchasable most times." diff --git a/html/changelogs/AutoChangeLog-pr-10949.yml b/html/changelogs/AutoChangeLog-pr-10949.yml new file mode 100644 index 0000000000..3c7000a0e1 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10949.yml @@ -0,0 +1,4 @@ +author: "kevinz000" +delete-after: True +changes: + - bugfix: "reactive repulse armor now has an item limit" diff --git a/html/changelogs/AutoChangeLog-pr-10955.yml b/html/changelogs/AutoChangeLog-pr-10955.yml new file mode 100644 index 0000000000..46ff62efaf --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10955.yml @@ -0,0 +1,4 @@ +author: "kevinz000" +delete-after: True +changes: + - rscadd: "gravity gun repulse and chaos now work in all angles, rather than just basic cardinals and diagonals. fun." diff --git a/html/changelogs/AutoChangeLog-pr-10961.yml b/html/changelogs/AutoChangeLog-pr-10961.yml new file mode 100644 index 0000000000..eaaafab472 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10961.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixed an issue with the nearsighted prescription glasses taking over worn eyewear." diff --git a/html/changelogs/AutoChangeLog-pr-10967.yml b/html/changelogs/AutoChangeLog-pr-10967.yml new file mode 100644 index 0000000000..f242dd57bc --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10967.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixed AI unanchoring not properly removing the no teleport trait. My bad." diff --git a/html/changelogs/AutoChangeLog-pr-10969.yml b/html/changelogs/AutoChangeLog-pr-10969.yml new file mode 100644 index 0000000000..fdd53cdd2f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10969.yml @@ -0,0 +1,4 @@ +author: "Seris02" +delete-after: True +changes: + - rscadd: "crowbarring manifests off crates" diff --git a/html/changelogs/AutoChangeLog-pr-10970.yml b/html/changelogs/AutoChangeLog-pr-10970.yml new file mode 100644 index 0000000000..7182c5f6a6 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10970.yml @@ -0,0 +1,4 @@ +author: "kevinz000" +delete-after: True +changes: + - balance: "Public autolathes can no longer be hacked." diff --git a/html/changelogs/AutoChangeLog-pr-10971.yml b/html/changelogs/AutoChangeLog-pr-10971.yml new file mode 100644 index 0000000000..e7882646f8 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10971.yml @@ -0,0 +1,4 @@ +author: "Trilbyspaceclone" +delete-after: True +changes: + - rscadd: "Alien stools and chairs" diff --git a/html/changelogs/AutoChangeLog-pr-10972.yml b/html/changelogs/AutoChangeLog-pr-10972.yml new file mode 100644 index 0000000000..9cc2e64687 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10972.yml @@ -0,0 +1,4 @@ +author: "Trilbyspaceclone" +delete-after: True +changes: + - tweak: "Bone armor/Dagger are now crafting from bones rather then crafting menu" diff --git a/html/changelogs/AutoChangeLog-pr-10973.yml b/html/changelogs/AutoChangeLog-pr-10973.yml new file mode 100644 index 0000000000..8946cddb43 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10973.yml @@ -0,0 +1,4 @@ +author: "Trilbyspaceclone" +delete-after: True +changes: + - rscadd: "Firing pins that only works when not on station" diff --git a/html/changelogs/AutoChangeLog-pr-10976.yml b/html/changelogs/AutoChangeLog-pr-10976.yml new file mode 100644 index 0000000000..34ef082829 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10976.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixed another issue with hering comsig." diff --git a/html/changelogs/AutoChangeLog-pr-10981.yml b/html/changelogs/AutoChangeLog-pr-10981.yml new file mode 100644 index 0000000000..df0d7990cb --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10981.yml @@ -0,0 +1,4 @@ +author: "IHOPMommyLich" +delete-after: True +changes: + - tweak: "Changed the multiplicative_slowdown of Stimulants from -1 to -0.5" diff --git a/html/changelogs/AutoChangeLog-pr-10984.yml b/html/changelogs/AutoChangeLog-pr-10984.yml new file mode 100644 index 0000000000..137536b430 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10984.yml @@ -0,0 +1,4 @@ +author: "Trilbyspaceclone" +delete-after: True +changes: + - balance: "Heads of staff have been better screened by NT before being promoted" diff --git a/html/changelogs/AutoChangeLog-pr-10987.yml b/html/changelogs/AutoChangeLog-pr-10987.yml new file mode 100644 index 0000000000..abea439a86 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10987.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - imageadd: "Fixed dozen missing privates sprites." diff --git a/html/changelogs/AutoChangeLog-pr-10988.yml b/html/changelogs/AutoChangeLog-pr-10988.yml new file mode 100644 index 0000000000..ebd9de7689 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10988.yml @@ -0,0 +1,4 @@ +author: "YakumoChen" +delete-after: True +changes: + - tweak: "Observe is back in the OOC tab" diff --git a/html/changelogs/AutoChangeLog-pr-10989.yml b/html/changelogs/AutoChangeLog-pr-10989.yml new file mode 100644 index 0000000000..0a5b2ad3c8 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10989.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "A little fix concerning some R&D and reagents." diff --git a/html/changelogs/AutoChangeLog-pr-10992.yml b/html/changelogs/AutoChangeLog-pr-10992.yml new file mode 100644 index 0000000000..1d6d10396b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10992.yml @@ -0,0 +1,4 @@ +author: "Hatterhat" +delete-after: True +changes: + - balance: "Buckshot individual pellet damage up from 10 to 12.5. Still firing 6 pellets." diff --git a/html/changelogs/AutoChangeLog-pr-10994.yml b/html/changelogs/AutoChangeLog-pr-10994.yml new file mode 100644 index 0000000000..c27a1afc00 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10994.yml @@ -0,0 +1,4 @@ +author: "DeltaFire15" +delete-after: True +changes: + - balance: "Nar'Sie runes no longer benefit from runed floors." diff --git a/html/changelogs/AutoChangeLog-pr-10996.yml b/html/changelogs/AutoChangeLog-pr-10996.yml new file mode 100644 index 0000000000..8bb7646cd6 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10996.yml @@ -0,0 +1,6 @@ +author: "PersianXerxes" +delete-after: True +changes: + - rscadd: "SMES and PACMAN attached to gulag Security to power electrified windows +remove: Removed Sec vendor from gulag Security" + - tweak: "Separation of gulag and public mining" diff --git a/html/changelogs/AutoChangeLog-pr-10997.yml b/html/changelogs/AutoChangeLog-pr-10997.yml new file mode 100644 index 0000000000..a380a04f68 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10997.yml @@ -0,0 +1,12 @@ +author: "Owai-Seek" +delete-after: True +changes: + - rscadd: "Bacon and Eggs food item. Delicious! Added a Lemony Poppy Seed Muffin." + - tweak: "Snack Vendor has Chocolates, Tortilla Chips, and a Marshmallow Box" + - balance: "Mops can now be printed at service lathe once tools are researched." + - balance: "Biobags can hold most organic limbs/organs, but not brains, implants, or cybernetics." + - balance: "Trash Bag can now hold limbs (but not heads.)" + - balance: "Most snack vendor items reduced by 1." + - bugfix: "Trash Cans are now actually craftable, and only require metal instead of plastic." + - imageadd: "Bacon and Eggs, Drying Agent Bottle." + - imageadd: "Mugs now show reagent colors of contained reagents. Thanks Seris!" diff --git a/html/changelogs/AutoChangeLog-pr-11000.yml b/html/changelogs/AutoChangeLog-pr-11000.yml new file mode 100644 index 0000000000..5e496af81f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11000.yml @@ -0,0 +1,4 @@ +author: "Seris02" +delete-after: True +changes: + - balance: "makes RCDs cost a better amount" diff --git a/html/changelogs/AutoChangeLog-pr-11001.yml b/html/changelogs/AutoChangeLog-pr-11001.yml new file mode 100644 index 0000000000..1cfa8977b4 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11001.yml @@ -0,0 +1,4 @@ +author: "Arturlang" +delete-after: True +changes: + - bugfix: "Fixed the pandemic naming and the radiation healing symptom UI crashing" diff --git a/html/changelogs/AutoChangeLog-pr-11003.yml b/html/changelogs/AutoChangeLog-pr-11003.yml new file mode 100644 index 0000000000..4c551c4d09 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11003.yml @@ -0,0 +1,4 @@ +author: "kevinz000" +delete-after: True +changes: + - bugfix: "Energy weapons now once again have their lens in contents." diff --git a/html/changelogs/AutoChangeLog-pr-11005.yml b/html/changelogs/AutoChangeLog-pr-11005.yml new file mode 100644 index 0000000000..d0576c7ba8 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11005.yml @@ -0,0 +1,4 @@ +author: "Arturlang" +delete-after: True +changes: + - tweak: "Hyposprays now switch modes on CTRL click, instead of alt, as it was already reserved for dispension amount." diff --git a/html/changelogs/AutoChangeLog-pr-11011.yml b/html/changelogs/AutoChangeLog-pr-11011.yml new file mode 100644 index 0000000000..d0a7b916f7 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11011.yml @@ -0,0 +1,4 @@ +author: "Tlaltecuhtli, ported by Hatterhat" +delete-after: True +changes: + - balance: "Ripley, Firefighter, Odysseus and H.O.N.K. mechs now also use scanning modules and capacitors on construction. This means that they also gain reduced power consumption and EMP protection from higher-tier stock parts." diff --git a/html/changelogs/AutoChangeLog-pr-11012.yml b/html/changelogs/AutoChangeLog-pr-11012.yml new file mode 100644 index 0000000000..1d233f0692 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11012.yml @@ -0,0 +1,4 @@ +author: "keronshb" +delete-after: True +changes: + - rscadd: "Adds the CogChamp drink and Sprite" diff --git a/html/changelogs/AutoChangeLog-pr-11013.yml b/html/changelogs/AutoChangeLog-pr-11013.yml new file mode 100644 index 0000000000..a9806d796d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11013.yml @@ -0,0 +1,5 @@ +author: "r4d6" +delete-after: True +changes: + - rscadd: "Added Plasteel Pickaxe" + - rscadd: "Added Titanium Pickaxe" diff --git a/html/changelogs/AutoChangeLog-pr-11018.yml b/html/changelogs/AutoChangeLog-pr-11018.yml new file mode 100644 index 0000000000..2795317861 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11018.yml @@ -0,0 +1,4 @@ +author: "kevinz000" +delete-after: True +changes: + - bugfix: "pais are no longer muted for literally a whole hour on emp." diff --git a/html/changelogs/AutoChangeLog-pr-11020.yml b/html/changelogs/AutoChangeLog-pr-11020.yml new file mode 100644 index 0000000000..52677b98e9 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11020.yml @@ -0,0 +1,4 @@ +author: "Zellular" +delete-after: True +changes: + - imageadd: "Movement state for pupdozer and its decals" diff --git a/html/changelogs/AutoChangeLog-pr-11022.yml b/html/changelogs/AutoChangeLog-pr-11022.yml new file mode 100644 index 0000000000..ac317e56b0 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11022.yml @@ -0,0 +1,4 @@ +author: "kevinz000" +delete-after: True +changes: + - rscadd: "auto profiler subsystem from tg" diff --git a/html/changelogs/AutoChangeLog-pr-11024.yml b/html/changelogs/AutoChangeLog-pr-11024.yml new file mode 100644 index 0000000000..3af136f15e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11024.yml @@ -0,0 +1,4 @@ +author: "kevinz000" +delete-after: True +changes: + - bugfix: "Brig cells now are more accurate by using timeofday instead of realtime" diff --git a/html/changelogs/AutoChangeLog-pr-11026.yml b/html/changelogs/AutoChangeLog-pr-11026.yml new file mode 100644 index 0000000000..c99aad2d14 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11026.yml @@ -0,0 +1,5 @@ +author: "Trilbyspaceclone" +delete-after: True +changes: + - balance: "The suit full of spiders also known as a ninja now is a tactical turtleneck" + - balance: "The Wiznerds now dont have suits set to max" diff --git a/html/changelogs/AutoChangeLog-pr-11027.yml b/html/changelogs/AutoChangeLog-pr-11027.yml new file mode 100644 index 0000000000..4e5f5b46ba --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11027.yml @@ -0,0 +1,5 @@ +author: "ShadeAware" +delete-after: True +changes: + - rscadd: "The Captain's Wardrobe, a special one-of-a-kind and ID-locked wardrobe for the Captain that holds all of their snowflakey gear. +Remove: Snowflake gear from the Captain's locker, since now it has its own vendor." diff --git a/html/changelogs/AutoChangeLog-pr-11028.yml b/html/changelogs/AutoChangeLog-pr-11028.yml new file mode 100644 index 0000000000..de94b1d35f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11028.yml @@ -0,0 +1,4 @@ +author: "Trilbyspaceclone" +delete-after: True +changes: + - tweak: "Meat wheat no longer has blood" diff --git a/html/changelogs/AutoChangeLog-pr-11029.yml b/html/changelogs/AutoChangeLog-pr-11029.yml new file mode 100644 index 0000000000..17f34bbfa6 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11029.yml @@ -0,0 +1,4 @@ +author: "Putnam3145" +delete-after: True +changes: + - tweak: "default should be... default" diff --git a/html/changelogs/AutoChangeLog-pr-11032.yml b/html/changelogs/AutoChangeLog-pr-11032.yml new file mode 100644 index 0000000000..6d026e444a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11032.yml @@ -0,0 +1,4 @@ +author: "kevinz000" +delete-after: True +changes: + - bugfix: "Cryo now actually transfers reagents at tier 4 on enter rather than every 80 machine fire()-process()s regardless of if it was \"reset\" by open/close." diff --git a/html/changelogs/AutoChangeLog-pr-11035.yml b/html/changelogs/AutoChangeLog-pr-11035.yml new file mode 100644 index 0000000000..94a57db904 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11035.yml @@ -0,0 +1,4 @@ +author: "kevinz000" +delete-after: True +changes: + - bugfix: "ctf claymores now actually spawn (and fit)." diff --git a/html/changelogs/AutoChangeLog-pr-11038.yml b/html/changelogs/AutoChangeLog-pr-11038.yml new file mode 100644 index 0000000000..b157c31af8 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11038.yml @@ -0,0 +1,4 @@ +author: "kevinz000" +delete-after: True +changes: + - bugfix: "STOP_PROCESSING now removes from currentrun to prevent another process cycle from happening where it shouldn't." diff --git a/html/changelogs/AutoChangeLog-pr-11040.yml b/html/changelogs/AutoChangeLog-pr-11040.yml new file mode 100644 index 0000000000..cc0514517b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11040.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Further mob holder fixes." diff --git a/html/changelogs/AutoChangeLog-pr-11042.yml b/html/changelogs/AutoChangeLog-pr-11042.yml new file mode 100644 index 0000000000..4238f76b75 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11042.yml @@ -0,0 +1,4 @@ +author: "Arturlang" +delete-after: True +changes: + - balance: "The pandemic can no longer make vaccines or synthblood as quickly." diff --git a/html/changelogs/AutoChangeLog-pr-11043.yml b/html/changelogs/AutoChangeLog-pr-11043.yml new file mode 100644 index 0000000000..28217af630 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11043.yml @@ -0,0 +1,4 @@ +author: "Seris02" +delete-after: True +changes: + - bugfix: "apc icons" diff --git a/html/changelogs/AutoChangeLog-pr-11044.yml b/html/changelogs/AutoChangeLog-pr-11044.yml new file mode 100644 index 0000000000..7dec153778 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11044.yml @@ -0,0 +1,4 @@ +author: "Arturlang" +delete-after: True +changes: + - rscadd: "The syndicate uplinks interface has been redone in TGUI Next" diff --git a/html/changelogs/AutoChangeLog-pr-11045.yml b/html/changelogs/AutoChangeLog-pr-11045.yml new file mode 100644 index 0000000000..9e3e0a9ee4 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11045.yml @@ -0,0 +1,4 @@ +author: "Trilbyspaceclone" +delete-after: True +changes: + - bugfix: "Flat guns can no longer be suppressed" diff --git a/html/changelogs/AutoChangeLog-pr-11046.yml b/html/changelogs/AutoChangeLog-pr-11046.yml new file mode 100644 index 0000000000..c40286e901 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11046.yml @@ -0,0 +1,4 @@ +author: "Trilbyspaceclone" +delete-after: True +changes: + - tweak: "replaced stickmans .45 caliber with 10mm, for consistency." diff --git a/html/changelogs/AutoChangeLog-pr-11047.yml b/html/changelogs/AutoChangeLog-pr-11047.yml new file mode 100644 index 0000000000..5bc42d1219 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11047.yml @@ -0,0 +1,5 @@ +author: "Trilbyspaceclone" +delete-after: True +changes: + - tweak: "Meatwheat and Oats now have rarity" + - balance: "Oats now have at lest 50% more flour in them" diff --git a/html/changelogs/AutoChangeLog-pr-11048.yml b/html/changelogs/AutoChangeLog-pr-11048.yml new file mode 100644 index 0000000000..77af926906 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11048.yml @@ -0,0 +1,4 @@ +author: "Trilbyspaceclone" +delete-after: True +changes: + - balance: "BDM now uses a PKA rather then a normal KA" diff --git a/html/changelogs/AutoChangeLog-pr-11051.yml b/html/changelogs/AutoChangeLog-pr-11051.yml new file mode 100644 index 0000000000..8ac7939b00 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11051.yml @@ -0,0 +1,4 @@ +author: "kevinz000" +delete-after: True +changes: + - balance: "hand teleporters now require 30 deciseconds of still movement by the user to dispel portals. there's a beam effect too." diff --git a/html/changelogs/AutoChangeLog-pr-11056.yml b/html/changelogs/AutoChangeLog-pr-11056.yml new file mode 100644 index 0000000000..b56efb3557 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11056.yml @@ -0,0 +1,4 @@ +author: "necromanceranne" +delete-after: True +changes: + - rscdel: "Bullets causing bleed rates equal to unmitigated damage through all forms of defense." diff --git a/html/changelogs/AutoChangeLog-pr-11060.yml b/html/changelogs/AutoChangeLog-pr-11060.yml new file mode 100644 index 0000000000..c78f03a26d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11060.yml @@ -0,0 +1,4 @@ +author: "kevinz000" +delete-after: True +changes: + - balance: "Sort of a bugfix but cult blood magic and all guns now respect stamina softcrit." diff --git a/html/changelogs/AutoChangeLog-pr-11061.yml b/html/changelogs/AutoChangeLog-pr-11061.yml new file mode 100644 index 0000000000..5225edc141 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11061.yml @@ -0,0 +1,4 @@ +author: "Trilbyspaceclone" +delete-after: True +changes: + - tweak: "Gang tower shield is no longer transparent" diff --git a/html/changelogs/AutoChangeLog-pr-11062.yml b/html/changelogs/AutoChangeLog-pr-11062.yml new file mode 100644 index 0000000000..b9bc85b1c1 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11062.yml @@ -0,0 +1,4 @@ +author: "kevinz000" +delete-after: True +changes: + - balance: "Organ healing rate doubled. Organ decay rate halved to match its define (15 minutes for full decay, so at around 8-10 minutes it'll be really fucked)." diff --git a/html/changelogs/AutoChangeLog-pr-11063.yml b/html/changelogs/AutoChangeLog-pr-11063.yml new file mode 100644 index 0000000000..c729fb5ed9 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11063.yml @@ -0,0 +1,4 @@ +author: "Zellular" +delete-after: True +changes: + - tweak: "Tweaked the movement state for the pupdozer's eyes" diff --git a/html/changelogs/AutoChangeLog-pr-11070.yml b/html/changelogs/AutoChangeLog-pr-11070.yml new file mode 100644 index 0000000000..3c923bddb0 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11070.yml @@ -0,0 +1,4 @@ +author: "kevinz000" +delete-after: True +changes: + - tweak: "Storage now caches max screen size and only stores when being opened by a non ghost, meaning ghosts will no longer distort living player screens when viewing storage." diff --git a/html/changelogs/AutoChangeLog-pr-11071.yml b/html/changelogs/AutoChangeLog-pr-11071.yml new file mode 100644 index 0000000000..e8581b325e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11071.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixed being unable to dump a trash bag's contents directly into disposal bins." diff --git a/html/changelogs/AutoChangeLog-pr-11072.yml b/html/changelogs/AutoChangeLog-pr-11072.yml new file mode 100644 index 0000000000..ab21d91e19 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11072.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Doubled the halved flavor text maximum length." diff --git a/html/changelogs/AutoChangeLog-pr-11073.yml b/html/changelogs/AutoChangeLog-pr-11073.yml new file mode 100644 index 0000000000..078c5fb300 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11073.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Reduced tongue organ damage and tasting pH message spam." diff --git a/html/changelogs/AutoChangeLog-pr-11075.yml b/html/changelogs/AutoChangeLog-pr-11075.yml new file mode 100644 index 0000000000..0eb612a81e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11075.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixed agent IDs not registering the inputted name. Thanks MrPerson." diff --git a/html/changelogs/AutoChangeLog-pr-11076.yml b/html/changelogs/AutoChangeLog-pr-11076.yml new file mode 100644 index 0000000000..e0f187a038 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11076.yml @@ -0,0 +1,4 @@ +author: "nemvar" +delete-after: True +changes: + - code_imp: "Changed mob biotypes from lists to flags." diff --git a/html/changelogs/AutoChangeLog-pr-11079.yml b/html/changelogs/AutoChangeLog-pr-11079.yml new file mode 100644 index 0000000000..b613b6c867 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11079.yml @@ -0,0 +1,4 @@ +author: "Arturlang" +delete-after: True +changes: + - tweak: "Valentines can now be converted by bloodsuckers" diff --git a/html/changelogs/AutoChangeLog-pr-11081.yml b/html/changelogs/AutoChangeLog-pr-11081.yml new file mode 100644 index 0000000000..2fcb15b7aa --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11081.yml @@ -0,0 +1,4 @@ +author: "Detective-Google" +delete-after: True +changes: + - bugfix: "valentines candy no longer prefbreaks" diff --git a/html/changelogs/AutoChangeLog-pr-11086.yml b/html/changelogs/AutoChangeLog-pr-11086.yml new file mode 100644 index 0000000000..e11113e71c --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11086.yml @@ -0,0 +1,6 @@ +author: "YakumoChen" +delete-after: True +changes: + - imageadd: "Rings look nicer. Sprites used from RP." + - imageadd: "Ring on-hands. Diamond rings sparkle!" + - tweak: "You can now propose using a diamond ring in your hand." diff --git a/html/changelogs/AutoChangeLog-pr-11093.yml b/html/changelogs/AutoChangeLog-pr-11093.yml new file mode 100644 index 0000000000..4815818b0d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11093.yml @@ -0,0 +1,5 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixed something about slime blood and the law of conservation of mass." + - bugfix: "Fixed flypeople being emetic machine guns." diff --git a/html/changelogs/AutoChangeLog-pr-11094.yml b/html/changelogs/AutoChangeLog-pr-11094.yml new file mode 100644 index 0000000000..a6db5bd93f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11094.yml @@ -0,0 +1,4 @@ +author: "Trilbyspaceclone" +delete-after: True +changes: + - tweak: "Cosmic winter coat now glows like the bedsheet, and holds normal winter coat gear" diff --git a/html/changelogs/AutoChangeLog-pr-11101.yml b/html/changelogs/AutoChangeLog-pr-11101.yml new file mode 100644 index 0000000000..5305e2b923 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11101.yml @@ -0,0 +1,4 @@ +author: "coiax" +delete-after: True +changes: + - rscadd: "Admin and event only pair pinpointers! They come in a box of two, and each pinpointer will always point at its corresponding pair. Aww." diff --git a/html/changelogs/AutoChangeLog-pr-11105.yml b/html/changelogs/AutoChangeLog-pr-11105.yml new file mode 100644 index 0000000000..0c7ac7b1e6 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11105.yml @@ -0,0 +1,4 @@ +author: "Trilbyspaceclone" +delete-after: True +changes: + - bugfix: "Crabs are now made of crab meat." diff --git a/html/changelogs/AutoChangeLog-pr-11120.yml b/html/changelogs/AutoChangeLog-pr-11120.yml new file mode 100644 index 0000000000..64a435146c --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11120.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixed sprint buffer cost and regen being rounded down." diff --git a/icons/mob/back.dmi b/icons/mob/back.dmi index 26f81b70df..7a28827903 100644 Binary files a/icons/mob/back.dmi and b/icons/mob/back.dmi differ diff --git a/icons/mob/belt.dmi b/icons/mob/belt.dmi index 6843bac6bf..070034d778 100644 Binary files a/icons/mob/belt.dmi and b/icons/mob/belt.dmi differ diff --git a/icons/mob/hands.dmi b/icons/mob/hands.dmi index b69c6c88b1..63263b835c 100644 Binary files a/icons/mob/hands.dmi and b/icons/mob/hands.dmi differ diff --git a/icons/mob/suit_digi.dmi b/icons/mob/suit_digi.dmi index bb00742a17..c6bda60d38 100644 Binary files a/icons/mob/suit_digi.dmi and b/icons/mob/suit_digi.dmi differ diff --git a/icons/obj/abductor.dmi b/icons/obj/abductor.dmi index fd0893b300..75f84347b6 100644 Binary files a/icons/obj/abductor.dmi and b/icons/obj/abductor.dmi differ diff --git a/icons/obj/clothing/belts.dmi b/icons/obj/clothing/belts.dmi index e329720cf7..1ff87b26e4 100644 Binary files a/icons/obj/clothing/belts.dmi and b/icons/obj/clothing/belts.dmi differ diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index 8c2abcd3b9..28fc29cd71 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ diff --git a/icons/obj/drinks.dmi b/icons/obj/drinks.dmi index b03a1cdeae..17d6024586 100644 Binary files a/icons/obj/drinks.dmi and b/icons/obj/drinks.dmi differ diff --git a/icons/obj/food/containers.dmi b/icons/obj/food/containers.dmi index 93acc07453..2639d6860a 100644 Binary files a/icons/obj/food/containers.dmi and b/icons/obj/food/containers.dmi differ diff --git a/icons/obj/food/food.dmi b/icons/obj/food/food.dmi index a719150f11..670269da00 100644 Binary files a/icons/obj/food/food.dmi and b/icons/obj/food/food.dmi differ diff --git a/icons/obj/implants.dmi b/icons/obj/implants.dmi index 8dc2f08fdc..a6d4697673 100644 Binary files a/icons/obj/implants.dmi and b/icons/obj/implants.dmi differ diff --git a/icons/obj/janitor.dmi b/icons/obj/janitor.dmi index cb3870dc61..9128654a5b 100644 Binary files a/icons/obj/janitor.dmi and b/icons/obj/janitor.dmi differ diff --git a/icons/obj/lighting.dmi b/icons/obj/lighting.dmi index 396d681f22..675005da91 100644 Binary files a/icons/obj/lighting.dmi and b/icons/obj/lighting.dmi differ diff --git a/icons/obj/mining.dmi b/icons/obj/mining.dmi index a7593e4a55..f2e98aff32 100644 Binary files a/icons/obj/mining.dmi and b/icons/obj/mining.dmi differ diff --git a/icons/obj/plushes.dmi b/icons/obj/plushes.dmi index c6f25f1b29..3abb25d8b2 100644 Binary files a/icons/obj/plushes.dmi and b/icons/obj/plushes.dmi differ diff --git a/icons/obj/power.dmi b/icons/obj/power.dmi index 1ba953d284..1f84da44d4 100644 Binary files a/icons/obj/power.dmi and b/icons/obj/power.dmi differ diff --git a/icons/obj/ring.dmi b/icons/obj/ring.dmi index 52fe249394..e24f1fab4c 100644 Binary files a/icons/obj/ring.dmi and b/icons/obj/ring.dmi differ diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi index 4aa54a2308..a92af16e96 100644 Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ diff --git a/icons/obj/vending.dmi b/icons/obj/vending.dmi index 7d08a83fb7..b11e43d665 100644 Binary files a/icons/obj/vending.dmi and b/icons/obj/vending.dmi differ diff --git a/icons/obj/vending_restock.dmi b/icons/obj/vending_restock.dmi index c9437d7d80..035c01de6b 100644 Binary files a/icons/obj/vending_restock.dmi and b/icons/obj/vending_restock.dmi differ diff --git a/modular_citadel/code/modules/admin/chat_commands.dm b/modular_citadel/code/modules/admin/chat_commands.dm index 501e0fa25a..ddac7b5953 100644 --- a/modular_citadel/code/modules/admin/chat_commands.dm +++ b/modular_citadel/code/modules/admin/chat_commands.dm @@ -14,6 +14,13 @@ saltresult += "[saltprimarysubject] [saltsecondarysubject]" return "[saltresult]!" +/datum/tgs_chat_command/valentine + name = "valentine" + help_text = "Get a random flirt line." + +/datum/tgs_chat_command/valentine/Run(datum/tgs_chat_user/sender, params) + return "[pick(GLOB.flirts)]" + /datum/tgs_chat_command/despacito name = "despacito" //someone please high effort this sometime and make it a full on ytdl search help_text = "This is so sad." diff --git a/modular_citadel/code/modules/arousal/arousal.dm b/modular_citadel/code/modules/arousal/arousal.dm index 3a586d061d..5c7d5a39e9 100644 --- a/modular_citadel/code/modules/arousal/arousal.dm +++ b/modular_citadel/code/modules/arousal/arousal.dm @@ -10,12 +10,6 @@ var/hidden_undershirt = FALSE var/hidden_socks = FALSE -//Species vars -/datum/species - var/list/cum_fluids = list("semen") - var/list/milk_fluids = list("milk") - var/list/femcum_fluids = list("femcum") - //Mob procs /mob/living/carbon/human/proc/underwear_toggle() set name = "Toggle undergarments" @@ -46,20 +40,12 @@ var/list/obj/item/organ/genital/genit_list = list() if(!client?.prefs.arousable || (aphro && (client?.prefs.cit_toggles & NO_APHRO)) || (maso && !HAS_TRAIT(src, TRAIT_MASO))) return // no adjusting made here - if(strength>0) - for(var/obj/item/organ/genital/G in internal_organs) - if(!G.aroused_state && prob(strength*G.sensitivity)) - G.set_aroused_state(TRUE) - G.update_appearance() - if(G.aroused_state) - genit_list += G - else - for(var/obj/item/organ/genital/G in internal_organs) - if(G.aroused_state && prob(strength*G.sensitivity)) - G.set_aroused_state(FALSE) - G.update_appearance() - if(G.aroused_state) - genit_list += G + for(var/obj/item/organ/genital/G in internal_organs) + if(G.genital_flags & GENITAL_CAN_AROUSE && !G.aroused_state && prob(strength*G.sensitivity)) + G.set_aroused_state(strength > 0) + G.update_appearance() + if(G.aroused_state) + genit_list += G return genit_list /obj/item/organ/genital/proc/climaxable(mob/living/carbon/human/H, silent = FALSE) //returns the fluid source (ergo reagents holder) if found. diff --git a/modular_citadel/code/modules/arousal/genitals.dm b/modular_citadel/code/modules/arousal/genitals.dm index ca01ef46cb..d5191b0532 100644 --- a/modular_citadel/code/modules/arousal/genitals.dm +++ b/modular_citadel/code/modules/arousal/genitals.dm @@ -20,35 +20,29 @@ var/linked_organ_slot //used for linking an apparatus' organ to its other half on update_link(). var/layer_index = GENITAL_LAYER_INDEX //Order should be very important. FIRST vagina, THEN testicles, THEN penis, as this affects the order they are rendered in. -/obj/item/organ/genital/Initialize(mapload, mob/living/carbon/human/H) +/obj/item/organ/genital/Initialize(mapload, do_update = TRUE) . = ..() if(fluid_id) - create_reagents(fluid_max_volume) + create_reagents(fluid_max_volume, NONE, NO_REAGENTS_VALUE) if(CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION)) reagents.add_reagent(fluid_id, fluid_max_volume) - if(H) - get_features(H) - Insert(H) - else + if(do_update) update() -/obj/item/organ/genital/Destroy() - if(linked_organ) - update_link(TRUE)//this should remove any other links it has - return ..() - /obj/item/organ/genital/proc/set_aroused_state(new_state) + if(!(genital_flags & GENITAL_CAN_AROUSE)) + return FALSE if(!((HAS_TRAIT(owner,TRAIT_PERMABONER) && !new_state) || HAS_TRAIT(owner,TRAIT_NEVERBONER) && new_state)) aroused_state = new_state return aroused_state -/obj/item/organ/genital/proc/update(removing = FALSE) +/obj/item/organ/genital/proc/update() if(QDELETED(src)) return update_size() update_appearance() - if(linked_organ_slot || (linked_organ && removing)) - update_link(removing) + if(linked_organ_slot || (linked_organ && !owner)) + update_link() //exposure and through-clothing code /mob/living/carbon @@ -113,17 +107,7 @@ set desc = "Allows you to toggle which genitals are showing signs of arousal." var/list/genital_list = list() for(var/obj/item/organ/genital/G in internal_organs) - var/datum/sprite_accessory/S - switch(G.type) - if(/obj/item/organ/genital/penis) - S = GLOB.cock_shapes_list[G.shape] - if(/obj/item/organ/genital/testicles) - S = GLOB.balls_shapes_list[G.shape] - if(/obj/item/organ/genital/vagina) - S = GLOB.vagina_shapes_list[G.shape] - if(/obj/item/organ/genital/breasts) - S = GLOB.breasts_shapes_list[G.shape] - if(S?.alt_aroused) + if(G.genital_flags & GENITAL_CAN_AROUSE) genital_list += G if(!genital_list.len) //There's nothing that can show arousal return @@ -174,19 +158,18 @@ return TRUE return FALSE -/obj/item/organ/genital/proc/update_link(removing = FALSE) - if(!removing && owner) +/obj/item/organ/genital/proc/update_link() + if(owner) if(linked_organ) - return + return FALSE linked_organ = owner.getorganslot(linked_organ_slot) if(linked_organ) linked_organ.linked_organ = src linked_organ.upon_link() upon_link() return TRUE - else - if(linked_organ) - linked_organ.linked_organ = null + if(linked_organ) + linked_organ.linked_organ = null linked_organ = null return FALSE @@ -200,10 +183,13 @@ update() RegisterSignal(owner, COMSIG_MOB_DEATH, .proc/update_appearance) -/obj/item/organ/genital/Remove(mob/living/carbon/M, special = FALSE, drop_if_replaced = TRUE) - update(TRUE) - if(!QDELETED(owner)) - UnregisterSignal(owner, COMSIG_MOB_DEATH) +/obj/item/organ/genital/Remove(special = FALSE) + . = ..() + var/mob/living/carbon/human/H = . + update() + if(!QDELETED(H)) + UnregisterSignal(H, COMSIG_MOB_DEATH) + H.update_genitals() //proc to give a player their genitals and stuff when they log in /mob/living/carbon/human/proc/give_genitals(clean = FALSE)//clean will remove all pre-existing genitals. proc will then give them any genitals that are enabled in their DNA @@ -232,18 +218,14 @@ /mob/living/carbon/human/proc/give_genital(obj/item/organ/genital/G) if(!dna || (NOGENITALS in dna.species.species_traits) || getorganslot(initial(G.slot))) return FALSE - G = new G(null, src) + G = new G(null, FALSE) + G.get_features(src) + G.Insert(src) return G /obj/item/organ/genital/proc/get_features(mob/living/carbon/human/H) return -/datum/species/proc/genitals_layertext(layer) - switch(layer) - if(GENITALS_BEHIND_LAYER) - return "BEHIND" - if(GENITALS_FRONT_LAYER) - return "FRONT" //procs to handle sprite overlays being applied to humans @@ -262,8 +244,91 @@ update_genitals() /mob/living/carbon/human/proc/update_genitals() - if(!QDELETED(src)) - dna.species.handle_genitals(src) + if(QDELETED(src)) + return + var/static/list/relevant_layers = list("[GENITALS_BEHIND_LAYER]" = "BEHIND", "[GENITALS_FRONT_LAYER]" = "FRONT") + var/static/list/layers_num + if(!layers_num) + for(var/L in relevant_layers) + LAZYSET(layers_num, L, text2num(L)) + for(var/L in relevant_layers) //Less hardcode + remove_overlay(layers_num[L]) + remove_overlay(GENITALS_EXPOSED_LAYER) + if(!LAZYLEN(internal_organs) || ((NOGENITALS in dna.species.species_traits) && !genital_override) || HAS_TRAIT(src, TRAIT_HUSK)) + return + + //start scanning for genitals + + var/list/gen_index[GENITAL_LAYER_INDEX_LENGTH] + var/list/genitals_to_add + var/list/fully_exposed + for(var/obj/item/organ/genital/G in internal_organs) + if(G.is_exposed()) //Checks appropriate clothing slot and if it's through_clothes + LAZYADD(gen_index[G.layer_index], G) + for(var/L in gen_index) + if(L) //skip nulls + LAZYADD(genitals_to_add, L) + if(!genitals_to_add) + return + //Now we added all genitals that aren't internal and should be rendered + //start applying overlays + for(var/layer in relevant_layers) + var/list/standing = list() + var/layertext = relevant_layers[layer] + for(var/A in genitals_to_add) + var/obj/item/organ/genital/G = A + var/datum/sprite_accessory/S + var/size = G.size + switch(G.type) + if(/obj/item/organ/genital/penis) + S = GLOB.cock_shapes_list[G.shape] + if(/obj/item/organ/genital/testicles) + S = GLOB.balls_shapes_list[G.shape] + if(/obj/item/organ/genital/vagina) + S = GLOB.vagina_shapes_list[G.shape] + if(/obj/item/organ/genital/breasts) + S = GLOB.breasts_shapes_list[G.shape] + + if(!S || S.icon_state == "none") + continue + var/aroused_state = G.aroused_state && S.alt_aroused + + var/mutable_appearance/genital_overlay = mutable_appearance(S.icon, layer = -layer) + if(S.center) + genital_overlay = center_image(genital_overlay, S.dimension_x, S.dimension_y) + + if(dna.species.use_skintones && dna.features["genitals_use_skintone"]) + genital_overlay.color = "#[skintone2hex(skin_tone)]" + else + switch(S.color_src) + if("cock_color") + genital_overlay.color = "#[dna.features["cock_color"]]" + if("balls_color") + genital_overlay.color = "#[dna.features["balls_color"]]" + if("breasts_color") + genital_overlay.color = "#[dna.features["breasts_color"]]" + if("vag_color") + genital_overlay.color = "#[dna.features["vag_color"]]" + + genital_overlay.icon_state = "[G.slot]_[S.icon_state]_[size][dna.species.use_skintones ? "_s" : ""]_[aroused_state]_[layertext]" + + if(layer == GENITALS_FRONT_LAYER && CHECK_BITFIELD(G.genital_flags, GENITAL_THROUGH_CLOTHES)) + genital_overlay.layer = -GENITALS_EXPOSED_LAYER + LAZYADD(fully_exposed, genital_overlay) // to be added to a layer with higher priority than clothes, hence the name of the bitflag. + else + genital_overlay.layer = -layers_num[layer] + standing += genital_overlay + + if(LAZYLEN(standing)) + overlays_standing[layers_num[layer]] = standing + + if(LAZYLEN(fully_exposed)) + overlays_standing[GENITALS_EXPOSED_LAYER] = fully_exposed + apply_overlay(GENITALS_EXPOSED_LAYER) + + for(var/L in relevant_layers) + apply_overlay(layers_num[L]) + //Checks to see if organs are new on the mob, and changes their colours so that they don't get crazy colours. /mob/living/carbon/human/proc/emergent_genital_call() @@ -292,86 +357,3 @@ else if (willyCheck == FALSE) dna.features["cock_color"] = dna.features["breasts_color"] return TRUE - -/datum/species/proc/handle_genitals(mob/living/carbon/human/H)//more like handle sadness - if(!H)//no args - CRASH("H = null") - if(!LAZYLEN(H.internal_organs) || ((NOGENITALS in species_traits) && !H.genital_override) || HAS_TRAIT(H, TRAIT_HUSK)) - return - var/list/relevant_layers = list(GENITALS_BEHIND_LAYER, GENITALS_FRONT_LAYER) - - for(var/L in relevant_layers) //Less hardcode - H.remove_overlay(L) - H.remove_overlay(GENITALS_EXPOSED_LAYER) - //start scanning for genitals - - var/list/gen_index[GENITAL_LAYER_INDEX_LENGTH] - var/list/genitals_to_add - var/list/fully_exposed - for(var/obj/item/organ/genital/G in H.internal_organs) - if(G.is_exposed()) //Checks appropriate clothing slot and if it's through_clothes - LAZYADD(gen_index[G.layer_index], G) - for(var/L in gen_index) - if(L) //skip nulls - LAZYADD(genitals_to_add, L) - if(!genitals_to_add) - return - //Now we added all genitals that aren't internal and should be rendered - //start applying overlays - for(var/layer in relevant_layers) - var/list/standing = list() - var/layertext = genitals_layertext(layer) - for(var/A in genitals_to_add) - var/obj/item/organ/genital/G = A - var/datum/sprite_accessory/S - var/size = G.size - var/aroused_state = G.aroused_state - switch(G.type) - if(/obj/item/organ/genital/penis) - S = GLOB.cock_shapes_list[G.shape] - if(/obj/item/organ/genital/testicles) - S = GLOB.balls_shapes_list[G.shape] - if(/obj/item/organ/genital/vagina) - S = GLOB.vagina_shapes_list[G.shape] - if(/obj/item/organ/genital/breasts) - S = GLOB.breasts_shapes_list[G.shape] - - if(!S || S.icon_state == "none") - continue - - var/mutable_appearance/genital_overlay = mutable_appearance(S.icon, layer = -layer) - genital_overlay.icon_state = "[G.slot]_[S.icon_state]_[size]_[aroused_state]_[layertext]" - - if(S.center) - genital_overlay = center_image(genital_overlay, S.dimension_x, S.dimension_y) - - if(use_skintones && H.dna.features["genitals_use_skintone"]) - genital_overlay.color = "#[skintone2hex(H.skin_tone)]" - else - switch(S.color_src) - if("cock_color") - genital_overlay.color = "#[H.dna.features["cock_color"]]" - if("balls_color") - genital_overlay.color = "#[H.dna.features["balls_color"]]" - if("breasts_color") - genital_overlay.color = "#[H.dna.features["breasts_color"]]" - if("vag_color") - genital_overlay.color = "#[H.dna.features["vag_color"]]" - - genital_overlay.icon_state = "[G.slot]_[S.icon_state]_[size]-s_[aroused_state]_[layertext]" - - if(layer == GENITALS_FRONT_LAYER && CHECK_BITFIELD(G.genital_flags, GENITAL_THROUGH_CLOTHES)) - genital_overlay.layer = -GENITALS_EXPOSED_LAYER - LAZYADD(fully_exposed, genital_overlay) // to be added to a layer with higher priority than clothes, hence the name of the bitflag. - else - standing += genital_overlay - - if(LAZYLEN(standing)) - H.overlays_standing[layer] = standing - - if(LAZYLEN(fully_exposed)) - H.overlays_standing[GENITALS_EXPOSED_LAYER] = fully_exposed - H.apply_overlay(GENITALS_EXPOSED_LAYER) - - for(var/L in relevant_layers) - H.apply_overlay(L) diff --git a/modular_citadel/code/modules/arousal/genitals_sprite_accessories.dm b/modular_citadel/code/modules/arousal/genitals_sprite_accessories.dm index 0c1763b8e2..594fc83e46 100644 --- a/modular_citadel/code/modules/arousal/genitals_sprite_accessories.dm +++ b/modular_citadel/code/modules/arousal/genitals_sprite_accessories.dm @@ -85,36 +85,36 @@ //Vaginas /datum/sprite_accessory/vagina icon = 'modular_citadel/icons/obj/genitals/vagina_onmob.dmi' - icon_state = null name = "vagina" color_src = "vag_color" + alt_aroused = TRUE /datum/sprite_accessory/vagina/human icon_state = "human" name = "Human" - alt_aroused = TRUE /datum/sprite_accessory/vagina/tentacles icon_state = "tentacle" name = "Tentacle" - alt_aroused = TRUE /datum/sprite_accessory/vagina/dentata icon_state = "dentata" name = "Dentata" - alt_aroused = TRUE /datum/sprite_accessory/vagina/hairy icon_state = "hairy" name = "Hairy" + alt_aroused = FALSE /datum/sprite_accessory/vagina/spade icon_state = "spade" name = "Spade" + alt_aroused = FALSE /datum/sprite_accessory/vagina/furred icon_state = "furred" name = "Furred" + alt_aroused = FALSE /datum/sprite_accessory/vagina/gaping icon_state = "gaping" @@ -125,7 +125,6 @@ icon = 'modular_citadel/icons/obj/genitals/breasts_onmob.dmi' name = "breasts" color_src = "breasts_color" - alt_aroused = TRUE /datum/sprite_accessory/breasts/pair icon_state = "pair" diff --git a/modular_citadel/code/modules/arousal/organs/breasts.dm b/modular_citadel/code/modules/arousal/organs/breasts.dm index 1537d5cebe..f3ce834838 100644 --- a/modular_citadel/code/modules/arousal/organs/breasts.dm +++ b/modular_citadel/code/modules/arousal/organs/breasts.dm @@ -1,3 +1,6 @@ +#define BREASTS_ICON_MIN_SIZE 1 +#define BREASTS_ICON_MAX_SIZE 6 + /obj/item/organ/genital/breasts name = "breasts" desc = "Female milk producing organs." @@ -9,7 +12,7 @@ fluid_id = /datum/reagent/consumable/milk fluid_rate = MILK_RATE shape = "pair" - genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH|GENITAL_FUID_PRODUCTION + genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH|GENITAL_FUID_PRODUCTION|GENITAL_CAN_AROUSE masturbation_verb = "massage" arousal_verb = "Your breasts start feeling sensitive" unarousal_verb = "Your breasts no longer feel sensitive" @@ -19,8 +22,8 @@ var/cached_size //these two vars pertain size modifications and so should be expressed in NUMBERS. var/prev_size //former cached_size value, to allow update_size() to early return should be there no significant changes. -/obj/item/organ/genital/breasts/Initialize(mapload, mob/living/carbon/human/H) - if(!H) +/obj/item/organ/genital/breasts/Initialize(mapload, do_update = TRUE) + if(do_update) cached_size = breast_values[size] prev_size = cached_size return ..() @@ -49,21 +52,21 @@ var/datum/reagent/R = GLOB.chemical_reagents_list[fluid_id] if(R) desc += " They're leaking [lowertext(R.name)]." - var/string + var/datum/sprite_accessory/S = GLOB.breasts_shapes_list[shape] + var/icon_shape = S ? S.icon_state : "pair" + var/icon_size = CLAMP(breast_values[size], BREASTS_ICON_MIN_SIZE, BREASTS_ICON_MAX_SIZE) + icon_state = "breasts_[icon_shape]_[breast_values[icon_size]]" if(owner) if(owner.dna.species.use_skintones && owner.dna.features["genitals_use_skintone"]) if(ishuman(owner)) // Check before recasting type, although someone fucked up if you're not human AND have use_skintones somehow... var/mob/living/carbon/human/H = owner // only human mobs have skin_tone, which we need. color = "#[skintone2hex(H.skin_tone)]" - string = "breasts_[GLOB.breasts_shapes_icons[shape]]_[size]-s" + icon_state += "_s" else color = "#[owner.dna.features["breasts_color"]]" - string = "breasts_[GLOB.breasts_shapes_icons[shape]]_[size]" if(ishuman(owner)) var/mob/living/carbon/human/H = owner - icon_state = sanitize_text(string) H.update_genitals() - icon_state = sanitize_text(string) //Allows breasts to grow and change size, with sprite changes too. //maximum wah @@ -130,3 +133,6 @@ cached_size = size size = breast_values[size] prev_size = cached_size + +#undef BREASTS_ICON_MIN_SIZE +#undef BREASTS_ICON_MAX_SIZE \ No newline at end of file diff --git a/modular_citadel/code/modules/arousal/organs/penis.dm b/modular_citadel/code/modules/arousal/organs/penis.dm index c6d3c764ac..38f463a97c 100644 --- a/modular_citadel/code/modules/arousal/organs/penis.dm +++ b/modular_citadel/code/modules/arousal/organs/penis.dm @@ -8,13 +8,13 @@ masturbation_verb = "stroke" arousal_verb = "You pop a boner" unarousal_verb = "Your boner goes down" - genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH + genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH|GENITAL_CAN_AROUSE linked_organ_slot = ORGAN_SLOT_TESTICLES fluid_transfer_factor = 0.5 size = 2 //arbitrary value derived from length and girth for sprites. layer_index = PENIS_LAYER_INDEX var/length = 6 //inches - var/prev_length = 6 //really should be renamed to prev_length + var/prev_length = 6 var/girth = 4.38 var/girth_ratio = COCK_GIRTH_RATIO_DEF //0.73; check citadel_defines.dm @@ -73,22 +73,21 @@ /obj/item/organ/genital/penis/update_appearance() . = ..() - var/string + var/datum/sprite_accessory/S = GLOB.cock_shapes_list[shape] + var/icon_shape = S ? S.icon_state : "human" + icon_state = "penis_[icon_shape]_[size]" var/lowershape = lowertext(shape) desc = "You see [aroused_state ? "an erect" : "a flaccid"] [lowershape] [name]. You estimate it's about [round(length, 0.25)] inch[round(length, 0.25) != 1 ? "es" : ""] long and [round(girth, 0.25)] inch[round(girth, 0.25) != 1 ? "es" : ""] in girth." - if(owner) if(owner.dna.species.use_skintones && owner.dna.features["genitals_use_skintone"]) if(ishuman(owner)) // Check before recasting type, although someone fucked up if you're not human AND have use_skintones somehow... var/mob/living/carbon/human/H = owner // only human mobs have skin_tone, which we need. color = "#[skintone2hex(H.skin_tone)]" - string = "penis_[GLOB.cock_shapes_icons[shape]]_[size]-s" + icon_state += "_s" else color = "#[owner.dna.features["cock_color"]]" - string = "penis_[GLOB.cock_shapes_icons[shape]]_[size]" if(ishuman(owner)) var/mob/living/carbon/human/H = owner - icon_state = sanitize_text(string) H.update_genitals() /obj/item/organ/genital/penis/get_features(mob/living/carbon/human/H) diff --git a/modular_citadel/code/modules/arousal/organs/testicles.dm b/modular_citadel/code/modules/arousal/organs/testicles.dm index 9573020417..eb6c1536cb 100644 --- a/modular_citadel/code/modules/arousal/organs/testicles.dm +++ b/modular_citadel/code/modules/arousal/organs/testicles.dm @@ -43,19 +43,19 @@ /obj/item/organ/genital/testicles/update_appearance() . = ..() desc = "You see an [size_name] pair of testicles." + var/datum/sprite_accessory/S = GLOB.balls_shapes_list[shape] + var/icon_shape = S ? S.icon_state : "single" + icon_state = "testicles_[icon_shape]_[size]" if(owner) - var/string if(owner.dna.species.use_skintones && owner.dna.features["genitals_use_skintone"]) if(ishuman(owner)) // Check before recasting type, although someone fucked up if you're not human AND have use_skintones somehow... var/mob/living/carbon/human/H = owner // only human mobs have skin_tone, which we need. color = "#[skintone2hex(H.skin_tone)]" - string = "testicles_[GLOB.balls_shapes_icons[shape]]_[size]-s" + icon_state += "_s" else color = "#[owner.dna.features["balls_color"]]" - string = "testicles_[GLOB.balls_shapes_icons[shape]]_[size]" if(ishuman(owner)) var/mob/living/carbon/human/H = owner - icon_state = sanitize_text(string) H.update_genitals() /obj/item/organ/genital/testicles/get_features(mob/living/carbon/human/H) diff --git a/modular_citadel/code/modules/arousal/organs/vagina.dm b/modular_citadel/code/modules/arousal/organs/vagina.dm index 3f1bcc5f9b..311afe75b0 100644 --- a/modular_citadel/code/modules/arousal/organs/vagina.dm +++ b/modular_citadel/code/modules/arousal/organs/vagina.dm @@ -6,7 +6,7 @@ zone = BODY_ZONE_PRECISE_GROIN slot = "vagina" size = 1 //There is only 1 size right now - genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH + genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH|GENITAL_CAN_AROUSE masturbation_verb = "finger" arousal_verb = "You feel wetness on your crotch" unarousal_verb = "You no longer feel wet" @@ -22,7 +22,7 @@ /obj/item/organ/genital/vagina/update_appearance() . = ..() - var/string //Keeping this code here, so making multiple sprites for the different kinds is easier. + icon_state = "vagina" var/lowershape = lowertext(shape) var/details @@ -55,13 +55,11 @@ if(ishuman(owner)) // Check before recasting type, although someone fucked up if you're not human AND have use_skintones somehow... var/mob/living/carbon/human/H = owner // only human mobs have skin_tone, which we need. color = "#[skintone2hex(H.skin_tone)]" - string = "vagina-s" + icon_state += "_s" else color = "#[owner.dna.features["vag_color"]]" - string = "vagina" if(ishuman(owner)) var/mob/living/carbon/human/H = owner - icon_state = sanitize_text(string) H.update_genitals() /obj/item/organ/genital/vagina/get_features(mob/living/carbon/human/H) diff --git a/modular_citadel/code/modules/custom_loadout/custom_items.dm b/modular_citadel/code/modules/custom_loadout/custom_items.dm index 03a4a56147..e1d204c74d 100644 --- a/modular_citadel/code/modules/custom_loadout/custom_items.dm +++ b/modular_citadel/code/modules/custom_loadout/custom_items.dm @@ -557,3 +557,13 @@ icon = 'icons/obj/custom.dmi' alternate_worn_icon = 'icons/mob/custom_w.dmi' mutantrace_variation = NONE + +/obj/item/toy/plush/mammal/dog/fritz + icon = 'icons/obj/custom.dmi' + icon_state = "fritz" + item_state = "fritz" + attack_verb = list("barked", "boofed", "shotgun'd") + obj_flags = UNIQUE_RENAME + unique_reskin = list("Goodboye" = "fritz", "Badboye" = "fritz_bad") + mutantrace_variation = NONE + diff --git a/modular_citadel/code/modules/mob/cit_emotes.dm b/modular_citadel/code/modules/mob/cit_emotes.dm index d0ad0d3232..2be83733e5 100644 --- a/modular_citadel/code/modules/mob/cit_emotes.dm +++ b/modular_citadel/code/modules/mob/cit_emotes.dm @@ -14,13 +14,10 @@ emote_type = EMOTE_AUDIBLE /datum/emote/living/insult/run_emote(mob/living/user, params) - var/insult_message = "" - var/miming = user.mind ? user.mind.miming : 0 - if(!user.is_muzzled()) - insult_message += pick_list_replacements(INSULTS_FILE, "insult_gen") - message = insult_message - else if(miming) + if(user.mind?.miming) message = "creatively gesticulates." + else if(!user.is_muzzled()) + message = pick_list_replacements(INSULTS_FILE, "insult_gen") else message = "muffles something." . = ..() @@ -36,7 +33,7 @@ sound = 'modular_citadel/sound/voice/scream_silicon.ogg' if(iscyborg(user)) var/mob/living/silicon/robot/S = user - if(S.cell.charge < 20) + if(S.cell?.charge < 20) to_chat(S, "Scream module deactivated. Please recharge.") return S.cell.use(200) diff --git a/modular_citadel/icons/mob/markings_notmammals.dmi b/modular_citadel/icons/mob/markings_notmammals.dmi index 79c97968ed..43452c8d14 100644 Binary files a/modular_citadel/icons/mob/markings_notmammals.dmi and b/modular_citadel/icons/mob/markings_notmammals.dmi differ diff --git a/modular_citadel/icons/mob/widerobot.dmi b/modular_citadel/icons/mob/widerobot.dmi index a77a109eb9..50c29bb75f 100644 Binary files a/modular_citadel/icons/mob/widerobot.dmi and b/modular_citadel/icons/mob/widerobot.dmi differ diff --git a/modular_citadel/icons/obj/genitals/breasts.dmi b/modular_citadel/icons/obj/genitals/breasts.dmi index d70207ee69..24656062d2 100644 Binary files a/modular_citadel/icons/obj/genitals/breasts.dmi and b/modular_citadel/icons/obj/genitals/breasts.dmi differ diff --git a/modular_citadel/icons/obj/genitals/breasts_onmob.dmi b/modular_citadel/icons/obj/genitals/breasts_onmob.dmi index 371041b6f4..578086c4c3 100644 Binary files a/modular_citadel/icons/obj/genitals/breasts_onmob.dmi and b/modular_citadel/icons/obj/genitals/breasts_onmob.dmi differ diff --git a/modular_citadel/icons/obj/genitals/penis.dmi b/modular_citadel/icons/obj/genitals/penis.dmi index 517758b248..c3fd184a7c 100644 Binary files a/modular_citadel/icons/obj/genitals/penis.dmi and b/modular_citadel/icons/obj/genitals/penis.dmi differ diff --git a/modular_citadel/icons/obj/genitals/penis_onmob.dmi b/modular_citadel/icons/obj/genitals/penis_onmob.dmi index 4f84c52360..c074eaf306 100644 Binary files a/modular_citadel/icons/obj/genitals/penis_onmob.dmi and b/modular_citadel/icons/obj/genitals/penis_onmob.dmi differ diff --git a/modular_citadel/icons/obj/genitals/taur_penis_onmob.dmi b/modular_citadel/icons/obj/genitals/taur_penis_onmob.dmi index ae2339e2e0..e8efbec216 100644 Binary files a/modular_citadel/icons/obj/genitals/taur_penis_onmob.dmi and b/modular_citadel/icons/obj/genitals/taur_penis_onmob.dmi differ diff --git a/modular_citadel/icons/obj/genitals/testicles.dmi b/modular_citadel/icons/obj/genitals/testicles.dmi index 3d7a5f4f48..386eab0956 100644 Binary files a/modular_citadel/icons/obj/genitals/testicles.dmi and b/modular_citadel/icons/obj/genitals/testicles.dmi differ diff --git a/modular_citadel/icons/obj/genitals/vagina.dmi b/modular_citadel/icons/obj/genitals/vagina.dmi index 39bdd48e89..1bbe62ba0e 100644 Binary files a/modular_citadel/icons/obj/genitals/vagina.dmi and b/modular_citadel/icons/obj/genitals/vagina.dmi differ diff --git a/modular_citadel/icons/obj/genitals/vagina_onmob.dmi b/modular_citadel/icons/obj/genitals/vagina_onmob.dmi index ab71b22e3b..6c34ffadfa 100644 Binary files a/modular_citadel/icons/obj/genitals/vagina_onmob.dmi and b/modular_citadel/icons/obj/genitals/vagina_onmob.dmi differ diff --git a/sound/weapons/bowdraw.wav b/sound/weapons/bowdraw.wav new file mode 100644 index 0000000000..bba8a87e06 Binary files /dev/null and b/sound/weapons/bowdraw.wav differ diff --git a/sound/weapons/bowfire.wav b/sound/weapons/bowfire.wav new file mode 100644 index 0000000000..c079d43475 Binary files /dev/null and b/sound/weapons/bowfire.wav differ diff --git a/tgstation.dme b/tgstation.dme index 28ae7eee99..28f469ac25 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -152,6 +152,7 @@ #include "code\__HELPERS\type2type_vr.dm" #include "code\__HELPERS\typelists.dm" #include "code\__HELPERS\unsorted.dm" +#include "code\__HELPERS\vector.dm" #include "code\__HELPERS\view.dm" #include "code\__HELPERS\sorts\__main.dm" #include "code\__HELPERS\sorts\InsertSort.dm" @@ -233,6 +234,7 @@ #include "code\controllers\configuration\entries\fail2topic.dm" #include "code\controllers\configuration\entries\game_options.dm" #include "code\controllers\configuration\entries\general.dm" +#include "code\controllers\configuration\entries\plushies.dm" #include "code\controllers\subsystem\acid.dm" #include "code\controllers\subsystem\adjacent_air.dm" #include "code\controllers\subsystem\air.dm" @@ -272,6 +274,7 @@ #include "code\controllers\subsystem\pathfinder.dm" #include "code\controllers\subsystem\persistence.dm" #include "code\controllers\subsystem\ping.dm" +#include "code\controllers\subsystem\profiler.dm" #include "code\controllers\subsystem\radiation.dm" #include "code\controllers\subsystem\radio.dm" #include "code\controllers\subsystem\research.dm" @@ -290,7 +293,6 @@ #include "code\controllers\subsystem\vis_overlays.dm" #include "code\controllers\subsystem\vore.dm" #include "code\controllers\subsystem\vote.dm" -#include "code\controllers\subsystem\weather.dm" #include "code\controllers\subsystem\processing\chemistry.dm" #include "code\controllers\subsystem\processing\circuit.dm" #include "code\controllers\subsystem\processing\fastprocess.dm" @@ -301,6 +303,7 @@ #include "code\controllers\subsystem\processing\processing.dm" #include "code\controllers\subsystem\processing\projectiles.dm" #include "code\controllers\subsystem\processing\quirks.dm" +#include "code\controllers\subsystem\processing\weather.dm" #include "code\controllers\subsystem\processing\wet_floors.dm" #include "code\datums\action.dm" #include "code\datums\ai_laws.dm" @@ -493,7 +496,6 @@ #include "code\datums\helper_datums\getrev.dm" #include "code\datums\helper_datums\icon_snapshot.dm" #include "code\datums\helper_datums\teleport.dm" -#include "code\datums\helper_datums\topic_input.dm" #include "code\datums\looping_sounds\_looping_sound.dm" #include "code\datums\looping_sounds\item_sounds.dm" #include "code\datums\looping_sounds\machinery_sounds.dm" @@ -665,7 +667,6 @@ #include "code\game\machinery\magnet.dm" #include "code\game\machinery\mass_driver.dm" #include "code\game\machinery\navbeacon.dm" -#include "code\game\machinery\newscaster.dm" #include "code\game\machinery\PDApainter.dm" #include "code\game\machinery\quantum_pad.dm" #include "code\game\machinery\recharger.dm" @@ -867,6 +868,7 @@ #include "code\game\objects\items\cosmetics.dm" #include "code\game\objects\items\courtroom.dm" #include "code\game\objects\items\crayons.dm" +#include "code\game\objects\items\debug_items.dm" #include "code\game\objects\items\defib.dm" #include "code\game\objects\items\dehy_carp.dm" #include "code\game\objects\items\dice.dm" @@ -979,6 +981,7 @@ #include "code\game\objects\items\implants\implant_exile.dm" #include "code\game\objects\items\implants\implant_explosive.dm" #include "code\game\objects\items\implants\implant_freedom.dm" +#include "code\game\objects\items\implants\implant_hijack.dm" #include "code\game\objects\items\implants\implant_krav_maga.dm" #include "code\game\objects\items\implants\implant_mindshield.dm" #include "code\game\objects\items\implants\implant_misc.dm" @@ -2462,6 +2465,15 @@ #include "code\modules\modular_computers\hardware\printer.dm" #include "code\modules\modular_computers\hardware\recharger.dm" #include "code\modules\modular_computers\NTNet\NTNRC\conversation.dm" +#include "code\modules\newscaster\_news.dm" +#include "code\modules\newscaster\feed_channel.dm" +#include "code\modules\newscaster\feed_comment.dm" +#include "code\modules\newscaster\feed_message.dm" +#include "code\modules\newscaster\ghostread.dm" +#include "code\modules\newscaster\news_network.dm" +#include "code\modules\newscaster\newscaster_machine.dm" +#include "code\modules\newscaster\newspaper.dm" +#include "code\modules\newscaster\wanted_message.dm" #include "code\modules\ninja\__ninjaDefines.dm" #include "code\modules\ninja\energy_katana.dm" #include "code\modules\ninja\ninja_event.dm" @@ -2579,6 +2591,7 @@ #include "code\modules\projectiles\ammunition\ballistic\smg.dm" #include "code\modules\projectiles\ammunition\ballistic\sniper.dm" #include "code\modules\projectiles\ammunition\caseless\_caseless.dm" +#include "code\modules\projectiles\ammunition\caseless\arrow.dm" #include "code\modules\projectiles\ammunition\caseless\ferromagnetic.dm" #include "code\modules\projectiles\ammunition\caseless\foam.dm" #include "code\modules\projectiles\ammunition\caseless\misc.dm" @@ -2609,6 +2622,7 @@ #include "code\modules\projectiles\boxes_magazines\external\toy.dm" #include "code\modules\projectiles\boxes_magazines\internal\_cylinder.dm" #include "code\modules\projectiles\boxes_magazines\internal\_internal.dm" +#include "code\modules\projectiles\boxes_magazines\internal\bow.dm" #include "code\modules\projectiles\boxes_magazines\internal\grenade.dm" #include "code\modules\projectiles\boxes_magazines\internal\misc.dm" #include "code\modules\projectiles\boxes_magazines\internal\revolver.dm" @@ -2619,6 +2633,7 @@ #include "code\modules\projectiles\guns\energy.dm" #include "code\modules\projectiles\guns\magic.dm" #include "code\modules\projectiles\guns\ballistic\automatic.dm" +#include "code\modules\projectiles\guns\ballistic\bow.dm" #include "code\modules\projectiles\guns\ballistic\laser_gatling.dm" #include "code\modules\projectiles\guns\ballistic\launchers.dm" #include "code\modules\projectiles\guns\ballistic\magweapon.dm" @@ -2671,6 +2686,7 @@ #include "code\modules\projectiles\projectile\energy\tesla.dm" #include "code\modules\projectiles\projectile\magic\spellcard.dm" #include "code\modules\projectiles\projectile\reusable\_reusable.dm" +#include "code\modules\projectiles\projectile\reusable\arrow.dm" #include "code\modules\projectiles\projectile\reusable\foam_dart.dm" #include "code\modules\projectiles\projectile\reusable\magspear.dm" #include "code\modules\projectiles\projectile\special\curse.dm" diff --git a/tgui-next/README.md b/tgui-next/README.md index df801684c6..beb7aaff80 100644 --- a/tgui-next/README.md +++ b/tgui-next/README.md @@ -65,6 +65,9 @@ Run one of the following: hot module replacement and logging facilities in all running instances of tgui. In short, this means that you will instantly see changes in the game as you code it. Very useful, highly recommended. + In order to use, you should start the game server first, connect to it so dreamseeker is + open, then start the dev server. You'll know if it's hooked correctly if data gets dumped + to the log when tgui windows are opened. - `bin/tgui --dev --reload` - reload byond cache once. - `bin/tgui --dev --debug` - run server with debug logging enabled. - `bin/tgui --dev --no-hot` - disable hot module replacement (helps when @@ -220,7 +223,6 @@ This way, `Button` can pull out the `className` generated by the `Box`. ``` `Box` units, like width, height and margins can be defined in two ways: - - By plain numbers (1 unit equals `0.5em`); - In absolute measures, by providing a full unit string (e.g. `100px`). @@ -239,6 +241,8 @@ Props: - `height: number` - Box height. - `minHeight: number` - Box minimum height. - `maxHeight: number` - Box maximum height. +- `fontSize: number` - Font size. +- `fontFamily: string` - Font family. - `lineHeight: number` - Directly affects the height of text lines. Useful for adjusting button height. - `inline: boolean` - Forces the `Box` to appear as an `inline-block`, @@ -254,6 +258,7 @@ all available horizontal space. - `opacity: number` - Opacity, from 0 to 1. - `bold: boolean` - Make text bold. - `italic: boolean` - Make text italic. +- `nowrap: boolean` - Stops text from wrapping. - `textAlign: string` - Align text inside the box. - `left` (default) - `center` @@ -293,11 +298,55 @@ over the button. - `bottom` (default) - Show tooltip below the button. - `left` - Show tooltip on the left of the button. - `right` - Show tooltip on the right of the button. +- `ellipsis: boolean` - If button width is constrained, button text will +be truncated with an ellipsis. Be careful however, because this prop breaks +the baseline alignment. - `title: string` - A native browser tooltip, which appears when hovering over the button. - `content/children: any` - Content to render inside the button. - `onClick: function` - Called when element is clicked. +### `Button.Checkbox` + +A ghetto checkbox, made entirely using existing Button API. + +Props: + +- See inherited props: [Button](#button) +- `checked: boolean` - Boolean value, which marks the checkbox as checked. + +### `Button.Confirm` + +A button with a an extra confirmation step, using native button component. + +Props: + +- See inherited props: [Button](#button) +- `confirmMessage: string` - Text to display after first click; defaults to "Confirm?" +- `confirmColor: string` - Color to display after first click; default to "bad" + +### `Button.Input` + +A button that turns into an input box after the first click. Turns back into a button after the user hits enter, defocuses, or hits escape. Enter and defocus commit, while escape cancels. + +Props: + - See inherited props: [Box](#box) + - `fluid`: fill availible horizontal space + - `onCommit: (e, value) => void`: function that is called after the user defocuses the input or presses enter + - `currentValue: string`: default string to display when the input is shown + - `defaultValue: string`: default value emitted if the user leaves the box blank when hitting enter or defocusing. If left undefined, will cancel the change on a blank defocus/enter + +### `Collapsible` + +Displays contents when open, acts as a fluid button when closed. Click to toggle, closed by default. + +Props: + - See inherited props: [Box](#box) + - `children: any` - What is collapsed when closed + - `title: string` - Text to display on the button for collapsing + - `color: string` - Color of the button; see [Button](#button) + - `buttons: any` - Buttons or other content to render inline with the button + ### `ColorBox` Displays a 1-character wide colored square. Can be used as a status indicator, @@ -319,6 +368,21 @@ Props: - See inherited props: [Box](#box) +### `Dropdown` + +A simple dropdown box component. Lets the user select from a list of options and displays selected entry. + +Props: + + - See inherited props: [Box](#box) + - `options: string[]` - An array of strings which will be displayed in the dropdown when open + - `selected: string` - Currently selected entry + - `width: number` - Width of dropdown button and resulting menu + - `over: boolean` - dropdown renders over instead of below + - `color: string` - color of dropdown button + - `onClick: (e) => void` - Called when dropdown button is clicked + - `onSelected: (value) => void` - Called when a value is picked from the list, `value` is the value that was picked + ### `Flex` Quickly manage the layout, alignment, and sizing of grid columns, navigation, components, and more with a full suite of responsive flexbox utilities. @@ -350,6 +414,10 @@ two flex items as far as possible from each other. Props: - See inherited props: [Box](#box) +- `spacing: number` - Spacing between flex items, in integer units +(1 unit - 0.5em). Does not directly relate to a flex css property +(adds a modifier class under the hood), and only integer numbers are +supported. - `direction: string` - This establishes the main-axis, thus defining the direction flex items are placed in the flex container. - `row` (default) - left to right. @@ -406,6 +474,7 @@ remaining space is distributed. It can be a length (e.g. `20%`, `5rem`, etc.), an `auto` or `content` keyword. - `align: string` - This allows the default alignment (or the one specified by align-items) to be overridden for individual flex items. See: [Flex](#flex). + ### `Grid` Helps you to divide horizontal space into two or more equal sections. @@ -432,7 +501,7 @@ Props: Props: -- See inherited props: [Table.Cell](#table-cell) +- See inherited props: [Table.Cell](#tablecell) - `size: number` (default: 1) - Size of the column relative to other columns. ### `Icon` @@ -445,7 +514,6 @@ Renders one of the FontAwesome icons of your choice. To smoothen the transition from v4 to v5, we have added a v4 semantic to transform names with `-o` suffixes to FA Regular icons. For example: - - `square` will get transformed to `fas square` - `square-o` will get transformed to `far square` @@ -470,7 +538,9 @@ Props: - See inherited props: [Box](#box) - `value: string` - Value of an input. +- `placeholder: string` - Text placed into Input box when value is otherwise nothing. Clears automatically when focused. - `fluid: boolean` - Fill all available horizontal space. +- `selfClear: boolean` - Clear after hitting enter, as well as remain focused when this happens. Useful for things like chat inputs - `onChange: (e, value) => void` - An event, which fires when you commit the text by either unfocusing the input box, or by pressing the Enter key. - `onInput: (e, value) => void` - An event, which fires on every keypress. @@ -562,6 +632,9 @@ dragging the input. - `stepPixelSize: number` (default: 1) - Screen distance mouse needs to travel to adjust value by one `step`. - `width: string|number` - Width of the element, in `Box` units or pixels. +- `height: string|numer` - Height of the element, in `Box` units or pixels. +- `lineHeight: string|number` - lineHeight of the element, in `Box` units or pixels. +- `fontSize: string|number` - fontSize of the element, in `Box` units or pixels. - `format: value => value` - Format value using this function before displaying it. - `suppressFlicker: number` - A number in milliseconds, for which the input @@ -738,6 +811,8 @@ Props: - `vertical: boolean` - Use a vertical configuration, where tabs will appear stacked on the left side of the container. +- `altSelection` - Whether the tab buttons select via standard select (color change) or by adding a white indicator to the selected tab. + Intended for usage on interfaces where tab color has relevance. - `children: Tab[]` - This component only accepts tabs as its children. ### `Tabs.Tab` diff --git a/tgui-next/bin/tgui b/tgui-next/bin/tgui old mode 100644 new mode 100755 diff --git a/tgui-next/packages/tgui/interfaces/Apc.js b/tgui-next/packages/tgui/interfaces/Apc.js index d74c3e8e57..c899ea8ae7 100644 --- a/tgui-next/packages/tgui/interfaces/Apc.js +++ b/tgui-next/packages/tgui/interfaces/Apc.js @@ -201,6 +201,29 @@ export const Apc = props => { onClick={() => act('toggle_nightshift')} /> )} /> + {data.hijackable && ( +
+