diff --git a/.github/workflows/auto_changelog.yml b/.github/workflows/auto_changelog.yml index 3feaaf87c236..37dc7d2e054e 100644 --- a/.github/workflows/auto_changelog.yml +++ b/.github/workflows/auto_changelog.yml @@ -14,7 +14,7 @@ jobs: if: github.event.pull_request.merged == true steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Generate App Token id: app-token-generation diff --git a/.github/workflows/autowiki.yml b/.github/workflows/autowiki.yml index b022eda4ea4f..2f6cadbbf922 100644 --- a/.github/workflows/autowiki.yml +++ b/.github/workflows/autowiki.yml @@ -20,7 +20,7 @@ jobs: echo "SECRETS_ENABLED=$SECRET_EXISTS" >> $GITHUB_OUTPUT - name: Checkout if: steps.secrets_set.outputs.SECRETS_ENABLED - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Install BYOND if: steps.secrets_set.outputs.SECRETS_ENABLED uses: ./.github/actions/restore_or_install_byond diff --git a/.github/workflows/codeowner_reviews.yml b/.github/workflows/codeowner_reviews.yml index 8ebaed36a53f..cc5d8e8a20e0 100644 --- a/.github/workflows/codeowner_reviews.yml +++ b/.github/workflows/codeowner_reviews.yml @@ -12,7 +12,7 @@ jobs: steps: # Checks-out your repository under $GITHUB_WORKSPACE, so the job can access it - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 #Parse the Codeowner file on non draft PRs - name: CodeOwnersParser diff --git a/.github/workflows/collect_data.yml b/.github/workflows/collect_data.yml index dba143f0e05f..b82575bfd873 100644 --- a/.github/workflows/collect_data.yml +++ b/.github/workflows/collect_data.yml @@ -27,7 +27,7 @@ jobs: required_build_versions: ${{ steps.setup_required_build_versions.outputs.required_build_versions }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Find Maps id: map_finder run: | diff --git a/.github/workflows/compare_screenshots.yml b/.github/workflows/compare_screenshots.yml index b0c024508296..f899e5e4b5cd 100644 --- a/.github/workflows/compare_screenshots.yml +++ b/.github/workflows/compare_screenshots.yml @@ -8,7 +8,7 @@ jobs: timeout-minutes: 15 runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Setup directory run: mkdir -p artifacts # If we ever add more artifacts, this is going to break, but it'll be obvious. diff --git a/.github/workflows/compile_all_maps.yml b/.github/workflows/compile_all_maps.yml index 528120051851..2512d5fa9796 100644 --- a/.github/workflows/compile_all_maps.yml +++ b/.github/workflows/compile_all_maps.yml @@ -14,7 +14,7 @@ jobs: timeout-minutes: 5 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Setup Bun uses: ./.github/actions/setup_bun - name: Restore BYOND from Cache @@ -35,7 +35,7 @@ jobs: timeout-minutes: 5 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Setup Bun uses: ./.github/actions/setup_bun - name: Restore BYOND from Cache diff --git a/.github/workflows/compile_changelogs.yml b/.github/workflows/compile_changelogs.yml index 01fcb6f7f0e8..eae668d4a4ed 100644 --- a/.github/workflows/compile_changelogs.yml +++ b/.github/workflows/compile_changelogs.yml @@ -35,7 +35,7 @@ jobs: - name: "Checkout" if: steps.value_holder.outputs.ACTIONS_ENABLED - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 25 persist-credentials: false diff --git a/.github/workflows/discord_discussions.yml b/.github/workflows/discord_discussions.yml index 439315cbb954..7f894fa18ca2 100644 --- a/.github/workflows/discord_discussions.yml +++ b/.github/workflows/discord_discussions.yml @@ -34,7 +34,7 @@ jobs: dotnet-quality: ga - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Build Tgstation.DiscordDiscussions run: dotnet publish -c Release -o discord_discussions_bins tools/Tgstation.DiscordDiscussions/Tgstation.DiscordDiscussions.csproj diff --git a/.github/workflows/gbp.yml b/.github/workflows/gbp.yml index 62e7dbec7dba..4931252e962e 100644 --- a/.github/workflows/gbp.yml +++ b/.github/workflows/gbp.yml @@ -12,7 +12,7 @@ jobs: issues: write # to apply labels steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Run Auto Labeler uses: actions/github-script@v7 with: @@ -40,7 +40,7 @@ jobs: echo "ACTIONS_ENABLED=$SECRET_EXISTS" >> $GITHUB_OUTPUT - name: Checkout if: steps.value_holder.outputs.ACTIONS_ENABLED - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Setup git if: steps.value_holder.outputs.ACTIONS_ENABLED run: | @@ -48,7 +48,7 @@ jobs: git config --global user.email "<>" - name: Checkout alternate branch if: steps.value_holder.outputs.ACTIONS_ENABLED - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: "gbp-balances" # The branch name path: gbp-balances diff --git a/.github/workflows/gbp_collect.yml b/.github/workflows/gbp_collect.yml index 644595e13365..1e83e860ab72 100644 --- a/.github/workflows/gbp_collect.yml +++ b/.github/workflows/gbp_collect.yml @@ -18,7 +18,7 @@ jobs: echo "ACTIONS_ENABLED=$SECRET_EXISTS" >> $GITHUB_OUTPUT - name: Checkout if: steps.value_holder.outputs.ACTIONS_ENABLED - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Setup git if: steps.value_holder.outputs.ACTIONS_ENABLED run: | @@ -26,7 +26,7 @@ jobs: git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" - name: Checkout alternate branch if: steps.value_holder.outputs.ACTIONS_ENABLED - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: "gbp-balances" # The branch name path: gbp-balances diff --git a/.github/workflows/generate_documentation.yml b/.github/workflows/generate_documentation.yml index 79c6f180ffe0..79dc2593681d 100644 --- a/.github/workflows/generate_documentation.yml +++ b/.github/workflows/generate_documentation.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-22.04 concurrency: gen-docs steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Setup cache uses: actions/cache@v4 with: diff --git a/.github/workflows/remove_guide_comments.yml b/.github/workflows/remove_guide_comments.yml index 2c65239133f8..4bbc0c602515 100644 --- a/.github/workflows/remove_guide_comments.yml +++ b/.github/workflows/remove_guide_comments.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Remove guide comments uses: actions/github-script@v7 with: diff --git a/.github/workflows/rerun_flaky_tests.yml b/.github/workflows/rerun_flaky_tests.yml index b7313767f4d0..fc9238bcf025 100644 --- a/.github/workflows/rerun_flaky_tests.yml +++ b/.github/workflows/rerun_flaky_tests.yml @@ -10,7 +10,7 @@ jobs: if: ${{ github.event.workflow_run.conclusion == 'failure' && github.event.workflow_run.run_attempt == 1 }} steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Rerun flaky tests uses: actions/github-script@v7 with: @@ -22,7 +22,7 @@ jobs: if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.run_attempt == 2 }} steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Report flaky tests uses: actions/github-script@v7 with: diff --git a/.github/workflows/run_integration_tests.yml b/.github/workflows/run_integration_tests.yml index c61d3238aa1e..3e7a052781df 100644 --- a/.github/workflows/run_integration_tests.yml +++ b/.github/workflows/run_integration_tests.yml @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 15 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Restore BYOND from Cache uses: ./.github/actions/restore_or_install_byond with: diff --git a/.github/workflows/run_linters.yml b/.github/workflows/run_linters.yml index 294286722cde..81c963c25edf 100644 --- a/.github/workflows/run_linters.yml +++ b/.github/workflows/run_linters.yml @@ -9,7 +9,7 @@ jobs: timeout-minutes: 5 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Restore SpacemanDMM cache uses: actions/cache@v4 with: diff --git a/.github/workflows/setup_build_artifact.yml b/.github/workflows/setup_build_artifact.yml index a6a6a94068bd..aaf4cfb45538 100644 --- a/.github/workflows/setup_build_artifact.yml +++ b/.github/workflows/setup_build_artifact.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 5 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Setup Bun uses: ./.github/actions/setup_bun - name: Restore BYOND from Cache diff --git a/.github/workflows/show_screenshot_test_results.yml b/.github/workflows/show_screenshot_test_results.yml index b48ca983b35e..6901e1d1d176 100644 --- a/.github/workflows/show_screenshot_test_results.yml +++ b/.github/workflows/show_screenshot_test_results.yml @@ -25,7 +25,7 @@ jobs: echo "SECRETS_ENABLED=$SECRET_EXISTS" >> $GITHUB_OUTPUT - name: Checkout if: steps.secrets_set.outputs.SECRETS_ENABLED - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Prepare module if: steps.secrets_set.outputs.SECRETS_ENABLED run: | diff --git a/.github/workflows/test_merge_bot.yml b/.github/workflows/test_merge_bot.yml index 00f6bd19cb59..101c3ad2b322 100644 --- a/.github/workflows/test_merge_bot.yml +++ b/.github/workflows/test_merge_bot.yml @@ -23,7 +23,7 @@ jobs: echo "GET_TEST_MERGES_URL=$SECRET_EXISTS" >> $GITHUB_OUTPUT - name: Checkout if: steps.secrets_set.outputs.GET_TEST_MERGES_URL - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Prepare module if: steps.secrets_set.outputs.GET_TEST_MERGES_URL run: | diff --git a/.github/workflows/tgs_test.yml b/.github/workflows/tgs_test.yml index 466d4ee86cd7..6c689ae7d1a0 100644 --- a/.github/workflows/tgs_test.yml +++ b/.github/workflows/tgs_test.yml @@ -64,7 +64,7 @@ jobs: dotnet-version: 8.0.x - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Test TGS Integration run: dotnet run -c Release --project tools/tgs_test ${{ github.repository }} /tgs_instances/tgstation ${{ env.TGS_API_PORT }} ${{ github.event.pull_request.head.sha || github.sha }} ${{ secrets.GITHUB_TOKEN }} ${{ env.PR_NUMBER }} diff --git a/.github/workflows/update_tgs_dmapi.yml b/.github/workflows/update_tgs_dmapi.yml index 977a8affc520..885ac26c8391 100644 --- a/.github/workflows/update_tgs_dmapi.yml +++ b/.github/workflows/update_tgs_dmapi.yml @@ -14,7 +14,7 @@ jobs: pull-requests: write steps: - name: Clone - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Branch run: | diff --git a/Dockerfile b/Dockerfile index 2265d03ada62..332d18e840fc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,6 +12,7 @@ FROM base AS byond WORKDIR /byond RUN apt-get install -y --no-install-recommends \ + libcurl4 \ curl \ unzip \ make \ diff --git a/_maps/RandomRuins/IceRuins/icemoon_underground_mining_site.dmm b/_maps/RandomRuins/IceRuins/icemoon_underground_mining_site.dmm index 0ea4048d1276..137ddbbca247 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_underground_mining_site.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_underground_mining_site.dmm @@ -74,9 +74,10 @@ /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/underground/explored) "mQ" = ( -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /turf/open/misc/asteroid/snow/icemoon, /area/icemoon/underground/explored) @@ -103,9 +104,10 @@ /area/icemoon/underground/explored) "pi" = ( /obj/effect/turf_decal/weather/snow/corner, -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /turf/open/misc/ice/icemoon, /area/icemoon/underground/explored) @@ -121,17 +123,19 @@ /area/icemoon/underground/explored) "rx" = ( /obj/structure/flora/rock/pile/icy, -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /turf/open/misc/asteroid/snow/icemoon, /area/icemoon/underground/explored) "rI" = ( /obj/effect/decal/cleanable/glass, -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /turf/open/misc/ice/icemoon, /area/icemoon/underground/explored) @@ -151,9 +155,10 @@ /turf/open/misc/asteroid/snow/icemoon, /area/icemoon/underground/explored) "uN" = ( -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /turf/open/misc/ice/icemoon, /area/icemoon/underground/explored) @@ -161,9 +166,10 @@ /obj/effect/turf_decal/weather/snow/corner{ dir = 5 }, -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /turf/open/misc/ice/icemoon, /area/icemoon/underground/explored) @@ -171,9 +177,10 @@ /obj/effect/turf_decal/weather/snow/corner{ dir = 1 }, -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /turf/open/misc/ice/icemoon, /area/icemoon/underground/explored) @@ -215,9 +222,10 @@ /obj/effect/turf_decal/weather/snow/corner{ dir = 10 }, -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /turf/open/misc/ice/icemoon, /area/icemoon/underground/explored) @@ -303,9 +311,10 @@ /obj/effect/turf_decal/weather/snow/corner{ dir = 4 }, -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /turf/open/misc/ice/icemoon, /area/icemoon/underground/explored) diff --git a/_maps/RandomRuins/IceRuins/icemoon_underground_syndidome.dmm b/_maps/RandomRuins/IceRuins/icemoon_underground_syndidome.dmm index 94bdf86b23d7..f93bfc737a0f 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_underground_syndidome.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_underground_syndidome.dmm @@ -560,6 +560,19 @@ /obj/machinery/light/small/red/directional/west, /turf/open/floor/mineral/plastitanium/red, /area/ruin/syndibiodome) +"hC" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 9 + }, +/obj/structure/closet/syndicate, +/obj/item/clothing/mask/gas/syndicate, +/obj/machinery/light/small/dim/directional/west, +/obj/item/polymorph_belt/functioning, +/obj/item/pen/edagger, +/obj/item/clothing/under/costume/seifuku/red, +/obj/structure/sign/poster/contraband/communist_state/directional/west, +/turf/open/floor/carpet/green, +/area/ruin/syndibiodome) "hF" = ( /obj/structure/chair/office/tactical{ dir = 8 @@ -1320,6 +1333,10 @@ }, /turf/open/floor/mineral/plastitanium/red, /area/ruin/syndibiodome) +"qJ" = ( +/obj/effect/turf_decal/trimline/tram/filled, +/turf/closed/indestructible/syndicate, +/area/ruin/syndibiodome) "qN" = ( /turf/closed/indestructible/syndicate, /area/ruin/syndibiodome) @@ -2192,9 +2209,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark, /area/ruin/syndibiodome) -"zM" = ( -/turf/closed/indestructible/syndicate/nodiagonal, -/area/ruin/syndibiodome) "zP" = ( /obj/machinery/door/airlock/hatch{ name = "Observation Room" @@ -3077,19 +3091,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/ruin/syndibiodome) -"Lg" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 9 - }, -/obj/structure/closet/syndicate, -/obj/item/clothing/mask/gas/syndicate, -/obj/machinery/light/small/dim/directional/west, -/obj/item/polymorph_belt/functioning, -/obj/item/pen/edagger, -/obj/item/clothing/under/costume/seifuku/red, -/obj/structure/sign/poster/contraband/communist_state/directional/west, -/turf/open/floor/carpet/green, -/area/ruin/syndibiodome) "Lm" = ( /obj/effect/turf_decal/siding/wideplating/dark{ dir = 5 @@ -3411,10 +3412,6 @@ /obj/effect/turf_decal/trimline/neutral/line, /turf/open/floor/iron/dark, /area/ruin/syndibiodome) -"Os" = ( -/obj/effect/turf_decal/trimline/tram/filled, -/turf/closed/indestructible/syndicate/nodiagonal, -/area/ruin/syndibiodome) "Oy" = ( /obj/effect/spawner/structure/window/reinforced/plasma/plastitanium, /obj/machinery/door/poddoor/shutters/indestructible{ @@ -4527,9 +4524,9 @@ mZ ys ys ys -zM +qN zT -zM +qN ys tL JU @@ -4573,11 +4570,11 @@ mZ ys ys ys -zM -zM +qN +qN IF -zM -zM +qN +qN LN tL UG @@ -4620,11 +4617,11 @@ ys ck ys ys -zM +qN QM VJ MK -zM +qN ys ys ys @@ -4666,13 +4663,13 @@ ys ys ys ys -zM -zM -zM +qN +qN +qN OH -zM -zM -zM +qN +qN +qN ys ys LN @@ -4710,17 +4707,17 @@ ys ys ys ys -zM -zM -zM -zM +qN +qN +qN +qN Tc bb ui oq Mc -zM -zM +qN +qN ys ys ys @@ -4757,7 +4754,7 @@ ys ck ys ys -zM +qN Kl on xi @@ -4767,8 +4764,8 @@ xi xH ZD oq -zM -zM +qN +qN ys ys ys @@ -4803,22 +4800,22 @@ ys ys ys Hi -zM -zM +qN +qN mW -zM +qN Sr -zM +qN Ui zl YG qN Ux Bw -zM -zM -zM -zM +qN +qN +qN +qN qN ys LN @@ -4850,23 +4847,23 @@ ys jS ys ys -zM +qN Kl Kl -zM +qN Sr -zM -zM -zM -zM +qN +qN +qN +qN qN Gm NP OI -zM +qN AA ab -zM +qN qN ys Aw @@ -4896,16 +4893,16 @@ Wz RL pg pg -zM -zM +qN +qN Kl -zM -zM +qN +qN Ab -zM +qN Lm kX -zM +qN qN WH JQ @@ -4943,10 +4940,10 @@ ys bJ zd ys -zM +qN Db Kl -zM +qN kK MB oQ @@ -4990,10 +4987,10 @@ ha pg pg pg -zM +qN ic Kl -zM +qN rK YZ yH @@ -5037,10 +5034,10 @@ ys Gx uD ys -zM +qN wY Kl -zM +qN cB ja oQ @@ -5051,11 +5048,11 @@ sD Vw jR qx -zM +qN yi LR UK -zM +qN ys cO ys @@ -5084,25 +5081,25 @@ Wz RL pg pg -zM -zM +qN +qN mW -zM -zM -Os -zM +qN +qN +qJ +qN xf oH -zM +qN qN Tx vO qN -zM +qN OL AV -zM -zM +qN +qN ys ys LN @@ -5132,25 +5129,25 @@ ys AI ys ys -zM +qN Kl Kl Iq Ro -zM -zM -zM -zM +qN +qN +qN +qN GM Ax Ij ue -zM -zM -zM -zM -zM -zM +qN +qN +qN +qN +qN +qN ys ys ys @@ -5179,12 +5176,12 @@ ys ys ck Hi -zM -zM +qN +qN Ut Kl Ut -zM +qN qN qU Ss @@ -5197,8 +5194,8 @@ PY qh tk xq -zM -zM +qN +qN ys ys ys @@ -5227,8 +5224,8 @@ ys ys ys ys -zM -zM +qN +qN Kl Kl Kl @@ -5245,8 +5242,8 @@ Sr kw FW Sr -zM -zM +qN +qN ys cO ys @@ -5271,14 +5268,14 @@ mZ mZ ys ys -zM -zM -zM -zM -zM -zM -zM -zM +qN +qN +qN +qN +qN +qN +qN +qN YN rQ XC @@ -5293,7 +5290,7 @@ ip Sr Sr ux -zM +qN ys ys ys @@ -5317,15 +5314,15 @@ mZ mZ ys ys -zM -zM +qN +qN Dd Ex kb -zM +qN km SH -zM +qN wf XC nn @@ -5340,7 +5337,7 @@ WB ip Sr vg -zM +qN ys VG ys @@ -5363,8 +5360,8 @@ mZ mZ ys ys -zM -zM +qN +qN xP dl cJ @@ -5387,10 +5384,10 @@ WB WB my QS -zM -zM -zM -zM +qN +qN +qN +qN ys ys Dg @@ -5437,8 +5434,8 @@ Sr iH qN vl -zM -zM +qN +qN eM up ys @@ -5532,7 +5529,7 @@ ts qN xL BY -zM +qN Lv ys Wq @@ -5551,8 +5548,8 @@ mZ mZ ys ys -zM -zM +qN +qN Dr Mo gH @@ -5599,8 +5596,8 @@ mZ mZ ys ys -zM -zM +qN +qN NE TF iS @@ -5625,8 +5622,8 @@ Vv iH qN cu -zM -zM +qN +qN vZ JU ys @@ -5646,12 +5643,12 @@ mZ mZ ys ys -zM -zM -zM -zM -zM -zM +qN +qN +qN +qN +qN +qN qN vx qN @@ -5669,10 +5666,10 @@ WB WB GD ux -zM -zM -zM -zM +qN +qN +qN +qN ys ys vZ @@ -5693,8 +5690,8 @@ mZ mZ ys ck -zM -zM +qN +qN vH bp ir @@ -5716,7 +5713,7 @@ WB wf xi vg -zM +qN ys Nl ys @@ -5740,14 +5737,14 @@ mZ ys ys ys -zM +qN MP bp -zM -zM +qN +qN Ut -zM -zM +qN +qN qN QG Sr @@ -5763,7 +5760,7 @@ wf kO Sr QS -zM +qN xN ys ys @@ -5787,13 +5784,13 @@ ys ys ys ys -zM +qN qa bp -zM -zM +qN +qN dS -zM +qN pA qN VK @@ -5809,8 +5806,8 @@ CK uL xi jd -zM -zM +qN +qN ys ys ck @@ -5833,11 +5830,11 @@ ys ys ys ys -zM -zM +qN +qN Sv bp -zM +qN wx RH Do @@ -5855,8 +5852,8 @@ al hR QE WR -zM -zM +qN +qN ys ys ys @@ -5879,12 +5876,12 @@ mZ Gr ck ys -zM -zM +qN +qN rZ Ut bp -zM +qN Ra RX Do @@ -5893,18 +5890,18 @@ Va bK XC By -zM -zM +qN +qN Oy Oy -zM +qN ag vF hU -zM -zM -zM -zM +qN +qN +qN +qN ys jS ys @@ -5925,13 +5922,13 @@ mZ mZ mZ ys -zM -zM -zM -zM -zM +qN +qN +qN +qN +qN bp -zM +qN Pw Oi Do @@ -5939,19 +5936,19 @@ Uu kd gv Vv -zM -zM -zM +qN +qN +qN uE oV -zM -zM +qN +qN Ze -zM -zM +qN +qN Xt Se -zM +qN pg pg RL @@ -5972,23 +5969,23 @@ mZ mZ ys ys -zM -Lg +qN +hC xZ yt -zM +qN ON -zM -zM -zM -zM +qN +qN +qN +qN qN qN kq Vv -zM +qN ym -zM +qN aC ws Oy @@ -5998,7 +5995,7 @@ hA WB yU Zd -zM +qN ys zd bJ @@ -6018,12 +6015,12 @@ mZ (34,1,1) = {" mZ ys -zM -zM +qN +qN Uc qp sR -zM +qN bp bp LA @@ -6035,7 +6032,7 @@ uW Vv qN Ks -zM +qN tb sM Oy @@ -6045,7 +6042,7 @@ kQ WB FH Fn -zM +qN pg pg pg @@ -6069,20 +6066,20 @@ bB KS he OK -zM -zM -zM -zM -zM -zM -zM +qN +qN +qN +qN +qN +qN +qN qN pY XC XC To Ut -zM +qN Vj Uh Oy @@ -6092,7 +6089,7 @@ Mt WB iX cN -zM +qN ys uD fI @@ -6136,10 +6133,10 @@ qN qN SJ qN -zM +qN kz -zM -zM +qN +qN pg pg RL @@ -6163,7 +6160,7 @@ bB DL jT Lc -zM +qN uH EY WJ @@ -6185,7 +6182,7 @@ uS gB pE cb -zM +qN ys ys AI @@ -6206,22 +6203,22 @@ mZ (38,1,1) = {" mZ ys -zM -zM -zM -zM -zM -zM +qN +qN +qN +qN +qN +qN zu WJ NB -zM -zM -zM -zM -zM +qN +qN +qN +qN +qN To -zM +qN LU qN lg @@ -6230,9 +6227,9 @@ wR vJ Ye ZT -zM -zM -zM +qN +qN +qN xN ys ys @@ -6258,14 +6255,14 @@ Av ze hM OR -zM +qN mV WJ Ol -zM +qN ek Dc -zM +qN Mr Ut Mr @@ -6277,8 +6274,8 @@ of xj TL MX -zM -zM +qN +qN ys ys ys @@ -6312,19 +6309,19 @@ DS mA MM bu -zM +qN Kz Ut Ut Ut -zM +qN lx qC SY xk Jm Ib -zM +qN ys ys ys @@ -6348,30 +6345,30 @@ mZ mZ Gr ck -zM -zM -zM +qN +qN +qN tq -zM +qN SO xB vA -zM +qN oA fV -zM +qN Db io Ut cE -zM +qN DI Br nH oc cG -zM -zM +qN +qN ys ck ys @@ -6397,27 +6394,27 @@ mZ ys ys ys -zM -zM -zM -zM +qN +qN +qN +qN Nj GA -zM +qN UW -zM -zM +qN +qN qa TJ Ay -zM -zM -zM +qN +qN +qN wi aa Ba -zM -zM +qN +qN ys ys ys @@ -6445,25 +6442,25 @@ mZ ys ys ys -zM -zM +qN +qN jV Ie lh -zM -zM -zM -zM -zM -zM -zM -zM +qN +qN +qN +qN +qN +qN +qN +qN ys -zM -zM -zM -zM -zM +qN +qN +qN +qN +qN ys ys ys @@ -6493,12 +6490,12 @@ mZ ys ck ys -zM +qN XM me Hp -zM -zM +qN +qN ys ys ys @@ -6540,11 +6537,11 @@ mZ mZ ys ys -zM +qN si si si -zM +qN ys mZ mZ diff --git a/_maps/RandomRuins/SpaceRuins/dragoontomb.dmm b/_maps/RandomRuins/SpaceRuins/dragoontomb.dmm index b9bf82f72412..eb168fbedc76 100644 --- a/_maps/RandomRuins/SpaceRuins/dragoontomb.dmm +++ b/_maps/RandomRuins/SpaceRuins/dragoontomb.dmm @@ -426,9 +426,6 @@ /obj/structure/statue/dragonman, /turf/open/misc/asteroid/basalt/airless, /area/ruin/unpowered/no_grav) -"BU" = ( -/turf/open/space, -/area/space) "BX" = ( /obj/structure/stone_tile/block{ dir = 1 @@ -915,138 +912,138 @@ /area/ruin/unpowered/no_grav) (1,1,1) = {" -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP "} (2,1,1) = {" -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP "} (3,1,1) = {" -BU -BU -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP +TP +TP wD wD Rp Rp -BU -BU -BU -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP +TP +TP +TP Rp Rp Rp Rp Rp Rp -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP "} (4,1,1) = {" -BU -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP +TP wD wD wD @@ -1054,9 +1051,9 @@ Rp Rp Rp Rp -BU -BU -BU +TP +TP +TP Rp Rp Rp @@ -1071,24 +1068,24 @@ Rp Rp Rp Rp -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP "} (5,1,1) = {" -BU -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP +TP wD wD Rp @@ -1119,17 +1116,17 @@ Rp Rp Rp Rp -BU -BU -BU -BU +TP +TP +TP +TP "} (6,1,1) = {" -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP wD wD wD @@ -1162,15 +1159,15 @@ Rp Rp Rp Rp -BU -BU -BU +TP +TP +TP "} (7,1,1) = {" -BU -BU -BU -BU +TP +TP +TP +TP wD wD wD @@ -1204,14 +1201,14 @@ VZ Rp Rp Rp -BU -BU -BU +TP +TP +TP "} (8,1,1) = {" -BU -BU -BU +TP +TP +TP wD wD wD @@ -1246,14 +1243,14 @@ wD Rp Rp Rp -BU -BU -BU +TP +TP +TP "} (9,1,1) = {" -BU -BU -BU +TP +TP +TP Rp Rp Rp @@ -1289,13 +1286,13 @@ Rp Rp Rp Rp -BU -BU +TP +TP "} (10,1,1) = {" -BU -BU -BU +TP +TP +TP Rp Rp Rp @@ -1331,14 +1328,14 @@ Rp Rp Rp Rp -BU -BU +TP +TP "} (11,1,1) = {" -BU -BU -BU -BU +TP +TP +TP +TP Rp Rp Rp @@ -1373,13 +1370,13 @@ Rp Rp Rp Rp -BU -BU +TP +TP "} (12,1,1) = {" -BU -BU -BU +TP +TP +TP wD Rp Rp @@ -1415,13 +1412,13 @@ Rp Rp Rp wD -BU -BU +TP +TP "} (13,1,1) = {" -BU -BU -BU +TP +TP +TP wD Rp Rp @@ -1457,12 +1454,12 @@ Rp Rp Rp wD -BU -BU +TP +TP "} (14,1,1) = {" -BU -BU +TP +TP wD wD Rp @@ -1498,13 +1495,13 @@ Rp Rp wD wD -BU -BU -BU +TP +TP +TP "} (15,1,1) = {" -BU -BU +TP +TP wD Rp Rp @@ -1540,13 +1537,13 @@ Rp Rp wD wD -BU -BU +TP +TP TP "} (16,1,1) = {" -BU -BU +TP +TP wD Rp Rp @@ -1582,13 +1579,13 @@ Rp wD wD wD -BU -BU -BU +TP +TP +TP "} (17,1,1) = {" -BU -BU +TP +TP wD wD Rp @@ -1624,14 +1621,14 @@ Rp wD wD wD -BU -BU -BU +TP +TP +TP "} (18,1,1) = {" -BU -BU -BU +TP +TP +TP wD Rp Rp @@ -1666,14 +1663,14 @@ Rp wD wD wD -BU -BU -BU +TP +TP +TP "} (19,1,1) = {" -BU -BU -BU +TP +TP +TP wD Rp Rp @@ -1708,14 +1705,14 @@ Rp Rp wD wD -BU -BU -BU +TP +TP +TP "} (20,1,1) = {" -BU -BU -BU +TP +TP +TP wD Rp Rp @@ -1750,15 +1747,15 @@ Rp Rp Rp wD -BU -BU -BU +TP +TP +TP "} (21,1,1) = {" -BU -BU -BU -BU +TP +TP +TP +TP Rp Rp wD @@ -1793,15 +1790,15 @@ Rp Rp wD wD -BU -BU +TP +TP "} (22,1,1) = {" -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP Rp Rp Rl @@ -1835,15 +1832,15 @@ Rp Rp Rp Rp -BU -BU +TP +TP "} (23,1,1) = {" -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP Rp Rp Ew @@ -1876,16 +1873,16 @@ Rp Rp Rp Rp -BU -BU -BU +TP +TP +TP "} (24,1,1) = {" -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP wD Rp nm @@ -1918,19 +1915,19 @@ Rp Rp Rp Rp -BU -BU -BU +TP +TP +TP "} (25,1,1) = {" -BU -BU -BU -BU -BU -wD -Rp -Rp +TP +TP +TP +TP +TP +wD +Rp +Rp Rp Rp wD @@ -1961,15 +1958,15 @@ Rp Rp Rp Rp -BU -BU +TP +TP "} (26,1,1) = {" -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP wD wD Rp @@ -2003,15 +2000,15 @@ Rp Rp Rp Rp -BU -BU +TP +TP "} (27,1,1) = {" -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP wD wD Rp @@ -2045,16 +2042,16 @@ wD wD wD wD -BU -BU +TP +TP "} (28,1,1) = {" -BU -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP +TP wD Rp wD @@ -2087,17 +2084,17 @@ wD wD wD wD -BU -BU +TP +TP "} (29,1,1) = {" -BU -BU -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP +TP +TP Rp Rp we @@ -2128,19 +2125,19 @@ wD wD Rp Rp -BU -BU -BU +TP +TP +TP "} (30,1,1) = {" -BU -BU -BU -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP +TP +TP +TP Rp Rp Yf @@ -2171,19 +2168,19 @@ Rp Rp wD wD -BU -BU +TP +TP "} (31,1,1) = {" -BU -BU -BU -BU -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP +TP +TP +TP +TP Rp Rp Rp @@ -2212,20 +2209,20 @@ wD Rp Rp wD -BU -BU -BU +TP +TP +TP "} (32,1,1) = {" -BU -BU -BU -BU -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP +TP +TP +TP +TP Rp Rp Rp @@ -2254,21 +2251,21 @@ Rp Rp Rp Rp -BU -BU -BU +TP +TP +TP "} (33,1,1) = {" -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP Rp Rp Rp @@ -2296,22 +2293,22 @@ Rp Rp Rp Rp -BU -BU -BU +TP +TP +TP "} (34,1,1) = {" -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP Rp Rp Rp @@ -2338,23 +2335,23 @@ Rp Rp Rp Rp -BU -BU -BU +TP +TP +TP "} (35,1,1) = {" -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP TP Rp Rp @@ -2379,24 +2376,24 @@ Rp Rp Rp Rp -BU -BU -BU -BU +TP +TP +TP +TP "} (36,1,1) = {" -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP TP TP TP @@ -2420,29 +2417,29 @@ Rp Rp Rp Rp -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP "} (37,1,1) = {" -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP Rp Rp Rp @@ -2461,136 +2458,136 @@ Rp Rp Rp Rp -BU -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP +TP "} (38,1,1) = {" -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -Rp -Rp -Rp -Rp -Rp -Rp -BU -BU -BU -BU -Rp -Rp -Rp -BU -BU -BU -BU -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +Rp +Rp +Rp +Rp +Rp +Rp +TP +TP +TP +TP +Rp +Rp +Rp +TP +TP +TP +TP +TP +TP +TP +TP +TP "} (39,1,1) = {" -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -Rp -Rp -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +Rp +Rp +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP "} (40,1,1) = {" -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU -BU +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP +TP "} diff --git a/_maps/RandomZLevels/SnowCabin.dmm b/_maps/RandomZLevels/SnowCabin.dmm index 09fffa494c8f..91c1feb25456 100644 --- a/_maps/RandomZLevels/SnowCabin.dmm +++ b/_maps/RandomZLevels/SnowCabin.dmm @@ -2719,9 +2719,10 @@ /area/awaymission/cabin/caves) "pv" = ( /obj/effect/decal/cleanable/blood/old, -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /obj/structure/statue/snow/snowlegion{ anchored = 1; @@ -3080,16 +3081,18 @@ "ts" = ( /obj/effect/decal/cleanable/blood/old, /obj/effect/decal/remains/human, -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /turf/open/misc/asteroid/snow/snow_cabin, /area/awaymission/cabin/caves) "tC" = ( -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /turf/open/misc/asteroid/snow/snow_cabin, /area/awaymission/cabin/caves) @@ -3344,9 +3347,10 @@ /turf/open/floor/plating/snowed/snow_cabin, /area/awaymission/cabin/snowforest/sovietsurface) "vJ" = ( -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /obj/effect/decal/cleanable/plasma, /turf/open/misc/asteroid/snow/snow_cabin, @@ -3457,9 +3461,10 @@ /turf/open/misc/asteroid/snow/snow_cabin, /area/awaymission/cabin) "xw" = ( -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /obj/structure/statue/snow/snowlegion{ anchored = 1; @@ -3471,9 +3476,10 @@ "xx" = ( /obj/effect/decal/cleanable/blood/old, /obj/item/knife/shiv/carrot, -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /turf/open/misc/asteroid/snow/snow_cabin, /area/awaymission/cabin/caves) @@ -3684,9 +3690,10 @@ /area/awaymission/cabin/caves) "zI" = ( /obj/item/weldingtool/mini, -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /turf/open/misc/asteroid/snow/snow_cabin, /area/awaymission/cabin/caves) @@ -3926,9 +3933,10 @@ /turf/open/misc/ice/smooth, /area/awaymission/cabin/caves) "Dw" = ( -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /obj/effect/decal/cleanable/generic, /turf/open/misc/asteroid/snow/snow_cabin, @@ -4071,9 +4079,10 @@ /turf/open/floor/plating/snowed/smoothed, /area/awaymission/cabin/caves) "EU" = ( -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /obj/effect/decal/cleanable/blood/oil, /turf/open/misc/asteroid/snow/snow_cabin, @@ -4473,9 +4482,10 @@ /area/awaymission/cabin/caves) "Lj" = ( /obj/effect/decal/remains/xeno, -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /turf/open/misc/asteroid/snow/snow_cabin, /area/awaymission/cabin/caves) @@ -4551,9 +4561,10 @@ /area/awaymission/cabin/snowforest/sovietsurface) "Mk" = ( /obj/effect/decal/cleanable/blood/old, -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /turf/open/misc/asteroid/snow/snow_cabin, /area/awaymission/cabin/caves) @@ -4615,9 +4626,10 @@ /turf/open/floor/wood, /area/awaymission/cabin) "Nb" = ( -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /obj/effect/decal/remains/xeno/larva, /turf/open/misc/asteroid/snow/snow_cabin, @@ -4736,9 +4748,10 @@ /area/awaymission/cabin/snowforest) "Po" = ( /obj/effect/decal/remains/human, -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /turf/open/misc/asteroid/snow/snow_cabin, /area/awaymission/cabin/caves) @@ -4856,9 +4869,10 @@ /area/awaymission/cabin/snowforest/sovietsurface) "QT" = ( /obj/item/chair/stool, -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /turf/open/misc/asteroid/snow/snow_cabin, /area/awaymission/cabin/caves) @@ -4893,9 +4907,10 @@ /turf/open/misc/asteroid/snow/snow_cabin, /area/awaymission/cabin/snowforest) "RD" = ( -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /mob/living/basic/statue/frosty, /turf/open/misc/asteroid/snow/snow_cabin, @@ -5086,9 +5101,10 @@ /turf/open/floor/wood/freezing, /area/awaymission/cabin/lumbermill) "SS" = ( -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /obj/effect/decal/cleanable/molten_object/large, /turf/open/misc/asteroid/snow/snow_cabin, @@ -5148,9 +5164,10 @@ /turf/open/floor/wood, /area/awaymission/cabin) "TU" = ( -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /obj/effect/decal/cleanable/shreds, /turf/open/misc/asteroid/snow/snow_cabin, @@ -5326,9 +5343,10 @@ /area/awaymission/cabin/caves) "WH" = ( /obj/effect/decal/cleanable/blood/old, -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /obj/item/clothing/head/helmet/skull, /turf/open/misc/asteroid/snow/snow_cabin, @@ -5424,9 +5442,10 @@ "Yc" = ( /obj/effect/decal/cleanable/blood/old, /obj/item/melee/baseball_bat, -/obj/effect/decal/cleanable/glitter/blue{ +/obj/effect/decal/cleanable/glitter{ desc = "It looks like fancy glitter to me."; - name = "icy wind" + name = "icy wind"; + color = "4040ff" }, /turf/open/misc/asteroid/snow/snow_cabin, /area/awaymission/cabin/caves) diff --git a/_maps/RandomZLevels/caves.dmm b/_maps/RandomZLevels/caves.dmm index f507c0be1208..b8dc837fadf9 100644 --- a/_maps/RandomZLevels/caves.dmm +++ b/_maps/RandomZLevels/caves.dmm @@ -3,7 +3,7 @@ /turf/closed/indestructible/rock, /area/space/nearstation) "ab" = ( -/turf/open/space, +/turf/open/space/basic, /area/space) "ac" = ( /turf/closed/mineral/volcanic, diff --git a/_maps/RandomZLevels/moonoutpost19.dmm b/_maps/RandomZLevels/moonoutpost19.dmm index aa6aa8d80c97..a06679e94556 100644 --- a/_maps/RandomZLevels/moonoutpost19.dmm +++ b/_maps/RandomZLevels/moonoutpost19.dmm @@ -1,7 +1,4 @@ //MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE -"aa" = ( -/turf/open/space, -/area/space) "ab" = ( /obj/effect/turf_decal/tile/red, /obj/effect/turf_decal/tile/red{ @@ -52945,51 +52942,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -53202,51 +53199,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -53459,51 +53456,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -53716,51 +53713,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -53973,51 +53970,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -54230,51 +54227,6 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa IM IM IM @@ -54330,8 +54282,53 @@ IM IM IM IM -"} -(182,1,1) = {" +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +"} +(182,1,1) = {" IM IM IM @@ -54487,51 +54484,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -54744,51 +54741,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -55001,51 +54998,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -55258,51 +55255,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -55515,51 +55512,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -55772,51 +55769,6 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa IM IM IM @@ -55872,8 +55824,53 @@ IM IM IM IM -"} -(188,1,1) = {" +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +"} +(188,1,1) = {" IM IM IM @@ -56029,51 +56026,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -56286,51 +56283,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -56543,51 +56540,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -56800,51 +56797,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -57057,51 +57054,6 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa IM IM IM @@ -57157,8 +57109,53 @@ IM IM IM IM -"} -(193,1,1) = {" +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +"} +(193,1,1) = {" IM IM IM @@ -57314,51 +57311,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -57571,51 +57568,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -57828,51 +57825,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -58085,51 +58082,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -58342,51 +58339,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -58599,51 +58596,6 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa IM IM IM @@ -58699,8 +58651,53 @@ IM IM IM IM -"} -(199,1,1) = {" +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +"} +(199,1,1) = {" IM IM IM @@ -58856,51 +58853,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -59113,51 +59110,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -59370,51 +59367,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -59627,51 +59624,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -59884,51 +59881,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -60141,51 +60138,6 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa IM IM IM @@ -60241,8 +60193,53 @@ IM IM IM IM -"} -(205,1,1) = {" +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +"} +(205,1,1) = {" IM IM IM @@ -60398,51 +60395,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -60655,51 +60652,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -60912,51 +60909,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -61169,51 +61166,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -61426,51 +61423,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -61683,51 +61680,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -61940,51 +61937,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -62197,51 +62194,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -62454,51 +62451,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM @@ -62711,51 +62708,51 @@ zk zk zk zk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM +IM IM IM IM diff --git a/_maps/RandomZLevels/research.dmm b/_maps/RandomZLevels/research.dmm index e37038cf57d8..64f2a725a51f 100644 --- a/_maps/RandomZLevels/research.dmm +++ b/_maps/RandomZLevels/research.dmm @@ -1,6 +1,6 @@ //MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE "aa" = ( -/turf/open/space, +/turf/open/space/basic, /area/space) "ab" = ( /turf/closed/mineral, diff --git a/_maps/RandomZLevels/undergroundoutpost45.dmm b/_maps/RandomZLevels/undergroundoutpost45.dmm index b7d9cc58540b..25dbeb28cc12 100644 --- a/_maps/RandomZLevels/undergroundoutpost45.dmm +++ b/_maps/RandomZLevels/undergroundoutpost45.dmm @@ -1,6 +1,6 @@ //MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE "aa" = ( -/turf/open/space, +/turf/open/space/basic, /area/space) "ab" = ( /turf/closed/indestructible/riveted, diff --git a/_maps/map_files/CatwalkStation/CatwalkStation_2023.dmm b/_maps/map_files/CatwalkStation/CatwalkStation_2023.dmm index 4b2979d62294..a53d4f78e5bf 100644 --- a/_maps/map_files/CatwalkStation/CatwalkStation_2023.dmm +++ b/_maps/map_files/CatwalkStation/CatwalkStation_2023.dmm @@ -763,6 +763,9 @@ /area/station/security/warden) "amk" = ( /obj/item/radio/intercom/directional/south, +/obj/structure/closet/crate/trashcart/laundry, +/obj/effect/spawner/random/clothing/costume, +/obj/effect/spawner/random/clothing/backpack, /turf/open/floor/iron/cafeteria, /area/station/commons/locker) "ams" = ( @@ -2897,7 +2900,9 @@ /turf/open/floor/wood, /area/station/maintenance/starboard/central) "aVv" = ( -/obj/effect/decal/cleanable/glitter/pink, +/obj/effect/decal/cleanable/glitter{ + color = "ff8080" + }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -4598,10 +4603,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/port/fore) -"bvs" = ( -/obj/structure/lattice, -/turf/open/space, -/area/space/nearstation) "bvt" = ( /obj/machinery/telecomms/server/presets/security, /obj/effect/turf_decal/tile/red/fourcorners, @@ -8555,11 +8556,6 @@ /obj/machinery/light/directional, /turf/open/floor/iron/dark/smooth_large, /area/station/service/hydroponics) -"cAs" = ( -/obj/item/banner, -/obj/structure/disposalpipe/segment, -/turf/open/floor/plating, -/area/station/maintenance/port) "cAv" = ( /obj/effect/turf_decal/trimline/purple/filled/line{ dir = 1 @@ -11218,17 +11214,6 @@ }, /turf/open/floor/engine, /area/station/engineering/supermatter/room) -"doU" = ( -/obj/structure/table, -/obj/effect/spawner/random/bureaucracy/paper, -/obj/item/paper/fluff/ids_for_dummies{ - pixel_x = -6; - pixel_y = 14 - }, -/obj/item/pen, -/obj/structure/sign/poster/contraband/missing_gloves/directional/west, -/turf/open/floor/wood, -/area/station/commons/dorms) "dpo" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -12475,6 +12460,7 @@ /obj/machinery/power/apc/auto_name/directional/north, /obj/structure/cable, /obj/machinery/camera/autoname/directional/north, +/obj/machinery/washing_machine, /turf/open/floor/iron/cafeteria, /area/station/commons/locker) "dJB" = ( @@ -13006,7 +12992,9 @@ /turf/open/floor/iron/smooth, /area/station/science/robotics) "dRo" = ( -/obj/effect/decal/cleanable/glitter/pink, +/obj/effect/decal/cleanable/glitter{ + color = "ff8080" + }, /obj/effect/landmark/generic_maintenance_landmark, /turf/open/floor/plating, /area/station/maintenance/starboard/aft) @@ -15963,6 +15951,7 @@ "eLk" = ( /obj/structure/table, /obj/machinery/firealarm/directional/west, +/obj/effect/spawner/random/clothing/gloves, /turf/open/floor/iron/cafeteria, /area/station/commons/locker) "eLl" = ( @@ -17835,7 +17824,9 @@ /turf/open/floor/plating, /area/station/maintenance/department/science/central) "foP" = ( -/obj/effect/decal/cleanable/glitter/pink, +/obj/effect/decal/cleanable/glitter{ + color = "ff8080" + }, /obj/machinery/power/apc/auto_name/directional/north, /obj/structure/cable, /turf/open/floor/plating, @@ -19116,6 +19107,13 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/construction) +"fHm" = ( +/obj/structure/table, +/obj/effect/spawner/random/bureaucracy/paper, +/obj/item/pen, +/obj/structure/sign/poster/contraband/missing_gloves/directional/west, +/turf/open/floor/wood, +/area/station/commons/dorms) "fHp" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/showcase/machinery/oldpod{ @@ -27827,7 +27825,9 @@ /turf/open/floor/eighties, /area/station/maintenance/hallway/abandoned_recreation) "iiT" = ( -/obj/effect/decal/cleanable/glitter/pink, +/obj/effect/decal/cleanable/glitter{ + color = "ff8080" + }, /obj/machinery/space_heater, /obj/structure/disposalpipe/segment{ dir = 10 @@ -27851,7 +27851,10 @@ /area/station/medical/virology) "iji" = ( /obj/structure/table, -/obj/structure/bedsheetbin, +/obj/item/reagent_containers/cup/glass/mug{ + pixel_x = -3; + pixel_y = 4 + }, /turf/open/floor/iron/cafeteria, /area/station/commons/locker) "ijl" = ( @@ -28710,23 +28713,6 @@ /obj/structure/cable, /turf/open/floor/iron/textured_large, /area/station/medical/abandoned) -"iwY" = ( -/obj/structure/table/wood, -/obj/item/paper/fluff/ids_for_dummies{ - pixel_x = 4; - pixel_y = 3 - }, -/obj/item/paper_bin{ - pixel_x = -5; - pixel_y = 4 - }, -/obj/item/stamp/head/hop{ - pixel_x = 8; - pixel_y = 4 - }, -/obj/structure/cable, -/turf/open/floor/carpet, -/area/station/command/heads_quarters/hop) "ixf" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -30672,12 +30658,11 @@ /area/station/hallway/primary/starboard) "iZD" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on, -/obj/effect/decal/cleanable/glitter/pink, +/obj/effect/decal/cleanable/glitter{ + color = "ff8080" + }, /turf/open/floor/plating, /area/station/maintenance/starboard/aft) -"iZH" = ( -/turf/open/space, -/area/space) "iZI" = ( /obj/machinery/computer/bank_machine, /obj/machinery/light_switch/directional/west{ @@ -32501,7 +32486,9 @@ /area/station/commons/dorms) "jyZ" = ( /obj/item/tank/internals/plasma/empty, -/obj/effect/decal/cleanable/glitter/pink, +/obj/effect/decal/cleanable/glitter{ + color = "ff8080" + }, /obj/structure/cable, /obj/structure/disposalpipe/segment{ dir = 4 @@ -33866,6 +33853,15 @@ /obj/structure/table/wood/fancy, /turf/open/floor/wood/large, /area/station/service/library/private) +"jTT" = ( +/obj/effect/decal/cleanable/dirt, +/obj/item/banner/blue{ + inspiration_available = 0 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/eighties, +/area/station/maintenance/hallway/abandoned_recreation) "jTZ" = ( /obj/effect/turf_decal/tile/dark_blue/half{ dir = 4 @@ -35905,6 +35901,7 @@ network = list("ss13","medbay"); c_tag = "Medbay - Upper Morgue" }, +/obj/structure/filingcabinet/chestdrawer, /turf/open/floor/iron/dark/textured_large, /area/station/medical/morgue) "kwQ" = ( @@ -38792,7 +38789,9 @@ /turf/open/floor/iron/dark, /area/station/hallway/secondary/exit/departure_lounge) "luD" = ( -/obj/effect/decal/cleanable/glitter/pink, +/obj/effect/decal/cleanable/glitter{ + color = "ff8080" + }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/disposalpipe/segment{ dir = 4 @@ -41098,7 +41097,9 @@ /turf/open/floor/engine, /area/station/engineering/supermatter/room) "mcs" = ( -/obj/effect/decal/cleanable/glitter/pink, +/obj/effect/decal/cleanable/glitter{ + color = "ff8080" + }, /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/disposalpipe/segment{ @@ -41174,11 +41175,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/textured, /area/station/cargo/warehouse) -"mdn" = ( -/obj/effect/decal/cleanable/dirt, -/obj/item/banner/red, -/turf/open/floor/eighties, -/area/station/maintenance/hallway/abandoned_recreation) "mdp" = ( /obj/structure/closet, /obj/effect/turf_decal/tile/purple/opposingcorners, @@ -41623,6 +41619,11 @@ /obj/structure/broken_flooring/corner/directional/east, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) +"mjk" = ( +/obj/structure/disposalpipe/segment, +/obj/item/banner/command/mundane, +/turf/open/floor/plating, +/area/station/maintenance/port) "mjm" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/closet/firecloset, @@ -49676,7 +49677,9 @@ /turf/open/floor/plating, /area/station/hallway/secondary/entry) "oEA" = ( -/obj/effect/decal/cleanable/glitter/pink, +/obj/effect/decal/cleanable/glitter{ + color = "ff8080" + }, /turf/open/floor/plating, /area/station/maintenance/starboard/aft) "oEI" = ( @@ -49836,6 +49839,7 @@ "oHh" = ( /obj/machinery/light/directional/north, /obj/machinery/light_switch/directional/north, +/obj/structure/closet/wardrobe/white, /turf/open/floor/iron/cafeteria, /area/station/commons/locker) "oHu" = ( @@ -54205,6 +54209,7 @@ pixel_x = -4; pixel_y = 9 }, +/obj/effect/spawner/random/entertainment/coin, /turf/open/floor/iron/cafeteria, /area/station/commons/locker) "pSY" = ( @@ -59315,6 +59320,7 @@ /obj/item/clothing/suit/hooded/wintercoat, /obj/item/clothing/shoes/winterboots, /obj/machinery/status_display/ai/directional/south, +/obj/effect/spawner/random/clothing/backpack, /turf/open/floor/iron, /area/station/commons/dorms) "rwh" = ( @@ -61121,7 +61127,9 @@ /turf/open/floor/iron, /area/station/science/xenobiology/hallway) "rYa" = ( -/obj/effect/decal/cleanable/glitter/pink, +/obj/effect/decal/cleanable/glitter{ + color = "ff8080" + }, /obj/effect/spawner/random/maintenance, /turf/open/floor/plating, /area/station/maintenance/starboard/aft) @@ -62150,7 +62158,9 @@ /turf/open/floor/iron/textured_large, /area/station/medical/abandoned) "spm" = ( -/obj/effect/decal/cleanable/glitter/pink, +/obj/effect/decal/cleanable/glitter{ + color = "ff8080" + }, /obj/structure/cable, /obj/structure/disposalpipe/segment{ dir = 4 @@ -64044,13 +64054,6 @@ "sTv" = ( /turf/closed/wall, /area/station/security/courtroom) -"sTK" = ( -/obj/effect/decal/cleanable/dirt, -/obj/item/banner/blue, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/eighties, -/area/station/maintenance/hallway/abandoned_recreation) "sTT" = ( /obj/structure/railing/corner/end/flip{ dir = 4 @@ -64629,6 +64632,7 @@ /obj/structure/closet/secure_closet/personal, /obj/item/clothing/suit/hooded/wintercoat, /obj/item/clothing/shoes/winterboots, +/obj/effect/spawner/random/clothing/backpack, /turf/open/floor/iron, /area/station/commons/dorms) "tda" = ( @@ -67612,8 +67616,7 @@ /turf/open/floor/plating/airless, /area/station/maintenance/space_hut) "tYi" = ( -/obj/structure/table, -/obj/effect/spawner/random/clothing/costume, +/obj/structure/closet/wardrobe/grey, /turf/open/floor/iron/cafeteria, /area/station/commons/locker) "tYl" = ( @@ -71168,6 +71171,13 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/grimy, /area/station/security/detectives_office/private_investigators_office) +"uXW" = ( +/obj/structure/table, +/obj/structure/bedsheetbin/empty{ + pixel_y = 6 + }, +/turf/open/floor/iron/cafeteria, +/area/station/commons/locker) "uXZ" = ( /obj/effect/spawner/random/structure/closet_maintenance, /obj/effect/spawner/random/maintenance/three, @@ -72327,6 +72337,7 @@ /area/station/maintenance/solars/starboard/fore) "vpp" = ( /obj/item/radio/intercom/directional/north, +/obj/effect/spawner/random/clothing/wardrobe_closet_colored, /turf/open/floor/iron/cafeteria, /area/station/commons/locker) "vpt" = ( @@ -75806,6 +75817,9 @@ /area/station/service/library) "wqE" = ( /obj/structure/extinguisher_cabinet/directional/south, +/obj/structure/closet/crate/trashcart/laundry, +/obj/effect/spawner/random/clothing/backpack, +/obj/effect/spawner/random/clothing/backpack, /turf/open/floor/iron/cafeteria, /area/station/commons/locker) "wqI" = ( @@ -76975,6 +76989,19 @@ /obj/machinery/holopad, /turf/open/floor/wood, /area/station/service/chapel) +"wJu" = ( +/obj/structure/table/wood, +/obj/item/paper_bin{ + pixel_x = -5; + pixel_y = 4 + }, +/obj/item/stamp/head/hop{ + pixel_x = 8; + pixel_y = 4 + }, +/obj/structure/cable, +/turf/open/floor/carpet, +/area/station/command/heads_quarters/hop) "wJI" = ( /obj/effect/turf_decal/siding/dark, /obj/effect/turf_decal/siding/dark{ @@ -77894,6 +77921,13 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/station/cargo/storage) +"wXR" = ( +/obj/effect/decal/cleanable/dirt, +/obj/item/banner/red{ + inspiration_available = 0 + }, +/turf/open/floor/eighties, +/area/station/maintenance/hallway/abandoned_recreation) "wXU" = ( /obj/item/bedsheet/captain, /obj/structure/bed, @@ -78522,8 +78556,10 @@ /turf/open/floor/iron/dark/smooth_large, /area/station/service/hydroponics) "xhT" = ( -/obj/structure/closet/crate/trashcart/laundry, -/obj/effect/spawner/random/clothing/costume, +/obj/structure/table, +/obj/structure/bedsheetbin{ + pixel_y = 6 + }, /turf/open/floor/iron/cafeteria, /area/station/commons/locker) "xhX" = ( @@ -107566,7 +107602,7 @@ jBd lOd nKj jIX -sTK +jTT vYH cFL xAj @@ -109155,7 +109191,7 @@ bFe rPE srD jDx -cAs +mjk ovx tRJ dWj @@ -112993,7 +113029,7 @@ oTK tQI eLU eLU -iZH +dcE gmE bYe ltW @@ -113236,7 +113272,7 @@ dDX vuO ugN tGb -iwY +wJu loc ltm kRk @@ -113249,8 +113285,8 @@ iis iis iis aWV -bvs -bvs +heR +heR gmE rgb qeX @@ -113506,7 +113542,7 @@ dNc rPQ qCe aWV -iZH +dcE gmE gmE bTU @@ -113763,7 +113799,7 @@ mYf qSv sSY lll -iZH +dcE gmE rVE eRs @@ -114020,7 +114056,7 @@ wTU vCW jkn lll -bvs +heR gmE mcX eRs @@ -114277,7 +114313,7 @@ duE ibO ibO lll -iZH +dcE gmE mbY eRs @@ -114534,7 +114570,7 @@ sAm wtz iXw lll -bvs +heR gmE czp aZd @@ -114791,7 +114827,7 @@ cSO jMo lmA gDc -iZH +dcE gmE irL lbT @@ -115048,7 +115084,7 @@ yes xvw tRt lll -bvs +heR gmE xef vFZ @@ -115305,7 +115341,7 @@ aNb gzt jFp lll -iZH +dcE gmE eqa vFZ @@ -115562,7 +115598,7 @@ nFA oSb gBG aWV -iZH +dcE gmE gmE ruc @@ -115819,8 +115855,8 @@ nIo aWV aWV aWV -bvs -bvs +heR +heR gmE fQQ qeX @@ -116076,8 +116112,8 @@ aNb opj wXU aWV -iZH -iZH +dcE +dcE gmE lsW njT @@ -116822,7 +116858,7 @@ dTL dJx uzN oqd -sjO +uXW dCm nZb ayn @@ -119643,7 +119679,7 @@ pRO mcY tFy qNn -doU +fHm clF pRO ntw @@ -170535,7 +170571,7 @@ eIJ eIJ nKj ipm -mdn +wXR lOd gPW wKg diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index d5713b90b622..fdca48d02378 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -2,19 +2,6 @@ "aaa" = ( /turf/open/space/basic, /area/space) -"aab" = ( -/obj/effect/landmark/carpspawn, -/turf/open/space, -/area/space) -"aac" = ( -/obj/structure/lattice, -/obj/structure/grille, -/turf/open/space, -/area/space/nearstation) -"aad" = ( -/obj/structure/lattice, -/turf/open/space, -/area/space/nearstation) "aaf" = ( /obj/structure/sign/directions/engineering{ desc = "A sign that shows there are doors here. There are doors everywhere!"; @@ -89,10 +76,6 @@ "abi" = ( /turf/closed/wall, /area/station/construction/mining/aux_base) -"abj" = ( -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/space/nearstation) "abm" = ( /obj/effect/landmark/start/hangover, /obj/machinery/status_display/ai/directional/north, @@ -1228,11 +1211,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/engineering/supermatter/room) -"aoP" = ( -/obj/structure/cable, -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/station/solars/starboard/fore) "aoS" = ( /obj/structure/cable, /obj/machinery/computer/security{ @@ -2002,10 +1980,6 @@ /obj/machinery/light/small/directional/west, /turf/open/floor/iron, /area/station/hallway/primary/starboard) -"awk" = ( -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/station/solars/port/fore) "awl" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/loading_area{ @@ -2192,6 +2166,12 @@ /obj/effect/turf_decal/trimline/blue/filled/line, /turf/open/floor/iron/white, /area/station/medical/medbay) +"azt" = ( +/obj/structure/lattice, +/obj/structure/window/reinforced/spawner/directional/south, +/obj/structure/window/reinforced/spawner/directional/west, +/turf/open/space/basic, +/area/space/nearstation) "azy" = ( /obj/effect/turf_decal/tile/yellow{ dir = 1 @@ -2560,11 +2540,6 @@ /obj/item/clothing/under/rank/civilian/lawyer/black/skirt, /turf/open/floor/wood, /area/station/commons/dorms) -"aFo" = ( -/obj/structure/lattice, -/obj/structure/grille/broken, -/turf/open/space, -/area/space/nearstation) "aFp" = ( /obj/structure/sign/warning/secure_area/directional/south, /obj/effect/turf_decal/trimline/purple/filled/line{ @@ -2895,14 +2870,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/science/robotics/mechbay) -"aJC" = ( -/obj/docking_port/stationary/random{ - dir = 4; - name = "lavaland"; - shuttle_id = "pod_3_lavaland" - }, -/turf/open/space, -/area/space) "aJD" = ( /turf/closed/wall, /area/space/nearstation) @@ -3280,11 +3247,6 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/iron, /area/station/hallway/secondary/command) -"aOl" = ( -/obj/structure/window/reinforced/spawner/directional/west, -/obj/structure/lattice, -/turf/open/space, -/area/space/nearstation) "aOr" = ( /obj/structure/disposalpipe/segment, /obj/effect/turf_decal/tile/yellow{ @@ -4074,6 +4036,12 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/engineering/atmos) +"aYy" = ( +/obj/structure/window/reinforced/spawner/directional/south, +/obj/structure/window/reinforced/spawner/directional/east, +/obj/structure/lattice, +/turf/open/space/basic, +/area/space/nearstation) "aYF" = ( /obj/machinery/door/airlock/command/glass{ name = "Departures Customs Desk" @@ -4335,11 +4303,6 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/entry) -"bbD" = ( -/obj/structure/lattice/catwalk, -/obj/structure/cable, -/turf/open/space, -/area/station/solars/port/aft) "bbH" = ( /obj/machinery/duct, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -6216,11 +6179,6 @@ }, /turf/open/floor/iron/grimy, /area/station/command/heads_quarters/hos) -"bAU" = ( -/obj/structure/window/reinforced/spawner/directional/east, -/obj/structure/lattice, -/turf/open/space, -/area/space/nearstation) "bAV" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -6248,10 +6206,6 @@ /obj/machinery/firealarm/directional/east, /turf/open/floor/iron, /area/station/hallway/secondary/entry) -"bBc" = ( -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/station/solars/port/aft) "bBd" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -6978,6 +6932,13 @@ /obj/effect/landmark/start/hangover, /turf/open/floor/iron/grimy, /area/station/command/heads_quarters/ce) +"bIo" = ( +/obj/structure/lattice, +/obj/structure/transit_tube/curved/flipped{ + dir = 4 + }, +/turf/open/space/basic, +/area/space/nearstation) "bIr" = ( /obj/structure/table/wood, /obj/item/flashlight/lamp, @@ -7433,13 +7394,6 @@ /obj/structure/cable, /turf/open/floor/iron/white, /area/station/medical/virology) -"bNv" = ( -/obj/structure/lattice/catwalk, -/obj/structure/window/reinforced/spawner/directional/south, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/space, -/area/space/nearstation) "bNB" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -7630,6 +7584,11 @@ /obj/effect/turf_decal/tile/yellow/opposingcorners, /turf/open/floor/iron, /area/station/commons/lounge) +"bQY" = ( +/obj/structure/lattice/catwalk, +/obj/structure/sign/warning/directional/east, +/turf/open/space/basic, +/area/space/nearstation) "bRe" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -7750,25 +7709,6 @@ /obj/structure/sign/warning/vacuum, /turf/closed/wall, /area/space/nearstation) -"bRQ" = ( -/obj/structure/lattice, -/obj/structure/transit_tube/curved/flipped{ - dir = 4 - }, -/turf/open/space, -/area/space/nearstation) -"bRR" = ( -/obj/structure/lattice, -/obj/structure/transit_tube/crossing/horizontal, -/turf/open/space, -/area/space/nearstation) -"bRS" = ( -/obj/structure/lattice, -/obj/structure/transit_tube/curved{ - dir = 8 - }, -/turf/open/space, -/area/space/nearstation) "bRV" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -7965,13 +7905,6 @@ /obj/item/storage/belt/utility, /turf/open/floor/iron, /area/station/cargo/storage) -"bTJ" = ( -/obj/structure/lattice, -/obj/structure/transit_tube/diagonal{ - dir = 4 - }, -/turf/open/space, -/area/space/nearstation) "bTN" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -8318,11 +8251,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/science/genetics) -"bYm" = ( -/obj/structure/lattice, -/obj/structure/transit_tube/diagonal, -/turf/open/space, -/area/space/nearstation) "bYo" = ( /obj/machinery/door/poddoor/shutters/preopen{ dir = 8; @@ -8424,6 +8352,12 @@ }, /turf/open/floor/wood, /area/station/service/library/abandoned) +"bZF" = ( +/obj/structure/lattice, +/obj/structure/window/reinforced/spawner/directional/north, +/obj/structure/window/reinforced/spawner/directional/west, +/turf/open/space/basic, +/area/space/nearstation) "bZJ" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/cable, @@ -8492,20 +8426,6 @@ "cao" = ( /turf/closed/wall, /area/station/service/library) -"cap" = ( -/obj/structure/lattice, -/obj/structure/transit_tube/curved{ - dir = 4 - }, -/turf/open/space, -/area/space/nearstation) -"caq" = ( -/obj/structure/lattice, -/obj/structure/transit_tube/curved/flipped{ - dir = 8 - }, -/turf/open/space, -/area/space/nearstation) "cau" = ( /obj/machinery/computer/security/telescreen/entertainment/directional/west, /obj/effect/turf_decal/tile/neutral/half/contrasted{ @@ -8824,6 +8744,13 @@ }, /turf/open/floor/iron, /area/station/construction/mining/aux_base) +"ceu" = ( +/obj/structure/lattice, +/obj/structure/transit_tube/curved{ + dir = 4 + }, +/turf/open/space/basic, +/area/space/nearstation) "ceC" = ( /obj/structure/table/wood, /obj/item/storage/fancy/candle_box, @@ -12090,10 +12017,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/service/chapel/funeral) -"cVr" = ( -/obj/structure/window/reinforced/spawner/directional/east, -/turf/open/space, -/area/space/nearstation) "cVx" = ( /obj/effect/turf_decal/stripes/corner, /obj/effect/turf_decal/stripes/corner{ @@ -12145,12 +12068,6 @@ /obj/machinery/pipedispenser/disposal/transit_tube, /turf/open/floor/plating, /area/station/hallway/secondary/construction) -"cWJ" = ( -/obj/structure/lattice, -/obj/structure/window/reinforced/spawner/directional/north, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/space, -/area/space/nearstation) "cWX" = ( /obj/structure/chair/stool/directional/east, /obj/effect/turf_decal/trimline/red/filled/warning{ @@ -12512,6 +12429,12 @@ /obj/item/radio/intercom/directional/south, /turf/open/floor/iron/dark, /area/station/service/bar) +"dbJ" = ( +/obj/structure/window/reinforced/spawner/directional/south, +/obj/structure/window/reinforced/spawner/directional/west, +/obj/structure/lattice, +/turf/open/space/basic, +/area/space/nearstation) "dbO" = ( /obj/structure/chair/sofa/bench/right{ dir = 8 @@ -12747,6 +12670,11 @@ /obj/structure/reagent_dispensers/watertank, /turf/open/floor/plating, /area/station/maintenance/fore) +"deJ" = ( +/obj/structure/lattice, +/obj/structure/sign/warning/directional/west, +/turf/open/space/basic, +/area/space/nearstation) "deT" = ( /obj/structure/tank_dispenser/oxygen, /obj/machinery/light/directional/east, @@ -13120,6 +13048,13 @@ "dki" = ( /turf/closed/wall, /area/station/medical/psychology) +"dkm" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/lattice/catwalk, +/turf/open/space/basic, +/area/space/nearstation) "dkp" = ( /obj/structure/table, /obj/item/reagent_containers/cup/bottle/multiver{ @@ -14379,6 +14314,14 @@ "dzw" = ( /turf/closed/wall/r_wall, /area/station/security/brig) +"dAs" = ( +/obj/docking_port/stationary/random{ + dir = 4; + name = "lavaland"; + shuttle_id = "pod_3_lavaland" + }, +/turf/open/space/basic, +/area/space) "dBc" = ( /obj/effect/decal/cleanable/blood/old, /obj/effect/decal/remains/human, @@ -16130,11 +16073,6 @@ /obj/item/book/codex_gigas, /turf/open/floor/iron/dark, /area/station/service/library/printer) -"dXD" = ( -/obj/structure/window/reinforced/spawner/directional/south, -/obj/structure/window/reinforced/spawner/directional/east, -/turf/open/space, -/area/space/nearstation) "dXF" = ( /obj/structure/table/reinforced, /obj/machinery/light_switch/directional/south{ @@ -17441,9 +17379,6 @@ /obj/machinery/light/cold/directional/west, /turf/open/floor/engine/xenobio, /area/station/science/xenobiology) -"eqU" = ( -/turf/open/space, -/area/space) "erm" = ( /obj/structure/reagent_dispensers/plumbed{ dir = 4; @@ -17715,13 +17650,6 @@ }, /turf/open/floor/engine/xenobio, /area/station/science/xenobiology) -"etw" = ( -/obj/structure/lattice, -/obj/structure/sign/nanotrasen{ - pixel_y = 32 - }, -/turf/open/space, -/area/space/nearstation) "ety" = ( /obj/structure/cable, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ @@ -19064,11 +18992,6 @@ }, /turf/open/floor/iron/white, /area/station/command/heads_quarters/rd) -"eKN" = ( -/obj/structure/window/reinforced/spawner/directional/north, -/obj/structure/lattice, -/turf/open/space, -/area/space/nearstation) "eKQ" = ( /obj/structure/table/reinforced, /obj/item/weldingtool, @@ -19595,6 +19518,11 @@ dir = 1 }, /area/station/service/bar) +"eRb" = ( +/obj/structure/lattice, +/obj/structure/window/reinforced/spawner/directional/east, +/turf/open/space/basic, +/area/space/nearstation) "eRr" = ( /obj/effect/spawner/random/trash/moisture_trap, /turf/open/floor/plating, @@ -20040,12 +19968,6 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/iron, /area/station/hallway/secondary/exit/departure_lounge) -"eWj" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/cable, -/obj/structure/sign/poster/official/report_crimes/directional/west, -/turf/open/floor/plating, -/area/station/security/checkpoint/medical/medsci) "eWr" = ( /obj/machinery/door/poddoor/preopen{ id = "transitlock"; @@ -20120,12 +20042,6 @@ }, /turf/open/floor/iron, /area/station/science/ordnance/office) -"eXM" = ( -/obj/structure/lattice, -/obj/structure/window/reinforced/spawner/directional/north, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/space, -/area/space/nearstation) "eXN" = ( /obj/machinery/vending/wardrobe/engi_wardrobe, /obj/effect/turf_decal/delivery, @@ -20936,10 +20852,6 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron, /area/station/maintenance/department/crew_quarters/bar) -"fjf" = ( -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/station/solars/starboard/fore) "fjk" = ( /obj/structure/chair{ dir = 1; @@ -21078,12 +20990,6 @@ "flr" = ( /turf/open/floor/plating, /area/station/service/library/abandoned) -"flt" = ( -/obj/structure/lattice, -/obj/structure/window/reinforced/spawner/directional/north, -/obj/structure/window/reinforced/spawner/directional/west, -/turf/open/space, -/area/space/nearstation) "flw" = ( /obj/structure/disposalpipe/segment, /obj/structure/cable, @@ -21640,12 +21546,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/medical/pharmacy) -"fsr" = ( -/obj/structure/lattice, -/obj/structure/window/reinforced/spawner/directional/south, -/obj/structure/window/reinforced/spawner/directional/east, -/turf/open/space, -/area/space/nearstation) "fsv" = ( /obj/effect/turf_decal/plaque{ icon_state = "L8" @@ -22377,6 +22277,11 @@ }, /turf/open/floor/iron, /area/station/maintenance/port) +"fBF" = ( +/obj/structure/lattice/catwalk, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/space/basic, +/area/station/solars/starboard/fore) "fBG" = ( /obj/machinery/atmospherics/pipe/heat_exchanging/simple{ dir = 5 @@ -22519,6 +22424,11 @@ "fDF" = ( /turf/closed/wall/r_wall, /area/station/science/ordnance/office) +"fDJ" = ( +/obj/item/stack/cable_coil, +/obj/structure/lattice/catwalk, +/turf/open/space/basic, +/area/station/solars/starboard/aft) "fDO" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 4 @@ -22990,12 +22900,6 @@ }, /turf/open/floor/iron, /area/station/service/hydroponics) -"fJy" = ( -/obj/structure/lattice, -/obj/structure/window/reinforced/spawner/directional/north, -/obj/structure/window/reinforced/spawner/directional/east, -/turf/open/space, -/area/space/nearstation) "fJF" = ( /obj/machinery/firealarm/directional/east, /obj/structure/table, @@ -23086,11 +22990,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/maintenance/port/aft) -"fKU" = ( -/obj/structure/cable, -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/station/solars/port/fore) "fKY" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/table/wood, @@ -24103,9 +24002,6 @@ /obj/machinery/light/small/directional/north, /turf/open/floor/iron/dark, /area/station/engineering/transit_tube) -"fXz" = ( -/turf/open/space, -/area/space/nearstation) "fXC" = ( /obj/structure/cable, /obj/machinery/door/poddoor/preopen{ @@ -24759,11 +24655,6 @@ /obj/effect/landmark/start/medical_doctor, /turf/open/floor/iron/white, /area/station/medical/surgery/theatre) -"geN" = ( -/obj/structure/lattice/catwalk, -/obj/structure/cable, -/turf/open/space, -/area/station/solars/starboard/aft) "geP" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/door/airlock/command{ @@ -25026,6 +24917,12 @@ }, /turf/open/floor/iron, /area/station/commons/storage/tools) +"ghx" = ( +/obj/structure/lattice, +/obj/structure/window/reinforced/spawner/directional/north, +/obj/structure/window/reinforced/spawner/directional/east, +/turf/open/space/basic, +/area/space/nearstation) "ghA" = ( /obj/machinery/pdapainter/medbay, /obj/machinery/newscaster/directional/north, @@ -25046,6 +24943,11 @@ }, /turf/open/floor/iron, /area/station/maintenance/department/eva/abandoned) +"ghK" = ( +/obj/structure/lattice, +/obj/structure/transit_tube/crossing/horizontal, +/turf/open/space/basic, +/area/space/nearstation) "ghQ" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/door/poddoor/preopen{ @@ -25338,6 +25240,11 @@ }, /turf/open/floor/iron, /area/station/service/hydroponics) +"glz" = ( +/obj/structure/lattice/catwalk, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/space/basic, +/area/space/nearstation) "glW" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/yellow/half/contrasted{ @@ -27580,6 +27487,11 @@ /obj/machinery/power/apc/auto_name/directional/north, /turf/open/floor/wood, /area/station/command/meeting_room/council) +"gKN" = ( +/obj/structure/lattice, +/obj/item/toy/figure/ninja, +/turf/open/space/basic, +/area/space/nearstation) "gKW" = ( /obj/machinery/portable_atmospherics/canister, /obj/machinery/atmospherics/components/unary/portables_connector/visible{ @@ -29943,6 +29855,16 @@ /obj/item/kirbyplants/random, /turf/open/floor/plating, /area/station/science/research/abandoned) +"hrU" = ( +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ + dir = 10 + }, +/obj/structure/lattice/catwalk, +/turf/open/space/basic, +/area/space/nearstation) "hrV" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/neutral/full, @@ -30094,6 +30016,11 @@ }, /turf/open/floor/iron/white, /area/station/science/robotics/lab) +"htR" = ( +/obj/item/stack/cable_coil, +/obj/structure/lattice/catwalk, +/turf/open/space/basic, +/area/station/solars/port/aft) "htW" = ( /obj/item/kirbyplants/random, /obj/machinery/newscaster/directional/north, @@ -30622,14 +30549,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/maintenance/port/fore) -"hBu" = ( -/obj/docking_port/stationary/random{ - dir = 4; - name = "lavaland"; - shuttle_id = "pod_4_lavaland" - }, -/turf/open/space, -/area/space) "hBF" = ( /obj/structure/kitchenspike, /obj/effect/turf_decal/bot/left, @@ -30786,11 +30705,6 @@ }, /turf/open/floor/iron, /area/station/engineering/storage) -"hDU" = ( -/obj/structure/lattice/catwalk, -/obj/structure/cable, -/turf/open/space, -/area/space/nearstation) "hDX" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -32075,11 +31989,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/ai_monitored/aisat/exterior) -"hVE" = ( -/obj/structure/lattice/catwalk, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/space, -/area/space/nearstation) "hVI" = ( /obj/structure/table, /obj/item/plant_analyzer, @@ -32815,11 +32724,6 @@ "idT" = ( /turf/closed/wall/r_wall, /area/station/security/prison/garden) -"idU" = ( -/obj/structure/lattice, -/obj/structure/window/reinforced/spawner/directional/south, -/turf/open/space, -/area/space/nearstation) "iee" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -32979,13 +32883,6 @@ }, /turf/open/floor/iron, /area/station/security/office) -"igE" = ( -/obj/effect/turf_decal/trimline/red/filled/line{ - dir = 4 - }, -/obj/structure/sign/poster/official/report_crimes/directional/west, -/turf/open/floor/iron/white, -/area/station/science/research) "igI" = ( /obj/machinery/newscaster/directional/north, /obj/structure/cable, @@ -35700,6 +35597,13 @@ }, /turf/open/floor/iron, /area/station/engineering/lobby) +"iPf" = ( +/obj/structure/lattice, +/obj/structure/transit_tube/diagonal{ + dir = 4 + }, +/turf/open/space/basic, +/area/space/nearstation) "iPH" = ( /obj/structure/chair{ dir = 8 @@ -36450,16 +36354,6 @@ /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/floor/iron, /area/station/maintenance/port) -"iZn" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ - dir = 4 - }, -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/space/nearstation) "iZp" = ( /obj/structure/cable, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ @@ -37923,12 +37817,6 @@ /obj/effect/landmark/navigate_destination/chapel, /turf/open/floor/iron/grimy, /area/station/service/chapel) -"jpw" = ( -/obj/structure/window/reinforced/spawner/directional/south, -/obj/structure/window/reinforced/spawner/directional/west, -/obj/structure/lattice, -/turf/open/space, -/area/space/nearstation) "jpA" = ( /turf/open/floor/iron/grimy, /area/station/security/detectives_office/private_investigators_office) @@ -39290,16 +39178,6 @@ }, /turf/closed/wall/r_wall, /area/station/maintenance/port/aft) -"jGx" = ( -/obj/structure/disposalpipe/segment{ - dir = 10 - }, -/obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ - dir = 10 - }, -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/space/nearstation) "jGI" = ( /obj/machinery/atmospherics/pipe/bridge_pipe/yellow/visible, /obj/machinery/atmospherics/pipe/bridge_pipe/cyan/visible{ @@ -42508,11 +42386,6 @@ /obj/machinery/light/dim/directional/north, /turf/open/floor/iron, /area/station/service/abandoned_gambling_den/gaming) -"kvt" = ( -/obj/structure/lattice, -/obj/structure/sign/warning/electric_shock/directional/north, -/turf/open/space, -/area/space/nearstation) "kvu" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -42875,6 +42748,11 @@ /obj/structure/reagent_dispensers/water_cooler, /turf/open/floor/iron/white/smooth_large, /area/station/medical/psychology) +"kAB" = ( +/obj/structure/window/reinforced/spawner/directional/south, +/obj/structure/window/reinforced/spawner/directional/west, +/turf/open/space/basic, +/area/space/nearstation) "kAD" = ( /obj/structure/sign/warning/electric_shock, /turf/closed/wall/r_wall, @@ -43782,13 +43660,6 @@ }, /turf/open/floor/iron/dark, /area/station/engineering/transit_tube) -"kNB" = ( -/obj/structure/table/wood, -/obj/item/papercutter, -/obj/item/paper/fluff/ids_for_dummies, -/obj/item/radio/intercom/directional/east, -/turf/open/floor/wood, -/area/station/command/heads_quarters/hop) "kNC" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -43971,11 +43842,6 @@ }, /turf/open/floor/iron/cafeteria, /area/station/service/cafeteria) -"kQG" = ( -/obj/item/stack/cable_coil, -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/station/solars/port/aft) "kQK" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -44730,13 +44596,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/port) -"lbi" = ( -/obj/structure/lattice/catwalk, -/obj/structure/transit_tube/curved/flipped{ - dir = 8 - }, -/turf/open/space, -/area/space/nearstation) "lbl" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/green/visible, /obj/effect/turf_decal/stripes/line{ @@ -47826,6 +47685,11 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/engineering/atmos) +"lMb" = ( +/obj/structure/window/reinforced/spawner/directional/north, +/obj/structure/window/reinforced/spawner/directional/west, +/turf/open/space/basic, +/area/space/nearstation) "lMc" = ( /obj/structure/disposaloutlet{ dir = 8 @@ -49619,8 +49483,6 @@ /area/station/hallway/primary/central/aft) "mmf" = ( /obj/structure/window/reinforced/spawner/directional/west, -/obj/structure/window/reinforced/spawner/directional/south, -/obj/structure/filingcabinet/chestdrawer, /obj/effect/turf_decal/bot_white, /obj/effect/turf_decal/siding/dark_blue{ dir = 10 @@ -49630,6 +49492,7 @@ }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/smartfridge/organ, /turf/open/floor/iron/dark, /area/station/medical/morgue) "mmq" = ( @@ -50806,10 +50669,6 @@ "mAt" = ( /turf/closed/wall/r_wall, /area/station/service/abandoned_gambling_den) -"mAv" = ( -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/station/solars/starboard/aft) "mAA" = ( /obj/structure/sink/kitchen/directional/west, /turf/open/floor/iron/cafeteria, @@ -50933,6 +50792,11 @@ /obj/effect/spawner/random/structure/barricade, /turf/open/floor/iron, /area/station/maintenance/department/security) +"mBY" = ( +/obj/structure/lattice/catwalk, +/obj/structure/window/reinforced/spawner/directional/north, +/turf/open/space/basic, +/area/space/nearstation) "mCa" = ( /obj/structure/table/glass, /obj/item/paper_bin, @@ -53727,6 +53591,13 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/security/courtroom) +"noe" = ( +/obj/structure/lattice/catwalk, +/obj/structure/transit_tube/curved/flipped{ + dir = 8 + }, +/turf/open/space/basic, +/area/space/nearstation) "not" = ( /obj/effect/turf_decal/stripes/line{ dir = 10 @@ -54858,11 +54729,6 @@ /obj/item/pen/fountain, /turf/open/floor/wood/large, /area/station/service/library) -"nCB" = ( -/obj/structure/window/reinforced/spawner/directional/north, -/obj/structure/window/reinforced/spawner/directional/east, -/turf/open/space, -/area/space/nearstation) "nCI" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -55741,11 +55607,6 @@ /obj/machinery/light/directional/west, /turf/open/floor/iron/dark, /area/station/service/chapel) -"nOy" = ( -/obj/structure/lattice, -/obj/structure/window/reinforced/spawner/directional/west, -/turf/open/space, -/area/space/nearstation) "nOB" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -56814,13 +56675,6 @@ /obj/effect/turf_decal/tile/blue, /turf/open/floor/iron/white, /area/station/medical/paramedic) -"odd" = ( -/obj/docking_port/stationary/random{ - name = "lavaland"; - shuttle_id = "pod_2_lavaland" - }, -/turf/open/space, -/area/space) "odk" = ( /obj/structure/window/reinforced/spawner/directional/south, /obj/structure/window/reinforced/spawner/directional/west, @@ -56897,6 +56751,10 @@ }, /turf/open/floor/iron, /area/station/security/prison/safe) +"oeG" = ( +/obj/structure/lattice/catwalk, +/turf/open/space/basic, +/area/station/solars/starboard/fore) "oeW" = ( /obj/structure/table/wood, /obj/effect/decal/cleanable/dirt, @@ -56923,6 +56781,14 @@ }, /turf/open/floor/iron/white, /area/station/medical/virology) +"ofc" = ( +/obj/docking_port/stationary/random{ + dir = 4; + name = "lavaland"; + shuttle_id = "pod_4_lavaland" + }, +/turf/open/space/basic, +/area/space) "ofg" = ( /obj/structure/disposalpipe/segment, /obj/structure/cable, @@ -58941,12 +58807,6 @@ }, /turf/open/floor/engine, /area/station/science/genetics) -"oFv" = ( -/obj/docking_port/stationary/syndicate/northeast{ - dir = 8 - }, -/turf/open/space, -/area/space) "oFA" = ( /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -60134,6 +59994,13 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/department/science) +"oUP" = ( +/obj/structure/lattice, +/obj/structure/transit_tube/curved/flipped{ + dir = 8 + }, +/turf/open/space/basic, +/area/space/nearstation) "oUU" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/closet, @@ -60474,6 +60341,11 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/plating, /area/station/service/abandoned_gambling_den) +"pan" = ( +/obj/item/stack/cable_coil, +/obj/structure/lattice/catwalk, +/turf/open/space/basic, +/area/station/solars/starboard/fore) "paq" = ( /obj/effect/landmark/start/hangover, /turf/open/floor/wood, @@ -62366,10 +62238,6 @@ }, /turf/open/floor/iron/dark, /area/station/security/checkpoint/customs/aft) -"pzp" = ( -/obj/structure/window/reinforced/spawner/directional/north, -/turf/open/space, -/area/space/nearstation) "pzr" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -63097,6 +62965,12 @@ }, /turf/open/floor/iron/dark/corner, /area/station/maintenance/disposal/incinerator) +"pGu" = ( +/obj/structure/lattice, +/obj/structure/window/reinforced/spawner/directional/north, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/space/basic, +/area/space/nearstation) "pGv" = ( /obj/item/kirbyplants/random, /obj/machinery/light/small/directional/north, @@ -63145,11 +63019,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron/herringbone, /area/station/cargo/miningoffice) -"pHa" = ( -/obj/structure/lattice, -/obj/structure/sign/warning/directional/west, -/turf/open/space, -/area/space/nearstation) "pHd" = ( /obj/machinery/atmospherics/components/unary/portables_connector/visible{ dir = 4 @@ -63772,11 +63641,6 @@ /obj/machinery/light/small/directional/west, /turf/open/floor/iron/dark, /area/station/service/hydroponics/garden) -"pOH" = ( -/obj/structure/lattice/catwalk, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/space, -/area/station/solars/starboard/fore) "pOP" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/door/airlock/maintenance_hatch{ @@ -63956,11 +63820,6 @@ }, /turf/open/floor/iron, /area/station/engineering/storage_shared) -"pQx" = ( -/obj/structure/lattice, -/obj/structure/window/reinforced/spawner/directional/north, -/turf/open/space, -/area/space/nearstation) "pQN" = ( /obj/machinery/duct, /obj/effect/landmark/start/hangover, @@ -64258,12 +64117,6 @@ }, /turf/open/floor/iron, /area/station/medical/abandoned) -"pTR" = ( -/obj/structure/window/reinforced/spawner/directional/south, -/obj/structure/window/reinforced/spawner/directional/east, -/obj/structure/lattice, -/turf/open/space, -/area/space/nearstation) "pTT" = ( /obj/structure/sign/directions/engineering{ desc = "A sign that shows there are doors here. There are doors everywhere!"; @@ -64760,10 +64613,6 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/station/maintenance/disposal) -"pYJ" = ( -/obj/structure/window/reinforced/spawner/directional/south, -/turf/open/space, -/area/space/nearstation) "pYL" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/bridge_pipe/scrubbers/hidden{ @@ -65170,6 +65019,13 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/ai_monitored/aisat/exterior) +"qdJ" = ( +/obj/structure/lattice, +/obj/structure/sign/nanotrasen{ + pixel_y = -32 + }, +/turf/open/space/basic, +/area/space/nearstation) "qdP" = ( /obj/item/kirbyplants/random, /obj/structure/extinguisher_cabinet/directional/east, @@ -65677,6 +65533,11 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/security/prison) +"qkQ" = ( +/obj/structure/cable, +/obj/structure/lattice/catwalk, +/turf/open/space/basic, +/area/station/solars/starboard/fore) "qkS" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -66099,20 +65960,15 @@ /obj/machinery/computer/security/telescreen/ordnance/directional/west, /turf/open/floor/iron/dark, /area/station/science/ordnance/testlab) -"qpQ" = ( -/obj/structure/window/reinforced/spawner/directional/north, -/obj/structure/window/reinforced/spawner/directional/west, -/turf/open/space, -/area/space/nearstation) "qpU" = ( /obj/effect/turf_decal/trimline/neutral/mid_joiner{ dir = 4 }, -/obj/machinery/smartfridge/organ, /obj/effect/turf_decal/bot, /obj/effect/turf_decal/tile/dark_blue/anticorner/contrasted{ dir = 4 }, +/obj/structure/filingcabinet/chestdrawer, /turf/open/floor/iron/dark, /area/station/medical/morgue) "qqe" = ( @@ -66610,6 +66466,11 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat_interior) +"qxf" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable, +/turf/open/space/basic, +/area/station/solars/starboard/aft) "qxi" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 4 @@ -68127,11 +67988,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/engineering/atmos) -"qPm" = ( -/obj/structure/lattice/catwalk, -/obj/structure/window/reinforced/spawner/directional/north, -/turf/open/space, -/area/space/nearstation) "qPp" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/siding/purple{ @@ -68244,6 +68100,11 @@ "qQM" = ( /turf/closed/wall, /area/station/maintenance/port/aft) +"qQO" = ( +/obj/structure/lattice, +/obj/structure/transit_tube/diagonal, +/turf/open/space/basic, +/area/space/nearstation) "qQY" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -68730,11 +68591,6 @@ }, /turf/open/floor/iron, /area/station/engineering/main) -"qYG" = ( -/obj/structure/lattice/catwalk, -/obj/effect/landmark/generic_maintenance_landmark, -/turf/open/space, -/area/station/solars/port/aft) "qYL" = ( /turf/closed/wall, /area/station/medical/morgue) @@ -70647,12 +70503,6 @@ /obj/item/toy/crayon/spraycan/roboticist, /turf/open/floor/iron, /area/station/science/robotics/lab) -"ryt" = ( -/obj/structure/lattice, -/obj/structure/window/reinforced/spawner/directional/south, -/obj/structure/window/reinforced/spawner/directional/west, -/turf/open/space, -/area/space/nearstation) "ryA" = ( /obj/structure/chair{ dir = 1 @@ -71307,6 +71157,11 @@ /obj/machinery/light/directional/west, /turf/open/floor/iron, /area/station/hallway/secondary/exit) +"rHK" = ( +/obj/structure/lattice, +/obj/structure/window/reinforced/spawner/directional/north, +/turf/open/space/basic, +/area/space/nearstation) "rHQ" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/line{ @@ -72525,13 +72380,6 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/iron, /area/station/maintenance/port/fore) -"rUw" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/space/nearstation) "rUM" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /obj/effect/mapping_helpers/burnt_floor, @@ -72722,11 +72570,6 @@ /obj/structure/chair, /turf/open/floor/iron/dark, /area/station/service/chapel/funeral) -"rWQ" = ( -/obj/structure/lattice, -/obj/effect/spawner/random/structure/grille, -/turf/open/space, -/area/space/nearstation) "rWZ" = ( /obj/machinery/status_display/evac/directional/south, /obj/machinery/duct, @@ -72875,6 +72718,11 @@ }, /turf/open/floor/iron, /area/station/science/xenobiology) +"rYO" = ( +/obj/structure/lattice, +/obj/structure/window/reinforced/spawner/directional/west, +/turf/open/space/basic, +/area/space/nearstation) "rYR" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/closet/emcloset, @@ -73983,10 +73831,6 @@ /obj/machinery/portable_atmospherics/canister/nitrogen, /turf/open/floor/engine/n2, /area/station/engineering/atmos) -"smV" = ( -/obj/structure/window/reinforced/spawner/directional/west, -/turf/open/space, -/area/space/nearstation) "snc" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -74284,6 +74128,13 @@ }, /turf/open/floor/iron/checker, /area/station/maintenance/disposal/incinerator) +"srf" = ( +/obj/structure/lattice/catwalk, +/obj/structure/window/reinforced/spawner/directional/south, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/space/basic, +/area/space/nearstation) "srg" = ( /obj/structure/table/glass, /obj/item/food/pizzaslice/vegetable, @@ -75236,6 +75087,12 @@ "sBX" = ( /turf/closed/wall, /area/station/service/bar) +"sCb" = ( +/obj/structure/lattice, +/obj/structure/window/reinforced/spawner/directional/north, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/space/basic, +/area/space/nearstation) "sCd" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/shieldgen, @@ -76828,6 +76685,12 @@ /obj/structure/sign/warning/electric_shock/directional/east, /turf/open/space/basic, /area/space/nearstation) +"sVo" = ( +/obj/structure/table/wood, +/obj/item/papercutter, +/obj/item/radio/intercom/directional/east, +/turf/open/floor/wood, +/area/station/command/heads_quarters/hop) "sVC" = ( /obj/machinery/atmospherics/components/unary/thermomachine/freezer{ dir = 4 @@ -80893,6 +80756,12 @@ /obj/structure/water_source/puddle, /turf/open/misc/sandy_dirt, /area/station/service/hydroponics/garden) +"tWY" = ( +/obj/docking_port/stationary/syndicate/northeast{ + dir = 8 + }, +/turf/open/space/basic, +/area/space) "tXe" = ( /obj/effect/turf_decal/loading_area/red{ dir = 4 @@ -82540,6 +82409,11 @@ /obj/machinery/photocopier/prebuilt, /turf/open/floor/iron/checker, /area/station/hallway/secondary/service) +"uqU" = ( +/obj/structure/window/reinforced/spawner/directional/north, +/obj/structure/window/reinforced/spawner/directional/east, +/turf/open/space/basic, +/area/space/nearstation) "uqX" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/sign/poster/random/directional/north, @@ -83316,6 +83190,13 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos/project) +"uzK" = ( +/obj/structure/lattice, +/obj/structure/transit_tube/curved{ + dir = 8 + }, +/turf/open/space/basic, +/area/space/nearstation) "uzM" = ( /obj/structure/disposalpipe/sorting/wrap{ dir = 2 @@ -84118,11 +83999,6 @@ /obj/machinery/light/directional/east, /turf/open/floor/iron, /area/station/security/checkpoint/medical/medsci) -"uJr" = ( -/obj/structure/window/reinforced/spawner/directional/south, -/obj/structure/lattice, -/turf/open/space, -/area/space/nearstation) "uJH" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/closed/wall/r_wall, @@ -84569,13 +84445,6 @@ /obj/machinery/status_display/ai/directional/north, /turf/open/floor/plating, /area/station/service/abandoned_gambling_den) -"uOC" = ( -/obj/structure/lattice, -/obj/structure/sign/nanotrasen{ - pixel_y = -32 - }, -/turf/open/space, -/area/space/nearstation) "uOE" = ( /obj/structure/table/wood, /obj/effect/decal/cleanable/dirt, @@ -86505,11 +86374,6 @@ }, /turf/open/space/basic, /area/space/nearstation) -"vpl" = ( -/obj/structure/lattice/catwalk, -/obj/structure/sign/warning/directional/east, -/turf/open/space, -/area/space/nearstation) "vpC" = ( /obj/item/storage/medkit/regular, /obj/structure/table, @@ -87349,11 +87213,6 @@ }, /turf/open/floor/iron, /area/station/engineering/supermatter/room) -"vzw" = ( -/obj/structure/lattice, -/obj/structure/sign/warning/secure_area/directional/north, -/turf/open/space, -/area/space/nearstation) "vzy" = ( /obj/effect/spawner/random/vending/colavend, /obj/machinery/light/directional/north, @@ -88963,6 +88822,12 @@ dir = 1 }, /area/station/hallway/secondary/exit/departure_lounge) +"vUN" = ( +/obj/structure/lattice, +/obj/structure/window/reinforced/spawner/directional/south, +/obj/structure/window/reinforced/spawner/directional/east, +/turf/open/space/basic, +/area/space/nearstation) "vUT" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -89466,11 +89331,6 @@ }, /turf/open/floor/iron, /area/station/cargo/miningoffice) -"wct" = ( -/obj/item/stack/cable_coil, -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/station/solars/starboard/aft) "wcG" = ( /obj/structure/table/reinforced, /obj/item/radio/intercom/directional/west, @@ -90653,6 +90513,11 @@ /obj/item/papercutter, /turf/open/floor/iron, /area/station/cargo/office) +"wpQ" = ( +/obj/structure/lattice/catwalk, +/obj/effect/landmark/generic_maintenance_landmark, +/turf/open/space/basic, +/area/station/solars/port/aft) "wpU" = ( /obj/effect/turf_decal/bot, /obj/effect/turf_decal/siding/green, @@ -90983,6 +90848,13 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/engineering/atmos/pumproom) +"wur" = ( +/obj/docking_port/stationary/random{ + name = "lavaland"; + shuttle_id = "pod_2_lavaland" + }, +/turf/open/space/basic, +/area/space) "wus" = ( /obj/structure/cable, /obj/effect/decal/cleanable/cobweb/cobweb2, @@ -92697,6 +92569,11 @@ /obj/structure/window/reinforced/spawner/directional/north, /turf/open/floor/iron/grimy, /area/station/command/heads_quarters/captain) +"wRE" = ( +/obj/structure/lattice, +/obj/structure/sign/warning/electric_shock/directional/north, +/turf/open/space/basic, +/area/space/nearstation) "wRL" = ( /obj/effect/spawner/random/structure/crate, /obj/machinery/light/small/broken/directional/west, @@ -93099,6 +92976,13 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) +"wYv" = ( +/obj/structure/lattice/catwalk, +/obj/machinery/atmospherics/pipe/smart/simple/orange/visible{ + dir = 4 + }, +/turf/open/space/basic, +/area/space/nearstation) "wYH" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/door/poddoor/shutters/preopen{ @@ -93392,11 +93276,6 @@ /obj/item/reagent_containers/condiment/soymilk, /turf/open/floor/iron/kitchen_coldroom/dark, /area/station/service/kitchen/coldroom) -"xcd" = ( -/obj/item/stack/cable_coil, -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/station/solars/starboard/fore) "xce" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/disposalpipe/segment{ @@ -94672,11 +94551,6 @@ /obj/item/camera, /turf/open/floor/wood, /area/station/command/heads_quarters/captain) -"xsG" = ( -/obj/structure/lattice, -/obj/structure/window/reinforced/spawner/directional/east, -/turf/open/space, -/area/space/nearstation) "xsH" = ( /obj/machinery/door/window/brigdoor/left/directional/west{ name = "Secure Creature Pen"; @@ -97217,11 +97091,6 @@ /obj/machinery/computer/security/telescreen/vault/directional/east, /turf/open/floor/wood, /area/station/command/heads_quarters/hop) -"xYl" = ( -/obj/structure/lattice, -/obj/item/toy/figure/ninja, -/turf/open/space, -/area/space/nearstation) "xYs" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, @@ -97685,13 +97554,6 @@ /obj/effect/turf_decal/tile/purple/fourcorners, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) -"yfC" = ( -/obj/structure/lattice/catwalk, -/obj/machinery/atmospherics/pipe/smart/simple/orange/visible{ - dir = 4 - }, -/turf/open/space, -/area/space/nearstation) "yfI" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -98073,6 +97935,11 @@ /obj/effect/turf_decal/tile/neutral/full, /turf/open/floor/iron/dark/smooth_large, /area/station/science/genetics) +"yjQ" = ( +/obj/structure/lattice, +/obj/structure/window/reinforced/spawner/directional/south, +/turf/open/space/basic, +/area/space/nearstation) "yjV" = ( /obj/structure/chair/office, /obj/effect/landmark/start/hangover, @@ -98151,11 +98018,6 @@ /obj/machinery/light/small/directional/east, /turf/open/floor/wood, /area/station/service/electronic_marketing_den) -"yko" = ( -/obj/structure/window/reinforced/spawner/directional/south, -/obj/structure/window/reinforced/spawner/directional/west, -/turf/open/space, -/area/space/nearstation) "yks" = ( /obj/effect/turf_decal/bot_white, /obj/effect/turf_decal/tile/neutral/full, @@ -101216,7 +101078,7 @@ aaa aaa aaa aaa -aab +wVj aaa aaa aaa @@ -103033,7 +102895,7 @@ qYo efQ efQ efQ -aad +qYo efQ efQ aaa @@ -103290,7 +103152,7 @@ gLJ nxs gLJ nxs -cVr +gLJ aaa efQ aaa @@ -103536,7 +103398,7 @@ aaa aaa aaa qYo -pYJ +clr fMb chU hRq @@ -103793,17 +103655,17 @@ efQ efQ efQ efQ -uJr +xwo ePZ -qpQ -smV -ryt +lMb +oxt +azt urA oNB hfl -flt -smV -yko +bZF +oxt +kAB ePZ gvf qYo @@ -104036,23 +103898,23 @@ aaa aaa aaa aaa -aad +qYo aaa -bAU -cVr -cVr -bAU -cVr -cVr -bAU -cVr -cVr -bAU -cVr -bAU -dXD +nxs +gLJ +gLJ +nxs +gLJ +gLJ +nxs +gLJ +gLJ +nxs +gLJ +nxs +vgS ePZ -pQx +rHK bPC bPC bPC @@ -104060,7 +103922,7 @@ iGI fvZ bPC bPC -idU +yjQ ePZ mxs efQ @@ -104309,7 +104171,7 @@ chU chU chU aaQ -pzp +mxs bPC bRy eQF @@ -104317,7 +104179,7 @@ krT uTG tte bPC -pYJ +clr ePZ gvf efQ @@ -104553,19 +104415,19 @@ aaa efQ clr gGJ -flt -nOy -smV -smV -smV -nOy -smV -smV -nOy -smV -smV -nOy -smV +bZF +rYO +oxt +oxt +oxt +rYO +oxt +oxt +rYO +oxt +oxt +rYO +oxt aaa bPC bRz @@ -104574,16 +104436,16 @@ cOJ xRo caa bPC -pYJ +clr ePZ -nCB -cVr -bAU -cVr -cVr -bAU -cVr -bAU +uqU +gLJ +nxs +gLJ +gLJ +nxs +gLJ +nxs aaa efQ aaa @@ -104810,10 +104672,10 @@ aaa efQ clr gGJ -eKN -aad -aad -aad +gvf +qYo +qYo +qYo btH btH btH @@ -104831,7 +104693,7 @@ jYp vgi vdB bPC -idU +yjQ hVt chU chU @@ -105067,9 +104929,9 @@ aaa qYo xwo gGJ -pzp -aad -aad +mxs +qYo +qYo btH btH btH @@ -105089,14 +104951,14 @@ vgi cac bPC aaa -nOy -smV -smV -nOy -smV -smV -aOl -jpw +rYO +oxt +oxt +rYO +oxt +oxt +xHF +dbJ gGJ gvf efQ @@ -105324,7 +105186,7 @@ aaa efQ clr gGJ -pzp +mxs aaa btH btH @@ -105351,9 +105213,9 @@ chi chi cdt cdt -aad -aad -uJr +qYo +qYo +xwo gGJ mxs qYo @@ -105581,8 +105443,8 @@ efQ efQ xwo gGJ -pQx -aad +rHK +qYo btH btH cQh @@ -105609,8 +105471,8 @@ eCk fKM cdt cdt -aad -pYJ +qYo +clr gGJ gvf efQ @@ -105838,7 +105700,7 @@ aaa gLJ vgS gGJ -pzp +mxs aaa btH btH @@ -105867,10 +105729,10 @@ hmU bAK cdt cdt -pYJ +clr gGJ -nCB -bAU +uqU +nxs aaa efQ aaa @@ -106095,7 +105957,7 @@ clr pNp xWr mXQ -eXM +sCb sSb sSb sSb @@ -106124,7 +105986,7 @@ sdK qdV qGs cdt -idU +yjQ kXC jtr odk @@ -106352,7 +106214,7 @@ xwo kXC hwa hfl -pzp +mxs btH btH bwo @@ -106381,7 +106243,7 @@ hmU cfu ptq cdt -pYJ +clr kXC xRE hfl @@ -106609,7 +106471,7 @@ clr kXC cEq alK -qPm +mBY btH btH pKa @@ -106638,7 +106500,7 @@ bpT kmX uoO sGj -bNv +srf ygX fRa hfl @@ -106656,7 +106518,7 @@ aaa aaa aaa aaa -aab +wVj aaa aaa aaa @@ -106866,7 +106728,7 @@ xwo kXC hwa hfl -pzp +mxs btH btH cQw @@ -106895,7 +106757,7 @@ hmU cfu asO cdt -pYJ +clr kXC rAn hfl @@ -107123,7 +106985,7 @@ clr hcj miC uyA -cWJ +pGu uJH uJH uJH @@ -107152,7 +107014,7 @@ hmU tEd cJh cdt -idU +yjQ kXC uqd aaN @@ -107377,10 +107239,10 @@ aaa aaa efQ aaa -smV -yko +oxt +kAB gGJ -pzp +mxs aaa btH btH @@ -107409,10 +107271,10 @@ hmU enc cdt cdt -pYJ +clr gGJ -qpQ -aOl +lMb +xHF aaa efQ aaa @@ -107635,10 +107497,10 @@ aaa efQ efQ efQ -uJr +xwo gGJ -pQx -aad +rHK +qYo btH btH cQh @@ -107665,10 +107527,10 @@ eCk kex cdt cdt -aad -pYJ +qYo +clr gGJ -eKN +gvf efQ efQ efQ @@ -107892,9 +107754,9 @@ aaa aaa aaa efQ -pYJ +clr gGJ -pzp +mxs aaa btH btH @@ -107921,11 +107783,11 @@ chi chi cdt cdt -aad -aad -uJr +qYo +qYo +xwo gGJ -pzp +mxs efQ aaa aaa @@ -108149,11 +108011,11 @@ aaa aaa aaa qYo -pYJ +clr gGJ -pzp -aad -aad +mxs +qYo +qYo btH btH btH @@ -108173,16 +108035,16 @@ kkh eae bPC aaa -xsG -cVr -cVr -xsG -cVr -cVr -bAU -pTR +eRb +gLJ +gLJ +eRb +gLJ +gLJ +nxs +aYy gGJ -eKN +gvf efQ aaa aaa @@ -108406,12 +108268,12 @@ aaa aaa aaa efQ -pYJ +clr gGJ -eKN -aad -aad -aad +gvf +qYo +qYo +qYo btH btH btH @@ -108429,7 +108291,7 @@ bAN kkh fXG bPC -idU +yjQ fMb chU chU @@ -108439,7 +108301,7 @@ iPR hVA hVA dws -pzp +mxs qYo aaa aaa @@ -108663,21 +108525,21 @@ aaa aaa aaa efQ -pYJ +clr gGJ -fJy -xsG -cVr -cVr -cVr -xsG -cVr -cVr -xsG -cVr -cVr -xsG -cVr +ghx +eRb +gLJ +gLJ +gLJ +eRb +gLJ +gLJ +eRb +gLJ +gLJ +eRb +gLJ aaa bPC bRM @@ -108686,16 +108548,16 @@ uQY tWv pGJ bPC -pYJ +clr ePZ -qpQ -smV -aOl -smV -smV -aOl -smV -smV +lMb +oxt +xHF +oxt +oxt +xHF +oxt +oxt aaa efQ aaa @@ -108920,7 +108782,7 @@ aaa aaa aaa efQ -uJr +xwo omg hVA hVA @@ -108935,7 +108797,7 @@ chU chU chU iIm -pzp +mxs bPC uNh asa @@ -108943,9 +108805,9 @@ uQY asa olD bPC -pYJ +clr ePZ -eKN +gvf efQ efQ qYo @@ -109178,21 +109040,21 @@ aaa aaa efQ aaa -aOl -smV -smV -aOl -smV -smV -aOl -smV -smV -aOl -smV -aOl -yko +xHF +oxt +oxt +xHF +oxt +oxt +xHF +oxt +oxt +xHF +oxt +xHF +kAB ePZ -pQx +rHK bPC bPC bPC @@ -109200,9 +109062,9 @@ anC bPC bPC bPC -idU +yjQ ePZ -pzp +mxs efQ aaa aaa @@ -109447,19 +109309,19 @@ efQ efQ efQ efQ -uJr +xwo ePZ -nCB -cVr -fsr +uqU +gLJ +vUN jZc fkB fRA -fJy -cVr -dXD +ghx +gLJ +vgS ePZ -eKN +gvf efQ aaa aaa @@ -109704,7 +109566,7 @@ qYo aaa qYo efQ -pYJ +clr hVt nBm dNT @@ -109716,7 +109578,7 @@ chU chU chU aaQ -pzp +mxs qYo qYo qYo @@ -109962,14 +109824,14 @@ aaa qYo qYo aaa -yko +kAB cVx -qpQ -ryt +lMb +azt kXC qdF hfl -flt +bZF oxt xHF oxt @@ -110027,9 +109889,9 @@ aaa aaa aaa aaa -abj +vVc aaa -abj +vVc aaa aaa aaa @@ -110219,14 +110081,14 @@ aaa qYo efQ efQ -uJr +xwo nDt -eKN -idU +gvf +yjQ kXC qKi rZy -pQx +rHK efQ efQ efQ @@ -110284,9 +110146,9 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -110479,11 +110341,11 @@ qYo aaa vVc aaa -idU +yjQ kXC siT hfl -pQx +rHK aaa qYo aaa @@ -110540,11 +110402,11 @@ aaa aaa aaa aaa -aad -aad +qYo +qYo aaa -aad -aad +qYo +qYo aaa aaa aaa @@ -110736,11 +110598,11 @@ qYo aaa vVc aaa -idU +yjQ mJh wJq hfl -pQx +rHK aaa qYo aaa @@ -110796,13 +110658,13 @@ aaa aaa aaa aaa -aad -aad +qYo +qYo oec tnB oec -aad -aad +qYo +qYo aaa aaa aaa @@ -110990,18 +110852,18 @@ aaa efQ qYo qYo -aad +qYo vVc -aad +qYo bRP eOb qdF gnO aJD -aad -aad -aad -aad +qYo +qYo +qYo +qYo qYo efQ aaa @@ -111052,15 +110914,15 @@ aaa aaa aaa aaa -aad -aad +qYo +qYo tnB oec fSW oec tnB -aad -aad +qYo +qYo aaa aaa aaa @@ -111250,13 +111112,13 @@ qYo aaa vVc aaa -uJr +xwo eaA rjm mbY -eKN +gvf aaa -aad +qYo aaa aaa aaa @@ -111308,8 +111170,8 @@ aaa aaa aaa aaa -aad -aad +qYo +qYo oec oec fSr @@ -111317,8 +111179,8 @@ xEV rlQ oec oec -aad -aad +qYo +qYo aaa aaa aaa @@ -111507,13 +111369,13 @@ qYo aaa vVc aaa -bRQ -smV +bIo +oxt pwY -smV -cap +oxt +ceu aaa -aad +qYo aaa aaa aaa @@ -111563,9 +111425,9 @@ aaa aaa aaa aaa -abj -aad -aad +vVc +qYo +qYo tnB tnB ebF @@ -111575,9 +111437,9 @@ nEA iXw tnB tnB -aad -aad -abj +qYo +qYo +vVc aaa aaa aaa @@ -111761,18 +111623,18 @@ aaa efQ qYo qYo -aad +qYo vVc -aad -bRR -aad +qYo +ghK +qYo mmr -aad -bRR -aad -aad -aad -aad +qYo +ghK +qYo +qYo +qYo +qYo qYo efQ aaa @@ -112021,13 +111883,13 @@ qYo aaa vVc aaa -bRS +uzK aaa mmr aaa -caq +oUP aaa -aad +qYo aaa aaa aaa @@ -112077,9 +111939,9 @@ aaa aaa aaa aaa -abj -aad -aad +vVc +qYo +qYo tnB tnB pPf @@ -112089,9 +111951,9 @@ mcA pqX tnB tnB -aad -aad -abj +qYo +qYo +vVc aaa aaa aaa @@ -112278,13 +112140,13 @@ qYo aaa vVc aaa -aad -bTJ +qYo +iPf mmr -bYm -aad +qQO +qYo aaa -aad +qYo aaa aaa aaa @@ -112336,8 +112198,8 @@ aaa aaa aaa aaa -aad -aad +qYo +qYo oec oec jCK @@ -112345,8 +112207,8 @@ jbR fkd oec oec -aad -aad +qYo +qYo aaa aaa aaa @@ -112535,13 +112397,13 @@ qYo aaa vVc aaa -aad +qYo aaa iNi aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -112594,15 +112456,15 @@ aaa aaa aaa aaa -aad -aad +qYo +qYo tnB oec lob oec tnB -aad -aad +qYo +qYo aaa aaa aaa @@ -112789,17 +112651,17 @@ aaa efQ qYo qYo -aad +qYo vVc vVc vVc -aad +qYo oRu -aad -aad -aad -aad -aad +qYo +qYo +qYo +qYo +qYo qYo qYo qYo @@ -112852,13 +112714,13 @@ aaa aaa aaa aaa -aad -aad +qYo +qYo oec eln oec -aad -aad +qYo +qYo aaa aaa aaa @@ -113047,15 +112909,15 @@ qYo aaa qYo aaa -aad +qYo aaa vVc aaa oPn aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -113110,11 +112972,11 @@ aaa aaa aaa aaa -aad -aad +qYo +qYo aaa -aad -aad +qYo +qYo aaa aaa aaa @@ -113304,15 +113166,15 @@ efQ aaa qYo aaa -aad +qYo aaa vVc aaa oPn aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -113368,9 +113230,9 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -113560,17 +113422,17 @@ aaa efQ qYo qYo -aad -aad -aad +qYo +qYo +qYo vVc -aad +qYo cXx -aad -aad -aad -aad -aad +qYo +qYo +qYo +qYo +qYo qYo qYo efQ @@ -113625,9 +113487,9 @@ aaa aaa aaa aaa -abj +vVc aaa -abj +vVc aaa aaa aaa @@ -113818,15 +113680,15 @@ uHd qYo qYo aaa -aad +qYo aaa vVc aaa oPn aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -113849,7 +113711,7 @@ aaa aaa aaa aaa -eqU +aaa aaa wVj aaa @@ -113882,9 +113744,9 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -114071,19 +113933,19 @@ aaa aaa qYo aaa -aad -eqU qYo aaa -aad +qYo +aaa +qYo aaa vVc aaa oPn aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -114139,9 +114001,9 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -114333,15 +114195,15 @@ qYo qYo aaa qYo -aad +qYo vVc -aad +qYo oRu -aad -aad -aad -aad -aad +qYo +qYo +qYo +qYo +qYo qYo qYo efQ @@ -114396,9 +114258,9 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -114406,7 +114268,7 @@ aaa aaa aaa aaa -aab +wVj aaa aaa aaa @@ -114536,7 +114398,7 @@ aaa aaa aaa aaa -aab +wVj aaa aaa aaa @@ -114595,9 +114457,9 @@ vVc aaa oPn aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -114653,9 +114515,9 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -114852,9 +114714,9 @@ vVc aaa oPn aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -114910,9 +114772,9 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -115106,13 +114968,13 @@ uHd uHd qYo vVc -aad +qYo cXx -aad -aac -aac -aac -aad +qYo +uHd +uHd +uHd +qYo uHd qYo efQ @@ -115167,9 +115029,9 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -115366,9 +115228,9 @@ vVc aaa dVg aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -115424,9 +115286,9 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -115550,13 +115412,13 @@ aaa aaa aaa aaa -aac -aad -aac -aad -aac -aac -aac +uHd +qYo +uHd +qYo +uHd +uHd +uHd aaa aaa aaa @@ -115623,9 +115485,9 @@ vVc aaa dVg aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -115681,9 +115543,9 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -115803,21 +115665,21 @@ aaa aaa aaa aaa -aac -aac -aFo -aac -aac +uHd +uHd +xNe +uHd +uHd aaa -aad +qYo aaa -aad +qYo aaa -aac -aac -aad -aac -aac +uHd +uHd +qYo +uHd +uHd aaa aaa aaa @@ -115877,7 +115739,7 @@ qYo uHd qYo vVc -aad +qYo alZ qYo uHd @@ -115886,7 +115748,7 @@ uHd uHd uHd qYo -aac +uHd aaa qYo uKa @@ -115903,9 +115765,9 @@ qYo qYo uHd vVc -aad -aad -aad +qYo +qYo +qYo djY nCi nCi @@ -115938,9 +115800,9 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -116060,21 +115922,21 @@ aaa aaa aaa aaa -aac +uHd aaa -aad +qYo aaa -aad +qYo aaa vYu -fKU +waG vYu aaa -aad +qYo aaa -aad +qYo aaa -aac +uHd aaa aaa aaa @@ -116162,7 +116024,7 @@ uHd vVc qYo qYo -aad +qYo nCi nCi fbp @@ -116195,9 +116057,9 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -116317,21 +116179,21 @@ aaa aaa aaa aaa -aac +uHd aaa vYu -fKU +waG vYu aaa vYu -fKU +waG vYu aaa vYu -fKU +waG vYu aaa -aad +qYo aaa aaa aaa @@ -116417,8 +116279,8 @@ vVc qvs vVc vVc -vpl -abj +bQY +vVc vVc nCi jDc @@ -116452,9 +116314,9 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -116577,18 +116439,18 @@ aaa qYo aaa vYu -fKU +waG vYu aaa vYu -fKU +waG vYu aaa vYu -fKU +waG vYu aaa -aac +uHd aaa aaa aaa @@ -116647,9 +116509,9 @@ vVc vVc vVc sVm -abj -abj -lbi +vVc +vVc +noe qYo aaa nUT @@ -116709,9 +116571,9 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -116831,21 +116693,21 @@ aaa aaa aaa aaa -aac +uHd qYo vYu -fKU +waG vYu qYo vYu -fKU +waG vYu qYo vYu -fKU +waG vYu -aad -aac +qYo +uHd aaa aaa aaa @@ -116966,9 +116828,9 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -117088,21 +116950,21 @@ aaa aaa aaa aaa -aac +uHd aaa vYu -fKU +waG vYu aaa vYu -fKU +waG vYu aaa vYu -fKU +waG vYu aaa -aFo +xNe aaa aaa aaa @@ -117142,7 +117004,7 @@ aaa aaa aaa aaa -eqU +aaa aaa qYo aaa @@ -117223,9 +117085,9 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -117342,24 +117204,24 @@ aaa aaa aaa aaa -aac -aFo -aac -aac +uHd +xNe +uHd +uHd aaa vYu -fKU +waG vYu aaa qYo -fKU +waG qYo aaa vYu -fKU +waG vYu aaa -aFo +xNe uHd efQ efQ @@ -117480,9 +117342,9 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -117599,24 +117461,24 @@ aaa aaa aaa aaa -aac +uHd aaa -aad -aad +qYo +qYo aaa -aad -fKU -aad qYo -aad -fKU -aad +waG +qYo +qYo +qYo +waG +qYo +qYo +qYo +waG +qYo +qYo qYo -aad -fKU -aad -aad -aad aaa aaa qYo @@ -117731,15 +117593,15 @@ aaa aaa aaa aaa -eqU +aaa wVj aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -117856,22 +117718,22 @@ aaa aaa aaa aaa -aac -aad +uHd +qYo sCY -fKU -fKU -awk -awk -awk +waG +waG +qNi +qNi +qNi +qNi +qNi +qNi +qNi +qNi +qNi qNi -awk -awk -awk qNi -awk -awk -awk qNi qNi aaa @@ -117994,9 +117856,9 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -118113,22 +117975,22 @@ aaa aaa aaa aaa -aac +uHd +aaa +qYo +qYo aaa -aad -aad -eqU -aad -fKU -aad qYo -aad -fKU -aad +waG +qYo +qYo +qYo +waG +qYo +qYo +qYo +waG qYo -aad -fKU -aad qYo qNi qYo @@ -118145,30 +118007,30 @@ mDb iRf tQz qYo -aad -aad -eqU -aad +qYo +qYo aaa -aad -aad -aad +qYo aaa -aad -aad -aad +qYo +qYo +qYo aaa -aad -aad -aad +qYo +qYo +qYo aaa -aad -aad -aad +qYo +qYo +qYo aaa -aad -aad -aad +qYo +qYo +qYo +aaa +qYo +qYo +qYo aaa qYo qYo @@ -118251,9 +118113,9 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -118370,21 +118232,21 @@ aaa aaa aaa aaa -aac -aac -aad -aad +uHd +uHd +qYo +qYo aaa vYu -fKU +waG vYu aaa qYo -fKU +waG qYo aaa vYu -fKU +waG vYu qYo waG @@ -118415,7 +118277,7 @@ pxN pxN pxN pxN -abj +vVc pxN pxN pxN @@ -118429,7 +118291,7 @@ pxN pxN pxN pxN -yfC +wYv pxN pxN pxN @@ -118508,9 +118370,9 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -118630,18 +118492,18 @@ aaa aaa aaa aaa -aac +uHd aaa vYu -fKU +waG vYu aaa vYu -fKU +waG vYu aaa vYu -fKU +waG vYu aaa waG @@ -118672,7 +118534,7 @@ tMA rbC tMA pxN -aad +qYo pxN uVk ahV @@ -118686,7 +118548,7 @@ pgb fIB pgb pxN -yfC +wYv pxN fZO wJa @@ -118757,17 +118619,17 @@ gtx hvD jtC nCI -aad -aad +qYo +qYo aaa -aad -aad +qYo +qYo aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -118887,18 +118749,18 @@ aaa aaa aaa aaa -aac -aad +uHd +qYo vYu -fKU +waG vYu aaa vYu -fKU +waG vYu qYo vYu -fKU +waG vYu aaa waG @@ -118929,7 +118791,7 @@ sKb crE tMA pxN -abj +vVc pxN hUK spJ @@ -118943,7 +118805,7 @@ boV fjS pgb pxN -yfC +wYv pxN fZO fZO @@ -119018,13 +118880,13 @@ fYR nCI fYR fYR -aad +qYo efQ aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -119144,18 +119006,18 @@ aaa aaa aaa aaa -aac +uHd aaa vYu -fKU +waG vYu qYo vYu -fKU +waG vYu aaa vYu -fKU +waG vYu aaa waG @@ -119186,7 +119048,7 @@ uFx ldu uIF pxN -aad +qYo pxN vAc eEo @@ -119200,7 +119062,7 @@ xWJ bba ovb pxN -yfC +wYv pxN iZY kZT @@ -119275,13 +119137,13 @@ jxZ hHX bQz fYR -aad +qYo efQ efQ aaa qYo aaa -aad +qYo aaa aaa aaa @@ -119401,18 +119263,18 @@ aaa aaa aaa aaa -aad +qYo aaa vYu -fKU +waG vYu aaa vYu -fKU +waG vYu aaa vYu -fKU +waG vYu qYo waG @@ -119443,7 +119305,7 @@ rHc xlG nzi pxN -abj +vVc pxN dlj xlG @@ -119457,7 +119319,7 @@ dlj xlG psb pxN -yfC +wYv pxN hWh xlG @@ -119532,14 +119394,14 @@ vwC fNa jXz nCI -aad +qYo qYo qYo qYo qYo aaa -aad -aad +qYo +qYo efQ aaa aaa @@ -119660,15 +119522,15 @@ aaa aaa efQ aaa -aad +qYo aaa -aad +qYo aaa vYu -fKU +waG vYu aaa -aad +qYo aaa qYo aaa @@ -119790,12 +119652,12 @@ xJW fGt fYR aaa -aad +qYo aaa aaa qYo aaa -aad +qYo aaa efQ aaa @@ -119933,7 +119795,7 @@ waG aaa aaa qYo -iZn +kvq edx wlH raL @@ -120052,7 +119914,7 @@ aaa aaa qYo aaa -aad +qYo aaa qYo aaa @@ -120190,7 +120052,7 @@ qNi aaa aaa qYo -jGx +hrU elx gqR uuC @@ -120309,9 +120171,9 @@ aaa aaa qYo aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -120562,12 +120424,12 @@ gvG pNA spa fYR -aad +qYo qYo qYo aaa -aad -aad +qYo +qYo efQ aaa aaa @@ -120596,7 +120458,7 @@ aaa aaa aaa aaa -aab +wVj aaa aaa aaa @@ -120823,7 +120685,7 @@ aaa aaa qYo aaa -aad +qYo aaa efQ aaa @@ -120838,7 +120700,7 @@ aaa aaa aaa aaa -aab +wVj aaa aaa aaa @@ -121076,12 +120938,12 @@ fWJ pNA qVn fYR -aad +qYo qYo qYo aaa -aad -aad +qYo +qYo efQ aaa aaa @@ -121337,9 +121199,9 @@ aaa aaa qYo aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -121594,9 +121456,9 @@ aaa aaa qYo aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -121845,53 +121707,53 @@ fza lgW dJY fYR -aad -aaa -aaa -aaa qYo aaa -aad -aad -rWQ -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aac -aac -aac -aad -aFo -aac -aac -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa +aaa +aaa +qYo +aaa +qYo +qYo +lvw +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +uHd +uHd +uHd +qYo +xNe +uHd +uHd +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa aaa aaa aaa @@ -122102,13 +121964,13 @@ uKu srI uDR nCI -aad -aac -aac +qYo +uHd +uHd qYo qYo aaa -aad +qYo aaa efQ aaa @@ -122130,21 +121992,21 @@ aaa aaa aaa aaa -aac -aad -aFo -aac -aac +uHd +qYo +xNe +uHd +uHd aaa aaa -aad +qYo aaa aaa -aac -aac -aad -aac -aac +uHd +uHd +qYo +uHd +uHd aaa aaa aaa @@ -122359,14 +122221,14 @@ nZA geY skr fYR -aad +qYo efQ aaa aaa qYo aaa -aad -aad +qYo +qYo efQ aaa aaa @@ -122387,21 +122249,21 @@ aaa aaa aaa aaa -aac +uHd aaa aaa -aad +qYo aaa aaa qgl -bbD +kun qgl aaa aaa -aad +qYo aaa aaa -aac +uHd aaa aaa aaa @@ -122622,9 +122484,9 @@ aaa aaa qYo aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -122644,21 +122506,21 @@ aaa aaa aaa aaa -aac +uHd aaa qgl -bbD +kun qgl aaa qgl -bbD +kun qgl aaa qgl -bbD +kun qgl aaa -aFo +xNe aaa aaa aaa @@ -122879,9 +122741,9 @@ aaa aaa qYo aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -122901,21 +122763,21 @@ aaa aaa aaa aaa -aad +qYo aaa qgl -bbD +kun qgl aaa qgl -bbD +kun qgl aaa qgl -bbD +kun qgl aaa -aac +uHd aaa aaa aaa @@ -122992,7 +122854,7 @@ aaa aaa aaa aaa -aab +wVj aaa aaa aaa @@ -123136,9 +122998,9 @@ aaa aaa qYo aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -123158,21 +123020,21 @@ aaa aaa aaa aaa -aad -aad +qYo +qYo qgl -bbD +kun qgl -aad +qYo qgl -bbD +kun qgl -aad +qYo qgl -bbD +kun qgl -aad -aac +qYo +uHd aaa aaa aaa @@ -123392,10 +123254,10 @@ qYo vVc qYo vVc -aad -abj -aad -abj +qYo +vVc +qYo +vVc aaa aaa aaa @@ -123415,21 +123277,21 @@ aaa aaa aaa aaa -aac +uHd aaa qgl -bbD +kun qgl aaa qgl -bbD +kun qgl aaa qgl -bbD +kun qgl aaa -aad +qYo aaa aaa aaa @@ -123650,13 +123512,13 @@ vVc aaa qYo aaa -aad +qYo aaa -abj -aad -aad -aad -abj +vVc +qYo +qYo +qYo +vVc aaa aaa aaa @@ -123672,24 +123534,24 @@ aaa efQ efQ aaa -aac +uHd aaa qgl -bbD +kun qgl aaa -aad -bbD -aad +qYo +kun +qYo aaa qgl -bbD +kun qgl aaa -aad -aac -aac -aac +qYo +uHd +uHd +uHd aaa aaa aaa @@ -123906,18 +123768,18 @@ qYo vVc qYo vVc -aad -abj -aad -abj +qYo +vVc +qYo +vVc aaa aaa aaa -abj -aad -aad -aad -abj +vVc +qYo +qYo +qYo +vVc aaa aaa aaa @@ -123929,24 +123791,24 @@ qYo qYo qYo qYo -aad +qYo aaa aaa -bbD -aad -aad -aad -bBc -aad -aad -aad -bbD -aad +kun +qYo +qYo +qYo +pSj +qYo +qYo +qYo +kun +qYo aaa aaa -aad +qYo aaa -aac +uHd aaa aaa aaa @@ -124164,9 +124026,9 @@ aaa aaa qYo aaa -aad +qYo aaa -abj +vVc qYo qYo qYo @@ -124186,24 +124048,24 @@ pSj pSj pSj pSj -bBc -bBc -bBc -bBc -bBc -bBc -kQG -qYG -bBc -bBc -bBc -bBc -bBc -bbD -bbD +pSj +pSj +pSj +pSj +pSj +pSj +htR +wpQ +pSj +pSj +pSj +pSj +pSj +kun +kun etr -aad -aad +qYo +qYo aaa aaa aaa @@ -124421,7 +124283,7 @@ aaa aaa qYo aaa -aad +qYo aaa aaa aaa @@ -124443,24 +124305,24 @@ pSj qYo qYo qYo -aad +qYo aaa aaa -bbD -aad -aad -aad -bBc -aad -aad -aad -bbD -aad +kun +qYo +qYo +qYo +pSj +qYo +qYo +qYo +kun +qYo aaa aaa -aad +qYo aaa -aac +uHd aaa aaa aaa @@ -124678,7 +124540,7 @@ aaa aaa qYo aaa -aad +qYo aaa aaa aaa @@ -124700,24 +124562,24 @@ kun qYo aaa aaa -aac +uHd aaa qgl -bbD +kun qgl aaa -aad -bbD -aad +qYo +kun +qYo aaa qgl -bbD +kun qgl aaa -aFo -aac -aac -aac +xNe +uHd +uHd +uHd aaa aaa aaa @@ -124935,7 +124797,7 @@ aaa aaa qYo aaa -aad +qYo aaa aaa aaa @@ -124952,26 +124814,26 @@ qYo aaa aaa efQ -aad -bbD -aad +qYo +kun +qYo aaa aaa -aac +uHd aaa qgl -bbD +kun qgl aaa qgl -bbD +kun qgl aaa qgl -bbD +kun qgl aaa -aad +qYo aaa aaa aaa @@ -125186,13 +125048,13 @@ vfc hoY hoT qYo -aad +qYo efQ aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -125208,27 +125070,27 @@ efQ efQ qYo qYo -aad +qYo fuV ocY fuV -aad +qYo aaa -aac -aad +uHd +qYo qgl -bbD +kun qgl -aad +qYo qgl -bbD +kun qgl -aad +qYo qgl -bbD +kun qgl -aad -aac +qYo +uHd aaa aaa aaa @@ -125443,13 +125305,13 @@ wEE enw nEc aaa -aad +qYo aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -125465,27 +125327,27 @@ aaa aaa aaa aaa -aad +qYo fuV nhK fuV -aad +qYo aaa -aac +uHd aaa qgl -bbD +kun qgl aaa qgl -bbD +kun qgl aaa qgl -bbD +kun qgl aaa -aac +uHd aaa aaa aaa @@ -125700,15 +125562,15 @@ nEc nEc nEc aaa -aad -aad -aad -aad -abj +qYo +qYo +qYo +qYo +vVc aaa -abj -aad -aad +vVc +qYo +qYo qYo efQ efQ @@ -125722,27 +125584,27 @@ qYo efQ efQ qYo -aad +qYo fuV sfX fuV -aad -aad -aFo +qYo +qYo +xNe aaa qgl -bbD +kun qgl aaa qgl -bbD +kun qgl aaa qgl -bbD +kun qgl aaa -aFo +xNe aaa aaa aaa @@ -125957,13 +125819,13 @@ jUx wEI aaa aaa -aad +qYo aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -125984,22 +125846,22 @@ fuV ual fuV fuV -aad -aac +qYo +uHd aaa aaa -aad +qYo aaa aaa qgl -bbD +kun qgl aaa aaa -aad +qYo aaa aaa -aac +uHd aaa aaa aaa @@ -126199,7 +126061,7 @@ vCq aEe dso jDd -vzw +hrs lIv nly oRs @@ -126213,16 +126075,16 @@ dKR jUx wEI qYo -aad -aad -aad -aad -aad -abj +qYo +qYo +qYo +qYo +qYo +vVc aaa -abj -abj -abj +vVc +vVc +vVc qYo aaa efQ @@ -126241,22 +126103,22 @@ ubV bIU sin dPR -aad -aac -aac -aac -aFo -aac +qYo +uHd +uHd +uHd +xNe +uHd aaa aaa -aad +qYo aaa aaa -aFo -aac -aac -aad -aac +xNe +uHd +uHd +qYo +uHd aaa aaa aaa @@ -126498,18 +126360,18 @@ eNe bZc oDo dPR -aad +qYo aaa aaa aaa -aad -aac -aac -aac -aad -aac -aac -aFo +qYo +uHd +uHd +uHd +qYo +uHd +uHd +xNe aaa aaa aaa @@ -126749,19 +126611,19 @@ kGi kGi kGi qQM -aad +qYo dPR oto wvU kfS dPR -aad -aad +qYo +qYo qYo aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -126835,7 +126697,7 @@ aaa aaa aaa aaa -aab +wVj aaa aaa aaa @@ -127033,7 +126895,7 @@ aaa aaa aaa aaa -aab +wVj aaa aaa aaa @@ -127428,9 +127290,9 @@ oYs jzE oYs aaa -aad +qYo aaa -aad +qYo aJU keE tbf @@ -127528,8 +127390,8 @@ tTg bVo jzJ wjP -aad -aad +qYo +qYo qYo aaa efQ @@ -127684,7 +127546,7 @@ dvn oYs vnD oYs -aad +qYo kAD wVU aJU @@ -128198,7 +128060,7 @@ lEm fnb xiV mbR -aad +qYo wVU gfq rFZ @@ -128589,7 +128451,7 @@ aaa aaa aaa aaa -eqU +aaa aaa aaa aaa @@ -128712,7 +128574,7 @@ aMH oYs owb oYs -aad +qYo kAD wVU aJU @@ -128970,9 +128832,9 @@ oYs mcs oYs aaa -aad +qYo aaa -aad +qYo aJU akf tlp @@ -129155,28 +129017,28 @@ aaa aaa aaa aaa -aad -aad -aad -aad -aad -aad -aad +qYo +qYo +qYo +qYo +qYo +qYo +qYo qld bSq qld -aad +qYo aaa aaa -aad +qYo qld bSq qld -aad -aad -aad -aad -aad +qYo +qYo +qYo +qYo +qYo qYo qYo qYo @@ -129414,10 +129276,10 @@ aaa aaa aaa aaa -aad +qYo aaa aaa -aad +qYo aaa qld pvH @@ -129430,7 +129292,7 @@ qld pvH qld aaa -aad +qYo aaa aaa aaa @@ -130177,7 +130039,7 @@ aaa aaa aaa aaa -odd +wur aaa aaa aaa @@ -130611,7 +130473,7 @@ oPz lcF rQC qQM -aad +qYo aaa aaa qYo @@ -130952,14 +130814,14 @@ aaa aaa aaa aaa -aad -aad -aad +qYo +qYo +qYo aaa -aad +qYo aaa aaa -aad +qYo aaa qld rPR @@ -130972,7 +130834,7 @@ qld rPR qld aaa -aad +qYo aaa aaa aaa @@ -131211,28 +131073,28 @@ aaa aaa aaa aaa -aad -aad -aad -aad -aad -aad -aad +qYo +qYo +qYo +qYo +qYo +qYo +qYo qld pyz qld -aad +qYo aaa aaa -aad +qYo qld lxb qld -aad -aad -aad -aad -aad +qYo +qYo +qYo +qYo +qYo qld ePK kci @@ -131468,9 +131330,9 @@ aaa aaa aaa aaa -abj +vVc aaa -aad +qYo aaa aaa aaa @@ -131725,9 +131587,9 @@ aaa aaa aaa aaa -abj +vVc aaa -aad +qYo aaa aaa aaa @@ -131982,9 +131844,9 @@ aaa aaa aaa aaa -abj +vVc aaa -aad +qYo aaa aaa aaa @@ -132239,9 +132101,9 @@ aaa aaa aaa aaa -abj +vVc aaa -aad +qYo aaa aaa aaa @@ -132496,9 +132358,9 @@ aaa aaa aaa aaa -abj -aad -aad +vVc +qYo +qYo aaa iXn aaa @@ -132753,9 +132615,9 @@ aaa aaa aaa aaa -abj +vVc aaa -aad +qYo aaa aaa aaa @@ -133010,9 +132872,9 @@ aaa aaa aaa aaa -abj +vVc aaa -aad +qYo aaa aaa aaa @@ -133267,9 +133129,9 @@ aaa aaa aaa aaa -abj +vVc aaa -aad +qYo aaa aaa aaa @@ -133524,9 +133386,9 @@ aaa aaa aaa aaa -abj +vVc aaa -aad +qYo aaa aaa aaa @@ -133597,7 +133459,7 @@ wjO dOZ xms aaa -aad +qYo aaa diL nBJ @@ -133781,28 +133643,28 @@ aaa aaa aaa aaa -aad -aad -aad -aad -aad -aad -aad +qYo +qYo +qYo +qYo +qYo +qYo +qYo qld pRJ qld -aad +qYo aaa aaa -aad +qYo qld pRJ qld -aad -aad -aad -aad -aad +qYo +qYo +qYo +qYo +qYo qld kEn tzy @@ -133854,7 +133716,7 @@ wjO dOZ xms aaa -aad +qYo aaa diL uhH @@ -133956,7 +133818,7 @@ xPc tgT pOQ aaa -eqU +aaa qYo aaa efQ @@ -134036,14 +133898,14 @@ aaa aaa aaa aaa -aad -aad -aad +qYo +qYo +qYo aaa -aad +qYo aaa aaa -aad +qYo aaa qld pvH @@ -134056,7 +133918,7 @@ qld pvH qld aaa -aad +qYo aaa aaa aaa @@ -134111,7 +133973,7 @@ wjO dOZ xms aaa -aad +qYo aaa diL rzn @@ -134367,9 +134229,9 @@ iDP eem xny kOj -aad -aad -aad +qYo +qYo +qYo diL gab drj @@ -134625,7 +134487,7 @@ wjO dOZ xms aaa -aad +qYo aaa diL sVb @@ -134882,7 +134744,7 @@ otm dOZ xms aaa -aad +qYo aaa diL ipQ @@ -135139,7 +135001,7 @@ tgU dOZ xms aaa -aad +qYo aaa wyH rdu @@ -135153,7 +135015,7 @@ wmp rgW mGw pRS -kNB +sVo lAv nAz xYf @@ -135192,7 +135054,7 @@ kdq shU bbj dZc -igE +lhC uGE qmu qfi @@ -135395,9 +135257,9 @@ wxI aBL dTD kOj -aad -aad -aad +qYo +qYo +qYo wyH xdY pnV @@ -135449,7 +135311,7 @@ xWf uZs xWf dQT -eWj +qfi qfi qfi dQT @@ -135856,9 +135718,9 @@ bmC qld aaa aaa -aad -aad -aad +qYo +qYo +qYo qld oMr kci @@ -135934,8 +135796,8 @@ jDi jDi hup iyy -aad -aad +qYo +qYo oCs dmq xaP @@ -136114,7 +135976,7 @@ aaa aaa aaa aaa -aad +qYo qld qld rXr @@ -136371,7 +136233,7 @@ aaa aaa aaa aaa -aad +qYo pkd tQU oMr @@ -136680,7 +136542,7 @@ mBJ drQ ttz kOj -aad +qYo diL nYn iGB @@ -137399,7 +137261,7 @@ aaa aaa aaa aaa -aad +qYo cbY hvq plz @@ -137656,7 +137518,7 @@ aaa aaa aaa aaa -aad +qYo qld qld rbR @@ -137708,7 +137570,7 @@ pXg jkf iFG kOj -aad +qYo diL cnW iGB @@ -137912,9 +137774,9 @@ pRJ qld aaa aaa -aad -aad -aad +qYo +qYo +qYo qld rbR xQb @@ -138504,8 +138366,8 @@ jDi jDi hup iyy -aad -aad +qYo +qYo oCs hHQ uJm @@ -138993,9 +138855,9 @@ uwJ vPy dTD kOj -aad -aad -aad +qYo +qYo +qYo wyH eTS pnV @@ -139251,7 +139113,7 @@ dvy lSl xms aaa -aad +qYo aaa wyH lgG @@ -139508,7 +139370,7 @@ hRV lSl xms aaa -aad +qYo aaa diL ipQ @@ -139691,8 +139553,8 @@ aaa aaa aaa aaa -aad -aad +qYo +qYo abi jrG abi @@ -139765,7 +139627,7 @@ dvy lSl xms aaa -aad +qYo aaa diL pGz @@ -139948,8 +139810,8 @@ aaa aaa aaa aaa -abj -abj +vVc +vVc ckY gEl gwe @@ -140021,9 +139883,9 @@ pXg dvy lOf kOj -aad -aad -aad +qYo +qYo +qYo diL tch drj @@ -140131,7 +139993,7 @@ aaa aaa aaa aaa -eqU +aaa aaa aaa aaa @@ -140206,7 +140068,7 @@ aaa aaa aaa aaa -aad +qYo abi hYY abi @@ -140279,7 +140141,7 @@ dvy lSl xms aaa -aad +qYo aaa diL rzn @@ -140452,7 +140314,7 @@ aaa aaa aaa aaa -aab +wVj aaa aaa aaa @@ -140462,8 +140324,8 @@ aaa aaa aaa aaa -aac -aad +uHd +qYo abi adR xrr @@ -140536,7 +140398,7 @@ bmn lSl xms aaa -aad +qYo aaa diL uhH @@ -140719,16 +140581,16 @@ aaa aaa aaa aaa -aac -aad -aad -aad +uHd +qYo +qYo +qYo xrr jnq jvL btT xrr -aad +qYo abi adR adR @@ -140793,7 +140655,7 @@ dvy lSl xms aaa -aad +qYo aaa diL nBJ @@ -140976,10 +140838,10 @@ aaa aaa aaa aaa -aac -aac -aad -eqU +uHd +uHd +qYo +aaa csz fVt pHX @@ -141235,14 +141097,14 @@ aaa aaa aaa aaa -aad -aad +qYo +qYo xrr cqM axF pQh xrr -aad +qYo abi aeF aeF @@ -141492,14 +141354,14 @@ aaa aaa aaa aaa -aac -aad +uHd +qYo csz csz sPF csz csz -aad +qYo abi aeF aeF @@ -141750,13 +141612,13 @@ aaa aaa aaa aaa -aad -aad +qYo +qYo csz ezP csz -aad -aad +qYo +qYo abi aeF aeF @@ -142012,8 +141874,8 @@ aaa csz sQR csz -aad -eqU +qYo +aaa abi aeF aeF @@ -142256,20 +142118,20 @@ aaa aaa aaa aaa -aac -aac -aad -aac -aac -aad -aac +uHd +uHd +qYo +uHd +uHd +qYo +uHd aaa -aad -aad +qYo +qYo csz ljP csz -aad +qYo qYo abi aeF @@ -142509,25 +142371,25 @@ aaa aaa aaa aaa -aac -aac -aad -aac -aac +uHd +uHd +qYo +uHd +uHd aaa aaa -aad +qYo aaa aaa -aac -aac -aad -aad -aad -aoP -aad -aad -aad +uHd +uHd +qYo +qYo +qYo +qkQ +qYo +qYo +qYo abi aeF aeF @@ -142590,13 +142452,13 @@ hXg fmH tpZ aaa -aad +qYo aaa teY ykl teY aaa -aad +qYo aaa mjz iJT @@ -142766,25 +142628,25 @@ aaa aaa aaa aaa -aac +uHd aaa aaa -aad +qYo aaa aaa pAJ -aoP +qkQ pAJ aaa aaa -aad +qYo +aaa aaa +qYo +qkQ aaa -aad -aoP +uHd aaa -aac -eqU abi aeF aeF @@ -143023,25 +142885,25 @@ aaa aaa aaa aaa -aad +qYo aaa pAJ -aoP +qkQ pAJ aaa pAJ -aoP +qkQ pAJ aaa pAJ -aoP +qkQ pAJ aaa -aad -aoP -aad -aac -aad +qYo +qkQ +qYo +uHd +qYo abi aeF aeF @@ -143103,7 +142965,7 @@ why hXg uoz tpZ -aad +qYo lhY vZE ldU @@ -143111,7 +142973,7 @@ tcG vZE vZE lhY -aad +qYo mjz fLs azp @@ -143280,25 +143142,25 @@ aaa aaa aaa aaa -aac +uHd aaa pAJ -aoP +qkQ pAJ aaa pAJ -aoP +qkQ pAJ aaa pAJ -aoP +qkQ pAJ aaa -aad -aoP +qYo +qkQ aaa -aad -aad +qYo +qYo abi abi abi @@ -143319,11 +143181,11 @@ ksI qHQ mVI vno -aad -aad -rUw -rUw -aad +qYo +qYo +dkm +dkm +qYo oeX aNF tSu @@ -143537,35 +143399,35 @@ aaa aaa aaa aaa -aac -aad +uHd +qYo pAJ -aoP +qkQ pAJ -aad +qYo pAJ -aoP +qkQ pAJ -aad +qYo pAJ -aoP +qkQ pAJ -aad -aad -aoP +qYo +qYo +qkQ +aaa +uHd aaa -aac -eqU -aad -aad +qYo +qYo aaa -aad -aad -aad +qYo +qYo +qYo aaa -aad +qYo aaa -aad +qYo vno vno uHG @@ -143576,7 +143438,7 @@ vno dZQ vno vno -aad +qYo oeX pYG pYG @@ -143794,46 +143656,46 @@ aaa aaa aaa aaa -aad +qYo aaa pAJ -aoP +qkQ pAJ aaa pAJ -aoP +qkQ pAJ aaa pAJ -aoP +qkQ pAJ aaa -aad -aoP -aad -aac -qYo -aad -aac -aac -aac -aad -aac -aac -aac -aac -aac -aaa -aad -abj -abj -aad +qYo +qkQ +qYo +uHd +qYo +qYo +uHd +uHd +uHd +qYo +uHd +uHd +uHd +uHd +uHd +aaa +qYo +vVc +vVc +qYo vno ahI doI fUN vno -aad +qYo oeX bOl kVt @@ -144048,27 +143910,27 @@ aaa aaa aaa aaa -aac -aad -aac -aac -aad +uHd +qYo +uHd +uHd +qYo pAJ -aoP +qkQ pAJ aaa -aad -aoP -aad +qYo +qkQ +qYo aaa pAJ -aoP +qkQ pAJ aaa -aad -fjf +qYo +oeG aaa -aac +uHd aaa aaa aaa @@ -144080,17 +143942,17 @@ qYo aaa aaa qYo -aad -aad -aad -aad -aad +qYo +qYo +qYo +qYo +qYo vno iJj ove acU vno -aad +qYo oeX bRV agH @@ -144131,7 +143993,7 @@ bhJ tpZ tpZ tpZ -aad +qYo lhY yah vZE @@ -144139,7 +144001,7 @@ xrd vZE aSm lhY -aad +qYo mjz wus mJD @@ -144305,49 +144167,49 @@ aaa aaa aaa aaa -aac +uHd aaa -aad +qYo aaa aaa -aad -aoP -aad -aad -aad -fjf -aad -aad -aad -aoP -aad -aad -aad -fjf -aad -aac -aad +qYo +qkQ +qYo +qYo +qYo +oeG +qYo +qYo +qYo +qkQ +qYo +qYo +qYo +oeG +qYo +uHd +qYo aaa aaa aaa qYo aaa aaa -abj -aad -aad -abj +vVc +qYo +qYo +vVc aaa -aad +qYo aaa aaa -aad +qYo vno qaq tEN pzS vno -aad +qYo kic vcz kic @@ -144356,9 +144218,9 @@ xBu mvv fkS kic -aad -aad -aad +qYo +qYo +qYo tDx xEO xaE @@ -144366,11 +144228,11 @@ hhK xaE sJi tDx -aad -aad -aad -aad -aad +qYo +qYo +qYo +qYo +qYo aJE raF aAU @@ -144386,7 +144248,7 @@ cbh pkK tDD rWo -aad +qYo aaa aaa lhY @@ -144562,49 +144424,49 @@ aaa aaa aaa aaa -aad -aad +qYo +qYo lEh -aoP -aoP -fjf -fjf -fjf -fjf -pOH -fjf -fjf -fjf -xcd -fjf -fjf -fjf -fjf -fjf +qkQ +qkQ +oeG +oeG +oeG +oeG +fBF +oeG +oeG +oeG +pan +oeG +oeG +oeG +oeG +oeG aaa -aad +qYo aaa aaa aaa aaa -abj -aad -aad -abj +vVc +qYo +qYo +vVc aaa aaa -abj -aad -aad +vVc +qYo +qYo aaa aaa -aad +qYo vno vno vno vno vno -aad +qYo oeX sZt fQL @@ -144627,7 +144489,7 @@ aaa aaa aaa aaa -aad +qYo ljS gmo dfQ @@ -144643,15 +144505,15 @@ rWo rWo rWo rWo -aad +qYo aaa aaa aaa -aad +qYo aaa -xYl +gKN aaa -aad +qYo aaa aaa dCk @@ -144819,49 +144681,49 @@ aaa aaa aaa aaa -aac +uHd aaa -aad +qYo aaa aaa -aad -aoP -aad -aad -aad -fjf -aad -aad -aad -aoP -aad -aad -aad -aad -aad -aac -aad -abj -aad -aad -abj +qYo +qkQ +qYo +qYo +qYo +oeG +qYo +qYo +qYo +qkQ +qYo +qYo +qYo +qYo +qYo +uHd +qYo +vVc +qYo +qYo +vVc aaa aaa -abj -aad -aad -abj +vVc +qYo +qYo +vVc aaa -aad +qYo aaa aaa -aad -aad -aad -aad -aad -aad -aad +qYo +qYo +qYo +qYo +qYo +qYo +qYo oeX gdM lbu @@ -144884,7 +144746,7 @@ aaa aaa aaa aaa -aad +qYo ljS szZ bdF @@ -144892,25 +144754,25 @@ wob lwO oFI tgX -aad +qYo rWo juo mQj fvC rWo -aad -aad -aad -aad -aad -aad -aac -aac -aac -aac -aac -aad -aad +qYo +qYo +qYo +qYo +qYo +qYo +uHd +uHd +uHd +uHd +uHd +qYo +qYo oIU kJb qud @@ -145076,49 +144938,49 @@ aaa aaa aaa aaa -aac -aac -aac -aac -aad +uHd +uHd +uHd +uHd +qYo pAJ -aoP +qkQ pAJ aaa -aad -aoP -aad +qYo +qkQ +qYo aaa pAJ -aoP +qkQ pAJ -aad -aac -aad -aac -aac +qYo +uHd +qYo +uHd +uHd aaa -abj +vVc aaa aaa -abj -aad -aad -abj +vVc +qYo +qYo +vVc aaa aaa aaa aaa -aad -aad -aac -aac -aad +qYo +qYo +uHd +uHd +qYo aaa -aac -aac -aac -aad +uHd +uHd +uHd +qYo kic gdM qvW @@ -145141,7 +145003,7 @@ aaa aaa aaa aaa -aad +qYo aJE aJE rLg @@ -145159,13 +145021,13 @@ aaa aaa aaa aaa -abj -abj -abj -abj -abj -abj -abj +vVc +vVc +vVc +vVc +vVc +vVc +vVc aaa aaa oIU @@ -145336,29 +145198,29 @@ aaa aaa aaa aaa -aac +uHd aaa pAJ -aoP +qkQ pAJ aaa pAJ -aoP +qkQ pAJ aaa pAJ -aoP +qkQ pAJ aaa -aac -aad -aad +uHd +qYo +qYo aaa aaa -abj -aad -aad -abj +vVc +qYo +qYo +vVc aaa aaa aaa @@ -145374,8 +145236,8 @@ aaa aaa aaa aaa -aac -aad +uHd +qYo kic yhv syy @@ -145398,14 +145260,14 @@ aaa aaa aaa aaa -aad +qYo ofx pYh iWR xiB akc ofx -aad +qYo aaa rWo rWo @@ -145593,26 +145455,26 @@ aaa aaa aaa aaa -aad -aad +qYo +qYo pAJ -aoP +qkQ pAJ -aad +qYo pAJ -aoP +qkQ pAJ -aad +qYo pAJ -aoP +qkQ pAJ -aad -aac +qYo +uHd aaa aaa aaa aaa -abj +vVc aaa aaa aaa @@ -145631,8 +145493,8 @@ aaa aaa aaa aaa -aac -aad +uHd +qYo kic tKc kic @@ -145655,14 +145517,14 @@ aaa aaa aaa aaa -aad +qYo ofx oSE dgt rrE kOr ofx -aad +qYo aaa aaa aaa @@ -145850,21 +145712,21 @@ aaa aaa aaa aaa -aac +uHd aaa pAJ -aoP +qkQ pAJ aaa pAJ -aoP +qkQ pAJ aaa pAJ -aoP +qkQ pAJ aaa -aac +uHd aaa aaa aaa @@ -145883,20 +145745,20 @@ aaa aaa aaa aaa -aab +wVj aaa aaa aaa aaa aaa -aad -abj +qYo +vVc aaa -abj -aad -aad -aad -aad +vVc +qYo +qYo +qYo +qYo aaa aaa aaa @@ -145912,14 +145774,14 @@ aaa aaa aaa aaa -aad +qYo ofx udI tpE olI ilx ofx -aad +qYo aaa aaa aaa @@ -146107,21 +145969,21 @@ aaa aaa aaa aaa -aac +uHd aaa pAJ -aoP +qkQ pAJ aaa pAJ -aoP +qkQ pAJ aaa pAJ -aoP +qkQ pAJ aaa -aad +qYo aaa aaa aaa @@ -146147,12 +146009,12 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa -aac -aac +uHd +uHd aaa aaa aaa @@ -146169,14 +146031,14 @@ aaa aaa aaa aaa -aad +qYo ofx ofx aJE aJE ofx ofx -aad +qYo aaa aaa aaa @@ -146364,21 +146226,21 @@ aaa aaa aaa aaa -aac +uHd aaa aaa -aad +qYo aaa aaa pAJ -aoP +qkQ pAJ aaa aaa -aad +qYo aaa aaa -aac +uHd aaa aaa aaa @@ -146426,14 +146288,14 @@ aaa aaa aaa aaa -aad -aad -aad +qYo +qYo +qYo aaa aaa -aad -aad -aad +qYo +qYo +qYo aaa aaa aaa @@ -146621,21 +146483,21 @@ aaa aaa aaa aaa -aac -aac -aad -aac -aac +uHd +uHd +qYo +uHd +uHd aaa aaa -aad +qYo aaa aaa -aac -aac -aad -aac -aac +uHd +uHd +qYo +uHd +uHd aaa aaa aaa @@ -146671,24 +146533,24 @@ aaa aaa aaa aaa -abj -abj -abj -abj -abj -abj -abj -abj -abj +vVc +vVc +vVc +vVc +vVc +vVc +vVc +vVc +vVc aaa aaa aaa -aad +qYo aaa -aad -aad -aad -aad +qYo +qYo +qYo +qYo aaa aaa aaa @@ -146882,13 +146744,13 @@ aaa aaa aaa aaa -aac -aac -aad -aac -aac -aad -aac +uHd +uHd +qYo +uHd +uHd +qYo +uHd aaa aaa aaa @@ -146931,42 +146793,42 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa aaa aaa aaa -aac -aad -aad +uHd +qYo +qYo aaa aaa -aad +qYo aaa aaa -aad -abj -abj -abj -abj -abj -abj -aad -aad -aad +qYo +vVc +vVc +vVc +vVc +vVc +vVc +qYo +qYo +qYo faF fUg btm -aad +qYo btm fUg faF -aad -aad +qYo +qYo dCk oiH msb @@ -147188,30 +147050,30 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa aaa aaa aaa -aac +uHd aaa -aad +qYo aaa aaa -aad +qYo aaa aaa -aad +qYo aaa qYo aaa -aad +qYo aaa -aad +qYo aaa rJt rJt @@ -147442,29 +147304,29 @@ aaa aaa aaa aaa -aad -aad -aad -aad -aad -aad -aad -aad -aad -aad -aad -aad -aac +qYo +qYo +qYo +qYo +qYo +qYo +qYo +qYo +qYo +qYo +qYo +qYo +uHd aaa -aac -aad -aad -aad -aad -aad -aad +uHd +qYo +qYo +qYo +qYo +qYo +qYo aaa -aad +qYo aaa vgQ qIO @@ -147699,27 +147561,27 @@ aaa aaa aaa aaa -aad +qYo aaa aaa -aad +qYo aaa -aad +qYo aaa aaa -aac +uHd aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa -aad +qYo aaa aaa -aad +qYo vgQ vgQ vgQ @@ -147956,15 +147818,15 @@ aaa aaa aaa aaa -aad +qYo aaa aaa -aad -aad -aac -aac -aad -aad +qYo +qYo +uHd +uHd +qYo +qYo aaa aaa aaa @@ -148213,15 +148075,15 @@ aaa aaa aaa aaa -abj +vVc aaa aaa -abj +vVc aaa -aad +qYo aaa aaa -aad +qYo mSe mSe mSe @@ -148470,13 +148332,13 @@ aaa aaa aaa aaa -abj +vVc aaa aaa -abj -aad -aad -aad +vVc +qYo +qYo +qYo qYo qYo mSe @@ -148727,10 +148589,10 @@ aaa aaa aaa aaa -abj +vVc aaa nET -aad +qYo aaa aaa qYo @@ -148984,8 +148846,8 @@ aaa aaa aaa aaa -abj -aad +vVc +qYo qIH qIH vXr @@ -149351,7 +149213,7 @@ kvd aii rZI iLr -aad +qYo aaa aaa qYo @@ -149608,7 +149470,7 @@ jIQ xnT usy oLT -aad +qYo qYo qYo efQ @@ -150636,7 +150498,7 @@ pEi pEi ffY oLT -aad +qYo qYo aaa efQ @@ -150893,7 +150755,7 @@ gdr aii lXx oLT -fXz +sHt efQ aaa qYo @@ -151101,7 +150963,7 @@ rYA rYA aaa aaa -aad +qYo vop qqe qVa @@ -151150,7 +151012,7 @@ cYG uOE ruU iLr -aad +qYo efQ qYo xNe @@ -151353,11 +151215,11 @@ saT cqm uAL hEF -aad -aad -pHa -aad -aad +qYo +qYo +deJ +qYo +qYo uKw yaI pOP @@ -151382,7 +151244,7 @@ nXH fUq nXH nXH -aad +qYo nXH uFH put @@ -151407,7 +151269,7 @@ iLr oLT iLr iLr -fXz +sHt efQ sHt lvw @@ -151612,7 +151474,7 @@ cYD hEF aaa aaa -aad +qYo aaa aaa uKw @@ -151656,15 +151518,15 @@ oHG afm uGN pWe -aad -aad -aad -aad -aad -aad -aad -aad -aad +qYo +qYo +qYo +qYo +qYo +qYo +qYo +qYo +qYo aaa aaa efQ @@ -151833,7 +151695,7 @@ sgh lTJ gJk qIH -etw +pOQ qYo hQq fNW @@ -151867,11 +151729,11 @@ osc adM hci hEF -aad -aad -aad -aad -aad +qYo +qYo +qYo +qYo +qYo mfC rwh lrA @@ -151896,7 +151758,7 @@ iHH ojB qEB mfC -aad +qYo bBd uMb yan @@ -151904,7 +151766,7 @@ amS ufE qEb bBd -hDU +chp dhR fKY pwM @@ -152125,7 +151987,7 @@ adM nIn hEF aaa -aad +qYo aaa qYo aaa @@ -152347,7 +152209,7 @@ iCo yiA afQ eoB -aad +qYo qYo hQq rxT @@ -152382,7 +152244,7 @@ vCQ hEF hEF aaa -aad +qYo aaa qYo aaa @@ -152410,23 +152272,23 @@ huu baK cKZ mfC -aad -aad -eqU -eqU -aad -aaa -eqU -aad -hDU -aad -aad -eqU -aad +qYo +qYo +aaa +aaa +qYo +aaa +aaa +qYo +chp +qYo +qYo +aaa +qYo pWe dHy pWe -aad +qYo aaa aaa efQ @@ -152620,9 +152482,9 @@ szi wPA aIM iDq -aad +qYo aaa -aad +qYo bLs hXZ abw @@ -152637,12 +152499,12 @@ hyR lPH udb ggW -aad -aad +qYo +qYo efQ lvw efQ -aad +qYo mfC mGT sfA @@ -152667,24 +152529,24 @@ xBm baK eIQ mfC -aad +qYo qYo aaa aaa -aad +qYo aaa aaa -aad +qYo chp aaa aaa aaa -aad +qYo pWe onn pWe -aad -aad +qYo +qYo efQ efQ aaa @@ -152861,8 +152723,8 @@ iCo xwa qIH qIH -kvt -aad +wRE +qYo kOA kOA kOA @@ -152877,9 +152739,9 @@ iDq dql iDq iDq -aad +qYo aaa -aad +qYo bLs bLs gPh @@ -152895,10 +152757,10 @@ gCa gkt nEZ nEZ -aad +qYo aaa aaa -aad +qYo aaa mfC bEe @@ -152928,7 +152790,7 @@ qYo qYo aaa aaa -aad +qYo aaa aaa efQ @@ -152936,21 +152798,21 @@ vVc aaa aaa aaa -aad +qYo pWe gpg pWe -aad +qYo aaa -aad +qYo aaa aaa kpR -geN +qxf kpR aaa aaa -aad +qYo aaa aaa efQ @@ -153118,7 +152980,7 @@ lVn krO jrA aaa -aad +qYo aaa kOA nKE @@ -153137,7 +152999,7 @@ jUT qYo aaa qYo -pHa +deJ bLs bLs bLs @@ -153156,7 +153018,7 @@ qYo efQ qYo efQ -aad +qYo mfC twJ pdV @@ -153185,7 +153047,7 @@ qYo efQ aaa aaa -aad +qYo aaa aaa efQ @@ -153194,20 +153056,20 @@ aaa aaa aaa aaa -aad -geN -aad +qYo +qxf +qYo aaa kpR -geN +qxf kpR aaa kpR -geN +qxf kpR aaa kpR -geN +qxf kpR aaa qYo @@ -153349,7 +153211,7 @@ aaa aaa aaa aaa -aad +qYo aaa aaa aaa @@ -153374,9 +153236,9 @@ vxs tdj yiA jrA -aad -aad -aad +qYo +qYo +qYo bRF wQo piM @@ -153386,7 +153248,7 @@ hOw gOc ohq bRF -aad +qYo lvw efQ efQ @@ -153412,7 +153274,7 @@ nEZ qYo aaa aaa -aad +qYo aaa uKw aQG @@ -153450,21 +153312,21 @@ vVc qYo qYo qYo -aad -aad -geN -aad -aad +qYo +qYo +qxf +qYo +qYo kpR -geN +qxf kpR aaa kpR -geN +qxf kpR aaa kpR -geN +qxf kpR aaa efQ @@ -153632,7 +153494,7 @@ lCQ krO jrA aaa -aad +qYo aaa bRF gby @@ -153670,7 +153532,7 @@ qYo lvw qYo efQ -aad +qYo uKw nzk rwu @@ -153699,29 +153561,29 @@ qYo qYo aaa aaa -aad +qYo aaa aaa -aad +qYo vVc aaa aaa aaa aaa -aad -geN -aad +qYo +qxf +qYo aaa kpR -geN +qxf kpR -aad +qYo kpR -geN +qxf kpR -aad +qYo kpR -geN +qxf kpR qYo qYo @@ -153732,7 +153594,7 @@ aaa aaa aaa aaa -eqU +aaa aaa aaa aaa @@ -153842,7 +153704,7 @@ aaa aaa aaa aaa -oFv +tWY aaa aaa aaa @@ -153888,9 +153750,9 @@ eHO vip vhW qIH -aad -aad -aad +qYo +qYo +qYo bRF jst cLX @@ -153900,7 +153762,7 @@ aVo ida hMg bRF -aad +qYo xNe aaa lvw @@ -153935,7 +153797,7 @@ mfC uKw aaa qYo -hVE +glz aaa uKw ntP @@ -153945,7 +153807,7 @@ oHe uKw aaa spV -aad +qYo aaa mfC pEx @@ -153956,29 +153818,29 @@ qYo qYo aaa aaa -aad +qYo aaa aaa -aad +qYo vVc aaa aaa aaa aaa -aad -mAv -aad -aad +qYo +sKy +qYo +qYo kpR -geN +qxf kpR aaa kpR -geN +qxf kpR aaa kpR -geN +qxf kpR aaa efQ @@ -154147,7 +154009,7 @@ jrA qIH qIH qIH -aad +qYo kOA bVT dmB @@ -154184,13 +154046,13 @@ qYo aaa aaa efQ -aad +qYo uKw swP beP oRk uKw -aad +qYo mNC mNC mfC @@ -154203,7 +154065,7 @@ mfC mfC fIQ fIQ -aad +qYo mfC xGv dHX @@ -154213,7 +154075,7 @@ qYo qYo aaa aaa -aad +qYo aaa hUm vpk @@ -154227,15 +154089,15 @@ sKy qYo aaa kpR -geN +qxf kpR aaa -aad -geN -aad +qYo +qxf +qYo aaa kpR -geN +qxf kpR aaa efQ @@ -154404,7 +154266,7 @@ kLR qIH xFP qIH -aad +qYo kOA kOA gIw @@ -154414,7 +154276,7 @@ okz nGO kOA kOA -aad +qYo efQ aaa efQ @@ -154440,7 +154302,7 @@ uHd qYo uHd qYo -aad +qYo dTS uKw mfC @@ -154483,20 +154345,20 @@ qYo sKy qYo aaa -aad -geN -aad -aad -aad -mAv -aad -aad -aad -geN -aad +qYo +qxf +qYo +qYo +qYo +sKy +qYo +qYo +qYo +qxf +qYo aaa aaa -aad +qYo aaa efQ aaa @@ -154661,7 +154523,7 @@ aWb jgc hDc arz -abj +vVc aaa kOA cPR @@ -154671,7 +154533,7 @@ mgv cPR kOA aaa -aad +qYo efQ aaa efQ @@ -154698,7 +154560,7 @@ aaa uHd aaa efQ -aad +qYo uKw aaa sgI @@ -154720,9 +154582,9 @@ fIQ aaa mfC qYo -aad -aad -aad +qYo +qYo +qYo qYo qYo aaa @@ -154739,20 +154601,20 @@ vVc vVc sKy sKy -mAv -mAv -mAv -mAv -mAv -mAv -mAv -mAv -mAv -wct -mAv -mAv -geN -geN +sKy +sKy +sKy +sKy +sKy +sKy +sKy +sKy +sKy +fDJ +sKy +sKy +qxf +qxf dwr qYo efQ @@ -154918,7 +154780,7 @@ xmO qIH gJk qIH -aad +qYo aaa kOA gxW @@ -154928,7 +154790,7 @@ aNq rON kOA aaa -aad +qYo efQ qYo lvw @@ -154961,7 +154823,7 @@ aaa aaa aaa vGy -aad +qYo lAY cFG cFF @@ -154974,7 +154836,7 @@ cFF cFF cTi qOn -aad +qYo uKw qYo efQ @@ -154997,17 +154859,17 @@ aaa aaa qYo aaa -aad -geN -aad -aad -aad -mAv -aad -aad -aad -geN -aad +qYo +qxf +qYo +qYo +qYo +sKy +qYo +qYo +qYo +qxf +qYo aaa aaa qYo @@ -155158,7 +155020,7 @@ aaa aaa aaa aaa -aad +qYo aaa aaa bCC @@ -155175,8 +155037,8 @@ tsM bSJ gJk aaa -aad -aad +qYo +qYo kOA vCU bil @@ -155184,8 +155046,8 @@ wae pQd jjW kOA -aad -aad +qYo +qYo aaa qYo aaa @@ -155213,7 +155075,7 @@ aaa aaa efQ aaa -aad +qYo aaa aaa aaa @@ -155237,7 +155099,7 @@ qYo efQ aaa aaa -aad +qYo aaa aaa aaa @@ -155255,15 +155117,15 @@ qYo qYo aaa kpR -geN +qxf kpR aaa -aad -geN -aad +qYo +qxf +qYo aaa kpR -geN +qxf kpR aaa efQ @@ -155414,10 +155276,10 @@ uHd uHd uHd qYo -aFo -aad -aad -aad +xNe +qYo +qYo +qYo eHO eHO eHO @@ -155432,7 +155294,7 @@ tJn wIO jrA aaa -aad +qYo aaa kOA rwF @@ -155442,7 +155304,7 @@ yfO ykh kOA aaa -aad +qYo qYo efQ aaa @@ -155468,9 +155330,9 @@ aaa aaa aaa aaa -aad +qYo aaa -aad +qYo aaa aaa aaa @@ -155491,10 +155353,10 @@ fIQ aaa mfC qYo -aad +qYo aaa aaa -aad +qYo aaa aaa aaa @@ -155510,17 +155372,17 @@ qYo aaa aaa qYo -aad +qYo kpR -geN +qxf kpR aaa kpR -geN +qxf kpR aaa kpR -geN +qxf kpR aaa efQ @@ -155727,9 +155589,9 @@ aaa aaa efQ aaa -aad +qYo aaa -aJC +dAs aaa mfC aaa @@ -155751,7 +155613,7 @@ qYo efQ aaa aaa -aad +qYo aaa aaa aaa @@ -155769,17 +155631,17 @@ aaa efQ aaa kpR -geN +qxf kpR -aad +qYo kpR -geN +qxf kpR -aad +qYo kpR -geN +qxf kpR -aad +qYo efQ aaa aaa @@ -155946,14 +155808,14 @@ iud qzX gJk aaa -aad +qYo aaa jUT -aad +qYo aaa -aad +qYo aaa -aad +qYo jUT aaa qYo @@ -155983,13 +155845,13 @@ aaa aaa aaa efQ -aad -aad +qYo +qYo aaa aaa aaa uKw -aad +qYo lAY bnS cFF @@ -156002,7 +155864,7 @@ cFF cFF xVV qOn -aad +qYo uKw qYo efQ @@ -156026,15 +155888,15 @@ aaa efQ qYo kpR -geN +qxf kpR aaa kpR -geN +qxf kpR aaa kpR -geN +qxf kpR aaa qYo @@ -156196,14 +156058,14 @@ qYo qYo aaa aaa -aad +qYo gJk cBD hms qLF gJk pOQ -aad +qYo efQ efQ qYo @@ -156241,7 +156103,7 @@ aaa aaa lvw aaa -aad +qYo vVc vVc vVc @@ -156283,15 +156145,15 @@ qYo efQ aaa kpR -geN +qxf kpR aaa kpR -geN +qxf kpR aaa kpR -geN +qxf kpR aaa efQ @@ -156453,7 +156315,7 @@ vVc vVc aaa efQ -aad +qYo gJk qzX uqJ @@ -156498,10 +156360,10 @@ aaa aaa efQ efQ -aad -aad -aad -aad +qYo +qYo +qYo +qYo mfC aaa mNC @@ -156519,7 +156381,7 @@ fIQ aaa mfC qYo -aad +qYo qYo efQ efQ @@ -156544,7 +156406,7 @@ aaa aaa aaa kpR -geN +qxf kpR aaa aaa @@ -156710,7 +156572,7 @@ aaa aaa aaa efQ -aad +qYo gJk aaa sgI @@ -156755,10 +156617,10 @@ aaa aaa aaa aaa -aad -aad +qYo +qYo aaa -aad +qYo mfC aaa mNC @@ -156796,7 +156658,7 @@ qYo qYo efQ efQ -aad +qYo efQ efQ aaa @@ -157008,18 +156870,18 @@ aaa aaa aaa aaa -eqU +aaa aaa aaa efQ efQ -aad +qYo aaa -aad +qYo mfC aaa qYo -hVE +glz aaa uKw wBu @@ -157029,7 +156891,7 @@ urF uKw aaa spV -aad +qYo aaa mfC qYo @@ -157270,9 +157132,9 @@ aaa aaa aaa efQ -aad +qYo aaa -uOC +qdJ uKw mfC uKw @@ -157529,12 +157391,12 @@ aaa aaa aaa aaa -aad -aad -aad -aad -aad -aad +qYo +qYo +qYo +qYo +qYo +qYo mfC wSW hzK @@ -157542,12 +157404,12 @@ ond mJW fIQ qYo -aad qYo qYo qYo qYo -aad +qYo +qYo aaa aaa aaa @@ -157731,7 +157593,7 @@ aaa aaa aaa aaa -aab +wVj aaa aaa aaa @@ -157741,7 +157603,7 @@ aaa aaa aaa aaa -hBu +ofc aaa aaa aaa @@ -157786,11 +157648,11 @@ aaa aaa aaa aaa -aad +qYo efQ efQ aaa -aad +qYo qYo uKw rLt @@ -157799,7 +157661,7 @@ dhM vWR uKw qYo -aad +qYo aaa efQ efQ @@ -159109,7 +158971,7 @@ aaa aaa aaa aaa -aab +wVj aaa aaa aaa @@ -159549,7 +159411,7 @@ aaa aaa aaa aaa -aab +wVj aaa aaa aaa @@ -159564,7 +159426,7 @@ aaa aaa aaa aaa -aab +wVj aaa aaa aaa diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index 3cf0f6297bf1..d52d0bada566 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -2971,15 +2971,6 @@ "aPD" = ( /turf/closed/wall/r_wall, /area/station/engineering/storage_shared) -"aPM" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 8 - }, -/obj/effect/turf_decal/tile/neutral/half/contrasted{ - dir = 8 - }, -/turf/open/floor/iron, -/area/station/service/hydroponics/garden) "aPN" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -4613,11 +4604,6 @@ "bln" = ( /turf/open/misc/asteroid/snow/icemoon, /area/icemoon/surface/outdoors/nospawn) -"blA" = ( -/obj/machinery/hydroponics/soil, -/obj/machinery/light/directional/west, -/turf/open/floor/grass, -/area/station/service/hydroponics/garden) "blM" = ( /obj/effect/turf_decal/siding/wood{ dir = 8 @@ -11559,14 +11545,6 @@ /obj/structure/sign/calendar/directional/north, /turf/open/floor/iron, /area/station/commons/locker) -"ddZ" = ( -/obj/structure/cable, -/obj/effect/turf_decal/siding/green{ - dir = 4 - }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, -/turf/open/floor/iron/large, -/area/station/service/hydroponics/garden) "deg" = ( /obj/structure/cable/layer3, /turf/open/floor/circuit, @@ -14042,6 +14020,20 @@ /obj/effect/turf_decal/tile/red/half, /turf/open/floor/iron/smooth_half, /area/station/security/brig/upper) +"dPb" = ( +/obj/effect/landmark/start/assistant, +/obj/structure/cable, +/obj/effect/turf_decal/siding/green{ + dir = 4 + }, +/obj/effect/turf_decal/tile/green/half/contrasted{ + dir = 8 + }, +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/turf/open/floor/iron, +/area/station/service/hydroponics/garden) "dPj" = ( /obj/structure/ladder, /obj/effect/turf_decal/tile/neutral/diagonal_centre, @@ -15970,13 +15962,6 @@ /obj/machinery/telecomms/receiver/preset_left, /turf/open/floor/iron/dark/telecomms, /area/station/tcommsat/server) -"esv" = ( -/obj/structure/cable, -/obj/effect/turf_decal/siding/green{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/service/hydroponics/garden) "esC" = ( /obj/machinery/portable_atmospherics/canister/air, /obj/effect/decal/cleanable/dirt, @@ -17684,19 +17669,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/port/fore) -"eUi" = ( -/obj/item/seeds/apple, -/obj/item/seeds/banana, -/obj/item/seeds/cocoapod, -/obj/item/seeds/grape, -/obj/item/seeds/orange, -/obj/item/seeds/sugarcane, -/obj/item/seeds/wheat, -/obj/item/seeds/watermelon, -/obj/structure/table/glass, -/obj/item/seeds/tower, -/turf/open/floor/iron/dark, -/area/station/service/hydroponics/garden) "eUm" = ( /obj/machinery/airalarm/directional/south, /obj/effect/turf_decal/siding/thinplating/dark/corner{ @@ -17739,17 +17711,6 @@ dir = 1 }, /area/station/service/chapel) -"eUA" = ( -/obj/structure/cable, -/obj/effect/turf_decal/siding/green/corner{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/service/hydroponics/garden) "eUB" = ( /obj/structure/table, /obj/item/flashlight{ @@ -21426,16 +21387,6 @@ /obj/machinery/newscaster/directional/south, /turf/open/floor/stone, /area/station/service/bar/atrium) -"fYE" = ( -/obj/effect/turf_decal/tile/blue/anticorner/contrasted{ - dir = 8 - }, -/obj/machinery/modular_computer/preset/id{ - dir = 1 - }, -/obj/item/paper/fluff/ids_for_dummies, -/turf/open/floor/iron, -/area/station/command/heads_quarters/hop) "fYH" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -21909,16 +21860,6 @@ /obj/effect/spawner/random/maintenance, /turf/open/floor/plating, /area/station/maintenance/aft/lesser) -"geZ" = ( -/obj/structure/sink/directional/south, -/obj/effect/turf_decal/siding/wood{ - dir = 8 - }, -/obj/effect/turf_decal/tile/neutral/half/contrasted{ - dir = 8 - }, -/turf/open/floor/iron, -/area/station/service/hydroponics/garden) "gfb" = ( /turf/closed/wall/r_wall, /area/station/maintenance/central/greater) @@ -27801,6 +27742,21 @@ /obj/effect/turf_decal/trimline/yellow/filled/line, /turf/open/floor/iron/dark, /area/station/engineering/atmos/hfr_room) +"hPP" = ( +/obj/effect/turf_decal/tile/neutral/half/contrasted{ + dir = 8 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/turf_decal/tile/green/half/contrasted{ + dir = 1 + }, +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/turf/open/floor/iron, +/area/station/service/hydroponics/garden) "hPQ" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 1 @@ -32826,6 +32782,13 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/service/bar) +"jpk" = ( +/obj/structure/extinguisher_cabinet/directional/east, +/obj/machinery/hydroponics/constructable, +/obj/effect/turf_decal/siding/wood, +/obj/structure/railing, +/turf/open/floor/iron/dark, +/area/station/service/hydroponics/garden) "jpo" = ( /obj/machinery/door/poddoor/preopen{ id = "maint2" @@ -35399,11 +35362,6 @@ }, /turf/open/floor/iron, /area/mine/laborcamp) -"kby" = ( -/obj/machinery/hydroponics/soil, -/obj/structure/extinguisher_cabinet/directional/east, -/turf/open/floor/grass, -/area/station/service/hydroponics/garden) "kbJ" = ( /obj/machinery/field/generator, /turf/open/floor/plating, @@ -35714,6 +35672,20 @@ /obj/structure/cable, /turf/open/floor/iron, /area/mine/laborcamp) +"kfC" = ( +/obj/structure/cable, +/obj/effect/turf_decal/siding/green{ + dir = 4 + }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, +/obj/effect/turf_decal/tile/green/half/contrasted{ + dir = 8 + }, +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/turf/open/floor/iron/large, +/area/station/service/hydroponics/garden) "kfP" = ( /obj/structure/window/reinforced/spawner/directional/north, /obj/structure/window/reinforced/spawner/directional/east, @@ -38039,6 +38011,18 @@ /obj/structure/cable, /turf/open/floor/iron/dark/telecomms, /area/station/tcommsat/server) +"kNt" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral/half/contrasted{ + dir = 4 + }, +/obj/structure/railing/corner/end{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/service/hydroponics/garden) "kNA" = ( /obj/structure/disposalpipe/segment, /obj/structure/girder, @@ -38215,15 +38199,6 @@ /obj/structure/flora/bush/flowers_yw/style_random, /turf/open/floor/grass, /area/station/maintenance/starboard/aft) -"kPy" = ( -/obj/effect/turf_decal/tile/neutral/half/contrasted{ - dir = 4 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/service/hydroponics/garden) "kPH" = ( /obj/structure/stairs/south{ dir = 8 @@ -40909,14 +40884,6 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/iron, /area/station/science/xenobiology) -"lCb" = ( -/obj/effect/landmark/start/assistant, -/obj/structure/cable, -/obj/effect/turf_decal/siding/green{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/service/hydroponics/garden) "lCc" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/railing{ @@ -41824,6 +41791,21 @@ /obj/machinery/power/port_gen/pacman/pre_loaded, /turf/open/floor/plating, /area/station/maintenance/aft/lesser) +"lPA" = ( +/obj/item/seeds/apple, +/obj/item/seeds/banana, +/obj/item/seeds/cocoapod, +/obj/item/seeds/grape, +/obj/item/seeds/orange, +/obj/item/seeds/sugarcane, +/obj/item/seeds/wheat, +/obj/item/seeds/watermelon, +/obj/structure/table/glass, +/obj/item/seeds/tower, +/obj/item/storage/toolbox/fishing, +/obj/item/fishing_rod, +/turf/open/floor/iron/dark, +/area/station/service/hydroponics/garden) "lPC" = ( /obj/effect/turf_decal/trimline/green/filled/corner{ dir = 1 @@ -43713,12 +43695,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron, /area/station/engineering/atmos/storage) -"mut" = ( -/obj/machinery/hydroponics/soil, -/obj/machinery/light/directional/east, -/obj/machinery/newscaster/directional/east, -/turf/open/floor/grass, -/area/station/service/hydroponics/garden) "muv" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/chair/stool/directional/west, @@ -44303,10 +44279,6 @@ /obj/item/radio/intercom/chapel/directional/east, /turf/open/floor/wood/large, /area/station/service/chapel) -"mCT" = ( -/obj/machinery/hydroponics/soil, -/turf/open/floor/grass, -/area/station/service/hydroponics/garden) "mDf" = ( /obj/machinery/telecomms/server/presets/common, /turf/open/floor/iron/dark/telecomms, @@ -52239,6 +52211,10 @@ dir = 1 }, /area/station/command/gateway) +"oKp" = ( +/obj/machinery/light/directional/west, +/turf/open/water/no_planet_atmos/deep, +/area/station/service/hydroponics/garden) "oKv" = ( /obj/item/trash/popcorn, /turf/open/floor/plating, @@ -52340,6 +52316,12 @@ }, /turf/open/floor/iron/white/side, /area/mine/living_quarters) +"oLu" = ( +/obj/machinery/light/directional/east, +/obj/machinery/newscaster/directional/east, +/obj/machinery/hydroponics/constructable, +/turf/open/floor/iron/dark, +/area/station/service/hydroponics/garden) "oLz" = ( /obj/structure/disposalpipe/segment, /obj/structure/cable, @@ -56746,6 +56728,20 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/engineering/atmos) +"pYi" = ( +/obj/structure/cable, +/obj/effect/turf_decal/siding/green/corner{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/turf_decal/siding/wood/corner{ + dir = 1 + }, +/turf/open/floor/iron, +/area/station/service/hydroponics/garden) "pYn" = ( /obj/structure/table/wood, /obj/machinery/computer/security/telescreen/prison/directional/north, @@ -60054,18 +60050,6 @@ "qTf" = ( /turf/open/misc/asteroid/snow/standard_air, /area/station/science/cytology) -"qTm" = ( -/obj/effect/turf_decal/tile/neutral/half/contrasted{ - dir = 8 - }, -/obj/effect/turf_decal/siding/wood/corner{ - dir = 1 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/service/hydroponics/garden) "qTs" = ( /turf/open/floor/iron/showroomfloor, /area/station/security/prison/mess) @@ -63803,6 +63787,10 @@ /obj/effect/turf_decal/tile/green/full, /turf/open/floor/iron/dark/smooth_large, /area/station/medical/virology) +"rXp" = ( +/obj/machinery/hydroponics/constructable, +/turf/open/floor/iron/dark, +/area/station/service/hydroponics/garden) "rXr" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 4 @@ -66029,6 +66017,9 @@ /obj/structure/sign/warning/cold_temp/directional/north, /turf/open/openspace/icemoon/keep_below, /area/icemoon/surface/outdoors/nospawn) +"sCN" = ( +/turf/open/water/no_planet_atmos, +/area/station/service/hydroponics/garden) "sCQ" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -66622,6 +66613,19 @@ }, /turf/open/floor/iron/dark/corner, /area/station/security/processing) +"sLv" = ( +/obj/structure/cable, +/obj/effect/turf_decal/siding/green{ + dir = 4 + }, +/obj/effect/turf_decal/tile/green/half/contrasted{ + dir = 8 + }, +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/turf/open/floor/iron, +/area/station/service/hydroponics/garden) "sLD" = ( /obj/structure/table/reinforced, /obj/item/stack/sheet/iron/fifty, @@ -77148,6 +77152,18 @@ /obj/item/reagent_containers/syringe, /turf/open/floor/iron/white, /area/station/medical/chemistry) +"vSN" = ( +/obj/effect/turf_decal/tile/neutral/half/contrasted{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/turf_decal/siding/wood/corner{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/service/hydroponics/garden) "vSY" = ( /obj/structure/table, /obj/item/storage/box/beakers{ @@ -77708,6 +77724,15 @@ /obj/effect/turf_decal/tile/yellow/opposingcorners, /turf/open/floor/iron/dark, /area/station/engineering/atmos/project) +"wbv" = ( +/obj/effect/turf_decal/tile/blue/anticorner/contrasted{ + dir = 8 + }, +/obj/machinery/modular_computer/preset/id{ + dir = 1 + }, +/turf/open/floor/iron, +/area/station/command/heads_quarters/hop) "wbw" = ( /obj/effect/turf_decal/trimline/blue/filled/corner{ dir = 8 @@ -80165,6 +80190,9 @@ /obj/structure/rack, /turf/open/floor/plating, /area/station/maintenance/aft/lesser) +"wOL" = ( +/turf/open/water/no_planet_atmos/deep, +/area/station/service/hydroponics/garden) "wOO" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -231436,9 +231464,9 @@ lJO lJO lJO lJO -mCT -blA -mCT +wOL +oKp +wOL sGq oCO tdp @@ -231693,10 +231721,10 @@ lil anl pLZ lJO -geZ -aPM -aPM -qTm +sCN +sCN +sCN +hPP oCO oCO tmL @@ -231950,10 +231978,10 @@ hjI hjI anl icY -esv -lCb -ddZ -eUA +sLv +dPb +kfC +pYi aoc oCO oCO @@ -232208,7 +232236,7 @@ lJO lJO lJO dZJ -eUi +lPA eBB tNd nor @@ -232723,9 +232751,9 @@ kXI lJO wDf sAR -sAR +kNt lCn -kPy +vSN dQI pPT pPT @@ -232978,9 +233006,9 @@ lNj qDI lJO lJO -mCT -mut -kby +rXp +oLu +jpk oLm rbE wCL @@ -242523,7 +242551,7 @@ gMq pec fJl xMR -fYE +wbv cpm dnq ylU diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 603610316639..1baa8af52f94 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -2,14 +2,6 @@ "aaa" = ( /turf/open/space/basic, /area/space) -"aac" = ( -/obj/effect/landmark/carpspawn, -/turf/open/space, -/area/space) -"aaf" = ( -/obj/structure/lattice, -/turf/open/space, -/area/space/nearstation) "aag" = ( /turf/closed/wall, /area/station/commons/fitness) @@ -44,9 +36,6 @@ /obj/effect/spawner/random/engineering/atmospherics_portable, /turf/open/floor/plating, /area/station/maintenance/port/greater) -"aav" = ( -/turf/open/space, -/area/space) "aaz" = ( /obj/effect/spawner/random/trash/cigbutt, /obj/effect/turf_decal/trimline/yellow/filled/line{ @@ -106,10 +95,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/starboard/lesser) -"ack" = ( -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/space/nearstation) "acr" = ( /obj/structure/table, /obj/item/paper_bin{ @@ -129,6 +114,14 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/engineering/main) +"act" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/transit_tube/horizontal, +/obj/structure/window/reinforced/spawner/directional/west, +/turf/open/space/basic, +/area/space/nearstation) "acB" = ( /obj/structure/disposalpipe/segment, /turf/open/floor/carpet, @@ -1215,6 +1208,12 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/security/brig) +"axn" = ( +/obj/structure/lattice/catwalk, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/window/reinforced/spawner/directional/north, +/turf/open/space/basic, +/area/space/nearstation) "axx" = ( /obj/machinery/firealarm/directional/north, /obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ @@ -1260,13 +1259,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron/white/side, /area/station/medical/medbay/lobby) -"aye" = ( -/obj/structure/lattice/catwalk, -/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ - dir = 10 - }, -/turf/open/space, -/area/space/nearstation) "ayg" = ( /turf/open/floor/engine/o2, /area/station/engineering/atmos) @@ -1295,14 +1287,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/security/brig) -"azd" = ( -/obj/structure/lattice/catwalk, -/obj/machinery/atmospherics/pipe/heat_exchanging/simple, -/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ - dir = 4 - }, -/turf/open/space, -/area/space/nearstation) "azg" = ( /obj/item/stack/cable_coil, /turf/open/floor/plating/airless, @@ -1338,6 +1322,14 @@ /obj/machinery/light/directional/west, /turf/open/floor/iron/white, /area/station/science/research) +"azY" = ( +/obj/structure/lattice, +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/heat_exchanging/simple, +/turf/open/space/basic, +/area/space/nearstation) "azZ" = ( /obj/structure/closet/crate, /obj/item/reagent_containers/cup/bowl, @@ -1448,6 +1440,14 @@ }, /turf/open/floor/iron/dark, /area/station/command/bridge) +"aBt" = ( +/obj/structure/lattice/catwalk, +/obj/machinery/atmospherics/pipe/heat_exchanging/simple, +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ + dir = 4 + }, +/turf/open/space/basic, +/area/space/nearstation) "aBw" = ( /obj/structure/cable, /obj/effect/landmark/event_spawn, @@ -2411,13 +2411,6 @@ /obj/structure/window/reinforced/spawner/directional/north, /turf/open/floor/iron/dark, /area/station/ai_monitored/aisat/exterior) -"aQR" = ( -/obj/structure/lattice/catwalk, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/window/reinforced/spawner/directional/east, -/turf/open/space, -/area/space/nearstation) "aQS" = ( /obj/machinery/door/airlock/maintenance, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -2708,12 +2701,6 @@ /obj/machinery/telecomms/bus/preset_one, /turf/open/floor/circuit/green/telecomms/mainframe, /area/station/tcommsat/server) -"aWK" = ( -/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ - dir = 10 - }, -/turf/open/space, -/area/space/nearstation) "aWN" = ( /turf/open/floor/circuit, /area/station/ai_monitored/turret_protected/ai) @@ -2829,13 +2816,6 @@ }, /turf/open/floor/plating, /area/station/commons/fitness/recreation) -"aYx" = ( -/obj/structure/lattice, -/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ - dir = 4 - }, -/turf/open/space, -/area/space/nearstation) "aYz" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/door/poddoor/shutters/preopen{ @@ -3262,6 +3242,14 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/command/heads_quarters/ce) +"bgk" = ( +/obj/docking_port/stationary/random{ + dir = 4; + name = "lavaland"; + shuttle_id = "pod_3_lavaland" + }, +/turf/open/space/basic, +/area/space) "bgm" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -3572,12 +3560,6 @@ }, /turf/open/floor/iron/grimy, /area/station/tcommsat/computer) -"blw" = ( -/obj/structure/transit_tube/curved{ - dir = 8 - }, -/turf/open/space, -/area/space/nearstation) "blx" = ( /turf/closed/wall, /area/space/nearstation) @@ -3638,10 +3620,6 @@ /obj/machinery/light/directional/west, /turf/open/floor/iron, /area/station/hallway/primary/aft) -"bno" = ( -/obj/structure/transit_tube/diagonal, -/turf/open/space, -/area/space/nearstation) "bnr" = ( /obj/effect/turf_decal/trimline/blue/filled/line, /obj/structure/chair/sofa/corp/right{ @@ -3804,6 +3782,12 @@ dir = 4 }, /area/station/service/chapel) +"bpo" = ( +/obj/structure/transit_tube/curved/flipped{ + dir = 8 + }, +/turf/open/space/basic, +/area/space/nearstation) "bpq" = ( /obj/structure/table/reinforced, /obj/machinery/door/firedoor, @@ -3928,10 +3912,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/engineering/main) -"brO" = ( -/obj/structure/transit_tube/diagonal/topleft, -/turf/open/space, -/area/space/nearstation) "brX" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -6029,11 +6009,12 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central) -"ceP" = ( -/obj/structure/transit_tube/curved/flipped{ +"ceW" = ( +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ dir = 4 }, -/turf/open/space, +/obj/machinery/atmospherics/pipe/heat_exchanging/simple, +/turf/open/space/basic, /area/space/nearstation) "ceZ" = ( /obj/effect/turf_decal/tile/purple/half/contrasted{ @@ -6173,12 +6154,11 @@ }, /turf/closed/wall, /area/station/maintenance/central) -"cii" = ( -/obj/structure/disposalpipe/segment{ - dir = 10 +"cio" = ( +/obj/structure/transit_tube/curved/flipped{ + dir = 4 }, -/obj/structure/lattice/catwalk, -/turf/open/space, +/turf/open/space/basic, /area/space/nearstation) "ciE" = ( /obj/structure/cable, @@ -7112,11 +7092,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/service/chapel) -"cxl" = ( -/obj/structure/lattice, -/obj/machinery/atmospherics/pipe/smart/simple/green/visible, -/turf/open/space, -/area/space/nearstation) "cxq" = ( /obj/structure/disposalpipe/trunk{ dir = 1 @@ -8592,6 +8567,13 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/hallway/primary/central) +"dbl" = ( +/obj/structure/lattice/catwalk, +/obj/structure/transit_tube/horizontal, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/space/basic, +/area/space/nearstation) "dbm" = ( /obj/structure/table/wood, /obj/effect/spawner/random/food_or_drink/booze{ @@ -8864,79 +8846,6 @@ /obj/effect/turf_decal/box/corners, /turf/open/floor/iron, /area/station/engineering/atmos) -"dgd" = ( -/obj/machinery/atmospherics/pipe/heat_exchanging/simple, -/turf/open/space, -/area/space/nearstation) -"dge" = ( -/obj/structure/lattice/catwalk, -/obj/machinery/atmospherics/pipe/heat_exchanging/simple, -/turf/open/space, -/area/space/nearstation) -"dgf" = ( -/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ - dir = 6 - }, -/turf/open/space, -/area/space/nearstation) -"dgg" = ( -/obj/structure/lattice/catwalk, -/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ - dir = 6 - }, -/turf/open/space, -/area/space/nearstation) -"dgh" = ( -/obj/structure/lattice, -/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ - dir = 6 - }, -/turf/open/space, -/area/space/nearstation) -"dgj" = ( -/obj/structure/lattice, -/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ - dir = 5 - }, -/turf/open/space, -/area/space/nearstation) -"dgk" = ( -/obj/structure/lattice, -/obj/machinery/atmospherics/pipe/heat_exchanging/simple, -/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ - dir = 4 - }, -/turf/open/space, -/area/space/nearstation) -"dgm" = ( -/obj/structure/lattice, -/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/heat_exchanging/simple, -/turf/open/space, -/area/space/nearstation) -"dgt" = ( -/obj/machinery/atmospherics/pipe/heat_exchanging/simple, -/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ - dir = 4 - }, -/turf/open/space, -/area/space/nearstation) -"dgu" = ( -/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/heat_exchanging/simple, -/turf/open/space, -/area/space/nearstation) -"dgv" = ( -/obj/structure/lattice/catwalk, -/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ - dir = 9 - }, -/turf/open/space, -/area/space/nearstation) "dgz" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -8946,13 +8855,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white, /area/station/science/xenobiology) -"dgB" = ( -/obj/structure/lattice/catwalk, -/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ - dir = 5 - }, -/turf/open/space, -/area/space/nearstation) "dgD" = ( /turf/closed/wall, /area/station/security/range) @@ -9135,6 +9037,11 @@ /obj/structure/sign/poster/official/random/directional/north, /turf/open/floor/iron, /area/station/hallway/primary/port) +"djv" = ( +/obj/structure/lattice, +/obj/structure/window/reinforced/spawner/directional/west, +/turf/open/space/basic, +/area/space/nearstation) "dkx" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white, @@ -9829,11 +9736,6 @@ /obj/machinery/door/window/right/directional/east, /turf/open/floor/plating, /area/station/maintenance/disposal) -"dwJ" = ( -/obj/structure/lattice, -/obj/effect/spawner/random/structure/grille, -/turf/open/space, -/area/space/nearstation) "dwZ" = ( /obj/machinery/smartfridge/chemistry/preloaded, /obj/effect/turf_decal/tile/yellow/fourcorners, @@ -10129,6 +10031,11 @@ }, /turf/open/floor/iron, /area/station/engineering/gravity_generator) +"dEA" = ( +/obj/structure/lattice, +/obj/structure/window/reinforced/spawner/directional/east, +/turf/open/space/basic, +/area/space/nearstation) "dEF" = ( /obj/machinery/atmospherics/components/binary/pump/on, /obj/machinery/light/small/directional/east, @@ -14090,11 +13997,6 @@ }, /turf/open/floor/plating, /area/station/maintenance/department/science/xenobiology) -"eUu" = ( -/obj/structure/transit_tube/crossing/horizontal, -/obj/structure/lattice, -/turf/open/space, -/area/space/nearstation) "eUA" = ( /obj/structure/table/glass, /obj/machinery/light/small/directional/north, @@ -14837,6 +14739,13 @@ }, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) +"fhu" = ( +/obj/structure/lattice, +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ + dir = 5 + }, +/turf/open/space/basic, +/area/space/nearstation) "fhv" = ( /obj/effect/spawner/random/structure/closet_maintenance, /obj/item/extinguisher, @@ -15138,6 +15047,13 @@ /obj/structure/cable, /turf/open/floor/carpet, /area/station/command/heads_quarters/hop) +"flv" = ( +/obj/structure/lattice/catwalk, +/obj/machinery/atmospherics/pipe/smart/simple/orange/visible{ + dir = 5 + }, +/turf/open/space/basic, +/area/space/nearstation) "flx" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/public/glass{ @@ -15620,12 +15536,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/port/fore) -"ftb" = ( -/obj/structure/lattice, -/obj/structure/window/reinforced/spawner/directional/west, -/obj/structure/window/reinforced/spawner/directional/north, -/turf/open/space, -/area/space/nearstation) "ftd" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -15734,6 +15644,12 @@ /obj/effect/spawner/random/structure/crate, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) +"fwX" = ( +/obj/structure/transit_tube/curved{ + dir = 4 + }, +/turf/open/space/basic, +/area/space/nearstation) "fxa" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -16993,6 +16909,11 @@ "fWA" = ( /turf/closed/wall/r_wall, /area/station/maintenance/starboard/greater) +"fWD" = ( +/obj/structure/lattice, +/obj/structure/window/reinforced/spawner/directional/north, +/turf/open/space/basic, +/area/space/nearstation) "fWG" = ( /obj/item/kirbyplants/organic/plant5, /obj/effect/turf_decal/stripes/line{ @@ -17823,10 +17744,6 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/iron, /area/station/hallway/secondary/entry) -"gnh" = ( -/obj/structure/window/reinforced/spawner/directional/south, -/turf/open/space, -/area/space/nearstation) "gnk" = ( /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, @@ -17999,6 +17916,13 @@ /obj/item/plant_analyzer, /turf/open/floor/iron, /area/station/service/hydroponics/garden) +"gpn" = ( +/obj/structure/lattice, +/obj/machinery/atmospherics/pipe/smart/simple/yellow/visible{ + dir = 1 + }, +/turf/open/space/basic, +/area/space/nearstation) "gpv" = ( /obj/structure/cable, /obj/machinery/door/airlock{ @@ -18655,11 +18579,6 @@ /obj/structure/reagent_dispensers/fueltank, /turf/open/floor/plating, /area/station/maintenance/port/fore) -"gAu" = ( -/obj/structure/lattice, -/obj/structure/window/reinforced/spawner/directional/east, -/turf/open/space, -/area/space/nearstation) "gAw" = ( /obj/effect/turf_decal/delivery, /obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/hidden/layer4, @@ -20081,11 +20000,6 @@ /obj/structure/window/reinforced/spawner/directional/south, /turf/open/floor/iron/white, /area/station/science/lab) -"gZM" = ( -/obj/structure/window/reinforced/spawner/directional/east, -/obj/structure/window/reinforced/spawner/directional/north, -/turf/open/space, -/area/space/nearstation) "gZV" = ( /obj/structure/cable, /obj/effect/turf_decal/siding/wood{ @@ -20483,8 +20397,8 @@ /turf/open/floor/iron, /area/station/commons/lounge) "hif" = ( -/obj/structure/mannequin/skeleton, /obj/machinery/status_display/evac/directional/north, +/obj/structure/filingcabinet/chestdrawer, /turf/open/floor/iron/dark, /area/station/medical/morgue) "hio" = ( @@ -20602,6 +20516,11 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/starboard) +"hkl" = ( +/obj/structure/lattice/catwalk, +/obj/machinery/atmospherics/pipe/heat_exchanging/simple, +/turf/open/space/basic, +/area/space/nearstation) "hko" = ( /obj/effect/turf_decal/bot{ dir = 1 @@ -20814,11 +20733,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/wood, /area/station/commons/lounge) -"hns" = ( -/obj/machinery/atmospherics/pipe/smart/simple/orange/visible, -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/space/nearstation) "hnv" = ( /obj/effect/turf_decal/bot, /obj/structure/mecha_wreckage/ripley, @@ -21829,6 +21743,11 @@ /obj/structure/closet/secure_closet/atmospherics, /turf/open/floor/iron/dark, /area/station/engineering/atmospherics_engine) +"hFx" = ( +/obj/structure/lattice/catwalk, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/space/basic, +/area/space/nearstation) "hFz" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable, @@ -23106,6 +23025,13 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/central) +"ics" = ( +/obj/structure/lattice/catwalk, +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ + dir = 9 + }, +/turf/open/space/basic, +/area/space/nearstation) "icC" = ( /obj/structure/disposalpipe/segment{ dir = 9 @@ -23844,6 +23770,11 @@ }, /turf/open/floor/iron/white, /area/station/security/medical) +"iop" = ( +/obj/structure/lattice, +/obj/structure/window/reinforced/spawner/directional/south, +/turf/open/space/basic, +/area/space/nearstation) "iov" = ( /obj/machinery/power/apc/auto_name/directional/west, /obj/structure/cable, @@ -24030,13 +23961,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/engineering/supermatter/room) -"isc" = ( -/obj/docking_port/stationary/random{ - name = "lavaland"; - shuttle_id = "pod_2_lavaland" - }, -/turf/open/space, -/area/space) "ise" = ( /obj/effect/turf_decal/bot, /obj/item/robot_suit, @@ -24394,6 +24318,11 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/starboard/lesser) +"iyq" = ( +/obj/structure/window/reinforced/spawner/directional/east, +/obj/structure/window/reinforced/spawner/directional/south, +/turf/open/space/basic, +/area/space/nearstation) "iyy" = ( /obj/structure/table, /obj/item/folder/white{ @@ -25086,13 +25015,6 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos/storage/gas) -"iLe" = ( -/obj/structure/lattice/catwalk, -/obj/machinery/atmospherics/pipe/smart/simple/orange/visible{ - dir = 5 - }, -/turf/open/space, -/area/space/nearstation) "iLk" = ( /obj/effect/turf_decal/plaque{ icon_state = "L12" @@ -25593,6 +25515,11 @@ /obj/effect/mapping_helpers/airlock/access/any/command/minisat, /turf/open/floor/iron/dark, /area/station/engineering/transit_tube) +"iRp" = ( +/obj/structure/transit_tube/crossing/horizontal, +/obj/structure/lattice, +/turf/open/space/basic, +/area/space/nearstation) "iRr" = ( /obj/machinery/camera/directional/south{ c_tag = "Arrivals - Middle Arm" @@ -26282,6 +26209,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/security/courtroom) +"jdc" = ( +/obj/structure/lattice, +/obj/structure/window/reinforced/spawner/directional/west, +/obj/structure/window/reinforced/spawner/directional/north, +/turf/open/space/basic, +/area/space/nearstation) "jdg" = ( /obj/structure/flora/bush/ferny/style_random, /obj/structure/flora/bush/fullgrass/style_random, @@ -26329,14 +26262,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark/telecomms, /area/station/science/server) -"jdZ" = ( -/obj/docking_port/stationary/random{ - dir = 4; - name = "lavaland"; - shuttle_id = "pod_3_lavaland" - }, -/turf/open/space, -/area/space) "jef" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment, @@ -28183,6 +28108,12 @@ /obj/structure/cable, /turf/open/floor/wood, /area/station/commons/lounge) +"jIu" = ( +/obj/structure/lattice, +/obj/structure/window/reinforced/spawner/directional/east, +/obj/structure/window/reinforced/spawner/directional/south, +/turf/open/space/basic, +/area/space/nearstation) "jIz" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/disposalpipe/segment, @@ -28259,12 +28190,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/security/execution/transfer) -"jJC" = ( -/obj/structure/disposalpipe/segment, -/obj/structure/lattice/catwalk, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/visible/layer2, -/turf/open/space, -/area/space/nearstation) "jJR" = ( /obj/effect/turf_decal/trimline/blue/filled/corner{ dir = 4 @@ -28369,6 +28294,7 @@ dir = 4 }, /obj/effect/turf_decal/tile/dark_blue/half/contrasted, +/obj/structure/mannequin/skeleton, /turf/open/floor/iron/dark, /area/station/medical/morgue) "jLD" = ( @@ -28494,6 +28420,13 @@ }, /turf/open/floor/plating, /area/station/hallway/secondary/entry) +"jNd" = ( +/obj/structure/lattice/catwalk, +/obj/structure/transit_tube/crossing/horizontal, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/space/basic, +/area/space/nearstation) "jNo" = ( /obj/effect/turf_decal/stripes/line{ dir = 5 @@ -28564,6 +28497,13 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/white, /area/station/medical/chemistry) +"jOy" = ( +/obj/structure/lattice, +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ + dir = 4 + }, +/turf/open/space/basic, +/area/space/nearstation) "jOG" = ( /obj/effect/turf_decal/plaque{ icon_state = "L10" @@ -29181,11 +29121,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold/purple/visible, /turf/open/floor/iron, /area/station/engineering/atmos) -"jZC" = ( -/obj/structure/lattice/catwalk, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/space, -/area/space/nearstation) "jZP" = ( /obj/effect/turf_decal/siding/purple{ dir = 5 @@ -29306,6 +29241,12 @@ }, /turf/open/floor/iron, /area/station/service/janitor) +"kbP" = ( +/obj/structure/disposalpipe/segment, +/obj/structure/lattice/catwalk, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/visible/layer2, +/turf/open/space/basic, +/area/space/nearstation) "kbR" = ( /obj/structure/sign/poster/official/cleanliness/directional/east, /obj/machinery/door/window/right/directional/north{ @@ -29363,11 +29304,6 @@ /obj/effect/turf_decal/tile/yellow/half/contrasted, /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) -"kcU" = ( -/obj/structure/lattice, -/obj/structure/window/reinforced/spawner/directional/south, -/turf/open/space, -/area/space/nearstation) "kcV" = ( /obj/machinery/atmospherics/components/binary/pump{ dir = 4; @@ -29942,6 +29878,13 @@ /obj/machinery/status_display/evac, /turf/closed/wall, /area/station/commons/lounge) +"kmv" = ( +/obj/structure/lattice/catwalk, +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ + dir = 6 + }, +/turf/open/space/basic, +/area/space/nearstation) "kmN" = ( /turf/open/floor/plating, /area/station/maintenance/starboard/lesser) @@ -31654,6 +31597,13 @@ /obj/machinery/announcement_system, /turf/open/floor/iron/grimy, /area/station/tcommsat/computer) +"kRl" = ( +/obj/docking_port/stationary/random{ + name = "lavaland"; + shuttle_id = "pod_lavaland" + }, +/turf/open/space/basic, +/area/space) "kRA" = ( /obj/effect/spawner/random/engineering/atmospherics_portable, /obj/effect/mapping_helpers/broken_floor, @@ -34010,6 +33960,11 @@ /obj/structure/cable, /turf/open/floor/iron/dark, /area/station/command/bridge) +"lNN" = ( +/obj/structure/disposalpipe/segment, +/obj/structure/lattice/catwalk, +/turf/open/space/basic, +/area/space/nearstation) "lNO" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -34260,6 +34215,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, /turf/open/floor/plating, /area/station/maintenance/port/fore) +"lRB" = ( +/obj/structure/transit_tube/diagonal/topleft, +/turf/open/space/basic, +/area/space/nearstation) "lRS" = ( /obj/machinery/atmospherics/pipe/smart/simple/green/visible, /obj/effect/spawner/structure/window/reinforced, @@ -35511,11 +35470,6 @@ /obj/machinery/newscaster/directional/north, /turf/open/floor/iron/white, /area/station/science/research) -"moI" = ( -/obj/structure/window/reinforced/spawner/directional/west, -/obj/structure/window/reinforced/spawner/directional/south, -/turf/open/space, -/area/space/nearstation) "moV" = ( /obj/effect/spawner/structure/window/reinforced/tinted, /turf/open/floor/plating, @@ -35779,6 +35733,14 @@ dir = 1 }, /area/station/medical/treatment_center) +"mtt" = ( +/obj/machinery/atmospherics/pipe/smart/simple/orange/visible, +/obj/structure/lattice/catwalk, +/obj/structure/transit_tube/horizontal, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/space/basic, +/area/space/nearstation) "mtu" = ( /turf/open/floor/engine, /area/station/science/xenobiology) @@ -36705,9 +36667,6 @@ dir = 8 }, /area/station/science/lab) -"mJI" = ( -/turf/open/space, -/area/space/nearstation) "mJL" = ( /obj/machinery/airalarm/directional/south, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -36887,6 +36846,11 @@ /obj/machinery/power/apc/auto_name/directional/west, /turf/open/floor/iron/dark, /area/station/security/lockers) +"mMg" = ( +/obj/structure/window/reinforced/spawner/directional/west, +/obj/structure/window/reinforced/spawner/directional/north, +/turf/open/space/basic, +/area/space/nearstation) "mMl" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -36958,6 +36922,11 @@ }, /turf/open/floor/plating, /area/station/maintenance/aft/lesser) +"mNe" = ( +/obj/structure/window/reinforced/spawner/directional/east, +/obj/structure/window/reinforced/spawner/directional/north, +/turf/open/space/basic, +/area/space/nearstation) "mNj" = ( /obj/structure/closet/toolcloset, /obj/effect/turf_decal/tile/yellow/anticorner/contrasted{ @@ -37470,6 +37439,11 @@ }, /turf/open/floor/plating, /area/station/maintenance/starboard/greater) +"mWE" = ( +/obj/structure/lattice, +/obj/machinery/atmospherics/pipe/smart/simple/cyan/visible, +/turf/open/space/basic, +/area/space/nearstation) "mWU" = ( /turf/open/floor/iron, /area/station/maintenance/space_hut) @@ -38145,11 +38119,6 @@ dir = 8 }, /area/station/medical/morgue) -"niY" = ( -/obj/structure/disposalpipe/segment, -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/space/nearstation) "nja" = ( /obj/structure/disposalpipe/segment, /obj/structure/cable, @@ -39266,6 +39235,13 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron, /area/station/engineering/atmos) +"nAj" = ( +/obj/machinery/atmospherics/pipe/heat_exchanging/simple, +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ + dir = 4 + }, +/turf/open/space/basic, +/area/space/nearstation) "nAC" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -40334,6 +40310,12 @@ }, /turf/open/floor/iron/dark, /area/station/security/lockers) +"nUO" = ( +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ + dir = 10 + }, +/turf/open/space/basic, +/area/space/nearstation) "nVq" = ( /obj/structure/disposalpipe/segment, /obj/effect/spawner/random/maintenance, @@ -40423,10 +40405,6 @@ /obj/effect/turf_decal/trimline/blue/filled/warning, /turf/open/floor/iron/white, /area/station/medical/medbay/central) -"nWS" = ( -/obj/structure/window/reinforced/spawner/directional/west, -/turf/open/space, -/area/space/nearstation) "nXm" = ( /obj/structure/cable, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ @@ -41543,10 +41521,6 @@ /obj/structure/sign/warning/secure_area, /turf/closed/wall/r_wall, /area/station/security/brig) -"osz" = ( -/obj/structure/window/reinforced/spawner/directional/east, -/turf/open/space, -/area/space/nearstation) "osH" = ( /obj/structure/secure_safe/hos{ pixel_x = 36; @@ -41995,13 +41969,6 @@ }, /turf/open/floor/iron/dark, /area/station/security/brig) -"oAQ" = ( -/obj/structure/lattice/catwalk, -/obj/structure/transit_tube/horizontal, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/space, -/area/space/nearstation) "oBn" = ( /obj/structure/flora/bush/jungle/b/style_random, /obj/structure/flora/bush/flowers_pp/style_random, @@ -42532,11 +42499,6 @@ "oIa" = ( /turf/closed/wall, /area/station/commons/vacant_room/commissary) -"oId" = ( -/obj/structure/lattice, -/obj/machinery/atmospherics/pipe/smart/simple/cyan/visible, -/turf/open/space, -/area/space/nearstation) "oIg" = ( /turf/closed/wall/r_wall, /area/station/science/genetics) @@ -42808,6 +42770,12 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /turf/open/floor/carpet, /area/station/command/heads_quarters/hop) +"oOR" = ( +/obj/structure/transit_tube/curved{ + dir = 8 + }, +/turf/open/space/basic, +/area/space/nearstation) "oOU" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -42815,10 +42783,6 @@ dir = 8 }, /area/station/service/chapel) -"oOW" = ( -/obj/structure/window/reinforced/spawner/directional/north, -/turf/open/space, -/area/space/nearstation) "oOY" = ( /obj/structure/rack, /obj/item/fuel_pellet, @@ -43025,6 +42989,13 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/dark, /area/station/security/execution/education) +"oSm" = ( +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/structure/lattice/catwalk, +/turf/open/space/basic, +/area/space/nearstation) "oSo" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/door/poddoor/shutters/preopen{ @@ -43040,6 +43011,10 @@ /obj/effect/spawner/random/structure/grille, /turf/open/floor/plating, /area/station/maintenance/port/aft) +"oSJ" = ( +/obj/structure/transit_tube/diagonal, +/turf/open/space/basic, +/area/space/nearstation) "oTa" = ( /obj/machinery/vending/cart{ req_access = list("hop") @@ -43078,6 +43053,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/engineering/gravity_generator) +"oTW" = ( +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ + dir = 6 + }, +/turf/open/space/basic, +/area/space/nearstation) "oUh" = ( /obj/structure/reagent_dispensers/watertank, /obj/effect/turf_decal/stripes/corner{ @@ -45364,11 +45345,6 @@ /obj/structure/cable, /turf/open/floor/iron/freezer, /area/station/security/prison/shower) -"pJv" = ( -/obj/structure/window/reinforced/spawner/directional/west, -/obj/structure/window/reinforced/spawner/directional/north, -/turf/open/space, -/area/space/nearstation) "pJA" = ( /obj/structure/closet/secure_closet/cytology, /obj/structure/extinguisher_cabinet/directional/west, @@ -45913,15 +45889,6 @@ /obj/effect/spawner/random/engineering/atmospherics_portable, /turf/open/floor/plating, /area/station/maintenance/starboard/lesser) -"pSS" = ( -/obj/structure/lattice/catwalk, -/obj/structure/transit_tube/junction/flipped{ - dir = 8 - }, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/space, -/area/space/nearstation) "pSY" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/power/apc/auto_name/directional/south, @@ -46864,6 +46831,13 @@ /obj/item/food/pie/cream, /turf/open/floor/wood/large, /area/station/service/theater) +"qjb" = ( +/obj/structure/lattice/catwalk, +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ + dir = 10 + }, +/turf/open/space/basic, +/area/space/nearstation) "qjf" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -47059,6 +47033,13 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/service) +"qmz" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/window/reinforced/spawner/directional/east, +/turf/open/space/basic, +/area/space/nearstation) "qmE" = ( /obj/structure/cable, /obj/effect/turf_decal/stripes/line{ @@ -47143,12 +47124,6 @@ dir = 4 }, /area/station/science/lab) -"qot" = ( -/obj/structure/transit_tube/curved/flipped{ - dir = 8 - }, -/turf/open/space, -/area/space/nearstation) "qov" = ( /obj/machinery/atmospherics/components/unary/outlet_injector/monitored/oxygen_input{ dir = 1 @@ -47595,12 +47570,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/service/chapel/funeral) -"qyc" = ( -/obj/structure/lattice/catwalk, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/window/reinforced/spawner/directional/north, -/turf/open/space, -/area/space/nearstation) "qyr" = ( /obj/item/kirbyplants, /obj/effect/turf_decal/trimline/blue/filled/corner{ @@ -47663,12 +47632,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) -"qzs" = ( -/obj/structure/lattice/catwalk, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/space, -/area/space/nearstation) "qzz" = ( /obj/structure/chair{ dir = 1 @@ -49388,6 +49351,11 @@ /obj/structure/cable, /turf/open/floor/iron/dark, /area/station/science/ordnance/storage) +"rbg" = ( +/obj/machinery/atmospherics/pipe/smart/simple/orange/visible, +/obj/structure/lattice/catwalk, +/turf/open/space/basic, +/area/space/nearstation) "rbi" = ( /obj/effect/spawner/random/structure/closet_maintenance, /obj/effect/spawner/random/maintenance, @@ -49521,6 +49489,13 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos) +"rdM" = ( +/obj/structure/lattice, +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ + dir = 6 + }, +/turf/open/space/basic, +/area/space/nearstation) "rdT" = ( /obj/structure/toilet{ pixel_y = 8 @@ -50183,11 +50158,6 @@ /obj/structure/window/reinforced/spawner/directional/west, /turf/open/floor/iron, /area/station/security/range) -"rqK" = ( -/obj/structure/window/reinforced/spawner/directional/north, -/obj/structure/window/reinforced/spawner/directional/east, -/turf/open/space, -/area/space/nearstation) "rrg" = ( /obj/structure/cable, /obj/effect/spawner/structure/window/reinforced, @@ -51097,6 +51067,11 @@ /obj/machinery/power/apc/auto_name/directional/east, /turf/open/floor/iron, /area/station/security/holding_cell) +"rGa" = ( +/obj/structure/window/reinforced/spawner/directional/west, +/obj/structure/window/reinforced/spawner/directional/south, +/turf/open/space/basic, +/area/space/nearstation) "rGd" = ( /obj/structure/cable, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -51289,18 +51264,6 @@ /obj/effect/mapping_helpers/airlock/access/all/service/theatre, /turf/open/floor/wood, /area/station/maintenance/starboard/greater) -"rJr" = ( -/obj/machinery/camera/directional/south{ - c_tag = "Head of Personnel's Office" - }, -/obj/structure/table/wood, -/obj/machinery/light/directional/south, -/obj/item/papercutter{ - pixel_x = -4 - }, -/obj/item/paper/fluff/ids_for_dummies, -/turf/open/floor/wood, -/area/station/command/heads_quarters/hop) "rJA" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -52148,11 +52111,6 @@ /obj/effect/turf_decal/tile/red, /turf/open/floor/iron, /area/station/hallway/primary/fore) -"rYs" = ( -/obj/structure/window/reinforced/spawner/directional/east, -/obj/structure/window/reinforced/spawner/directional/south, -/turf/open/space, -/area/space/nearstation) "rYy" = ( /obj/machinery/power/smes, /obj/structure/cable, @@ -53387,6 +53345,11 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/hidden, /turf/open/floor/iron, /area/station/security/brig) +"swt" = ( +/obj/structure/window/reinforced/spawner/directional/north, +/obj/structure/window/reinforced/spawner/directional/east, +/turf/open/space/basic, +/area/space/nearstation) "swu" = ( /obj/machinery/vending/coffee, /obj/effect/turf_decal/delivery, @@ -54504,6 +54467,15 @@ /obj/machinery/light_switch/directional/north, /turf/open/floor/iron/white, /area/station/science/explab) +"sPJ" = ( +/obj/structure/lattice/catwalk, +/obj/structure/transit_tube/junction/flipped{ + dir = 8 + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/space/basic, +/area/space/nearstation) "sPO" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -54620,6 +54592,12 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/central) +"sRk" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/space/basic, +/area/space/nearstation) "sRm" = ( /turf/open/floor/iron/white, /area/station/medical/storage) @@ -55308,6 +55286,13 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) +"tcK" = ( +/obj/structure/lattice/catwalk, +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ + dir = 5 + }, +/turf/open/space/basic, +/area/space/nearstation) "tcN" = ( /obj/structure/disposalpipe/segment, /obj/structure/cable, @@ -55687,13 +55672,6 @@ /obj/effect/spawner/random/maintenance/two, /turf/open/floor/plating, /area/station/maintenance/port/aft) -"tkr" = ( -/obj/docking_port/stationary/random{ - name = "lavaland"; - shuttle_id = "pod_lavaland" - }, -/turf/open/space, -/area/space) "tkE" = ( /obj/machinery/requests_console/directional/east{ department = "Bridge"; @@ -56183,14 +56161,6 @@ /obj/machinery/light/directional/north, /turf/open/floor/iron, /area/station/hallway/primary/central) -"tsZ" = ( -/obj/machinery/atmospherics/pipe/smart/simple/orange/visible, -/obj/structure/lattice/catwalk, -/obj/structure/transit_tube/horizontal, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/turf/open/space, -/area/space/nearstation) "tth" = ( /obj/item/paper_bin/carbon, /obj/item/pen/fountain, @@ -56323,13 +56293,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/engineering/supermatter/room) -"twf" = ( -/obj/structure/lattice/catwalk, -/obj/structure/transit_tube/crossing/horizontal, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/space, -/area/space/nearstation) "twl" = ( /obj/structure/table, /obj/item/hand_tele, @@ -57155,6 +57118,14 @@ /obj/machinery/atmospherics/pipe/smart/simple/scrubbers/hidden, /turf/open/floor/iron, /area/station/engineering/atmos/storage/gas) +"tLf" = ( +/obj/structure/lattice, +/obj/machinery/atmospherics/pipe/heat_exchanging/simple, +/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ + dir = 4 + }, +/turf/open/space/basic, +/area/space/nearstation) "tLg" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/dark/visible, /obj/effect/decal/cleanable/dirt, @@ -58173,11 +58144,6 @@ dir = 4 }, /area/station/commons/fitness) -"ubw" = ( -/obj/structure/lattice, -/obj/structure/window/reinforced/spawner/directional/north, -/turf/open/space, -/area/space/nearstation) "ubB" = ( /obj/structure/table/reinforced, /obj/item/folder/blue{ @@ -58687,11 +58653,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/science/research) -"ulA" = ( -/obj/structure/lattice, -/obj/structure/window/reinforced/spawner/directional/west, -/turf/open/space, -/area/space/nearstation) "ulB" = ( /obj/effect/decal/cleanable/blood/oil, /obj/structure/railing/corner/end{ @@ -60889,6 +60850,17 @@ }, /turf/open/floor/iron, /area/station/security/mechbay) +"uWu" = ( +/obj/machinery/camera/directional/south{ + c_tag = "Head of Personnel's Office" + }, +/obj/structure/table/wood, +/obj/machinery/light/directional/south, +/obj/item/papercutter{ + pixel_x = -4 + }, +/turf/open/floor/wood, +/area/station/command/heads_quarters/hop) "uWx" = ( /obj/effect/turf_decal/bot/left, /turf/open/floor/engine, @@ -62772,14 +62744,6 @@ }, /turf/open/floor/iron/white, /area/station/science/research) -"vBJ" = ( -/obj/structure/lattice/catwalk, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/transit_tube/horizontal, -/obj/structure/window/reinforced/spawner/directional/west, -/turf/open/space, -/area/space/nearstation) "vCh" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -63409,13 +63373,6 @@ /obj/machinery/firealarm/directional/south, /turf/open/floor/iron, /area/station/hallway/secondary/entry) -"vNT" = ( -/obj/structure/lattice, -/obj/machinery/atmospherics/components/unary/passive_vent{ - dir = 1 - }, -/turf/open/space, -/area/space/nearstation) "vOh" = ( /obj/effect/turf_decal/stripes/end, /turf/open/floor/plating/airless, @@ -65835,6 +65792,10 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/exit/departure_lounge) +"wBZ" = ( +/obj/structure/window/reinforced/spawner/directional/south, +/turf/open/space/basic, +/area/space/nearstation) "wCb" = ( /obj/structure/table, /obj/effect/spawner/random/food_or_drink/donkpockets, @@ -66530,12 +66491,6 @@ }, /turf/open/floor/plating, /area/station/maintenance/port/fore) -"wQw" = ( -/obj/structure/lattice, -/obj/structure/window/reinforced/spawner/directional/east, -/obj/structure/window/reinforced/spawner/directional/south, -/turf/open/space, -/area/space/nearstation) "wQz" = ( /obj/structure/sign/poster/contraband/busty_backdoor_xeno_babes_6/directional/east, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, @@ -66560,11 +66515,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central) -"wQU" = ( -/obj/structure/lattice/catwalk, -/obj/structure/marker_beacon/burgundy, -/turf/open/space, -/area/space/nearstation) "wRg" = ( /obj/machinery/door/poddoor/incinerator_atmos_aux, /turf/open/floor/engine, @@ -67730,12 +67680,9 @@ /obj/structure/closet/crate/freezer, /turf/open/floor/iron/white, /area/station/medical/abandoned) -"xmT" = ( -/obj/structure/lattice, -/obj/machinery/atmospherics/pipe/smart/simple/yellow/visible{ - dir = 1 - }, -/turf/open/space, +"xmR" = ( +/obj/machinery/atmospherics/pipe/heat_exchanging/simple, +/turf/open/space/basic, /area/space/nearstation) "xnk" = ( /obj/structure/disposalpipe/segment{ @@ -68645,12 +68592,6 @@ /obj/effect/turf_decal/tile/bar, /turf/open/floor/iron, /area/station/hallway/primary/central) -"xCF" = ( -/obj/structure/transit_tube/curved{ - dir = 4 - }, -/turf/open/space, -/area/space/nearstation) "xCH" = ( /obj/effect/turf_decal/stripes/red/line{ dir = 6 @@ -69330,6 +69271,13 @@ /obj/structure/extinguisher_cabinet/directional/east, /turf/open/floor/iron/white, /area/station/medical/medbay/central) +"xQk" = ( +/obj/docking_port/stationary/random{ + name = "lavaland"; + shuttle_id = "pod_2_lavaland" + }, +/turf/open/space/basic, +/area/space) "xQx" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -70457,6 +70405,10 @@ /obj/effect/spawner/random/bureaucracy/stamp, /turf/open/floor/wood, /area/station/commons/vacant_room/office) +"yjN" = ( +/obj/structure/window/reinforced/spawner/directional/west, +/turf/open/space/basic, +/area/space/nearstation) "ykn" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper, /obj/machinery/door/airlock/external{ @@ -76101,7 +76053,7 @@ aaa aaa aaa aaa -aac +lKu aaa aaa aaa @@ -76634,7 +76586,7 @@ aaa aaa aaa aaa -aac +lKu aaa aaa aaa @@ -77112,7 +77064,7 @@ aaa aaa aaa aaa -aac +lKu aaa aaa aaa @@ -77863,7 +77815,7 @@ aaa aaa aaa aaa -aac +lKu aaa aaa aaa @@ -80197,7 +80149,7 @@ aaa aaa aaa aaa -tkr +kRl aaa aaa aaa @@ -82793,11 +82745,11 @@ qEt eIa vNM wdr -aaf +lMJ lXm jrY qEt -aaf +lMJ wdr sCZ aOf @@ -84257,7 +84209,7 @@ aaa aaa aaa aaa -aac +lKu aaa aaa aaa @@ -90723,10 +90675,10 @@ vxO jXu aaa aaa -aaf +lMJ aaa aaa -aaf +lMJ aaa aaa jXu @@ -90978,14 +90930,14 @@ jzq jXu paU jXu -aaf +lMJ rlU rlU rlU rlU rlU rlU -aaf +lMJ jXu rOz ciE @@ -92520,7 +92472,7 @@ dPt lRA lFF jXu -aaf +lMJ rlU rlU rlU @@ -92637,7 +92589,7 @@ aaa aaa aaa aaa -aac +lKu aaa aaa aaa @@ -94589,12 +94541,12 @@ fkD qWF aaa aaa -aaf +lMJ aaa aaa aaa aaa -aaf +lMJ aaa ihq uCq @@ -94612,7 +94564,7 @@ pJR pJR iiE rGj -rJr +uWu pJR oUB qRI @@ -95315,7 +95267,7 @@ aaa aaa aaa aaa -wQU +quc lMJ qrr sjP @@ -95358,7 +95310,7 @@ rsI oQZ ocg qWF -aaf +lMJ aJS dPV mph @@ -95829,7 +95781,7 @@ aaa aaa aaa aaa -isc +xQk aaa aaa aaa @@ -95887,9 +95839,9 @@ tBA dMv uoe tKN -aaf -aaf -aaf +lMJ +lMJ +lMJ dho dho alI @@ -96144,9 +96096,9 @@ puG htd uoe tKN -aaf -aaf -aaf +lMJ +lMJ +lMJ dsQ sVz aNe @@ -96386,7 +96338,7 @@ gUx cHE gTP qWF -aaf +lMJ aJS dPV jln @@ -96401,7 +96353,7 @@ uZo hPM uoe tKN -aaf +lMJ dsQ dsQ dho @@ -96658,7 +96610,7 @@ hZZ rng uoe tKN -aaf +lMJ dsQ mZL jbf @@ -96675,8 +96627,8 @@ dho uag aks qRI -aaf -aaf +lMJ +lMJ inX pRh uCH @@ -96739,7 +96691,7 @@ tXr hQu gRb aaa -aaf +lMJ aaa aaa aaa @@ -96915,7 +96867,7 @@ fMp htd uoe tKN -aaf +lMJ dsQ wag nxO @@ -96996,7 +96948,7 @@ kJB biA iUm xKd -aaf +lMJ aaa aaa aaa @@ -97159,12 +97111,12 @@ qWG uDP aaa aaa -aaf +lMJ aaa aaa aaa aaa -aaf +lMJ aaa ihq mur @@ -97172,7 +97124,7 @@ fVJ hpi uoe tKN -aaf +lMJ dsQ hfa dUj @@ -97253,7 +97205,7 @@ vje hQu gRb aaa -aaf +lMJ aaa aaa aaa @@ -97429,7 +97381,7 @@ exC dRZ uoe tKN -aaf +lMJ dho wss gGy @@ -97686,7 +97638,7 @@ gGa pWA uoe tKN -aaf +lMJ dsQ mXj dUj @@ -97943,7 +97895,7 @@ vVZ hcv rxZ tKN -aaf +lMJ dsQ sAz fMf @@ -98200,7 +98152,7 @@ wNN jOG qBC tKN -aaf +lMJ dsQ owv dUj @@ -98457,7 +98409,7 @@ vpQ iLk tGL tKN -aaf +lMJ dho vSh gGy @@ -98714,7 +98666,7 @@ xkr heF qBC tKN -aaf +lMJ dsQ qkA dUj @@ -98913,7 +98865,6 @@ aaa aaa aaa aaa -aav aaa aaa aaa @@ -98921,7 +98872,8 @@ aaa aaa aaa aaa -aav +aaa +aaa aaa aaa aaa @@ -98971,7 +98923,7 @@ tHR htd qBC tKN -aaf +lMJ dsQ hiu lNH @@ -99158,7 +99110,7 @@ aaa aaa aaa aaa -aac +lKu aaa aaa aaa @@ -99228,7 +99180,7 @@ wEG htd qBC tKN -aaf +lMJ dsQ kGc dTV @@ -99245,8 +99197,8 @@ dho fEX vQe qRI -aaf -aaf +lMJ +lMJ inX sxA cPU @@ -99485,7 +99437,7 @@ wEG rng qBC tKN -aaf +lMJ dsQ dsQ dho @@ -99742,9 +99694,9 @@ wEG htd qBC tKN -aaf -aaf -aaf +lMJ +lMJ +lMJ dsQ tkE iYA @@ -99999,9 +99951,9 @@ wEG tmK qBC tKN -aaf -aaf -aaf +lMJ +lMJ +lMJ dho dho dho @@ -100968,7 +100920,7 @@ aaa aaa aaa aaa -aav +aaa aaa aaa aaa @@ -101233,7 +101185,7 @@ aaa aaa aaa aaa -aav +aaa aaa aaa rrt @@ -102776,7 +102728,7 @@ aaa aaa aaa aaa -aav +aaa aaa aaa aaa @@ -103026,7 +102978,7 @@ aaa aaa aaa aaa -aav +aaa aaa aaa aaa @@ -103532,7 +103484,7 @@ aaa aaa aaa aaa -aac +lKu aaa aaa aaa @@ -104566,7 +104518,7 @@ aaa aaa aaa aaa -aav +aaa aaa aaa aaa @@ -104831,7 +104783,7 @@ aaa aaa aaa aaa -aav +aaa aaa aaa aaa @@ -104994,8 +104946,8 @@ lMJ lMJ aaa lMJ -aaf -aaf +lMJ +lMJ kJi kJi mgK @@ -105250,8 +105202,8 @@ lMJ aaa lMJ dxK -aaf -aaf +lMJ +lMJ weq kJi pgU @@ -105507,7 +105459,7 @@ aaa aaa aaa aaa -aaf +lMJ kJi kJi hxV @@ -105763,8 +105715,8 @@ aaa aaa aaa aaa -aaf -aaf +lMJ +lMJ jUq vOh sKJ @@ -106021,7 +105973,7 @@ aaa aaa aaa aaa -aaf +lMJ kJi kJi coc @@ -106278,8 +106230,8 @@ lMJ aaa lMJ dxK -aaf -aaf +lMJ +lMJ weq kJi vpl @@ -106536,8 +106488,8 @@ lMJ lMJ aaa lMJ -aaf -aaf +lMJ +lMJ kJi kJi hcl @@ -107150,7 +107102,7 @@ aaa rrt rrt lMJ -dwJ +rrt aaa lMJ aaa @@ -108161,7 +108113,7 @@ aaa aaa aaa aaa -aac +lKu aaa aaa aaa @@ -109465,7 +109417,7 @@ aaa aaa lMJ aaa -jdZ +bgk aaa nvn afD @@ -109809,7 +109761,7 @@ xpY wRg aaa aaa -aav +aaa aaa aaa aaa @@ -111340,13 +111292,13 @@ sgh kLp wxe uwQ -cii -niY -niY -niY -jJC -jJC -jJC +oSm +lNN +lNN +lNN +kbP +kbP +kbP jPJ xXp aaa @@ -111597,13 +111549,13 @@ xRc vIz pxC gAT -vNT +kuD eoU eoU eoU eoU eoU -aaf +lMJ ihW aaa aaa @@ -111854,13 +111806,13 @@ cyW keX hHt lRS -cxl +xtZ jYv wPZ isV isV eoU -aaf +lMJ aaa aaa aaa @@ -112111,13 +112063,13 @@ mvo oJL gyg lAh -aaf +lMJ gWn lpA rWi pMd eoU -aaf +lMJ aaa aaa aaa @@ -112368,13 +112320,13 @@ mei lXu fyY qSc -xmT +gpn xXm opZ fGR isV eoU -aaf +lMJ aaa aaa aaa @@ -112625,13 +112577,13 @@ vmx irz hGk tfs -aaf +lMJ eoU eoU eoU eoU eoU -aaf +lMJ lMJ lMJ lMJ @@ -112882,13 +112834,13 @@ nnD ndr sbl lRS -cxl +xtZ jYv qov ayg ayg eoU -aaf +lMJ aaa aaa lMJ @@ -113139,13 +113091,13 @@ qMm lMC smZ lAh -aaf +lMJ gWn bep drA kPU eoU -aaf +lMJ aaa aaa dxK @@ -113396,13 +113348,13 @@ smt xgN juC qSc -xmT +gpn xXm xNQ mgh ayg eoU -aaf +lMJ aaa aaa lMJ @@ -113653,13 +113605,13 @@ qua clO hGk tfs -aaf +lMJ eoU eoU eoU eoU eoU -aaf +lMJ lMJ lMJ lMJ @@ -113910,13 +113862,13 @@ smt mTy fPw okV -oId +mWE wPD vEl sUo sUo eoU -aaf +lMJ aaa aaa aaa @@ -114077,7 +114029,7 @@ aaa aaa aaa aaa -aac +lKu aaa aaa aaa @@ -114167,13 +114119,13 @@ qMm xcW smZ lAh -aaf +lMJ gWn eQs pfR wPB eoU -aaf +lMJ aaa aaa aaa @@ -114358,7 +114310,7 @@ aox lMJ aaa aaa -aav +aaa sxo qSh qSh @@ -114386,8 +114338,8 @@ fJP vBe wBV aUP -dgd -dgj +xmR +fhu gHI gHI fJy @@ -114424,13 +114376,13 @@ kEe sRy jie okV -oId +mWE eoj gYw cLt sUo eoU -aaf +lMJ aaa aaa aaa @@ -114644,10 +114596,10 @@ kcV lLu sGC aaa -aYx -dgf -dgj -ack +jOy +oTW +fhu +aox fJy mhW uNl @@ -114681,13 +114633,13 @@ sEI agw uRI uwQ -aaf +lMJ eoU eoU eoU eoU eoU -aaf +lMJ aaa aaa aaa @@ -114900,19 +114852,19 @@ qXj sgv ceo aUP -dge -azd -azd -azd -dgB +hkl +aBt +aBt +aBt +tcK fJy rrj bQj tcU gHI -vBJ -nWS -nWS +act +yjN +yjN bDq iRh qcd @@ -114938,13 +114890,13 @@ svj rhx ydM uwQ -aaf -aaf -aaf -aaf -aaf -aaf -aaf +lMJ +lMJ +lMJ +lMJ +lMJ +lMJ +lMJ aaa rrt aox @@ -115157,21 +115109,21 @@ sNt sTY sGC kYG -dgf -dgk -dgt -dgk -dgv +oTW +tLf +nAj +tLf +ics fJy bUC bQj jIV gHI -oAQ +dbl lMJ lMJ -aaf -ack +lMJ +aox qcd qcd qcd @@ -115386,7 +115338,7 @@ lMJ aaa aaa lMJ -aav +aaa sxo qSh qSh @@ -115414,26 +115366,26 @@ dHM lDP qZI kYG -aWK -dgk -dgt -dgk -dgB +nUO +tLf +nAj +tLf +tcK fJy xcz mzu bjF nyX -tsZ -hns -hns -hns -hns -hns +mtt +rbg +rbg +rbg +rbg +rbg oGw oGw oGw -iLe +flv uwQ vRS gyJ @@ -115671,17 +115623,17 @@ qLJ aBw xKl kYG -dgg -azd -azd -azd -dgv +kmv +aBt +aBt +aBt +ics fJy gHI eXo gHI fJy -twf +jNd lMJ aaa lMJ @@ -115928,17 +115880,17 @@ vxJ aib vLX kYG -aWK -dgk -dgt -dgk -dgB +nUO +tLf +nAj +tLf +tcK fJy mim diD gqf fJy -oAQ +dbl aaa aaa aaa @@ -116185,17 +116137,17 @@ twd aib qZI kYG -dgh -dgk -dgk -dgk -dgv +rdM +tLf +tLf +tLf +ics fJy gHI boq gHI fJy -twf +jNd aaa aaa aaa @@ -116442,17 +116394,17 @@ kYG kYG kYG kYG -aWK -dgm -dgu -dgm -dgB +nUO +azY +ceW +azY +tcK fJy aaa dBV aaa fJy -oAQ +dbl lMJ aaa lMJ @@ -116699,17 +116651,17 @@ aaa aaa aaa lMJ -ack -aye -dgv -aye -dgv +aox +qjb +ics +qjb +ics lMJ aaa aaa aaa lMJ -oAQ +dbl aaa aaa aaa @@ -116966,7 +116918,7 @@ aaa aaa aaa lMJ -oAQ +dbl aaa aaa aaa @@ -117220,10 +117172,10 @@ lMJ lMJ lMJ aaa -aav +aaa aaa lMJ -oAQ +dbl aaa aaa aaa @@ -117480,7 +117432,7 @@ aaa nXK aaa cpH -twf +jNd lMJ lMJ blx @@ -117737,7 +117689,7 @@ aaa aaa aaa aaa -oAQ +dbl aaa aaa aaa @@ -117994,7 +117946,7 @@ aaa aaa aaa aaa -oAQ +dbl aaa aaa aaa @@ -118251,7 +118203,7 @@ aaa aaa aaa aaa -twf +jNd aaa aaa aaa @@ -118508,7 +118460,7 @@ aaa aaa aaa aaa -oAQ +dbl aaa aaa aaa @@ -118761,11 +118713,11 @@ aaa aaa iGq jFr -aaf +lMJ vDl lMJ lMJ -oAQ +dbl lMJ lMJ blx @@ -119022,7 +118974,7 @@ aaa aaa aaa aaa -oAQ +dbl aaa aaa aaa @@ -119279,7 +119231,7 @@ aaa aaa aaa aaa -oAQ +dbl aaa aaa aaa @@ -119536,7 +119488,7 @@ aaa aaa aaa aaa -oAQ +dbl aaa aaa aaa @@ -119793,7 +119745,7 @@ iGq lMJ lMJ lMJ -oAQ +dbl lMJ lMJ blx @@ -120050,7 +120002,7 @@ aaa aaa aaa aaa -twf +jNd aaa aaa aaa @@ -120259,7 +120211,7 @@ aaa aaa aaa aaa -aac +lKu aaa aaa aaa @@ -120283,7 +120235,7 @@ aaa aaa aaa aaa -aac +lKu aaa aaa aaa @@ -120307,7 +120259,7 @@ aaa aaa aaa aaa -oAQ +dbl aaa aaa aaa @@ -120564,7 +120516,7 @@ aaa aaa aaa aaa -oAQ +dbl aaa aaa aaa @@ -120821,7 +120773,7 @@ lMJ lMJ lMJ lMJ -pSS +sPJ lMJ lMJ lMJ @@ -121077,10 +121029,10 @@ aaa aaa aaa lAu -bno -qzs -brO -mJI +oSJ +sRk +lRB +lAu aaa aox aaa @@ -121333,11 +121285,11 @@ aaa aaa aaa aaa -ceP +cio lAu -qzs +sRk lAu -xCF +fwX aaa aox aaa @@ -121590,11 +121542,11 @@ lMJ aox aox lMJ -eUu -aaf -qzs -aaf -eUu +iRp +lMJ +sRk +lMJ +iRp lMJ aox aaa @@ -121843,15 +121795,15 @@ aaa aaa aaa lMJ -gnh +wBZ qjC qjC -oOW -blw -osz -aQR -osz -qot +hBH +oOR +epM +qmz +epM +bpo aaa lMJ aaa @@ -122100,15 +122052,15 @@ aaa aaa aaa lMJ -gnh +wBZ pyP pyP -oOW -gnh +hBH +wBZ hzt jkG erP -oOW +hBH aaa aaa aaa @@ -122614,18 +122566,18 @@ aaa aaa aaa lMJ -rYs +iyq xew pyP -gZM -rYs +mNe +iyq fJt xXK oqe -gZM -osz -gAu -osz +mNe +epM +dEA +epM aaa aaa aaa @@ -122864,13 +122816,13 @@ lMJ anS lMJ aaa -gAu -osz -osz -osz -osz -osz -wQw +dEA +epM +epM +epM +epM +epM +jIu pAD fpd vgW @@ -122883,7 +122835,7 @@ pAD gCy gCy pMV -oOW +hBH aaa aaa aaa @@ -123116,11 +123068,11 @@ aaa aaa aaa aaa -osz -gAu +epM +dEA fHy -gAu -rYs +dEA +iyq eLr xgZ xgZ @@ -123129,30 +123081,30 @@ xgZ xgZ xgZ qIL -pJv -nWS -nWS -moI +mMg +yjN +yjN +rGa fJt neG eFX eNR -nWS -moI +yjN +rGa bhf -gZM -osz -osz -osz -osz -osz -osz -osz -osz -gAu +mNe +epM +epM +epM +epM +epM +epM +epM +epM +dEA aqs -gAu -osz +dEA +epM epM aaa aaa @@ -123372,19 +123324,19 @@ flb blx lMJ lMJ -kcU +iop doI xgZ xgZ xgZ xgZ uLz -pJv -nWS -nWS -nWS -nWS -nWS +mMg +yjN +yjN +yjN +yjN +yjN gfU aaa aaa @@ -123395,7 +123347,7 @@ mjH hLv eNR aaa -gnh +wBZ aHu xgZ xgZ @@ -123411,7 +123363,7 @@ sbG sbG sbG hey -ubw +fWD lMJ lMJ blx @@ -123629,12 +123581,12 @@ aaa rrt aaa aaa -gnh +wBZ trE -ftb +jdc bLR -ulA -nWS +djv +yjN gfU aaa aaa @@ -123654,21 +123606,21 @@ gfU aaa aaa gfU -nWS -nWS -nWS -nWS -nWS -nWS +yjN +yjN +yjN +yjN +yjN +yjN gfU -nWS -nWS -ulA +yjN +yjN +djv bLR -ulA -moI +djv +rGa trE -oOW +hBH aaa aaa rrt @@ -123886,9 +123838,9 @@ aaa rrt aaa aaa -gnh +wBZ trE -ubw +fWD anS lMJ lMJ @@ -123923,9 +123875,9 @@ aaa lMJ anS lMJ -kcU +iop trE -oOW +hBH aaa aaa rrt @@ -124143,7 +124095,7 @@ aaa rrt aaa aaa -gnh +wBZ trE iEj anS @@ -124182,7 +124134,7 @@ anS anS bwH trE -oOW +hBH aaa aaa rrt @@ -124400,9 +124352,9 @@ aaa rrt aaa aaa -gnh +wBZ trE -oOW +hBH aaa aaa gfU @@ -124437,9 +124389,9 @@ gfU gfU lMJ lMJ -kcU +iop trE -oOW +hBH aaa aaa rrt @@ -124656,10 +124608,10 @@ aaa aaa rrt aaa -osz -rYs +epM +iyq trE -oOW +hBH aaa aaa gfU @@ -124694,10 +124646,10 @@ ubl gfU aaa aaa -gnh +wBZ trE -rqK -osz +swt +epM aaa rrt aaa @@ -124912,11 +124864,11 @@ aaa aaa aaa rrt -gnh +wBZ doI pqH bCZ -oOW +hBH aaa gfU gfU @@ -124951,11 +124903,11 @@ bXk gfU eNR aaa -gnh +wBZ jjy pqH hey -oOW +hBH rrt aaa aaa @@ -125169,11 +125121,11 @@ aaa aaa aaa rrt -gnh +wBZ jjy iQr bCZ -oOW +hBH aaa gfU aTV @@ -125208,11 +125160,11 @@ pHi jGr gfU gfU -rYs +iyq jjy uKj bCZ -oOW +hBH rrt aaa aaa @@ -125430,8 +125382,8 @@ gfU nFL ddc gOv -qyc -jZC +axn +hFx pan mbS tVC @@ -125683,11 +125635,11 @@ aaa aaa aaa rrt -gnh +wBZ jjy iQr bCZ -oOW +hBH aaa gfU aTV @@ -125722,11 +125674,11 @@ rEK jGr gfU gfU -moI +rGa jjy uKj bCZ -oOW +hBH rrt aaa aaa @@ -125940,11 +125892,11 @@ aaa aaa aaa rrt -gnh +wBZ cZk qTS bCZ -oOW +hBH aaa gfU gfU @@ -125979,11 +125931,11 @@ fIE gfU eNR aaa -gnh +wBZ jjy qTS hBm -oOW +hBH rrt aaa aaa @@ -126198,10 +126150,10 @@ aaa aaa rrt aaa -nWS -moI +yjN +rGa trE -oOW +hBH aaa aaa gfU @@ -126236,10 +126188,10 @@ kOf gfU aaa aaa -gnh +wBZ trE -pJv -nWS +mMg +yjN aaa rrt aaa @@ -126456,9 +126408,9 @@ aaa rrt aaa aaa -gnh +wBZ trE -oOW +hBH aaa aaa gfU @@ -126493,9 +126445,9 @@ gfU gfU aaa aaa -gnh +wBZ trE -oOW +hBH aaa aaa rrt @@ -126713,9 +126665,9 @@ aaa rrt aaa aaa -gnh +wBZ trE -oOW +hBH aaa aaa aaa @@ -126750,9 +126702,9 @@ eNR aaa aaa aaa -gnh +wBZ trE -oOW +hBH aaa aaa rrt @@ -126970,9 +126922,9 @@ aaa rrt aaa aaa -gnh +wBZ trE -oOW +hBH aaa aaa aaa @@ -127007,9 +126959,9 @@ aaa aaa aaa aaa -gnh +wBZ trE -oOW +hBH aaa aaa rrt @@ -127227,12 +127179,12 @@ aaa rrt aaa aaa -gnh +wBZ trE -gZM -osz -osz -osz +mNe +epM +epM +epM gfU aaa aaa @@ -127252,21 +127204,21 @@ gfU aaa aaa gfU -osz -osz -osz -osz -osz -osz +epM +epM +epM +epM +epM +epM gfU -osz -osz -osz -osz -osz -rYs +epM +epM +epM +epM +epM +iyq trE -oOW +hBH aaa aaa rrt @@ -127484,19 +127436,19 @@ flb blx lMJ lMJ -kcU +iop cZk xgZ xgZ xgZ xgZ gNP -gZM -osz -osz -osz -osz -osz +mNe +epM +epM +epM +epM +epM gfU aaa aaa @@ -127507,7 +127459,7 @@ ikC gfU gfU aaa -gnh +wBZ aQe xgZ xgZ @@ -127523,7 +127475,7 @@ xgZ xgZ xgZ hBm -ubw +fWD lMJ lMJ blx @@ -127742,11 +127694,11 @@ rrt aaa aaa aaa -ulA -nWS -nWS -nWS -moI +djv +yjN +yjN +yjN +rGa cQV xgZ xgZ @@ -127755,31 +127707,31 @@ xgZ xgZ xgZ tpn -oOW +hBH aaa aaa aaa -gnh +wBZ beV -oOW +hBH aaa aaa -gnh +wBZ trE -pJv -nWS -nWS -nWS -nWS -nWS -nWS -nWS -nWS -nWS -nWS -nWS -nWS -ulA +mMg +yjN +yjN +yjN +yjN +yjN +yjN +yjN +yjN +yjN +yjN +yjN +yjN +djv aaa aaa aaa @@ -128004,26 +127956,26 @@ aaa aaa aaa aaa -ulA -nWS -nWS -nWS -nWS -nWS -moI +djv +yjN +yjN +yjN +yjN +yjN +rGa trE -gZM -osz -osz -osz -rYs +mNe +epM +epM +epM +iyq bhf -gZM -osz -osz -rYs +mNe +epM +epM +iyq trE -oOW +hBH aaa aaa aaa @@ -128267,7 +128219,7 @@ aaa aaa aaa aaa -gnh +wBZ cZk xgZ xgZ @@ -128280,7 +128232,7 @@ xgZ xgZ xgZ hBm -oOW +hBH aaa aaa aaa @@ -128525,18 +128477,18 @@ aaa aaa aaa aaa -ulA -nWS -nWS -nWS -nWS -nWS -nWS -nWS -nWS -nWS -nWS -ulA +djv +yjN +yjN +yjN +yjN +yjN +yjN +yjN +yjN +yjN +yjN +djv aaa aaa aaa diff --git a/_maps/map_files/NebulaStation/NebulaStation.dmm b/_maps/map_files/NebulaStation/NebulaStation.dmm index 0dbe454b5cad..1d463898d460 100644 --- a/_maps/map_files/NebulaStation/NebulaStation.dmm +++ b/_maps/map_files/NebulaStation/NebulaStation.dmm @@ -66211,7 +66211,7 @@ name = "lavaland"; shuttle_id = "pod_2_lavaland" }, -/turf/open/space, +/turf/open/space/basic, /area/space) "jPa" = ( /obj/structure/chair/office, @@ -88028,11 +88028,6 @@ /obj/item/radio/intercom/directional/south, /turf/open/floor/engine, /area/station/engineering/supermatter/room) -"nea" = ( -/obj/structure/lattice/catwalk, -/obj/structure/marker_beacon/lime, -/turf/open/space, -/area/space/nearstation) "ned" = ( /obj/structure/window/reinforced/spawner/directional/north, /obj/structure/window/reinforced/spawner/directional/south, @@ -98845,7 +98840,7 @@ dir = 1 }, /obj/structure/lattice/catwalk, -/turf/open/space, +/turf/open/space/basic, /area/space/nearstation) "oJw" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ @@ -102382,7 +102377,7 @@ "pgI" = ( /obj/machinery/atmospherics/pipe/smart/simple/cyan/visible, /obj/structure/lattice/catwalk, -/turf/open/space, +/turf/open/space/basic, /area/space/nearstation) "pgL" = ( /obj/structure/cable, @@ -120504,10 +120499,6 @@ }, /turf/open/floor/circuit/telecomms/server, /area/station/science/server) -"rQa" = ( -/obj/structure/lattice, -/turf/open/space, -/area/space/nearstation) "rQb" = ( /obj/structure/table/reinforced/plastitaniumglass, /turf/open/floor/iron/dark, @@ -145350,11 +145341,6 @@ /obj/machinery/camera/autoname/directional/east, /turf/open/floor/iron/dark, /area/station/security/checkpoint/supply) -"vzP" = ( -/obj/machinery/atmospherics/pipe/smart/simple/green/visible, -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/space/nearstation) "vzQ" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -159529,13 +159515,6 @@ /obj/structure/lattice/catwalk, /turf/open/floor/engine/hull/reinforced, /area/space/nearstation) -"xKJ" = ( -/obj/structure/lattice, -/obj/machinery/atmospherics/components/unary/passive_vent{ - dir = 1 - }, -/turf/open/space, -/area/space/nearstation) "xKK" = ( /obj/machinery/computer/teleporter, /obj/machinery/firealarm/directional/west, @@ -180751,7 +180730,7 @@ gym gym gym gym -nea +cJz gJT xzb ejn @@ -181779,7 +181758,7 @@ gym gym gym gym -nea +cJz gJT xzb ejn @@ -182807,7 +182786,7 @@ gym gym gym gym -nea +cJz gJT xzb ejn @@ -183835,7 +183814,7 @@ gym gym gym gym -nea +cJz gJT xzb ejn @@ -198066,13 +198045,13 @@ gih emX upO mSY -xKJ +acT trC trC trC trC trC -rQa +gJT ihJ gym gJT @@ -198323,13 +198302,13 @@ xyz mYR cKX aVG -vzP +sXb tbk qGg oxC oxC trC -rQa +gJT dew gJT dew @@ -198580,13 +198559,13 @@ jVY bSb jct jvZ -rQa +gJT cYz eBC sof wDA trC -rQa +gJT ihJ ykP dew @@ -198843,7 +198822,7 @@ mHk qOc oxC trC -rQa +gJT dew gJT dew @@ -199094,7 +199073,7 @@ aYL cWS oUY kpN -rQa +gJT trC trC trC @@ -199351,13 +199330,13 @@ ykv bKG iKr aVG -vzP +sXb tbk mrN fsx fsx trC -rQa +gJT dew gJT dew @@ -199608,13 +199587,13 @@ jSo eMn dmH jvZ -rQa +gJT cYz nrh wJx paH trC -rQa +gJT ihJ ykP dew @@ -199871,7 +199850,7 @@ eNX bLG fsx trC -rQa +gJT dew gJT dew @@ -200122,7 +200101,7 @@ uLW tYl oUY kpN -rQa +gJT trC trC trC @@ -200385,7 +200364,7 @@ gGE uCR uCR trC -rQa +gJT dew gJT dew @@ -200636,13 +200615,13 @@ rZX aab dmH jvZ -rQa +gJT cYz fEq kOH acG trC -rQa +gJT ihJ ykP dew @@ -200899,7 +200878,7 @@ ocT gKt uCR trC -rQa +gJT dew gJT dew @@ -201150,13 +201129,13 @@ cDb sBP eTX iwh -rQa +gJT trC trC trC trC trC -rQa +gJT ihJ gym gJT @@ -201407,11 +201386,11 @@ lmu yjn caH iwh -rQa +gJT ykP -rQa gJT -rQa +gJT +gJT ykP gJT gJT diff --git a/_maps/map_files/debug/runtimestation.dmm b/_maps/map_files/debug/runtimestation.dmm index 743b95f9e6b6..0dbf5d65af1f 100644 --- a/_maps/map_files/debug/runtimestation.dmm +++ b/_maps/map_files/debug/runtimestation.dmm @@ -4,10 +4,10 @@ /area/space) "ab" = ( /obj/structure/lattice, -/turf/open/space, +/turf/open/space/basic, /area/space/nearstation) "ac" = ( -/turf/open/space, +/turf/open/space/basic, /area/space/nearstation) "ad" = ( /obj/effect/turf_decal/stripes/line, @@ -17,7 +17,7 @@ "ae" = ( /obj/structure/lattice, /obj/structure/grille, -/turf/open/space, +/turf/open/space/basic, /area/space/nearstation) "af" = ( /obj/effect/turf_decal/stripes/line{ @@ -48,12 +48,12 @@ /area/station/engineering/atmos) "an" = ( /obj/structure/lattice/catwalk, -/turf/open/space, +/turf/open/space/basic, /area/space/nearstation) "ao" = ( /obj/structure/lattice/catwalk, /obj/structure/cable, -/turf/open/space, +/turf/open/space/basic, /area/space/nearstation) "ap" = ( /obj/structure/closet/secure_closet/engineering_electrical{ @@ -877,9 +877,6 @@ }, /turf/open/space/basic, /area/space) -"fg" = ( -/turf/open/space, -/area/space) "fh" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -2534,7 +2531,7 @@ /obj/machinery/atmospherics/components/unary/passive_vent/layer2{ dir = 8 }, -/turf/open/space, +/turf/open/space/basic, /area/space/nearstation) "TY" = ( /obj/machinery/button/door/directional/south{ @@ -6682,7 +6679,7 @@ dZ cN Tt bL -fg +aa aa aa aa @@ -6774,7 +6771,7 @@ dL cN dd bL -fg +aa aa aa aa @@ -6866,7 +6863,7 @@ dL cN Tt bL -fg +aa aa aa aa @@ -6958,7 +6955,7 @@ dL cN Tt Rb -fg +aa aa aa aa @@ -7050,7 +7047,7 @@ dL cN Tt Rb -fg +aa aa aa bs @@ -7142,7 +7139,7 @@ cZ cN Tt Rb -fg +aa aa aa aa @@ -8766,9 +8763,9 @@ aa aa aa aa -fg -fg -fg +aa +aa +aa aI af aX diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm index 98db0923396e..113a99e2abc0 100644 --- a/_maps/map_files/generic/CentCom.dmm +++ b/_maps/map_files/generic/CentCom.dmm @@ -2,9 +2,6 @@ "aa" = ( /turf/open/space/basic, /area/space) -"ad" = ( -/turf/open/space, -/area/space) "ak" = ( /obj/item/kirbyplants/organic/plant21, /obj/effect/turf_decal/tile/red/anticorner/contrasted{ @@ -4545,7 +4542,7 @@ shuttle_id = "emergency_away"; width = 50 }, -/turf/open/space, +/turf/open/space/basic, /area/space) "uA" = ( /obj/structure/chair{ @@ -5548,7 +5545,7 @@ shuttle_id = "cargo_away"; width = 20 }, -/turf/open/space, +/turf/open/space/basic, /area/space) "yW" = ( /obj/item/kirbyplants/organic/plant21, @@ -7453,7 +7450,7 @@ shuttle_id = "ferry_away"; width = 21 }, -/turf/open/space, +/turf/open/space/basic, /area/space) "Ip" = ( /obj/structure/chair/stool/bar/directional/east, @@ -65296,7 +65293,7 @@ aa aa aa aa -ad +aa aa aa aa diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index 0e8c80097d07..ed303f249652 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -3741,8 +3741,8 @@ /turf/open/floor/iron, /area/station/commons/storage/art) "axE" = ( -/obj/structure/window/reinforced/spawner/directional/north, /obj/effect/turf_decal/trimline/neutral/warning, +/obj/machinery/smartfridge/organ, /turf/open/floor/iron/dark, /area/station/medical/morgue) "axG" = ( @@ -5964,11 +5964,6 @@ /obj/machinery/photobooth, /turf/open/floor/iron/grimy, /area/station/service/library/lounge) -"aUh" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron, -/area/station/service/hydroponics/garden) "aUi" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -8889,14 +8884,6 @@ /obj/structure/cable, /turf/open/floor/glass/reinforced, /area/station/ai_monitored/turret_protected/aisat/hallway) -"bZG" = ( -/obj/effect/spawner/random/engineering/tracking_beacon, -/obj/effect/turf_decal/trimline/neutral/corner{ - dir = 8 - }, -/obj/effect/turf_decal/trimline/neutral/corner, -/turf/open/floor/iron, -/area/station/service/hydroponics/garden) "bZI" = ( /obj/machinery/door/window/brigdoor/left/directional/south{ name = "Secure Morgue Trays"; @@ -10374,6 +10361,14 @@ }, /turf/open/floor/iron/white, /area/station/science/xenobiology) +"cyS" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/turf_decal/siding/thinplating/corner, +/obj/effect/turf_decal/trimline/neutral/corner, +/turf/open/floor/iron, +/area/station/service/hydroponics/garden) "cyU" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -10512,7 +10507,6 @@ /turf/open/floor/iron, /area/station/commons/fitness/recreation) "cAK" = ( -/obj/effect/spawner/random/medical/two_percent_xeno_egg_spawner, /obj/machinery/atmospherics/pipe/smart/manifold4w/dark/visible, /obj/machinery/light/directional/north, /turf/open/floor/engine/xenobio, @@ -10795,15 +10789,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/security/brig) -"cGm" = ( -/obj/machinery/airalarm/directional/east, -/obj/effect/turf_decal/trimline/neutral/line, -/obj/effect/turf_decal/trimline/neutral/filled/line{ - dir = 4 - }, -/obj/structure/water_source/puddle, -/turf/open/floor/grass, -/area/station/service/hydroponics/garden) "cGy" = ( /obj/structure/chair/stool/directional/north, /obj/structure/disposalpipe/segment{ @@ -14342,6 +14327,9 @@ }, /turf/open/floor/iron, /area/station/engineering/break_room) +"dQQ" = ( +/turf/open/water/no_planet_atmos, +/area/station/service/hydroponics/garden) "dQR" = ( /obj/machinery/power/terminal{ dir = 1 @@ -17426,6 +17414,15 @@ /obj/machinery/light/cold/directional/south, /turf/open/floor/iron/white, /area/station/science/lobby) +"eYT" = ( +/obj/effect/turf_decal/siding/thinplating{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/neutral/line{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/service/hydroponics/garden) "eYZ" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/trimline/yellow/corner, @@ -18941,14 +18938,6 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/exit) -"fEf" = ( -/obj/structure/table/wood, -/obj/item/papercutter{ - pixel_x = -4 - }, -/obj/item/paper/fluff/ids_for_dummies, -/turf/open/floor/wood, -/area/station/command/heads_quarters/hop) "fEp" = ( /obj/effect/turf_decal/siding/wood{ dir = 4 @@ -19811,6 +19800,11 @@ /obj/machinery/meter, /turf/open/floor/iron, /area/station/engineering/atmos) +"fTk" = ( +/obj/machinery/light/directional/south, +/obj/machinery/hydroponics/constructable, +/turf/open/floor/iron/dark, +/area/station/service/hydroponics/garden) "fTz" = ( /obj/structure/table/wood, /obj/effect/turf_decal/siding/wood{ @@ -20755,12 +20749,6 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos/pumproom) -"gkR" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron, -/area/station/service/hydroponics/garden) "gkU" = ( /obj/effect/turf_decal/bot, /obj/machinery/power/shieldwallgen, @@ -24024,15 +24012,6 @@ }, /turf/open/floor/engine, /area/station/engineering/supermatter/room) -"hzR" = ( -/obj/effect/turf_decal/trimline/neutral/line{ - dir = 4 - }, -/obj/effect/turf_decal/trimline/neutral/line{ - dir = 8 - }, -/turf/open/floor/iron, -/area/station/service/hydroponics/garden) "hAv" = ( /obj/effect/turf_decal/bot, /obj/structure/closet/l3closet/scientist, @@ -24574,6 +24553,11 @@ /obj/machinery/transport/destination_sign/indicator/directional/south, /turf/open/floor/iron, /area/station/hallway/primary/tram/left) +"hLj" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/dark/visible, +/obj/effect/spawner/random/medical/two_percent_xeno_egg_spawner, +/turf/open/floor/engine/xenobio, +/area/station/science/xenobiology) "hLr" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 1 @@ -26628,6 +26612,10 @@ "iyc" = ( /turf/closed/wall, /area/station/commons/vacant_room/office) +"iyg" = ( +/obj/machinery/airalarm/directional/east, +/turf/open/water/no_planet_atmos, +/area/station/service/hydroponics/garden) "iyq" = ( /obj/effect/turf_decal/stripes/line{ dir = 6 @@ -29179,6 +29167,10 @@ }, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat_interior) +"jrU" = ( +/obj/machinery/light/directional/south, +/turf/open/water/no_planet_atmos/deep, +/area/station/service/hydroponics/garden) "jst" = ( /obj/machinery/airalarm/directional/east, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ @@ -38213,10 +38205,6 @@ /obj/structure/cable, /turf/open/openspace, /area/station/maintenance/solars/starboard/fore) -"mpw" = ( -/obj/machinery/hydroponics/soil, -/turf/open/floor/grass, -/area/station/service/hydroponics/garden) "mpx" = ( /obj/structure/window/reinforced/spawner/directional/east, /turf/open/floor/iron/dark/smooth_edge{ @@ -43286,6 +43274,13 @@ /obj/effect/landmark/start/head_of_personnel, /turf/open/floor/wood, /area/station/command/heads_quarters/hop) +"ofJ" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/turf_decal/trimline/neutral/line, +/obj/effect/turf_decal/siding/thinplating, +/turf/open/floor/iron, +/area/station/service/hydroponics/garden) "ofT" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 4 @@ -46877,15 +46872,6 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/exit) -"pzw" = ( -/obj/effect/turf_decal/bot, -/obj/machinery/power/apc/auto_name/directional/east, -/obj/effect/turf_decal/trimline/neutral/filled/line{ - dir = 4 - }, -/obj/structure/cable, -/turf/open/floor/iron, -/area/station/service/hydroponics/garden) "pAo" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/turf_decal/trimline/white/filled/line{ @@ -47357,6 +47343,12 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/cargo/miningdock) +"pIi" = ( +/obj/effect/turf_decal/trimline/neutral/line{ + dir = 8 + }, +/turf/open/floor/iron, +/area/station/service/hydroponics/garden) "pIk" = ( /obj/machinery/duct, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -48201,6 +48193,15 @@ /obj/item/kirbyplants/photosynthetic, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat_interior) +"pXn" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/neutral/line, +/obj/effect/turf_decal/siding/thinplating, +/turf/open/floor/iron, +/area/station/service/hydroponics/garden) "pXq" = ( /mob/living/simple_animal/bot/mulebot, /obj/effect/turf_decal/delivery, @@ -48716,7 +48717,6 @@ /turf/open/floor/catwalk_floor, /area/station/hallway/primary/tram/right) "qfS" = ( -/obj/machinery/smartfridge/organ, /obj/structure/window/reinforced/spawner/directional/west, /turf/open/floor/iron/dark, /area/station/medical/morgue) @@ -49197,10 +49197,6 @@ }, /turf/open/floor/iron, /area/station/command/heads_quarters/ce) -"qoZ" = ( -/obj/item/paper/fluff/ids_for_dummies, -/turf/open/misc/asteroid/airless, -/area/station/asteroid) "qpb" = ( /obj/structure/closet/secure_closet/exile, /obj/effect/turf_decal/bot, @@ -56237,13 +56233,6 @@ /obj/structure/cable, /turf/open/floor/circuit/telecomms/mainframe, /area/station/tcommsat/server) -"sMX" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/turf/open/floor/iron, -/area/station/service/hydroponics/garden) "sMZ" = ( /obj/effect/turf_decal/trimline/neutral/filled/corner{ dir = 8 @@ -56958,6 +56947,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/tram/right) +"sZo" = ( +/obj/machinery/hydroponics/constructable, +/turf/open/floor/iron/dark, +/area/station/service/hydroponics/garden) "sZv" = ( /obj/effect/turf_decal/sand/plating, /obj/effect/turf_decal/stripes/asteroid/line{ @@ -57525,6 +57518,13 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, /area/station/security/courtroom) +"tjM" = ( +/obj/structure/table/wood, +/obj/item/papercutter{ + pixel_x = -4 + }, +/turf/open/floor/wood, +/area/station/command/heads_quarters/hop) "tjP" = ( /obj/effect/turf_decal/stripes/corner{ dir = 8 @@ -59075,6 +59075,17 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/commons/fitness) +"tKI" = ( +/obj/effect/turf_decal/bot, +/obj/machinery/power/apc/auto_name/directional/east, +/obj/effect/turf_decal/trimline/neutral/filled/line{ + dir = 4 + }, +/obj/structure/cable, +/obj/effect/turf_decal/trimline/neutral/line, +/obj/effect/turf_decal/siding/thinplating, +/turf/open/floor/iron, +/area/station/service/hydroponics/garden) "tKK" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/door/poddoor/preopen{ @@ -59632,11 +59643,6 @@ }, /turf/open/floor/iron, /area/station/science/explab) -"tVO" = ( -/obj/machinery/hydroponics/soil, -/obj/machinery/light/directional/south, -/turf/open/floor/grass, -/area/station/service/hydroponics/garden) "tWb" = ( /obj/machinery/camera/directional/east{ c_tag = "Civilian - Theatre Stage" @@ -63812,6 +63818,13 @@ }, /turf/open/floor/iron/checker, /area/station/commons/lounge) +"vmZ" = ( +/obj/effect/spawner/random/engineering/tracking_beacon, +/obj/effect/turf_decal/trimline/neutral/corner{ + dir = 8 + }, +/turf/open/floor/iron, +/area/station/service/hydroponics/garden) "vne" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/light/small/directional/west, @@ -66439,6 +66452,9 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/tram/right) +"wiZ" = ( +/turf/open/water/no_planet_atmos/deep, +/area/station/service/hydroponics/garden) "wjk" = ( /obj/machinery/door/airlock/maintenance_hatch{ name = "Security Maintenance Hatch" @@ -68911,6 +68927,20 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/engineering/main) +"xfZ" = ( +/obj/effect/turf_decal/siding/thinplating{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/neutral/line{ + dir = 4 + }, +/obj/structure/table/glass, +/obj/item/storage/toolbox/fishing, +/obj/item/storage/toolbox/fishing, +/obj/item/fishing_rod, +/obj/item/fishing_rod, +/turf/open/floor/iron, +/area/station/service/hydroponics/garden) "xgh" = ( /obj/effect/turf_decal/siding/wood{ dir = 5 @@ -76259,7 +76289,7 @@ aaa gcp gcp gcp -qoZ +aac aac aaa aaa @@ -149170,7 +149200,7 @@ ckM nEF jBy iHr -mpw +sZo tdx mQa aju @@ -149427,7 +149457,7 @@ ckM pYh aow mdY -tVO +fTk tdx mQa tdx @@ -149684,7 +149714,7 @@ ckM wpu igT mdY -mpw +sZo tdx mQa tdx @@ -149941,7 +149971,7 @@ ilh ufK igT mdY -mpw +sZo tdx mQa tdx @@ -150197,8 +150227,8 @@ hTa uIo maz wwI -bZG -hzR +vmZ +pIi sZH mQa tdx @@ -150453,9 +150483,9 @@ kgr seh vpS mNC -gkR -mdY -mpw +cyS +eYT +xfZ tdx tdx tdx @@ -150710,9 +150740,9 @@ uzt hTa ckM edu -aUh -mdY -mpw +ofJ +dQQ +dQQ ckM bbM puN @@ -150967,9 +150997,9 @@ kly hTa ckM uOQ -sMX -mdY -tVO +pXn +dQQ +jrU ckM aHD iOi @@ -151224,9 +151254,9 @@ emO otX ckM pMz -pzw -cGm -mpw +tKI +iyg +wiZ ckM kwo iOi @@ -153262,7 +153292,7 @@ aBV aBV aBV wHT -fEf +tjM yhe vBn tRV @@ -183119,7 +183149,7 @@ pHX qVr cAK ttj -ttj +hLj ttj ttj nzg diff --git a/_maps/map_files/wawastation/wawastation.dmm b/_maps/map_files/wawastation/wawastation.dmm index 366919a82acc..9c6dc686b2a7 100644 --- a/_maps/map_files/wawastation/wawastation.dmm +++ b/_maps/map_files/wawastation/wawastation.dmm @@ -220,20 +220,6 @@ }, /turf/open/openspace, /area/station/maintenance/port/greater) -"adQ" = ( -/obj/structure/cable, -/obj/structure/closet/l3closet/scientist, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/machinery/camera/autoname/directional/south{ - network = list("ss13","rd","xeno") - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/iron/white/textured_large, -/area/station/science/xenobiology) "adV" = ( /obj/effect/turf_decal/tile/yellow, /obj/machinery/light/dim/directional/east, @@ -485,6 +471,17 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/hallway/secondary/command) +"ahz" = ( +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/structure/cable, +/obj/effect/turf_decal/stripes/corner, +/obj/machinery/firealarm/directional/north, +/turf/open/floor/iron/dark/corner{ + dir = 1 + }, +/area/station/engineering/atmos/upper) "ahE" = ( /turf/closed/wall, /area/station/commons/toilet/restrooms) @@ -631,6 +628,11 @@ }, /turf/open/floor/iron, /area/station/commons/locker) +"ako" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/firealarm/directional/east, +/turf/open/floor/plating, +/area/station/service/theater) "aks" = ( /obj/machinery/light/directional/north, /obj/structure/stairs/east, @@ -819,12 +821,6 @@ /mob/living/basic/mimic/crate, /turf/open/floor/iron/white, /area/station/maintenance/aft/upper) -"ank" = ( -/obj/effect/landmark/firealarm_sanity, -/turf/open/floor/engine{ - name = "Holodeck Projector Floor" - }, -/area/station/holodeck/rec_center) "anu" = ( /obj/machinery/atmospherics/pipe/heat_exchanging/junction, /turf/closed/wall/r_wall, @@ -867,6 +863,10 @@ "aod" = ( /turf/open/floor/iron/herringbone, /area/station/hallway/primary/central) +"aof" = ( +/obj/effect/landmark/firealarm_sanity, +/turf/open/openspace, +/area/station/cargo/storage) "aor" = ( /obj/structure/frame/machine, /obj/item/stack/cable_coil/five, @@ -908,6 +908,13 @@ /obj/effect/mapping_helpers/airlock/access/all/supply/general, /turf/open/floor/plating, /area/station/cargo/storage) +"aoP" = ( +/obj/structure/cable, +/obj/machinery/door/firedoor, +/turf/open/floor/iron/dark/textured_edge{ + dir = 4 + }, +/area/station/science/xenobiology) "apb" = ( /obj/structure/cable, /obj/effect/decal/cleanable/dirt/dust, @@ -1040,6 +1047,18 @@ /obj/machinery/atmospherics/pipe/multiz/scrubbers/visible/layer2, /turf/open/floor/plating, /area/station/maintenance/port/lesser) +"arq" = ( +/obj/machinery/door/airlock/highsecurity{ + name = "Gravity Generator Room" + }, +/obj/effect/mapping_helpers/airlock/access/all/engineering/construction, +/obj/structure/cable, +/obj/effect/landmark/navigate_destination, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/door/firedoor/heavy, +/turf/open/floor/iron, +/area/station/engineering/gravity_generator) "arr" = ( /turf/open/floor/iron/dark, /area/station/engineering/gravity_generator) @@ -1109,18 +1128,16 @@ /turf/open/floor/iron/white, /area/station/medical/medbay/central) "asP" = ( -/obj/machinery/light/directional/north, +/obj/effect/turf_decal/trimline/blue/filled/line, /obj/structure/cable, -/obj/effect/turf_decal/trimline/purple/filled/arrow_ccw, -/obj/effect/turf_decal/trimline/purple/filled/arrow_ccw{ - dir = 1 - }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/item/radio/intercom/directional/south, -/obj/machinery/firealarm/directional/north, -/turf/open/floor/iron/white/smooth_large, -/area/station/science/xenobiology/hallway) +/obj/structure/disposalpipe/segment{ + dir = 8 + }, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/iron/white, +/area/station/medical/paramedic) "asZ" = ( /turf/open/floor/glass/airless, /area/space/nearstation) @@ -1131,6 +1148,15 @@ /obj/structure/closet/firecloset, /turf/open/floor/iron/white, /area/station/hallway/secondary/entry) +"atb" = ( +/obj/structure/railing{ + dir = 8 + }, +/obj/effect/spawner/random/vending/colavend, +/obj/machinery/camera/autoname/directional/north, +/obj/machinery/firealarm/directional/north, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "ath" = ( /obj/machinery/door/window/left/directional/west, /turf/open/floor/grass, @@ -1434,10 +1460,6 @@ /obj/item/radio/intercom/directional/east, /turf/open/floor/iron, /area/station/hallway/primary/central) -"axO" = ( -/obj/effect/landmark/firealarm_sanity, -/turf/open/openspace, -/area/station/maintenance/central/greater) "axQ" = ( /obj/effect/turf_decal/stripes, /obj/machinery/atmospherics/components/binary/valve/digital/on{ @@ -1637,14 +1659,6 @@ }, /turf/open/floor/iron/white/smooth_large, /area/station/medical/medbay/central) -"aBe" = ( -/obj/structure/table/reinforced, -/obj/effect/turf_decal/tile/dark_blue/half/contrasted{ - dir = 1 - }, -/obj/item/storage/medkit/advanced, -/turf/open/floor/iron/dark, -/area/station/command/bridge) "aBM" = ( /obj/structure/table/wood, /obj/item/food/carneburrito{ @@ -1775,6 +1789,15 @@ /obj/effect/spawner/random/structure/closet_empty/crate, /turf/open/floor/iron, /area/station/cargo/warehouse/upper) +"aEd" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/table/wood, +/obj/item/storage/toolbox/fishing, +/obj/item/storage/toolbox/fishing, +/obj/item/fishing_rod, +/obj/item/fishing_rod, +/turf/open/floor/iron/large, +/area/station/service/hydroponics/garden) "aEh" = ( /obj/structure/table/wood, /obj/item/paper_bin{ @@ -2339,6 +2362,14 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/catwalk_floor/iron_white, /area/station/science/xenobiology) +"aMg" = ( +/obj/machinery/light/cold/directional/west, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/structure/table/reinforced, +/obj/item/electronics/apc, +/obj/machinery/firealarm/directional/west, +/turf/open/floor/iron/dark, +/area/station/ai_monitored/turret_protected/aisat/foyer) "aMx" = ( /obj/structure/cable, /obj/machinery/camera/autoname/motion/directional/south{ @@ -2657,12 +2688,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/wood/parquet, /area/station/service/theater) -"aSv" = ( -/obj/effect/turf_decal/tile/brown/anticorner/contrasted, -/obj/effect/spawner/random/clothing/wardrobe_closet_colored, -/obj/machinery/firealarm/directional/east, -/turf/open/floor/iron, -/area/station/cargo/boutique) "aSx" = ( /obj/machinery/door/airlock/atmos{ name = "Incinerator" @@ -3145,6 +3170,11 @@ /obj/machinery/byteforge, /turf/open/floor/iron/dark/textured, /area/station/cargo/bitrunning/den) +"bcm" = ( +/obj/machinery/camera/autoname/directional/south, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/iron/textured, +/area/station/engineering/storage/tech) "bco" = ( /turf/closed/wall/r_wall, /area/station/maintenance/solars/port) @@ -3233,6 +3263,12 @@ /obj/machinery/light/floor, /turf/open/floor/iron/textured, /area/station/command/heads_quarters/qm) +"beA" = ( +/obj/machinery/door/airlock/research{ + name = "Restroom" + }, +/turf/open/floor/iron/showroomfloor, +/area/station/science/research) "beE" = ( /obj/machinery/atmospherics/components/unary/portables_connector/visible, /turf/open/floor/iron/dark/textured_large, @@ -3662,6 +3698,11 @@ /obj/effect/spawner/random/engineering/tracking_beacon, /turf/open/floor/carpet, /area/station/service/theater) +"bmO" = ( +/obj/machinery/vending/clothing, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/wood/parquet, +/area/station/service/theater) "bnb" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/components/binary/valve{ @@ -4752,6 +4793,17 @@ /obj/machinery/status_display/ai/directional/west, /turf/open/floor/iron, /area/station/hallway/primary/central) +"bGF" = ( +/obj/effect/turf_decal/tile/red/half/contrasted{ + dir = 4 + }, +/obj/structure/chair{ + dir = 1; + name = "Prosecution" + }, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/iron, +/area/station/security/courtroom) "bGL" = ( /obj/machinery/button/door/directional/north{ id = "Xenolab"; @@ -4769,6 +4821,14 @@ dir = 8 }, /area/station/science/xenobiology) +"bGU" = ( +/obj/machinery/computer/atmos_alert/station_only{ + dir = 4 + }, +/obj/machinery/camera/autoname/directional/south, +/obj/item/radio/intercom/directional/west, +/turf/open/floor/iron, +/area/station/engineering/atmos/upper) "bGW" = ( /obj/structure/cable, /obj/effect/spawner/random/engineering/tracking_beacon, @@ -4895,12 +4955,6 @@ /obj/machinery/door/window/right/directional/west, /turf/open/floor/grass, /area/station/service/hydroponics/garden) -"bJc" = ( -/obj/structure/railing/corner, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/firealarm_sanity, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/lobby) "bJo" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/kitchen, @@ -4937,15 +4991,6 @@ }, /turf/open/misc/asteroid, /area/station/asteroid) -"bKP" = ( -/obj/machinery/power/apc/auto_name/directional/south, -/obj/effect/turf_decal/tile/brown/half/contrasted, -/obj/structure/table, -/obj/structure/cable, -/obj/item/healthanalyzer/simple, -/obj/effect/mapping_helpers/apc/full_charge, -/turf/open/floor/iron, -/area/station/cargo/storage) "bKQ" = ( /obj/structure/cable, /turf/open/floor/iron/dark/textured_large, @@ -5019,6 +5064,13 @@ dir = 4 }, /area/station/hallway/secondary/exit/departure_lounge) +"bMZ" = ( +/obj/machinery/ore_silo, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/bot_white, +/obj/machinery/status_display/ai/directional/north, +/turf/open/floor/iron/dark, +/area/station/ai_monitored/command/nuke_storage) "bNp" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -5443,18 +5495,6 @@ /obj/structure/flora/tree/palm/style_random, /turf/open/floor/grass, /area/station/medical/chemistry) -"bVa" = ( -/obj/structure/table/wood, -/obj/item/storage/crayons, -/obj/item/toy/crayon/spraycan{ - pixel_x = -4 - }, -/obj/item/toy/crayon/spraycan{ - pixel_x = -4 - }, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/carpet/purple, -/area/station/service/library) "bVg" = ( /obj/structure/chair/comfy/brown, /obj/effect/landmark/start/clown, @@ -5487,14 +5527,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central) -"bVB" = ( -/obj/effect/spawner/structure/window, -/obj/structure/curtain/cloth/fancy/mechanical{ - id = "law" - }, -/obj/machinery/door/firedoor, -/turf/open/floor/plating, -/area/station/service/lawoffice) "bVY" = ( /obj/machinery/holopad{ pixel_x = 1 @@ -5650,15 +5682,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/hallway/secondary/exit/departure_lounge) -"bYH" = ( -/obj/effect/turf_decal/siding/white{ - dir = 1 - }, -/obj/machinery/light/warm/dim/directional/north, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/firealarm/directional/north, -/turf/open/floor/iron/herringbone, -/area/station/hallway/primary/central) "bYP" = ( /obj/effect/turf_decal/tile/red/half/contrasted{ dir = 4 @@ -5950,13 +5973,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/department/medical/central) -"cdV" = ( -/obj/structure/stairs/east, -/obj/effect/landmark/firealarm_sanity, -/turf/open/floor/iron/stairs/medium{ - dir = 8 - }, -/area/station/medical/storage) "cdW" = ( /obj/structure/table/wood, /obj/machinery/fax/auto_name, @@ -6012,8 +6028,8 @@ /area/station/service/library) "ceF" = ( /obj/structure/table, -/obj/item/paper_bin/carbon, /obj/machinery/light_switch/directional/east, +/obj/item/flashlight/lamp, /turf/open/floor/iron/dark, /area/station/medical/morgue) "ceN" = ( @@ -6125,14 +6141,6 @@ }, /turf/open/floor/iron/white, /area/station/medical/virology) -"che" = ( -/obj/machinery/light/cold/directional/south, -/obj/effect/turf_decal/trimline/blue/filled/line, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/iron/white, -/area/station/medical/treatment_center) "chm" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white/smooth_large, @@ -6156,17 +6164,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/wood/large, /area/station/cargo/boutique) -"chM" = ( -/obj/structure/railing{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/door/firedoor/border_only{ - dir = 4 - }, -/obj/effect/landmark/firealarm_sanity, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/lobby) "chU" = ( /obj/effect/turf_decal/tile/red/diagonal_edge, /obj/effect/decal/cleanable/dirt, @@ -6260,10 +6257,21 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central) +"ciZ" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/firealarm/directional/east, +/turf/open/floor/circuit/green, +/area/station/ai_monitored/turret_protected/ai_upload) "cjp" = ( /obj/effect/spawner/random/structure/grille, /turf/open/floor/plating, /area/station/maintenance/central/greater) +"cjK" = ( +/obj/structure/lattice, +/obj/structure/cable, +/obj/effect/landmark/firealarm_sanity, +/turf/open/openspace, +/area/station/command/meeting_room) "cjV" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/visible, /obj/effect/turf_decal/delivery, @@ -6473,15 +6481,12 @@ }, /turf/open/floor/plating, /area/station/cargo/storage) -"cou" = ( -/obj/machinery/door/airlock/highsecurity{ - name = "Blast Chamber" - }, -/obj/effect/mapping_helpers/airlock/access/all/medical/chemistry, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/engine, -/area/station/medical/chemistry) +"coF" = ( +/obj/effect/turf_decal/tile/purple/fourcorners, +/obj/machinery/light/small/directional/north, +/obj/effect/landmark/firealarm_sanity, +/turf/open/floor/iron, +/area/station/science/ordnance) "coQ" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, @@ -6871,6 +6876,17 @@ /obj/structure/rack, /turf/open/floor/plating, /area/station/maintenance/central/lesser) +"cwR" = ( +/obj/structure/sign/warning/yes_smoking/circle/directional/west, +/obj/item/cigbutt, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 4 + }, +/obj/effect/landmark/firealarm_sanity, +/turf/open/floor/iron/dark/textured_corner{ + dir = 4 + }, +/area/station/science/breakroom) "cxg" = ( /turf/open/misc/asteroid/airless, /area/space/nearstation) @@ -7283,6 +7299,15 @@ }, /turf/open/floor/engine, /area/station/engineering/atmospherics_engine) +"cFF" = ( +/obj/machinery/power/apc/auto_name/directional/south, +/obj/effect/turf_decal/tile/brown/half/contrasted, +/obj/structure/table, +/obj/structure/cable, +/obj/item/healthanalyzer/simple, +/obj/effect/mapping_helpers/apc/full_charge, +/turf/open/floor/iron, +/area/station/cargo/storage) "cFH" = ( /obj/effect/turf_decal/tile/blue/half/contrasted, /obj/structure/cable, @@ -7453,6 +7478,12 @@ /obj/item/kirbyplants/random, /turf/open/floor/iron/white/smooth_large, /area/station/science/research) +"cIM" = ( +/obj/effect/turf_decal/siding, +/obj/structure/table, +/obj/machinery/camera/autoname/directional/north, +/turf/open/floor/iron/large, +/area/station/commons/locker) "cIN" = ( /obj/structure/barricade/wooden/crude, /turf/open/misc/asteroid, @@ -7506,11 +7537,6 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron/white, /area/station/medical/chemistry) -"cJM" = ( -/obj/structure/cable, -/obj/machinery/vending/wallmed/directional/north, -/turf/open/floor/iron/white, -/area/station/science/research) "cJO" = ( /obj/structure/cable, /obj/effect/turf_decal/tile/neutral{ @@ -7796,16 +7822,13 @@ dir = 4 }, /area/station/science/research) -"cPp" = ( -/obj/machinery/ore_silo, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/effect/turf_decal/bot_white, -/obj/machinery/status_display/ai/directional/north, -/turf/open/floor/iron/dark, -/area/station/ai_monitored/command/nuke_storage) "cPt" = ( /turf/closed/wall/r_wall, /area/station/science/lab) +"cPz" = ( +/mob/living/basic/axolotl, +/turf/open/water/no_planet_atmos, +/area/station/service/hydroponics/garden) "cPE" = ( /obj/machinery/light/small/directional/west, /turf/open/misc/asteroid, @@ -8066,6 +8089,17 @@ /obj/machinery/light/dim/directional/south, /turf/open/floor/wood, /area/station/service/library) +"cTX" = ( +/obj/machinery/computer/crew{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/blue/filled/line, +/obj/machinery/camera/autoname/directional/south{ + network = list("ss13","medbay") + }, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/iron/white, +/area/station/medical/paramedic) "cUe" = ( /obj/machinery/rnd/production/protolathe/department/science, /turf/open/floor/iron/white, @@ -8165,6 +8199,21 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron/white/small, /area/station/science/lobby) +"cVF" = ( +/obj/machinery/disposal/bin{ + desc = "A pneumatic waste disposal unit. This one leads into space!"; + name = "deathsposal unit" + }, +/obj/effect/turf_decal/stripes/end{ + dir = 1 + }, +/obj/machinery/light/directional/south, +/obj/structure/disposalpipe/trunk{ + dir = 8 + }, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/iron/white/textured_large, +/area/station/science/xenobiology) "cVL" = ( /obj/structure/closet/firecloset, /turf/open/floor/iron/textured, @@ -8313,6 +8362,16 @@ /obj/effect/decal/cleanable/blood/tracks, /turf/open/floor/plating/airless, /area/station/maintenance/department/medical/central) +"cYq" = ( +/obj/machinery/door/airlock/engineering/glass{ + name = "Primary Tool Storage" + }, +/obj/structure/cable, +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/door/firedoor, +/turf/open/floor/iron, +/area/station/commons/storage/primary) "cYs" = ( /obj/effect/spawner/random/structure/crate, /obj/effect/spawner/random/maintenance, @@ -8652,28 +8711,12 @@ }, /turf/open/floor/engine, /area/station/science/explab) -"dek" = ( -/obj/structure/cable, -/obj/effect/turf_decal/trimline/blue/filled/line{ - dir = 4 - }, -/obj/machinery/firealarm/directional/east, -/turf/open/floor/iron/white, -/area/station/medical/treatment_center) "des" = ( /obj/structure/closet/lasertag/blue, /obj/effect/turf_decal/tile/blue/fourcorners, /obj/effect/landmark/start/hangover/closet, /turf/open/floor/iron, /area/station/commons/fitness/recreation) -"deR" = ( -/obj/machinery/computer/atmos_alert/station_only{ - dir = 4 - }, -/obj/machinery/camera/autoname/directional/south, -/obj/item/radio/intercom/directional/west, -/turf/open/floor/iron, -/area/station/engineering/atmos/upper) "deY" = ( /obj/effect/turf_decal/tile/neutral, /obj/machinery/firealarm/directional/east, @@ -8766,6 +8809,14 @@ }, /turf/open/floor/plating, /area/station/medical/storage) +"dgG" = ( +/obj/effect/turf_decal/trimline/yellow/filled/line{ + dir = 1 + }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, +/obj/machinery/firealarm/directional/north, +/turf/open/floor/iron, +/area/station/engineering/gravity_generator) "dgS" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -9082,6 +9133,11 @@ dir = 1 }, /area/station/command/bridge) +"dlg" = ( +/obj/structure/window/spawner/directional/east, +/obj/structure/flora/bush/lavendergrass, +/turf/open/floor/grass, +/area/station/service/hydroponics/garden) "dlp" = ( /obj/structure/cable, /obj/effect/turf_decal/tile/green/full, @@ -9285,6 +9341,10 @@ /obj/item/pickaxe/improvised, /turf/open/misc/asteroid, /area/station/maintenance/department/medical) +"dpb" = ( +/obj/effect/landmark/firealarm_sanity, +/turf/open/openspace, +/area/station/command/corporate_showroom) "dpc" = ( /obj/structure/table/wood, /obj/structure/railing{ @@ -9392,19 +9452,26 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/catwalk_floor/iron_dark, /area/station/ai_monitored/turret_protected/aisat_interior) -"dqJ" = ( -/obj/effect/turf_decal/siding/purple{ - dir = 1 - }, -/obj/machinery/light/dim/directional/west, -/obj/item/radio/intercom/directional/west, -/turf/open/floor/iron/white, -/area/station/science/ordnance/testlab) "dqK" = ( /obj/structure/lattice, /obj/machinery/atmospherics/pipe/heat_exchanging/manifold4w, /turf/open/space/basic, /area/space/nearstation) +"dqU" = ( +/obj/machinery/camera/autoname/directional/south{ + network = list("ss13","rd") + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/iron/white/smooth_edge{ + dir = 1 + }, +/area/station/science/research) "dqW" = ( /obj/effect/turf_decal/sand/plating, /obj/effect/turf_decal/stripes/asteroid/line{ @@ -9515,6 +9582,18 @@ "dsy" = ( /turf/open/floor/iron/dark/textured_large, /area/station/security/interrogation) +"dsB" = ( +/obj/machinery/door/poddoor/shutters/window/preopen{ + dir = 8; + id = "xbprotect1"; + name = "Security Shutters" + }, +/obj/structure/cable, +/obj/machinery/door/firedoor, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "dsF" = ( /obj/item/flashlight/lantern, /turf/open/misc/asteroid, @@ -9588,6 +9667,16 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/wood/parquet, /area/station/cargo/boutique) +"dtI" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/structure/table, +/obj/machinery/light/directional/south, +/obj/item/radio/intercom/directional/south, +/obj/item/storage/box/bandages, +/turf/open/floor/iron, +/area/station/command/gateway) "dtQ" = ( /obj/structure/cable, /turf/open/misc/asteroid, @@ -10282,28 +10371,12 @@ /obj/structure/cable, /turf/open/floor/carpet/executive, /area/station/command/heads_quarters/captain/private) -"dGi" = ( -/obj/structure/lattice, -/obj/structure/cable, -/obj/effect/landmark/firealarm_sanity, -/turf/open/openspace, -/area/station/command/meeting_room) "dGq" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 8 }, /turf/open/floor/carpet/orange, /area/station/service/theater) -"dGr" = ( -/obj/effect/turf_decal/trimline/blue/filled/line, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment{ - dir = 5 - }, -/turf/open/floor/iron/white, -/area/station/medical/paramedic) "dGs" = ( /obj/structure/table/reinforced, /obj/effect/turf_decal/trimline/yellow/filled/line{ @@ -10364,6 +10437,15 @@ /obj/structure/cable, /turf/open/floor/iron/white, /area/station/medical/surgery/theatre) +"dGO" = ( +/obj/machinery/disposal/bin, +/obj/structure/disposalpipe/trunk{ + dir = 1 + }, +/obj/machinery/camera/autoname/directional/south, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/wood, +/area/station/service/lawoffice) "dGR" = ( /obj/structure/fluff/minepost, /obj/machinery/light/small/dim/directional/north, @@ -10540,12 +10622,6 @@ }, /turf/open/floor/iron, /area/station/commons/locker) -"dJI" = ( -/obj/machinery/vending/wallmed/directional/west, -/turf/open/floor/iron/white/smooth_half{ - dir = 8 - }, -/area/station/science/xenobiology) "dJJ" = ( /obj/structure/plasticflaps, /obj/machinery/navbeacon{ @@ -10568,6 +10644,19 @@ /obj/effect/decal/cleanable/blood/old, /turf/open/floor/engine/xenobio, /area/station/science/xenobiology) +"dKo" = ( +/obj/machinery/door/airlock/research/glass{ + name = "Secure Pen" + }, +/obj/effect/mapping_helpers/airlock/access/all/science/xenobio, +/obj/structure/cable, +/obj/machinery/door/poddoor/preopen{ + id = "Xenolab"; + name = "Test Chamber Blast Door" + }, +/obj/machinery/door/firedoor, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "dKp" = ( /obj/structure/lattice/catwalk, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -10734,6 +10823,14 @@ }, /turf/open/floor/iron/dark/small, /area/station/science/cytology) +"dOl" = ( +/obj/machinery/atmospherics/pipe/multiz/scrubbers/visible/layer2{ + name = "chimpanzee filth exhaust" + }, +/obj/machinery/light/directional/north, +/obj/machinery/firealarm/directional/east, +/turf/open/floor/iron/white, +/area/station/science/research) "dOv" = ( /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -10789,23 +10886,6 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, /area/station/hallway/primary/starboard) -"dPe" = ( -/obj/machinery/door/airlock/research/glass{ - name = "Xenobiology Space Bridge" - }, -/obj/structure/cable, -/obj/effect/mapping_helpers/airlock/access/all/science/xenobio, -/obj/machinery/door/firedoor, -/obj/effect/turf_decal/trimline/purple/filled/arrow_ccw{ - dir = 8 - }, -/obj/effect/turf_decal/trimline/purple/filled/arrow_ccw{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron/white/smooth_large, -/area/station/science/xenobiology/hallway) "dPf" = ( /turf/open/floor/circuit/telecomms/mainframe, /area/station/tcommsat/server) @@ -11844,10 +11924,6 @@ /obj/structure/filingcabinet/chestdrawer, /turf/open/floor/iron, /area/station/security/brig/entrance) -"ehq" = ( -/obj/effect/landmark/firealarm_sanity, -/turf/open/openspace, -/area/station/science/research) "ehs" = ( /obj/structure/table, /obj/effect/turf_decal/tile/blue/fourcorners, @@ -11974,14 +12050,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/department/medical/central) -"ejk" = ( -/obj/machinery/disposal/bin, -/obj/structure/disposalpipe/trunk{ - dir = 1 - }, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/iron/dark/textured, -/area/station/command/heads_quarters/cmo) "ejl" = ( /obj/machinery/holopad/secure, /turf/open/floor/carpet/red, @@ -12121,16 +12189,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/engineering/atmos/upper) -"elm" = ( -/obj/effect/turf_decal/trimline/blue/filled/line{ - dir = 1 - }, -/obj/machinery/camera/autoname/directional/north{ - network = list("ss13","medbay") - }, -/obj/machinery/firealarm/directional/north, -/turf/open/floor/iron/white, -/area/station/medical/medbay/central) "ely" = ( /obj/machinery/door/airlock/maintenance_hatch, /obj/effect/mapping_helpers/airlock/access/all/engineering/maintenance, @@ -12175,6 +12233,16 @@ /obj/machinery/door/firedoor, /turf/open/floor/iron, /area/station/hallway/primary/starboard) +"emO" = ( +/obj/effect/turf_decal/trimline/yellow/filled/line{ + dir = 4 + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/obj/machinery/vending/wallmed/directional/east, +/turf/open/floor/iron, +/area/station/engineering/lobby) "eng" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -12321,10 +12389,6 @@ /obj/machinery/light/small/directional/north, /turf/open/floor/iron/dark, /area/station/engineering/main) -"epI" = ( -/obj/effect/landmark/firealarm_sanity, -/turf/open/openspace, -/area/station/hallway/secondary/entry) "epK" = ( /turf/closed/wall/r_wall, /area/station/cargo/warehouse/upper) @@ -12380,10 +12444,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark/textured, /area/station/science/robotics/lab) -"eqZ" = ( -/obj/machinery/firealarm/directional/south, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/ordnance/testlab) "era" = ( /obj/structure/cable, /obj/machinery/door/firedoor, @@ -12491,6 +12551,20 @@ /obj/effect/spawner/random/maintenance, /turf/open/floor/plating, /area/station/maintenance/central/greater) +"esV" = ( +/obj/machinery/door/firedoor/border_only, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/structure/railing, +/obj/effect/turf_decal/stripes/line, +/obj/structure/cable, +/obj/machinery/light/dim/directional/north, +/obj/structure/extinguisher_cabinet/directional/north, +/turf/open/floor/iron/dark/corner{ + dir = 1 + }, +/area/station/engineering/atmos/upper) "esX" = ( /obj/structure/table/reinforced, /obj/item/stock_parts/power_store/cell/high{ @@ -12966,14 +13040,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/catwalk_floor/iron_white, /area/station/science/lab) -"eBD" = ( -/obj/item/kirbyplants/random, -/obj/structure/railing/corner{ - dir = 8 - }, -/obj/item/radio/intercom/directional/north, -/turf/open/floor/iron/white, -/area/station/science/research) "eBE" = ( /obj/structure/disposalpipe/segment, /obj/structure/cable, @@ -13330,6 +13396,19 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/commons/storage/art) +"eGM" = ( +/obj/machinery/light/directional/north, +/obj/structure/cable, +/obj/effect/turf_decal/trimline/purple/filled/arrow_ccw, +/obj/effect/turf_decal/trimline/purple/filled/arrow_ccw{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/item/radio/intercom/directional/south, +/obj/machinery/firealarm/directional/north, +/turf/open/floor/iron/white/smooth_large, +/area/station/science/xenobiology/hallway) "eGN" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -13393,6 +13472,13 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/maintenance/port/lesser) +"eIM" = ( +/obj/effect/turf_decal/siding/dark, +/obj/machinery/door/firedoor/border_only, +/turf/open/floor/iron/dark/side{ + dir = 4 + }, +/area/station/command/corporate_showroom) "eIO" = ( /obj/effect/landmark/atmospheric_sanity/ignore_area, /turf/closed/wall, @@ -13458,6 +13544,14 @@ /obj/machinery/camera/autoname/directional/south, /turf/open/floor/carpet/executive, /area/station/command/corporate_showroom) +"eJM" = ( +/obj/effect/spawner/structure/window, +/obj/structure/curtain/cloth/fancy/mechanical{ + id = "law" + }, +/obj/machinery/door/firedoor, +/turf/open/floor/plating, +/area/station/service/lawoffice) "eJQ" = ( /obj/structure/flora/bush/flowers_pp/style_random, /obj/structure/window/spawner/directional/south, @@ -13771,6 +13865,12 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, /area/station/maintenance/department/science) +"eRy" = ( +/obj/effect/landmark/firealarm_sanity, +/turf/open/floor/engine{ + name = "Holodeck Projector Floor" + }, +/area/station/holodeck/rec_center) "eRA" = ( /obj/effect/turf_decal/tile/red/half/contrasted{ dir = 8 @@ -13907,16 +14007,6 @@ /obj/structure/table, /turf/open/floor/iron, /area/station/hallway/primary/central) -"eTH" = ( -/obj/effect/turf_decal/tile/blue/anticorner/contrasted{ - dir = 4 - }, -/obj/structure/table, -/obj/machinery/airalarm/directional/east, -/obj/structure/sign/departments/chemistry/pharmacy/directional/north, -/obj/item/storage/box/bandages, -/turf/open/floor/iron/white, -/area/station/medical/medbay/lobby) "eTZ" = ( /obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ dir = 8 @@ -13950,6 +14040,11 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron, /area/station/engineering/main) +"eVl" = ( +/obj/machinery/light/warm/directional/south, +/obj/structure/flora/grass/jungle, +/turf/open/water/no_planet_atmos, +/area/station/service/hydroponics/garden) "eVq" = ( /obj/structure/cable, /obj/machinery/power/terminal{ @@ -14068,6 +14163,17 @@ /obj/machinery/door/firedoor, /turf/open/floor/iron, /area/station/commons/locker) +"eXW" = ( +/obj/machinery/fax{ + fax_name = "Psychology Office"; + name = "Psychology Office Fax Machine" + }, +/obj/structure/table/wood, +/obj/machinery/light/directional/south, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/wood/parquet, +/area/station/medical/psychology) "eYd" = ( /obj/effect/turf_decal/tile/brown/anticorner/contrasted, /obj/machinery/button/door/directional/south{ @@ -14147,13 +14253,6 @@ "eYP" = ( /turf/closed/wall/rust, /area/station/medical/chemistry/minisat) -"eYS" = ( -/obj/structure/closet/secure_closet/warden, -/obj/item/gun/energy/laser, -/obj/item/radio/intercom/directional/north, -/obj/machinery/firealarm/directional/east, -/turf/open/floor/carpet/red, -/area/station/security/warden) "eYT" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/item/radio/intercom/prison/directional/north, @@ -14277,18 +14376,6 @@ /obj/effect/turf_decal/trimline/yellow/filled/mid_joiner, /turf/open/floor/iron/white/smooth_edge, /area/station/medical/pharmacy) -"faF" = ( -/obj/structure/cable, -/obj/effect/turf_decal/trimline/purple/filled/arrow_ccw, -/obj/effect/turf_decal/trimline/purple/filled/arrow_ccw{ - dir = 1 - }, -/obj/machinery/light/directional/south, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/iron/white/smooth_large, -/area/station/science/xenobiology/hallway) "faK" = ( /turf/open/floor/glass/reinforced, /area/station/ai_monitored/turret_protected/ai_upload_foyer) @@ -14510,26 +14597,6 @@ }, /turf/closed/wall/r_wall, /area/station/engineering/atmos/pumproom) -"ffP" = ( -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, -/obj/structure/cable, -/obj/effect/turf_decal/stripes/corner, -/obj/machinery/firealarm/directional/north, -/turf/open/floor/iron/dark/corner{ - dir = 1 - }, -/area/station/engineering/atmos/upper) -"ffT" = ( -/obj/structure/rack, -/obj/effect/spawner/random/maintenance/no_decals/two, -/obj/machinery/camera/autoname/motion/directional/east{ - network = list("minisat") - }, -/obj/machinery/firealarm/directional/east, -/turf/open/floor/catwalk_floor/iron_dark, -/area/station/ai_monitored/turret_protected/aisat/uppersouth) "fgi" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -14627,6 +14694,14 @@ /obj/effect/mapping_helpers/airlock/access/all/engineering/maintenance, /turf/open/floor/plating, /area/station/maintenance/department/science) +"fhP" = ( +/obj/structure/railing/corner{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/firealarm_sanity, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/lobby) "fib" = ( /obj/machinery/conveyor/auto{ id = "hoptroll" @@ -15080,10 +15155,6 @@ /obj/structure/sign/poster/official/random/directional/east, /turf/open/floor/iron, /area/station/service/hydroponics) -"fre" = ( -/obj/effect/landmark/firealarm_sanity, -/turf/open/openspace, -/area/station/command/corporate_showroom) "frh" = ( /obj/effect/spawner/random/trash/grille_or_waste, /turf/open/floor/plating, @@ -15283,15 +15354,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/asteroid) -"fuc" = ( -/obj/structure/railing{ - dir = 1 - }, -/obj/effect/turf_decal/tile/brown/half/contrasted{ - dir = 1 - }, -/turf/open/floor/iron, -/area/station/cargo/storage) "fuk" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/cable, @@ -15785,10 +15847,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/engineering/atmos) -"fCI" = ( -/obj/effect/landmark/firealarm_sanity, -/turf/open/openspace, -/area/station/command/meeting_room) "fCR" = ( /obj/effect/turf_decal/tile/red/anticorner/contrasted{ dir = 1 @@ -16030,6 +16088,16 @@ /obj/structure/disposalpipe/trunk/multiz/down, /turf/open/floor/iron/white, /area/station/medical/chemistry) +"fGj" = ( +/obj/machinery/door/firedoor, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron/dark, +/area/station/medical/treatment_center) "fGm" = ( /obj/effect/landmark/event_spawn, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, @@ -16426,13 +16494,6 @@ /obj/structure/closet/secure_closet/freezer/meat, /turf/open/floor/iron/kitchen_coldroom/freezerfloor, /area/station/service/kitchen/coldroom) -"fNH" = ( -/obj/effect/turf_decal/tile/yellow{ - dir = 8 - }, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/iron/dark/corner, -/area/station/engineering/atmos) "fNW" = ( /obj/effect/landmark/carpspawn, /turf/open/space/openspace, @@ -16621,6 +16682,14 @@ }, /turf/open/floor/carpet/royalblue, /area/station/command/heads_quarters/captain/private) +"fQm" = ( +/obj/effect/turf_decal/tile/neutral, +/obj/effect/spawner/random/entertainment/arcade{ + dir = 1 + }, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation) "fQp" = ( /obj/machinery/disposal/bin, /obj/effect/turf_decal/trimline/yellow/filled/line{ @@ -16983,26 +17052,6 @@ /obj/item/sticker/clown, /turf/open/misc/asteroid, /area/station/asteroid) -"fWU" = ( -/obj/item/reagent_containers/spray/plantbgone{ - pixel_y = 3 - }, -/obj/item/reagent_containers/spray/plantbgone{ - pixel_x = 8; - pixel_y = 8 - }, -/obj/item/reagent_containers/spray/plantbgone{ - pixel_x = 13; - pixel_y = 5 - }, -/obj/item/watertank, -/obj/item/grenade/chem_grenade/antiweed, -/obj/structure/table/glass, -/obj/effect/turf_decal/stripes/line{ - dir = 5 - }, -/turf/open/floor/iron, -/area/station/service/hydroponics) "fWZ" = ( /obj/structure/girder, /obj/structure/lattice/catwalk, @@ -17282,6 +17331,14 @@ }, /turf/open/floor/iron/kitchen, /area/station/service/kitchen) +"gbR" = ( +/obj/item/kirbyplants/random, +/obj/structure/railing/corner{ + dir = 8 + }, +/obj/item/radio/intercom/directional/north, +/turf/open/floor/iron/white, +/area/station/science/research) "gbS" = ( /obj/effect/landmark/start/botanist, /turf/open/floor/glass/reinforced, @@ -17487,11 +17544,6 @@ dir = 1 }, /area/station/science/research) -"ggl" = ( -/obj/machinery/camera/autoname/directional/west, -/obj/structure/water_source/puddle, -/turf/open/floor/grass, -/area/station/service/hydroponics/garden) "ggu" = ( /obj/machinery/door/airlock/public/glass{ name = "Library" @@ -17870,6 +17922,12 @@ /obj/structure/window/reinforced/spawner/directional/south, /turf/open/floor/engine, /area/station/command/heads_quarters/rd) +"gmX" = ( +/obj/structure/reagent_dispensers/fueltank, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/firealarm/directional/west, +/turf/open/floor/iron, +/area/station/commons/storage/primary) "gnh" = ( /obj/item/knife/kitchen, /turf/open/misc/asteroid, @@ -17968,6 +18026,14 @@ /obj/effect/landmark/start/hangover/closet, /turf/open/floor/iron/textured, /area/station/hallway/primary/central) +"gpT" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/dark_blue/half/contrasted{ + dir = 1 + }, +/obj/item/storage/medkit/advanced, +/turf/open/floor/iron/dark, +/area/station/command/bridge) "gpV" = ( /obj/structure/cable, /obj/effect/turf_decal/tile/red/opposingcorners, @@ -18014,6 +18080,23 @@ }, /turf/open/floor/plating, /area/station/maintenance/port/lesser) +"gqB" = ( +/obj/machinery/door/airlock{ + name = "Law Office" + }, +/obj/effect/mapping_helpers/airlock/access/all/service/lawyer, +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/disposalpipe/segment{ + dir = 8 + }, +/obj/machinery/door/firedoor, +/turf/open/floor/wood, +/area/station/service/lawoffice) "gqN" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/visible, /turf/closed/wall/r_wall, @@ -18195,16 +18278,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/white, /area/station/science/lobby) -"gtC" = ( -/obj/machinery/door/airlock/engineering/glass{ - name = "Primary Tool Storage" - }, -/obj/structure/cable, -/obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/door/firedoor, -/turf/open/floor/iron, -/area/station/commons/storage/primary) "gtE" = ( /obj/machinery/door/poddoor/shutters/window/preopen{ dir = 8; @@ -18236,14 +18309,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/security/brig/entrance) -"gtY" = ( -/obj/machinery/rnd/production/techfab/department/service, -/obj/machinery/firealarm/directional/west, -/obj/machinery/light/directional/south, -/obj/effect/turf_decal/tile/dark_green/opposingcorners, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/iron, -/area/station/hallway/secondary/service) "gub" = ( /obj/machinery/firealarm/directional/north, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -18441,16 +18506,6 @@ }, /turf/open/floor/iron/dark, /area/station/medical/treatment_center) -"gwF" = ( -/obj/effect/decal/cleanable/dirt/dust, -/obj/effect/decal/cleanable/blood/old, -/obj/machinery/airalarm/directional/north, -/obj/machinery/camera/autoname/motion/directional/east{ - network = list("minisat") - }, -/obj/machinery/firealarm/directional/east, -/turf/open/floor/iron/dark, -/area/station/ai_monitored/turret_protected/aisat/uppernorth) "gwS" = ( /obj/structure/cable, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ @@ -18780,6 +18835,19 @@ }, /turf/open/floor/iron/dark, /area/station/security/prison/safe) +"gBW" = ( +/obj/machinery/disposal/bin{ + desc = "A pneumatic waste disposal unit. This one leads into space!"; + name = "deathsposal unit" + }, +/obj/effect/turf_decal/stripes/end, +/obj/machinery/light/directional/north, +/obj/structure/disposalpipe/trunk{ + dir = 8 + }, +/obj/machinery/firealarm/directional/north, +/turf/open/floor/iron/white/textured_large, +/area/station/science/xenobiology) "gBY" = ( /obj/effect/turf_decal/stripes/red/line{ dir = 5 @@ -19151,6 +19219,16 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/security/brig/entrance) +"gIq" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/siding/purple{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/firealarm/directional/north, +/turf/open/floor/iron/white, +/area/station/ai_monitored/turret_protected/ai_upload_foyer) "gIw" = ( /obj/machinery/door/airlock/research/glass{ name = "Robotics Lab" @@ -19279,13 +19357,6 @@ }, /turf/open/floor/plating, /area/station/maintenance/department/engine) -"gLa" = ( -/obj/effect/turf_decal/trimline/yellow/filled/line{ - dir = 9 - }, -/obj/machinery/firealarm/directional/north, -/turf/open/floor/iron, -/area/station/engineering/lobby) "gLp" = ( /obj/structure/closet/secure_closet/personal, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -19408,13 +19479,6 @@ }, /turf/open/floor/wood/tile, /area/station/service/chapel) -"gNu" = ( -/obj/effect/turf_decal/tile/brown/half/contrasted{ - dir = 4 - }, -/obj/machinery/vending/wallmed/directional/east, -/turf/open/floor/iron, -/area/station/cargo/storage) "gNB" = ( /obj/effect/turf_decal/tile/yellow{ dir = 4 @@ -19591,14 +19655,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/wood/tile, /area/station/commons/dorms) -"gQu" = ( -/obj/structure/railing/corner{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/firealarm_sanity, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/lobby) "gQK" = ( /obj/structure/cable, /obj/effect/landmark/event_spawn, @@ -19818,35 +19874,6 @@ dir = 10 }, /area/station/command/meeting_room) -"gUI" = ( -/obj/machinery/light/directional/west, -/obj/machinery/button/door/directional/north{ - id = "Xenolab"; - name = "Test Chamber Blast Doors"; - pixel_x = 6; - pixel_y = -2; - req_access = list("xenobiology") - }, -/obj/machinery/button/ignition{ - id = "Xenobio"; - pixel_x = -6 - }, -/obj/structure/table/reinforced/plastitaniumglass, -/obj/machinery/firealarm/directional/west{ - pixel_y = -4 - }, -/turf/open/floor/iron/dark/textured_corner, -/area/station/science/xenobiology) -"gUK" = ( -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/effect/turf_decal/siding/purple{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/firealarm/directional/north, -/turf/open/floor/iron/white, -/area/station/ai_monitored/turret_protected/ai_upload_foyer) "gUY" = ( /obj/structure/chair/sofa/bench/left{ dir = 1 @@ -20444,6 +20471,15 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/plating, /area/station/maintenance/department/engine) +"heZ" = ( +/obj/structure/railing{ + dir = 1 + }, +/obj/effect/turf_decal/tile/brown/half/contrasted{ + dir = 1 + }, +/turf/open/floor/iron, +/area/station/cargo/storage) "hfd" = ( /obj/machinery/atmospherics/pipe/bridge_pipe/cyan/visible, /obj/machinery/atmospherics/pipe/bridge_pipe/green/visible{ @@ -20501,15 +20537,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/catwalk_floor/iron_dark, /area/station/ai_monitored/turret_protected/aisat_interior) -"hfQ" = ( -/obj/structure/railing{ - dir = 8 - }, -/obj/effect/spawner/random/vending/colavend, -/obj/machinery/camera/autoname/directional/north, -/obj/machinery/firealarm/directional/north, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "hfS" = ( /obj/machinery/door/airlock{ id_tag = "Cabin5"; @@ -20527,6 +20554,16 @@ }, /turf/open/floor/engine, /area/station/engineering/supermatter/room) +"hfV" = ( +/obj/effect/turf_decal/trimline/blue/filled/line{ + dir = 1 + }, +/obj/machinery/camera/autoname/directional/north{ + network = list("ss13","medbay") + }, +/obj/machinery/firealarm/directional/north, +/turf/open/floor/iron/white, +/area/station/medical/medbay/central) "hgi" = ( /obj/effect/turf_decal/tile/brown/half/contrasted{ dir = 4 @@ -20724,17 +20761,6 @@ dir = 4 }, /area/station/medical/pharmacy) -"hkb" = ( -/mob/living/basic/parrot/poly, -/obj/structure/filingcabinet/chestdrawer, -/obj/effect/turf_decal/trimline/yellow/filled/line{ - dir = 9 - }, -/obj/item/paper/monitorkey, -/obj/machinery/camera/autoname/directional/west, -/obj/machinery/firealarm/directional/north, -/turf/open/floor/iron, -/area/station/command/heads_quarters/ce) "hkc" = ( /obj/effect/turf_decal/stripes/corner{ dir = 8 @@ -20994,21 +21020,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating/airless, /area/station/maintenance/department/science) -"hoh" = ( -/obj/structure/table, -/obj/item/storage/toolbox/mechanical, -/obj/item/geiger_counter{ - pixel_x = 7; - pixel_y = 3 - }, -/obj/effect/turf_decal/trimline/red/filled/line{ - dir = 9 - }, -/obj/machinery/airalarm/directional/west, -/obj/machinery/camera/autoname/directional/north, -/obj/machinery/firealarm/directional/north, -/turf/open/floor/iron/dark, -/area/station/security/checkpoint/engineering) "hon" = ( /obj/effect/turf_decal/tile/yellow{ dir = 4 @@ -21233,10 +21244,6 @@ /obj/item/stock_parts/subspace/treatment, /turf/open/floor/iron/dark, /area/station/engineering/storage/tcomms) -"hrq" = ( -/obj/machinery/firealarm/directional/east, -/turf/open/floor/iron/dark, -/area/station/science/xenobiology) "hru" = ( /obj/effect/landmark/start/coroner, /obj/effect/turf_decal/trimline/neutral/filled/warning{ @@ -21741,6 +21748,15 @@ }, /turf/open/floor/engine/cult, /area/station/service/library) +"hCc" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/disposal/bin, +/obj/structure/disposalpipe/trunk{ + dir = 8 + }, +/obj/machinery/firealarm/directional/north, +/turf/open/floor/wood/parquet, +/area/station/cargo/boutique) "hCs" = ( /turf/closed/wall, /area/station/service/hydroponics) @@ -21903,21 +21919,17 @@ /obj/machinery/newscaster/directional/east, /turf/open/floor/iron/white, /area/station/medical/chemistry) +"hEX" = ( +/obj/machinery/light/small/dim/directional/south, +/obj/effect/turf_decal/tile/red/fourcorners, +/obj/effect/landmark/firealarm_sanity, +/turf/open/floor/iron, +/area/station/security/warden) "hFa" = ( /obj/machinery/light/small/directional/east, /obj/machinery/atmospherics/components/tank/plasma, /turf/open/misc/asteroid, /area/station/maintenance/disposal/incinerator) -"hFu" = ( -/obj/structure/transport/linear/public{ - base_icon_state = "catwalk"; - icon = 'icons/obj/smooth_structures/catwalk.dmi'; - icon_state = "catwalk-255" - }, -/obj/effect/turf_decal/caution/stand_clear, -/obj/effect/landmark/firealarm_sanity, -/turf/open/floor/plating/elevatorshaft, -/area/station/cargo/storage) "hFz" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /obj/structure/cable, @@ -21984,6 +21996,12 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/fore) +"hGC" = ( +/obj/structure/filingcabinet/filingcabinet, +/obj/effect/turf_decal/bot_red, +/obj/machinery/firealarm/directional/east, +/turf/open/floor/iron/textured_large, +/area/station/cargo/sorting) "hGE" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -22069,6 +22087,13 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, /area/station/maintenance/port/greater) +"hHO" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/firealarm/directional/west, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/ai_monitored/turret_protected/aisat_interior) "hHS" = ( /obj/machinery/airalarm/directional/north, /obj/structure/cable, @@ -22231,14 +22256,6 @@ }, /turf/open/floor/iron/white, /area/station/medical/exam_room) -"hLy" = ( -/obj/machinery/washing_machine, -/obj/effect/turf_decal/tile/blue/opposingcorners{ - dir = 1 - }, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/iron/cafeteria, -/area/station/commons/locker) "hLA" = ( /obj/machinery/smartfridge/extract/preloaded, /turf/open/floor/iron/white/textured_large, @@ -23073,16 +23090,6 @@ /obj/machinery/light/directional/south, /turf/open/floor/iron, /area/station/commons/fitness/recreation) -"iaa" = ( -/obj/effect/turf_decal/trimline/yellow/filled/line{ - dir = 4 - }, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/obj/machinery/vending/wallmed/directional/east, -/turf/open/floor/iron, -/area/station/engineering/lobby) "iac" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 6 @@ -23092,6 +23099,9 @@ /obj/machinery/airalarm/directional/east, /turf/open/floor/iron/white, /area/station/medical/medbay/central) +"iak" = ( +/turf/open/water/no_planet_atmos, +/area/station/service/hydroponics/garden) "iau" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/structure/sign/poster/contraband/random/directional/south, @@ -23106,18 +23116,16 @@ "iaN" = ( /turf/closed/wall, /area/station/cargo/miningoffice) -"ibb" = ( -/obj/machinery/disposal/bin{ - desc = "A pneumatic waste disposal unit. This one leads into space!"; - name = "deathsposal unit" - }, -/obj/effect/turf_decal/stripes/end, -/obj/machinery/light/directional/north, -/obj/structure/disposalpipe/trunk{ - dir = 8 +"iaP" = ( +/obj/machinery/door/airlock/research{ + glass = 1; + name = "Slime Euthanization Chamber"; + opacity = 0 }, -/obj/machinery/firealarm/directional/north, -/turf/open/floor/iron/white/textured_large, +/obj/effect/turf_decal/tile/blue/fourcorners, +/obj/effect/mapping_helpers/airlock/access/all/science/xenobio, +/obj/structure/plasticflaps/kitchen, +/turf/open/floor/glass/reinforced, /area/station/science/xenobiology) "ibi" = ( /obj/structure/cable, @@ -23413,6 +23421,21 @@ /obj/machinery/newscaster/directional/east, /turf/open/floor/iron/white, /area/station/medical/storage) +"ifP" = ( +/obj/machinery/camera/autoname/directional/west, +/obj/item/radio/intercom/directional/east, +/obj/effect/turf_decal/tile/red/fourcorners, +/obj/structure/cable, +/obj/effect/landmark/event_spawn, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/light_switch/directional/west{ + pixel_y = 4 + }, +/obj/machinery/firealarm/directional/west{ + pixel_y = -5 + }, +/turf/open/floor/iron, +/area/station/security/brig) "ifV" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable, @@ -23791,15 +23814,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, /area/station/medical/morgue) -"iop" = ( -/obj/structure/showcase/cyborg/old{ - dir = 8; - pixel_x = 9; - pixel_y = 2 - }, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/catwalk_floor/iron_dark, -/area/station/ai_monitored/turret_protected/aisat/foyer) "iov" = ( /obj/structure/chair/office{ name = "grimy chair" @@ -23998,10 +24012,6 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /turf/open/floor/carpet, /area/station/commons/dorms) -"irD" = ( -/obj/effect/landmark/firealarm_sanity, -/turf/open/openspace, -/area/station/medical/medbay/central) "irJ" = ( /turf/open/floor/iron/white, /area/station/science/lab) @@ -24098,10 +24108,6 @@ dir = 1 }, /area/station/medical/chemistry/minisat) -"isP" = ( -/obj/machinery/firealarm/directional/west, -/turf/open/floor/circuit/green, -/area/station/ai_monitored/command/nuke_storage) "isT" = ( /turf/open/openspace, /area/station/engineering/break_room) @@ -24223,6 +24229,16 @@ }, /turf/open/floor/iron/dark, /area/station/engineering/supermatter/room) +"ivD" = ( +/obj/effect/turf_decal/trimline/blue/filled/line, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/turf/open/floor/iron/white, +/area/station/medical/paramedic) "ivR" = ( /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -24767,6 +24783,21 @@ /obj/effect/landmark/blobstart, /turf/open/floor/carpet/purple, /area/station/service/library) +"iGg" = ( +/obj/structure/closet{ + anchored = 1; + name = "Cold protection gear" + }, +/obj/item/clothing/shoes/winterboots, +/obj/item/clothing/shoes/winterboots, +/obj/item/clothing/shoes/winterboots, +/obj/item/clothing/suit/hooded/wintercoat/science, +/obj/item/clothing/suit/hooded/wintercoat/science, +/obj/item/clothing/suit/hooded/wintercoat/science, +/turf/open/floor/iron/white/smooth_corner{ + dir = 1 + }, +/area/station/science/xenobiology) "iGo" = ( /obj/structure/cable, /obj/machinery/door/airlock{ @@ -24847,10 +24878,6 @@ /obj/effect/mapping_helpers/mail_sorting/medbay/virology, /turf/open/floor/iron/white/smooth_large, /area/station/medical/virology) -"iHN" = ( -/obj/effect/landmark/firealarm_sanity, -/turf/open/openspace, -/area/station/cargo/storage) "iHO" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, @@ -25109,19 +25136,6 @@ /obj/machinery/recharger, /turf/open/floor/carpet/green, /area/station/command/heads_quarters/hop) -"iLH" = ( -/obj/effect/mapping_helpers/airlock/access/all/engineering/general, -/obj/machinery/door/airlock/engineering/glass{ - name = "Material Storage" - }, -/obj/structure/cable, -/obj/effect/landmark/navigate_destination, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment, -/obj/machinery/door/firedoor, -/turf/open/floor/iron, -/area/station/engineering/storage) "iLZ" = ( /obj/structure/disposalpipe/segment{ dir = 9 @@ -25427,6 +25441,15 @@ }, /turf/open/floor/iron/textured, /area/station/security/warden) +"iSw" = ( +/obj/machinery/computer/bank_machine{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/bot_white, +/obj/machinery/status_display/evac/directional/south, +/turf/open/floor/iron/dark, +/area/station/ai_monitored/command/nuke_storage) "iSz" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/effect/spawner/random/trash, @@ -25526,11 +25549,6 @@ /obj/effect/spawner/random/structure/grille, /turf/open/space/basic, /area/space/nearstation) -"iUJ" = ( -/turf/open/floor/iron/stairs/right{ - dir = 8 - }, -/area/station/science/lab) "iUP" = ( /obj/structure/railing/corner{ dir = 1 @@ -25550,11 +25568,6 @@ }, /turf/open/floor/iron/dark, /area/station/ai_monitored/security/armory) -"iVg" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/firealarm/directional/east, -/turf/open/floor/circuit/green, -/area/station/ai_monitored/turret_protected/ai_upload) "iVk" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -25914,6 +25927,13 @@ /obj/structure/cable, /turf/open/floor/carpet, /area/station/security/detectives_office) +"jcQ" = ( +/obj/machinery/camera/autoname/directional/east, +/obj/machinery/firealarm/directional/east, +/turf/open/floor/iron/dark/side{ + dir = 4 + }, +/area/station/command/corporate_showroom) "jcR" = ( /obj/structure/chair/sofa/bench/left{ dir = 4 @@ -26238,11 +26258,6 @@ /obj/docking_port/stationary/syndicate, /turf/open/space/openspace, /area/space) -"jjb" = ( -/obj/machinery/vending/clothing, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/wood/parquet, -/area/station/service/theater) "jjp" = ( /obj/item/reagent_containers/cup/bottle/fake_gbs, /turf/closed/mineral/random/stationside/asteroid/porus{ @@ -26417,6 +26432,10 @@ }, /turf/open/floor/iron/dark, /area/station/security/execution/education) +"jld" = ( +/obj/machinery/firealarm/directional/south, +/turf/open/floor/iron/dark, +/area/station/engineering/supermatter/room) "jle" = ( /obj/structure/chair{ dir = 4 @@ -26452,6 +26471,23 @@ /obj/machinery/camera/autoname/directional/south, /turf/open/floor/catwalk_floor/iron_dark, /area/station/command/corporate_dock) +"jlJ" = ( +/obj/machinery/door/airlock/engineering/glass{ + name = "Primary Tool Storage" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/door/firedoor, +/turf/open/floor/iron, +/area/station/commons/storage/primary) +"jlL" = ( +/obj/structure/rack, +/obj/effect/spawner/random/maintenance/no_decals/two, +/obj/machinery/camera/autoname/motion/directional/east{ + network = list("minisat") + }, +/obj/machinery/firealarm/directional/east, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/ai_monitored/turret_protected/aisat/uppersouth) "jlW" = ( /turf/open/floor/iron/freezer, /area/station/security/prison/shower) @@ -26640,6 +26676,14 @@ }, /turf/open/floor/iron, /area/station/commons/locker) +"jpv" = ( +/obj/machinery/disposal/bin, +/obj/structure/disposalpipe/trunk{ + dir = 1 + }, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/iron/dark/textured, +/area/station/command/heads_quarters/cmo) "jpx" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/effect/decal/cleanable/shreds, @@ -26681,6 +26725,20 @@ /obj/item/food/sandwich/philly_cheesesteak, /turf/open/floor/carpet/red, /area/station/command/heads_quarters/hos) +"jqf" = ( +/obj/structure/railing{ + dir = 5 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/door/firedoor/border_only{ + dir = 4 + }, +/obj/machinery/door/firedoor/border_only{ + dir = 1 + }, +/obj/effect/landmark/firealarm_sanity, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/lobby) "jqj" = ( /obj/effect/turf_decal/tile/neutral{ dir = 4 @@ -26755,6 +26813,18 @@ /obj/machinery/light/cold/directional/south, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat/teleporter) +"jqG" = ( +/obj/machinery/computer/security{ + dir = 1 + }, +/obj/effect/turf_decal/tile/red/opposingcorners, +/obj/machinery/light/directional/east, +/obj/machinery/camera/autoname/directional/south{ + network = list("ss13","rd") + }, +/obj/machinery/firealarm/directional/east, +/turf/open/floor/iron/dark, +/area/station/security/checkpoint/science) "jqT" = ( /obj/structure/chair{ dir = 4 @@ -26999,6 +27069,14 @@ /obj/machinery/camera/autoname/directional/south, /turf/open/floor/wood/tile, /area/station/security/courtroom) +"jwF" = ( +/obj/effect/turf_decal/siding/purple{ + dir = 1 + }, +/obj/machinery/light/dim/directional/west, +/obj/item/radio/intercom/directional/west, +/turf/open/floor/iron/white, +/area/station/science/ordnance/testlab) "jwI" = ( /obj/structure/table/reinforced, /obj/effect/turf_decal/tile/dark_red/opposingcorners, @@ -27406,14 +27484,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/catwalk_floor/iron_white, /area/station/hallway/secondary/entry) -"jCR" = ( -/obj/effect/turf_decal/trimline/blue/filled/line{ - dir = 4 - }, -/obj/structure/cable, -/obj/machinery/firealarm/directional/east, -/turf/open/floor/iron/white, -/area/station/medical/medbay/central) "jCT" = ( /obj/structure/cable, /obj/effect/turf_decal/siding/purple{ @@ -27993,14 +28063,6 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, /area/station/maintenance/department/cargo) -"jLA" = ( -/obj/structure/table, -/obj/item/stack/arcadeticket, -/obj/item/stack/arcadeticket, -/obj/machinery/camera/autoname/directional/north, -/obj/machinery/firealarm/directional/north, -/turf/open/floor/iron, -/area/station/commons/fitness/recreation) "jLC" = ( /obj/effect/turf_decal/siding/wood, /turf/open/floor/wood/parquet, @@ -28453,6 +28515,17 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, /area/station/cargo/miningoffice) +"jUz" = ( +/obj/machinery/portable_atmospherics/scrubber, +/obj/machinery/atmospherics/components/unary/portables_connector/visible/layer2{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 1 + }, +/obj/machinery/airalarm/directional/west, +/turf/open/floor/iron, +/area/station/hallway/primary/starboard) "jUD" = ( /obj/effect/turf_decal/tile/blue/half/contrasted{ dir = 4 @@ -28541,6 +28614,10 @@ /obj/structure/lattice, /turf/open/space/openspace, /area/space/nearstation) +"jVY" = ( +/obj/machinery/firealarm/directional/east, +/turf/open/floor/iron/dark, +/area/station/science/xenobiology) "jWb" = ( /obj/structure/closet/secure_closet/brig{ id = "Cell 1"; @@ -28609,12 +28686,6 @@ /obj/effect/turf_decal/stripes, /turf/open/floor/engine, /area/station/engineering/supermatter/room) -"jWM" = ( -/obj/structure/cable/layer3, -/obj/structure/cable, -/obj/effect/landmark/firealarm_sanity, -/turf/open/floor/catwalk_floor/iron_dark, -/area/station/ai_monitored/turret_protected/aisat_interior) "jWP" = ( /obj/machinery/meter, /obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ @@ -28827,16 +28898,6 @@ /obj/machinery/light/small/dim/directional/north, /turf/open/floor/plating, /area/station/maintenance/port/greater) -"kap" = ( -/obj/machinery/door/firedoor, -/obj/effect/turf_decal/stripes/line, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron/dark, -/area/station/medical/treatment_center) "kaz" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -28899,6 +28960,18 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, /area/station/maintenance/department/medical/central) +"kcc" = ( +/obj/effect/mapping_helpers/airlock/access/all/engineering/general, +/obj/machinery/door/airlock/engineering/glass{ + name = "Supermatter Engine Room" + }, +/obj/structure/cable, +/obj/machinery/door/firedoor, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable/layer1, +/turf/open/floor/engine, +/area/station/engineering/supermatter/room) "kcd" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -29231,17 +29304,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/hallway/primary/central) -"kgt" = ( -/obj/machinery/door/airlock/research{ - glass = 1; - name = "Slime Euthanization Chamber"; - opacity = 0 - }, -/obj/effect/turf_decal/tile/blue/fourcorners, -/obj/effect/mapping_helpers/airlock/access/all/science/xenobio, -/obj/structure/plasticflaps/kitchen, -/turf/open/floor/glass/reinforced, -/area/station/science/xenobiology) "kgA" = ( /obj/structure/table/reinforced, /obj/machinery/door/poddoor/shutters/preopen{ @@ -29256,11 +29318,6 @@ }, /turf/open/floor/iron/kitchen, /area/station/service/kitchen) -"kgM" = ( -/obj/structure/lattice/catwalk, -/obj/effect/landmark/firealarm_sanity, -/turf/open/openspace/xenobio, -/area/station/science/xenobiology) "kgT" = ( /obj/effect/turf_decal/tile/red/fourcorners, /obj/machinery/door/firedoor, @@ -29450,6 +29507,19 @@ /obj/machinery/portable_atmospherics/scrubber, /turf/open/floor/iron/dark/smooth_large, /area/station/science/ordnance) +"kjI" = ( +/obj/effect/mapping_helpers/airlock/access/all/engineering/general, +/obj/machinery/door/airlock/engineering/glass{ + name = "Material Storage" + }, +/obj/structure/cable, +/obj/effect/landmark/navigate_destination, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment, +/obj/machinery/door/firedoor, +/turf/open/floor/iron, +/area/station/engineering/storage) "kjR" = ( /obj/item/radio/intercom/directional/north, /obj/structure/rack, @@ -29645,6 +29715,15 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/wood/large, /area/station/cargo/boutique) +"kmo" = ( +/obj/structure/cable, +/obj/machinery/door/firedoor, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron/dark/textured_edge{ + dir = 4 + }, +/area/station/science/xenobiology) "kmu" = ( /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -29675,10 +29754,6 @@ /obj/structure/disposalpipe/trunk/multiz/down, /turf/open/floor/iron, /area/station/cargo/storage) -"kmZ" = ( -/obj/structure/lattice, -/turf/open/space, -/area/space/nearstation) "kno" = ( /obj/structure/chair/sofa/bench{ dir = 8 @@ -29762,6 +29837,25 @@ /obj/effect/turf_decal/bot_white/left, /turf/open/floor/iron/dark, /area/station/command/gateway) +"koK" = ( +/obj/machinery/light/directional/west, +/obj/machinery/button/door/directional/north{ + id = "Xenolab"; + name = "Test Chamber Blast Doors"; + pixel_x = 6; + pixel_y = -2; + req_access = list("xenobiology") + }, +/obj/machinery/button/ignition{ + id = "Xenobio"; + pixel_x = -6 + }, +/obj/structure/table/reinforced/plastitaniumglass, +/obj/machinery/firealarm/directional/west{ + pixel_y = -4 + }, +/turf/open/floor/iron/dark/textured_corner, +/area/station/science/xenobiology) "koM" = ( /obj/structure/table, /obj/effect/turf_decal/tile/blue/opposingcorners{ @@ -30531,6 +30625,13 @@ /obj/structure/cable, /turf/open/floor/iron/large, /area/station/service/hydroponics/garden) +"kBo" = ( +/obj/effect/turf_decal/siding/purple{ + dir = 1 + }, +/obj/machinery/firealarm/directional/north, +/turf/open/floor/iron/white/smooth_half, +/area/station/science/research) "kBt" = ( /obj/machinery/modular_computer/preset/civilian, /obj/machinery/button/door/directional/north{ @@ -30737,6 +30838,10 @@ /obj/effect/turf_decal/tile/neutral/anticorner/contrasted, /turf/open/floor/iron/dark, /area/station/hallway/secondary/exit/departure_lounge) +"kEs" = ( +/obj/effect/landmark/firealarm_sanity, +/turf/open/openspace, +/area/station/hallway/secondary/entry) "kEt" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -30888,18 +30993,6 @@ "kGS" = ( /turf/closed/wall/rust, /area/station/maintenance/department/medical) -"kGT" = ( -/obj/machinery/computer/security{ - dir = 1 - }, -/obj/effect/turf_decal/tile/red/opposingcorners, -/obj/machinery/light/directional/east, -/obj/machinery/camera/autoname/directional/south{ - network = list("ss13","rd") - }, -/obj/machinery/firealarm/directional/east, -/turf/open/floor/iron/dark, -/area/station/security/checkpoint/science) "kGZ" = ( /turf/open/floor/iron/dark, /area/station/engineering/atmospherics_engine) @@ -31093,6 +31186,13 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/aft/upper) +"kKU" = ( +/obj/structure/ladder, +/obj/item/radio/intercom/directional/west, +/obj/effect/turf_decal/tile/dark_green/opposingcorners, +/obj/machinery/vending/wallmed/directional/north, +/turf/open/floor/iron, +/area/station/hallway/secondary/service) "kLi" = ( /turf/closed/wall/mineral/plastitanium/nodiagonal, /area/station/maintenance/department/medical/central) @@ -31283,17 +31383,6 @@ /obj/machinery/light/directional/south, /turf/open/floor/iron/dark/corner, /area/station/engineering/atmos/project) -"kPb" = ( -/obj/effect/turf_decal/tile/red/half/contrasted{ - dir = 4 - }, -/obj/structure/chair{ - dir = 1; - name = "Prosecution" - }, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/iron, -/area/station/security/courtroom) "kPc" = ( /obj/structure/table/wood, /obj/item/camera_film{ @@ -31330,17 +31419,6 @@ /obj/structure/closet/firecloset, /turf/open/floor/iron/textured, /area/station/hallway/primary/central) -"kQt" = ( -/obj/structure/sign/warning/yes_smoking/circle/directional/west, -/obj/item/cigbutt, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 4 - }, -/obj/effect/landmark/firealarm_sanity, -/turf/open/floor/iron/dark/textured_corner{ - dir = 4 - }, -/area/station/science/breakroom) "kQv" = ( /obj/structure/disposalpipe/segment{ dir = 5 @@ -31492,6 +31570,15 @@ /obj/machinery/light/dim/directional/north, /turf/open/floor/iron, /area/station/security/prison) +"kSq" = ( +/obj/structure/lattice/catwalk, +/obj/structure/railing{ + dir = 8 + }, +/obj/machinery/light/directional/north, +/obj/machinery/firealarm/directional/north, +/turf/open/openspace, +/area/station/science/xenobiology) "kSy" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -32086,18 +32173,6 @@ /obj/machinery/camera/autoname/directional/south, /turf/open/floor/glass/reinforced, /area/station/engineering/lobby) -"lcE" = ( -/obj/machinery/door/airlock/highsecurity{ - name = "Gravity Generator Room" - }, -/obj/effect/mapping_helpers/airlock/access/all/engineering/construction, -/obj/structure/cable, -/obj/effect/landmark/navigate_destination, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/door/firedoor/heavy, -/turf/open/floor/iron, -/area/station/engineering/gravity_generator) "lcM" = ( /obj/machinery/atmospherics/components/unary/thermomachine/freezer, /obj/effect/turf_decal/tile/blue/fourcorners, @@ -32919,6 +32994,15 @@ /obj/effect/turf_decal/bot, /turf/open/floor/iron/dark, /area/station/service/cafeteria) +"lsT" = ( +/obj/machinery/door/airlock/highsecurity{ + name = "Blast Chamber" + }, +/obj/effect/mapping_helpers/airlock/access/all/medical/chemistry, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/engine, +/area/station/medical/chemistry) "lta" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 1 @@ -32954,21 +33038,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central) -"ltO" = ( -/obj/structure/closet{ - anchored = 1; - name = "Cold protection gear" - }, -/obj/item/clothing/shoes/winterboots, -/obj/item/clothing/shoes/winterboots, -/obj/item/clothing/shoes/winterboots, -/obj/item/clothing/suit/hooded/wintercoat/science, -/obj/item/clothing/suit/hooded/wintercoat/science, -/obj/item/clothing/suit/hooded/wintercoat/science, -/turf/open/floor/iron/white/smooth_corner{ - dir = 1 - }, -/area/station/science/xenobiology) "ltS" = ( /turf/closed/wall, /area/station/hallway/primary/starboard) @@ -33400,12 +33469,6 @@ dir = 4 }, /area/station/command/meeting_room) -"lAX" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/firealarm/directional/east, -/turf/open/floor/iron/dark, -/area/station/science/xenobiology) "lBu" = ( /obj/effect/turf_decal/tile/brown/half/contrasted{ dir = 1 @@ -33727,10 +33790,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/engineering/main) -"lFZ" = ( -/mob/living/basic/axolotl, -/turf/open/floor/grass, -/area/station/service/hydroponics/garden) "lGe" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -33791,20 +33850,6 @@ /obj/effect/spawner/random/medical/two_percent_xeno_egg_spawner, /turf/open/floor/engine/xenobio, /area/station/science/xenobiology) -"lHx" = ( -/obj/machinery/door/airlock/engineering{ - name = "Auxiliary Base Construction" - }, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/mapping_helpers/airlock/access/all/engineering/aux_base, -/obj/effect/turf_decal/tile/yellow/fourcorners, -/obj/effect/landmark/navigate_destination, -/obj/effect/decal/cleanable/dirt, -/obj/structure/barricade/wooden, -/turf/open/floor/iron, -/area/station/construction/mining/aux_base) "lHy" = ( /obj/machinery/button/door/directional/west{ id = "Cabin6"; @@ -33916,6 +33961,13 @@ }, /turf/open/floor/iron/white/smooth_large, /area/station/science/research) +"lJT" = ( +/obj/machinery/photocopier/prebuilt, +/obj/machinery/light_switch/directional/east, +/obj/structure/cable, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/carpet/black, +/area/station/command/heads_quarters/hos) "lKh" = ( /obj/machinery/vending/coffee, /obj/effect/turf_decal/trimline/blue/filled/line{ @@ -33963,16 +34015,14 @@ /obj/effect/turf_decal/sand/plating, /turf/open/floor/plating, /area/station/maintenance/department/cargo) -"lLa" = ( -/obj/machinery/light/small/dim/directional/south, -/obj/effect/turf_decal/tile/red/fourcorners, -/obj/effect/landmark/firealarm_sanity, -/turf/open/floor/iron, -/area/station/security/warden) "lLk" = ( /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron, /area/station/cargo/warehouse) +"lLm" = ( +/obj/machinery/firealarm/directional/south, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/ordnance/testlab) "lLo" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -34125,6 +34175,12 @@ /obj/machinery/atmospherics/pipe/heat_exchanging/simple, /turf/open/space/basic, /area/space/nearstation) +"lNV" = ( +/obj/machinery/light/small/directional/north, +/turf/open/floor/iron/stairs/left{ + dir = 8 + }, +/area/station/science/lab) "lOa" = ( /obj/machinery/door/airlock/atmos/glass{ name = "Crystallizer Room" @@ -34242,18 +34298,23 @@ /obj/machinery/door/firedoor, /turf/open/floor/plating, /area/station/hallway/secondary/command) +"lQA" = ( +/obj/structure/cable, +/obj/effect/turf_decal/trimline/purple/filled/arrow_ccw, +/obj/effect/turf_decal/trimline/purple/filled/arrow_ccw{ + dir = 1 + }, +/obj/machinery/light/directional/south, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/iron/white/smooth_large, +/area/station/science/xenobiology/hallway) "lQD" = ( /obj/effect/turf_decal/tile/dark_blue/half/contrasted, /obj/machinery/airalarm/directional/south, /turf/open/floor/iron, /area/station/command/bridge) -"lQH" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/firealarm/directional/west, -/turf/open/floor/catwalk_floor/iron_dark, -/area/station/ai_monitored/turret_protected/aisat_interior) "lQL" = ( /turf/open/openspace, /area/station/hallway/primary/starboard) @@ -34329,6 +34390,26 @@ /obj/machinery/light_switch/directional/west, /turf/open/floor/iron, /area/station/security/warden) +"lRN" = ( +/obj/item/reagent_containers/spray/plantbgone{ + pixel_y = 3 + }, +/obj/item/reagent_containers/spray/plantbgone{ + pixel_x = 8; + pixel_y = 8 + }, +/obj/item/reagent_containers/spray/plantbgone{ + pixel_x = 13; + pixel_y = 5 + }, +/obj/item/watertank, +/obj/item/grenade/chem_grenade/antiweed, +/obj/structure/table/glass, +/obj/effect/turf_decal/stripes/line{ + dir = 5 + }, +/turf/open/floor/iron, +/area/station/service/hydroponics) "lRU" = ( /obj/effect/turf_decal/tile/yellow{ dir = 4 @@ -34720,13 +34801,6 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron/white, /area/station/medical/medbay/central) -"lYw" = ( -/obj/structure/cable, -/obj/machinery/door/firedoor, -/turf/open/floor/iron/dark/textured_edge{ - dir = 4 - }, -/area/station/science/xenobiology) "lYA" = ( /obj/effect/spawner/random/maintenance/two, /obj/machinery/airalarm/directional/south, @@ -35179,14 +35253,6 @@ }, /turf/open/floor/iron/dark, /area/station/security/warden) -"mil" = ( -/obj/machinery/atmospherics/pipe/multiz/scrubbers/visible/layer2{ - name = "chimpanzee filth exhaust" - }, -/obj/machinery/light/directional/north, -/obj/machinery/firealarm/directional/east, -/turf/open/floor/iron/white, -/area/station/science/research) "mio" = ( /obj/machinery/computer/station_alert/station_only, /turf/open/floor/iron, @@ -35462,6 +35528,17 @@ "mmh" = ( /turf/closed/wall/r_wall, /area/station/security/checkpoint/engineering) +"mmi" = ( +/obj/structure/closet/secure_closet/security/med, +/obj/structure/cable, +/obj/effect/turf_decal/tile/red/fourcorners, +/obj/item/radio/intercom/directional/north, +/obj/machinery/power/apc/auto_name/directional/west, +/obj/machinery/firealarm/directional/north{ + pixel_x = -28 + }, +/turf/open/floor/iron/dark, +/area/station/security/checkpoint/medical) "mml" = ( /obj/structure/lattice/catwalk, /obj/structure/cable, @@ -35510,6 +35587,14 @@ /obj/effect/spawner/random/maintenance, /turf/open/floor/plating, /area/station/maintenance/central/greater) +"mnj" = ( +/obj/structure/table, +/obj/item/stack/arcadeticket, +/obj/item/stack/arcadeticket, +/obj/machinery/camera/autoname/directional/north, +/obj/machinery/firealarm/directional/north, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation) "mnk" = ( /obj/effect/spawner/random/structure/tank_holder, /obj/effect/decal/cleanable/dirt, @@ -35898,6 +35983,12 @@ }, /turf/open/floor/wood, /area/station/security/detectives_office/private_investigators_office) +"mtT" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable, +/obj/machinery/firealarm/directional/west, +/turf/open/floor/iron, +/area/station/maintenance/disposal/incinerator) "mua" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/effect/decal/cleanable/blood/old, @@ -36361,15 +36452,6 @@ }, /turf/open/floor/carpet/red, /area/station/command/heads_quarters/qm) -"mCc" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/obj/machinery/photocopier/prebuilt, -/obj/machinery/camera/autoname/directional/north, -/obj/machinery/firealarm/directional/north, -/turf/open/floor/wood, -/area/station/service/library) "mCm" = ( /obj/effect/turf_decal/stripes, /obj/item/radio/intercom/directional/south, @@ -36462,12 +36544,6 @@ /obj/structure/cable, /turf/open/floor/iron/white, /area/station/medical/treatment_center) -"mDK" = ( -/obj/machinery/light/small/directional/north, -/turf/open/floor/iron/stairs/left{ - dir = 8 - }, -/area/station/science/lab) "mDP" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper_multi{ cycle_id = "antesat" @@ -36610,15 +36686,6 @@ }, /turf/open/floor/iron, /area/station/command/heads_quarters/ce) -"mGU" = ( -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/vending/wallmed/directional/west, -/turf/open/floor/iron, -/area/station/hallway/primary/central) "mGV" = ( /obj/effect/mapping_helpers/airlock/access/all/engineering/atmos, /obj/machinery/door/firedoor, @@ -37002,6 +37069,17 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, /area/station/maintenance/central/greater) +"mMO" = ( +/obj/structure/railing{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/door/firedoor/border_only{ + dir = 4 + }, +/obj/effect/landmark/firealarm_sanity, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/lobby) "mMS" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/turf_decal/sand/plating, @@ -37013,13 +37091,6 @@ "mMZ" = ( /turf/open/floor/iron, /area/station/maintenance/disposal/incinerator) -"mNc" = ( -/obj/machinery/photocopier/prebuilt, -/obj/machinery/light_switch/directional/east, -/obj/structure/cable, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/carpet/black, -/area/station/command/heads_quarters/hos) "mNl" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /turf/open/floor/iron, @@ -37040,17 +37111,6 @@ }, /turf/open/floor/iron/white, /area/station/medical/treatment_center) -"mNw" = ( -/obj/machinery/door/poddoor/shutters/window/preopen{ - dir = 8; - id = "xbprotect"; - name = "Security Shutters" - }, -/obj/structure/cable, -/obj/machinery/door/firedoor, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "mNF" = ( /obj/machinery/light/directional/west, /turf/open/floor/catwalk_floor/iron_dark, @@ -37063,11 +37123,6 @@ /obj/effect/mapping_helpers/airalarm/surgery, /turf/open/floor/iron/white/textured, /area/station/medical/surgery/theatre) -"mNR" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/firealarm/directional/north, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/lobby) "mNZ" = ( /turf/closed/mineral/random/stationside/asteroid/porus, /area/station/asteroid) @@ -37321,17 +37376,6 @@ /obj/item/pen, /turf/open/floor/carpet, /area/station/service/lawoffice) -"mTZ" = ( -/obj/structure/closet/secure_closet/security/med, -/obj/structure/cable, -/obj/effect/turf_decal/tile/red/fourcorners, -/obj/item/radio/intercom/directional/north, -/obj/machinery/power/apc/auto_name/directional/west, -/obj/machinery/firealarm/directional/north{ - pixel_x = -28 - }, -/turf/open/floor/iron/dark, -/area/station/security/checkpoint/medical) "mUg" = ( /obj/effect/turf_decal/trimline/yellow/filled/line, /turf/open/floor/iron, @@ -37490,10 +37534,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/engine, /area/station/engineering/supermatter/room) -"mWu" = ( -/obj/machinery/firealarm/directional/north, -/turf/open/floor/catwalk_floor/iron_dark, -/area/station/ai_monitored/turret_protected/aisat/foyer) "mWB" = ( /obj/machinery/requests_console/auto_name/directional/south, /obj/effect/mapping_helpers/requests_console/supplies, @@ -37615,17 +37655,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/command/gateway) -"mYx" = ( -/obj/structure/closet/crate/goldcrate, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/effect/turf_decal/bot_white, -/obj/machinery/camera/motion/directional/south{ - c_tag = "Vault"; - network = list("vault") - }, -/obj/machinery/newscaster/directional/south, -/turf/open/floor/iron/dark, -/area/station/ai_monitored/command/nuke_storage) "mYD" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/purple/visible, /obj/effect/turf_decal/stripes, @@ -37713,6 +37742,14 @@ }, /turf/open/space/openspace, /area/space/nearstation) +"mZK" = ( +/obj/machinery/door/airlock/security/glass{ + name = "Prison Wing" + }, +/obj/effect/mapping_helpers/airlock/access/all/security/armory, +/obj/effect/turf_decal/tile/red/fourcorners, +/turf/open/floor/iron, +/area/station/security/warden) "mZL" = ( /obj/effect/spawner/random/structure/chair_flipped, /turf/open/floor/plating, @@ -38493,11 +38530,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron, /area/station/security) -"nnc" = ( -/obj/structure/table/wood, -/obj/effect/decal/cleanable/blood/old, -/turf/open/floor/plating, -/area/station/maintenance/central/greater) "nne" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -39422,14 +39454,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central) -"nFu" = ( -/obj/effect/mapping_helpers/airlock/access/all/service/kitchen, -/obj/machinery/door/airlock{ - name = "Kitchen" - }, -/obj/structure/cable, -/turf/open/floor/iron/kitchen, -/area/station/service/kitchen) "nFI" = ( /obj/effect/landmark/start/chief_medical_officer, /obj/effect/turf_decal/trimline/blue/filled/corner{ @@ -39761,6 +39785,20 @@ }, /turf/open/floor/iron, /area/station/cargo/storage) +"nKV" = ( +/obj/structure/cable, +/obj/structure/closet/l3closet/scientist, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/camera/autoname/directional/south{ + network = list("ss13","rd","xeno") + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/iron/white/textured_large, +/area/station/science/xenobiology) "nLb" = ( /obj/structure/closet/wardrobe/grey, /obj/effect/landmark/start/hangover/closet, @@ -39784,6 +39822,19 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, /area/station/engineering/atmospherics_engine) +"nLg" = ( +/obj/structure/cable, +/obj/machinery/light/small/directional/west, +/obj/effect/turf_decal/trimline/purple/filled/arrow_ccw{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/purple/filled/arrow_ccw{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/white/smooth_large, +/area/station/science/xenobiology/hallway) "nLi" = ( /obj/effect/turf_decal/trimline/yellow/filled/line{ dir = 1 @@ -40116,6 +40167,17 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/station/commons/storage/primary) +"nSN" = ( +/mob/living/basic/parrot/poly, +/obj/structure/filingcabinet/chestdrawer, +/obj/effect/turf_decal/trimline/yellow/filled/line{ + dir = 9 + }, +/obj/item/paper/monitorkey, +/obj/machinery/camera/autoname/directional/west, +/obj/machinery/firealarm/directional/north, +/turf/open/floor/iron, +/area/station/command/heads_quarters/ce) "nSP" = ( /obj/effect/turf_decal/trimline/blue/filled/corner{ dir = 4 @@ -40405,6 +40467,12 @@ /obj/item/radio/intercom/command/directional/west, /turf/open/floor/catwalk_floor/iron_dark, /area/station/command/corporate_dock) +"nZL" = ( +/obj/effect/turf_decal/tile/brown/anticorner/contrasted, +/obj/effect/spawner/random/clothing/wardrobe_closet_colored, +/obj/machinery/firealarm/directional/east, +/turf/open/floor/iron, +/area/station/cargo/boutique) "nZW" = ( /obj/structure/barricade/wooden, /obj/machinery/atmospherics/components/binary/pump/on/green/visible{ @@ -40468,14 +40536,6 @@ /obj/machinery/meter, /turf/closed/wall/r_wall, /area/station/engineering/supermatter/room) -"oaJ" = ( -/obj/machinery/door/airlock/engineering/glass{ - name = "Primary Tool Storage" - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/door/firedoor, -/turf/open/floor/iron, -/area/station/commons/storage/primary) "oaP" = ( /turf/open/floor/plating, /area/station/maintenance/department/medical/central) @@ -40668,15 +40728,6 @@ }, /turf/open/floor/plating, /area/station/security/courtroom) -"oei" = ( -/obj/structure/cable, -/obj/machinery/door/firedoor, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron/dark/textured_edge{ - dir = 4 - }, -/area/station/science/xenobiology) "oel" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /turf/open/floor/iron/white/smooth_large, @@ -40787,6 +40838,13 @@ /obj/structure/railing/corner, /turf/open/floor/iron/dark/textured_large, /area/station/science/xenobiology) +"ohe" = ( +/obj/effect/turf_decal/trimline/yellow/filled/line{ + dir = 9 + }, +/obj/machinery/firealarm/directional/north, +/turf/open/floor/iron, +/area/station/engineering/lobby) "ohh" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/landmark/start/hangover, @@ -40807,27 +40865,17 @@ /obj/structure/disposalpipe/junction/flip, /turf/open/floor/iron, /area/station/hallway/primary/central) -"ohx" = ( -/obj/structure/cable, -/obj/machinery/door/airlock/engineering{ - name = "Tech Storage" - }, -/obj/effect/mapping_helpers/airlock/access/all/engineering/tech_storage, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/landmark/navigate_destination/techstorage, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/mapping_helpers/airlock/unres{ - dir = 1 - }, -/obj/machinery/door/firedoor, -/turf/open/floor/iron/textured, -/area/station/engineering/storage/tech) "ohz" = ( /obj/structure/railing{ dir = 8 }, /turf/open/floor/engine, /area/station/engineering/supermatter/room) +"ohA" = ( +/obj/structure/urinal/directional/north, +/obj/machinery/firealarm/directional/east, +/turf/open/floor/iron/showroomfloor, +/area/station/engineering/main) "ohF" = ( /obj/effect/turf_decal/stripes{ dir = 1 @@ -40847,35 +40895,23 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/plating, /area/station/security/prison/work) -"oia" = ( -/obj/machinery/door/airlock/research/glass{ - name = "Secure Pen" - }, -/obj/effect/mapping_helpers/airlock/access/all/science/xenobio, -/obj/structure/cable, -/obj/machinery/door/poddoor/preopen{ - id = "Xenolab"; - name = "Test Chamber Blast Door" - }, -/obj/machinery/door/firedoor, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "oix" = ( /turf/open/floor/iron/white, /area/station/science/ordnance/testlab) +"oiC" = ( +/obj/effect/turf_decal/tile/blue/anticorner/contrasted{ + dir = 4 + }, +/obj/structure/table, +/obj/machinery/airalarm/directional/east, +/obj/structure/sign/departments/chemistry/pharmacy/directional/north, +/obj/item/storage/box/bandages, +/turf/open/floor/iron/white, +/area/station/medical/medbay/lobby) "ojc" = ( /obj/machinery/atmospherics/components/unary/outlet_injector/monitored/plasma_input, /turf/open/floor/engine/plasma, /area/station/engineering/atmos) -"ojj" = ( -/obj/machinery/disposal/bin, -/obj/structure/disposalpipe/trunk{ - dir = 1 - }, -/obj/machinery/camera/autoname/directional/south, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/wood, -/area/station/service/lawoffice) "ojv" = ( /obj/structure/window/reinforced/spawner/directional/east, /obj/effect/turf_decal/tile/neutral/diagonal_centre, @@ -41473,22 +41509,6 @@ /obj/structure/cable, /turf/open/floor/iron/dark, /area/station/service/cafeteria) -"ouQ" = ( -/obj/structure/closet/crate/engineering, -/obj/item/stack/sheet/mineral/plasma/five, -/obj/item/stack/sheet/mineral/plasma/five, -/obj/structure/sign/poster/official/random/directional/west, -/obj/item/storage/toolbox/emergency, -/obj/machinery/light_switch/directional/south{ - pixel_x = 4 - }, -/obj/machinery/firealarm/directional/south{ - pixel_x = -6 - }, -/turf/open/floor/iron/dark/side{ - dir = 10 - }, -/area/station/command/emergency_closet) "ovj" = ( /obj/effect/turf_decal/trimline/yellow/arrow_cw{ dir = 1 @@ -41592,6 +41612,11 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, /area/station/engineering/atmospherics_engine) +"oxe" = ( +/obj/item/radio/intercom/directional/north, +/obj/machinery/modular_computer/preset/id, +/turf/open/floor/iron/dark, +/area/station/command/heads_quarters/hos) "oxh" = ( /obj/effect/mapping_helpers/broken_floor, /obj/structure/girder/displaced, @@ -41642,14 +41667,6 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/wood/tile, /area/station/service/bar) -"oyq" = ( -/obj/machinery/light/cold/directional/west, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/structure/table/reinforced, -/obj/item/electronics/apc, -/obj/machinery/firealarm/directional/west, -/turf/open/floor/iron/dark, -/area/station/ai_monitored/turret_protected/aisat/foyer) "oyC" = ( /obj/structure/table, /obj/effect/turf_decal/tile/brown/opposingcorners{ @@ -41688,6 +41705,13 @@ }, /turf/open/floor/plating/elevatorshaft, /area/station/ai_monitored/turret_protected/aisat_interior) +"ozx" = ( +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/iron/dark/corner, +/area/station/engineering/atmos) "ozy" = ( /obj/machinery/camera/autoname/directional/east, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -41831,6 +41855,10 @@ /obj/machinery/firealarm/directional/south, /turf/open/floor/iron, /area/station/security) +"oBo" = ( +/obj/effect/landmark/firealarm_sanity, +/turf/open/openspace, +/area/station/engineering/atmos/upper) "oBt" = ( /obj/effect/turf_decal/tile/red/half/contrasted, /obj/structure/cable, @@ -41917,6 +41945,13 @@ /obj/machinery/meter, /turf/open/floor/engine, /area/station/engineering/supermatter/room) +"oDo" = ( +/obj/effect/turf_decal/tile/brown/half/contrasted{ + dir = 4 + }, +/obj/machinery/vending/wallmed/directional/east, +/turf/open/floor/iron, +/area/station/cargo/storage) "oDC" = ( /obj/effect/turf_decal/trimline/blue/filled/corner, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -42168,6 +42203,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/cargo/lobby) +"oHh" = ( +/obj/machinery/vending/wallmed/directional/west, +/turf/open/floor/iron/white/smooth_half{ + dir = 8 + }, +/area/station/science/xenobiology) "oHi" = ( /obj/structure/cable, /turf/open/floor/grass, @@ -42288,6 +42329,11 @@ }, /turf/open/floor/iron/large, /area/station/engineering/atmos) +"oJr" = ( +/obj/structure/sign/poster/random/directional/north, +/obj/effect/landmark/firealarm_sanity, +/turf/open/openspace, +/area/station/science/research) "oJt" = ( /obj/structure/lattice, /obj/structure/disposaloutlet{ @@ -42646,6 +42692,18 @@ dir = 8 }, /area/station/security/courtroom) +"oPD" = ( +/obj/structure/table/wood, +/obj/item/storage/crayons, +/obj/item/toy/crayon/spraycan{ + pixel_x = -4 + }, +/obj/item/toy/crayon/spraycan{ + pixel_x = -4 + }, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/carpet/purple, +/area/station/service/library) "oPL" = ( /obj/item/clothing/head/chameleon/broken, /turf/open/misc/asteroid/airless, @@ -42875,6 +42933,12 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/station/maintenance/central/greater) +"oTh" = ( +/obj/structure/cable/layer3, +/obj/structure/cable, +/obj/effect/landmark/firealarm_sanity, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/ai_monitored/turret_protected/aisat_interior) "oTv" = ( /obj/effect/spawner/structure/window/reinforced/plasma, /turf/open/floor/plating, @@ -42997,15 +43061,6 @@ /obj/machinery/camera/autoname/directional/west, /turf/open/floor/iron, /area/station/engineering/lobby) -"oVj" = ( -/obj/effect/turf_decal/siding/purple{ - dir = 1 - }, -/obj/machinery/door/firedoor/border_only{ - dir = 8 - }, -/turf/open/floor/iron/white/smooth_corner, -/area/station/science/research) "oVn" = ( /obj/structure/bed/dogbed/runtime, /mob/living/basic/pet/cat/runtime, @@ -43082,11 +43137,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/engineering/atmos) -"oWu" = ( -/obj/structure/urinal/directional/north, -/obj/machinery/firealarm/directional/east, -/turf/open/floor/iron/showroomfloor, -/area/station/engineering/main) "oWv" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -43200,21 +43250,6 @@ }, /turf/open/floor/iron/large, /area/station/hallway/secondary/exit/departure_lounge) -"oYm" = ( -/obj/machinery/camera/autoname/directional/west, -/obj/item/radio/intercom/directional/east, -/obj/effect/turf_decal/tile/red/fourcorners, -/obj/structure/cable, -/obj/effect/landmark/event_spawn, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/light_switch/directional/west{ - pixel_y = 4 - }, -/obj/machinery/firealarm/directional/west{ - pixel_y = -5 - }, -/turf/open/floor/iron, -/area/station/security/brig) "oYu" = ( /obj/machinery/mech_bay_recharge_port{ dir = 2 @@ -43484,13 +43519,6 @@ }, /turf/open/floor/iron/large, /area/station/hallway/secondary/exit/departure_lounge) -"pdi" = ( -/obj/structure/railing, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/door/firedoor/border_only, -/obj/effect/landmark/firealarm_sanity, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/lobby) "pdo" = ( /obj/structure/cable/multilayer/multiz, /turf/open/floor/glass, @@ -43664,6 +43692,17 @@ /obj/effect/landmark/start/medical_doctor, /turf/open/floor/iron/white, /area/station/medical/treatment_center) +"pha" = ( +/obj/structure/closet/crate/goldcrate, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/bot_white, +/obj/machinery/camera/motion/directional/south{ + c_tag = "Vault"; + network = list("vault") + }, +/obj/machinery/newscaster/directional/south, +/turf/open/floor/iron/dark, +/area/station/ai_monitored/command/nuke_storage) "phi" = ( /obj/machinery/duct, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -43690,15 +43729,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/catwalk_floor/iron_dark, /area/station/ai_monitored/turret_protected/aisat_interior) -"phH" = ( -/obj/machinery/duct, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 1 - }, -/obj/machinery/light/directional/west, -/obj/machinery/firealarm/directional/west, -/turf/open/floor/iron/freezer, -/area/station/commons/toilet/restrooms) "phJ" = ( /obj/structure/closet/secure_closet{ name = "contraband locker"; @@ -43935,25 +43965,6 @@ }, /turf/open/floor/iron/white/herringbone, /area/station/science/breakroom) -"plz" = ( -/obj/structure/window/spawner/directional/east, -/obj/structure/table, -/obj/item/reagent_containers/spray/cleaner{ - pixel_x = -14 - }, -/obj/item/storage/medkit/regular{ - pixel_y = 5 - }, -/obj/effect/turf_decal/tile/blue/anticorner/contrasted{ - dir = 4 - }, -/obj/structure/cable, -/obj/structure/disposalpipe/trunk/multiz{ - dir = 8 - }, -/obj/machinery/vending/wallmed/directional/north, -/turf/open/floor/iron/white, -/area/station/security/medical) "plA" = ( /turf/closed/wall/r_wall, /area/station/security/office) @@ -44049,16 +44060,6 @@ /obj/machinery/atmospherics/pipe/multiz/scrubbers/visible/layer2, /turf/open/floor/plating, /area/station/maintenance/port/greater) -"pnO" = ( -/obj/structure/closet/radiation{ - anchored = 1 - }, -/obj/effect/turf_decal/trimline/yellow/filled/line{ - dir = 4 - }, -/obj/machinery/firealarm/directional/east, -/turf/open/floor/iron, -/area/station/engineering/main) "pnQ" = ( /obj/effect/turf_decal/sand/plating, /obj/machinery/door/airlock/external, @@ -44072,6 +44073,11 @@ "pnS" = ( /turf/closed/mineral/random/stationside/asteroid, /area/station/asteroid) +"pof" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/firealarm/directional/north, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/lobby) "pog" = ( /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat/teleporter) @@ -44209,12 +44215,10 @@ dir = 1 }, /area/station/engineering/atmos/pumproom) -"ppU" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/cable, -/obj/machinery/door/firedoor, -/turf/open/floor/plating, -/area/station/security/warden) +"pqd" = ( +/obj/machinery/firealarm/directional/north, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/ai_monitored/turret_protected/aisat/foyer) "pql" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/dark/hidden, /obj/effect/mapping_helpers/airlock/locked, @@ -44290,6 +44294,10 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron/dark, /area/station/ai_monitored/command/storage/satellite) +"prB" = ( +/obj/effect/landmark/firealarm_sanity, +/turf/open/openspace, +/area/station/hallway/secondary/exit/departure_lounge) "prI" = ( /obj/item/kirbyplants/random, /obj/machinery/light_switch/directional/west, @@ -44532,6 +44540,20 @@ dir = 1 }, /area/station/science/research) +"pve" = ( +/obj/structure/cable, +/obj/machinery/light/floor, +/obj/effect/turf_decal/trimline/purple/filled/arrow_ccw{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/purple/filled/arrow_ccw{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/firealarm_sanity, +/turf/open/floor/iron/white/smooth_large, +/area/station/science/research) "pvo" = ( /obj/machinery/firealarm/directional/north, /obj/structure/table, @@ -45356,6 +45378,12 @@ }, /turf/open/floor/iron/white/smooth_large, /area/station/medical/storage) +"pJt" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/firealarm/directional/east, +/turf/open/floor/iron/dark, +/area/station/science/xenobiology) "pJw" = ( /obj/machinery/atmospherics/pipe/smart/manifold/cyan/visible, /turf/open/floor/iron, @@ -46654,6 +46682,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/department/engine) +"qfr" = ( +/obj/effect/landmark/firealarm_sanity, +/turf/open/openspace, +/area/station/science/research) "qfu" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/white/textured_large, @@ -46667,6 +46699,21 @@ /obj/item/flashlight/lamp, /turf/open/floor/carpet/red, /area/station/command/heads_quarters/qm) +"qgc" = ( +/obj/structure/cable, +/obj/machinery/door/airlock/engineering{ + name = "Tech Storage" + }, +/obj/effect/mapping_helpers/airlock/access/all/engineering/tech_storage, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/navigate_destination/techstorage, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 1 + }, +/obj/machinery/door/firedoor, +/turf/open/floor/iron/textured, +/area/station/engineering/storage/tech) "qgd" = ( /obj/structure/cable, /obj/effect/turf_decal/tile/dark_blue, @@ -47167,6 +47214,16 @@ /obj/structure/cable, /turf/open/floor/iron/large, /area/station/engineering/atmos/mix) +"qoC" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/decal/cleanable/blood/old, +/obj/machinery/airalarm/directional/north, +/obj/machinery/camera/autoname/motion/directional/east{ + network = list("minisat") + }, +/obj/machinery/firealarm/directional/east, +/turf/open/floor/iron/dark, +/area/station/ai_monitored/turret_protected/aisat/uppernorth) "qoJ" = ( /obj/structure/cable, /obj/effect/decal/cleanable/dirt, @@ -47435,24 +47492,18 @@ /obj/machinery/holopad, /turf/open/floor/carpet/executive, /area/station/command/heads_quarters/captain/private) -"qtm" = ( -/obj/machinery/door/poddoor/shutters/window/preopen{ - dir = 8; - id = "xbprotect1"; - name = "Security Shutters" - }, -/obj/structure/cable, -/obj/machinery/door/firedoor, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "qtx" = ( /obj/effect/turf_decal/siding/purple{ dir = 4 }, /turf/open/floor/iron/white/smooth_large, /area/station/science/research) +"qtA" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/firealarm/directional/east, +/turf/open/floor/iron, +/area/station/engineering/atmos/upper) "qtP" = ( /obj/structure/cable, /turf/open/floor/iron, @@ -48091,13 +48142,6 @@ /obj/structure/window/reinforced/spawner/directional/south, /turf/open/floor/glass/reinforced, /area/station/security/prison) -"qGd" = ( -/obj/effect/turf_decal/siding/purple{ - dir = 1 - }, -/obj/machinery/firealarm/directional/north, -/turf/open/floor/iron/white/smooth_half, -/area/station/science/research) "qGk" = ( /turf/closed/wall/r_wall, /area/station/hallway/secondary/command) @@ -48224,6 +48268,12 @@ /obj/effect/spawner/random/trash/mess, /turf/open/floor/iron, /area/station/maintenance/central/greater) +"qIt" = ( +/obj/effect/turf_decal/siding/purple, +/obj/machinery/light/dim/directional/west, +/obj/machinery/firealarm/directional/west, +/turf/open/floor/iron/white, +/area/station/science/ordnance/testlab) "qIw" = ( /obj/effect/turf_decal/tile/yellow{ dir = 4 @@ -48284,19 +48334,6 @@ }, /turf/open/floor/plating, /area/station/hallway/primary/central) -"qJv" = ( -/obj/structure/cable, -/obj/machinery/light/small/directional/west, -/obj/effect/turf_decal/trimline/purple/filled/arrow_ccw{ - dir = 8 - }, -/obj/effect/turf_decal/trimline/purple/filled/arrow_ccw{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron/white/smooth_large, -/area/station/science/xenobiology/hallway) "qJB" = ( /obj/machinery/power/tracker, /obj/structure/cable, @@ -48406,12 +48443,22 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, /area/station/service/bar/backroom) -"qMl" = ( -/obj/effect/turf_decal/siding, -/obj/structure/table, -/obj/machinery/camera/autoname/directional/north, -/turf/open/floor/iron/large, -/area/station/commons/locker) +"qMf" = ( +/obj/structure/closet/crate/engineering, +/obj/item/stack/sheet/mineral/plasma/five, +/obj/item/stack/sheet/mineral/plasma/five, +/obj/structure/sign/poster/official/random/directional/west, +/obj/item/storage/toolbox/emergency, +/obj/machinery/light_switch/directional/south{ + pixel_x = 4 + }, +/obj/machinery/firealarm/directional/south{ + pixel_x = -6 + }, +/turf/open/floor/iron/dark/side{ + dir = 10 + }, +/area/station/command/emergency_closet) "qMn" = ( /obj/structure/bodycontainer/morgue, /turf/open/floor/iron/dark/textured, @@ -48583,20 +48630,6 @@ dir = 9 }, /area/station/command/meeting_room) -"qQi" = ( -/obj/structure/cable, -/obj/machinery/light/floor, -/obj/effect/turf_decal/trimline/purple/filled/arrow_ccw{ - dir = 8 - }, -/obj/effect/turf_decal/trimline/purple/filled/arrow_ccw{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/firealarm_sanity, -/turf/open/floor/iron/white/smooth_large, -/area/station/science/research) "qQm" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 9 @@ -48830,6 +48863,18 @@ dir = 1 }, /area/station/engineering/atmos) +"qVe" = ( +/obj/structure/reagent_dispensers/fueltank, +/obj/machinery/airalarm/directional/south, +/obj/effect/turf_decal/tile/yellow/anticorner/contrasted, +/obj/machinery/light_switch/directional/east{ + pixel_y = 5 + }, +/obj/machinery/firealarm/directional/east{ + pixel_y = -5 + }, +/turf/open/floor/iron, +/area/station/commons/storage/tools) "qVn" = ( /obj/structure/cable, /obj/effect/turf_decal/trimline/yellow/filled/line{ @@ -49296,18 +49341,6 @@ dir = 8 }, /area/station/hallway/secondary/exit/departure_lounge) -"rbY" = ( -/obj/machinery/disposal/bin, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/disposalpipe/trunk{ - dir = 8 - }, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/iron/dark/textured_edge{ - dir = 1 - }, -/area/station/medical/pharmacy) "rce" = ( /obj/structure/table/wood, /obj/item/flashlight/lamp/green{ @@ -49319,10 +49352,6 @@ "rcl" = ( /turf/closed/wall/r_wall, /area/station/security/execution/transfer) -"rcq" = ( -/obj/effect/landmark/firealarm_sanity, -/turf/open/openspace, -/area/station/engineering/atmos/upper) "rcs" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, @@ -50174,6 +50203,26 @@ /obj/machinery/light/dim/directional/east, /turf/open/floor/iron/dark/textured, /area/station/security/execution/transfer) +"rpM" = ( +/obj/structure/table/wood/fancy/red, +/obj/effect/turf_decal/siding/wood, +/obj/machinery/recharger{ + pixel_x = 16; + pixel_y = 3 + }, +/obj/item/folder/red{ + pixel_x = 2; + pixel_y = 9 + }, +/obj/item/stamp/head/hos{ + pixel_y = 11; + pixel_x = 2 + }, +/obj/machinery/computer/records/security/laptop{ + dir = 1 + }, +/turf/open/floor/wood, +/area/station/command/heads_quarters/hos) "rpP" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -50199,6 +50248,11 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos) +"rqc" = ( +/obj/machinery/camera/autoname/directional/west, +/obj/structure/flora/grass/jungle, +/turf/open/water/no_planet_atmos, +/area/station/service/hydroponics/garden) "rqe" = ( /obj/structure/table, /obj/item/stock_parts/scanning_module{ @@ -50504,6 +50558,12 @@ }, /turf/open/floor/iron/white/textured, /area/station/medical/treatment_center) +"rvp" = ( +/obj/machinery/light/warm/directional/south, +/obj/effect/turf_decal/siding/wood, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/wood/tile, +/area/station/service/bar) "rwf" = ( /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, @@ -50567,6 +50627,13 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/engineering/atmos) +"rwG" = ( +/obj/effect/turf_decal/tile/neutral, +/obj/effect/spawner/random/structure/table, +/obj/machinery/airalarm/directional/south, +/obj/item/stack/medical/bruise_pack, +/turf/open/floor/iron, +/area/station/commons/fitness/recreation) "rwU" = ( /obj/structure/sign/painting/large/library{ dir = 4 @@ -50770,6 +50837,13 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/cargo/storage) +"rzI" = ( +/obj/machinery/camera/autoname/directional/south{ + network = list("ss13","rd") + }, +/obj/item/radio/intercom/directional/south, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/ordnance/testlab) "rzJ" = ( /obj/machinery/door/airlock/maintenance_hatch, /obj/effect/mapping_helpers/airlock/access/all/engineering/maintenance, @@ -50829,21 +50903,6 @@ }, /turf/open/floor/iron/dark/textured, /area/station/engineering/atmos/upper) -"rAz" = ( -/obj/machinery/camera/autoname/directional/south{ - network = list("ss13","rd") - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/iron/white/smooth_edge{ - dir = 1 - }, -/area/station/science/research) "rAK" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -50915,6 +50974,20 @@ /obj/machinery/airalarm/directional/south, /turf/open/floor/iron/dark/small, /area/station/engineering/transit_tube) +"rBU" = ( +/obj/machinery/door/airlock/engineering{ + name = "Auxiliary Base Construction" + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/mapping_helpers/airlock/access/all/engineering/aux_base, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/obj/effect/landmark/navigate_destination, +/obj/effect/decal/cleanable/dirt, +/obj/structure/barricade/wooden, +/turf/open/floor/iron, +/area/station/construction/mining/aux_base) "rBZ" = ( /obj/structure/cable, /obj/machinery/turretid{ @@ -51359,6 +51432,16 @@ /obj/structure/cable, /turf/open/floor/iron/dark, /area/station/hallway/secondary/exit/departure_lounge) +"rKH" = ( +/obj/effect/turf_decal/trimline/blue/filled/line{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment, +/obj/machinery/light/cold/directional/west, +/obj/machinery/firealarm/directional/west, +/turf/open/floor/iron/white, +/area/station/medical/treatment_center) "rKW" = ( /obj/machinery/photocopier/prebuilt, /obj/effect/turf_decal/bot_red, @@ -51396,10 +51479,6 @@ /obj/structure/cable/layer1, /turf/open/floor/engine, /area/station/engineering/supermatter/room) -"rLE" = ( -/obj/effect/landmark/firealarm_sanity, -/turf/open/openspace, -/area/station/hallway/secondary/exit/departure_lounge) "rLJ" = ( /obj/effect/turf_decal/sand/plating, /obj/effect/spawner/random/structure/girder, @@ -51467,12 +51546,31 @@ "rNJ" = ( /turf/open/misc/asteroid, /area/station/maintenance/department/medical) +"rOe" = ( +/obj/structure/table/reinforced, +/obj/machinery/coffeemaker{ + pixel_y = 5 + }, +/obj/effect/turf_decal/tile/red/anticorner/contrasted{ + dir = 1 + }, +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/obj/machinery/firealarm/directional/west, +/turf/open/floor/iron/half, +/area/station/security/breakroom) "rOq" = ( /obj/structure/chair{ dir = 1 }, /turf/open/floor/iron/textured, /area/station/hallway/primary/central) +"rOD" = ( +/obj/structure/lattice/catwalk, +/obj/effect/landmark/firealarm_sanity, +/turf/open/openspace/xenobio, +/area/station/science/xenobiology) "rOF" = ( /obj/effect/turf_decal/tile/red/half/contrasted{ dir = 4 @@ -51519,6 +51617,15 @@ /obj/structure/window/spawner/directional/north, /turf/open/misc/grass, /area/station/ai_monitored/turret_protected/aisat/foyer) +"rPk" = ( +/obj/effect/turf_decal/siding/white{ + dir = 1 + }, +/obj/machinery/light/warm/dim/directional/north, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/firealarm/directional/north, +/turf/open/floor/iron/herringbone, +/area/station/hallway/primary/central) "rPt" = ( /obj/structure/toilet{ dir = 8 @@ -51575,12 +51682,6 @@ /obj/structure/sign/poster/contraband/random/directional/north, /turf/open/floor/iron/white, /area/station/maintenance/department/medical) -"rPV" = ( -/obj/effect/turf_decal/tile/purple/fourcorners, -/obj/machinery/light/small/directional/north, -/obj/effect/landmark/firealarm_sanity, -/turf/open/floor/iron, -/area/station/science/ordnance) "rQe" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -52355,13 +52456,6 @@ /obj/structure/cable, /turf/open/floor/engine, /area/station/science/xenobiology) -"sal" = ( -/obj/structure/ladder, -/obj/item/radio/intercom/directional/west, -/obj/effect/turf_decal/tile/dark_green/opposingcorners, -/obj/machinery/vending/wallmed/directional/north, -/turf/open/floor/iron, -/area/station/hallway/secondary/service) "sap" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -52417,6 +52511,11 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/dark/textured, /area/station/science/robotics/lab) +"saY" = ( +/obj/structure/table/wood, +/obj/effect/decal/cleanable/blood/old, +/turf/open/floor/plating, +/area/station/maintenance/central/greater) "sbc" = ( /obj/structure/reagent_dispensers/watertank, /obj/effect/turf_decal/stripes/line{ @@ -52720,14 +52819,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/engineering/main) -"sgR" = ( -/obj/effect/turf_decal/tile/brown/half/contrasted{ - dir = 1 - }, -/obj/machinery/requests_console/auto_name/directional/north, -/obj/effect/mapping_helpers/requests_console/assistance, -/turf/open/floor/iron, -/area/station/cargo/storage) "sgW" = ( /obj/structure/chair/office/tactical{ dir = 8 @@ -52865,6 +52956,12 @@ /obj/effect/spawner/structure/window, /turf/open/floor/plating, /area/station/commons/storage/art) +"sjB" = ( +/obj/machinery/light/cold/directional/west, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/machinery/firealarm/directional/west, +/turf/open/floor/iron/dark, +/area/station/ai_monitored/turret_protected/aisat/foyer) "sjD" = ( /obj/effect/decal/cleanable/blood/tracks{ dir = 4 @@ -53068,12 +53165,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/maintenance/disposal/incinerator) -"smz" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/firealarm/directional/east, -/turf/open/floor/iron, -/area/station/engineering/atmos/upper) "smD" = ( /obj/machinery/door/airlock/external{ name = "Atmospherics External Airlock" @@ -53132,17 +53223,6 @@ /obj/effect/landmark/start/assistant, /turf/open/floor/iron, /area/station/commons/fitness/recreation) -"smW" = ( -/obj/machinery/portable_atmospherics/scrubber, -/obj/machinery/atmospherics/components/unary/portables_connector/visible/layer2{ - dir = 4 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/machinery/airalarm/directional/west, -/turf/open/floor/iron, -/area/station/hallway/primary/starboard) "smZ" = ( /obj/effect/turf_decal/tile/red/half/contrasted, /obj/structure/cable, @@ -53416,6 +53496,14 @@ /obj/machinery/suit_storage_unit/industrial/loader, /turf/open/floor/iron, /area/station/cargo/warehouse) +"srO" = ( +/obj/machinery/light/cold/directional/south, +/obj/effect/turf_decal/trimline/blue/filled/line, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/iron/white, +/area/station/medical/treatment_center) "srR" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -53565,15 +53653,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/maintenance/disposal/incinerator) -"sue" = ( -/obj/structure/lattice/catwalk, -/obj/structure/railing{ - dir = 8 - }, -/obj/machinery/light/directional/north, -/obj/machinery/firealarm/directional/north, -/turf/open/openspace, -/area/station/science/xenobiology) "sug" = ( /obj/machinery/sparker/directional/south{ id = "Xenobio" @@ -53681,20 +53760,6 @@ /obj/effect/turf_decal/trimline/blue/filled/line, /turf/open/floor/iron/white, /area/station/medical/medbay/central) -"svB" = ( -/obj/machinery/door/firedoor/border_only, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, -/obj/structure/railing, -/obj/effect/turf_decal/stripes/line, -/obj/structure/cable, -/obj/machinery/light/dim/directional/north, -/obj/structure/extinguisher_cabinet/directional/north, -/turf/open/floor/iron/dark/corner{ - dir = 1 - }, -/area/station/engineering/atmos/upper) "svF" = ( /obj/structure/closet/secure_closet/hop, /obj/effect/turf_decal/siding/dark_blue{ @@ -53712,6 +53777,11 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/catwalk_floor/iron_dark, /area/station/maintenance/department/engine) +"svL" = ( +/turf/open/floor/iron/stairs/right{ + dir = 8 + }, +/area/station/science/lab) "svS" = ( /obj/machinery/newscaster/directional/north, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -53849,13 +53919,6 @@ /obj/effect/turf_decal/sand/plating, /turf/open/floor/plating, /area/station/maintenance/department/cargo) -"syT" = ( -/obj/effect/turf_decal/siding/dark, -/obj/machinery/door/firedoor/border_only, -/turf/open/floor/iron/dark/side{ - dir = 4 - }, -/area/station/command/corporate_showroom) "syX" = ( /obj/effect/decal/cleanable/greenglow/radioactive, /turf/open/misc/asteroid, @@ -53958,6 +54021,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/white/smooth_large, /area/station/science/research) +"sAD" = ( +/obj/effect/landmark/firealarm_sanity, +/turf/open/openspace, +/area/station/command/meeting_room) "sAI" = ( /obj/machinery/door/airlock/atmos/glass{ name = "Atmospherics" @@ -54321,12 +54388,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/department/medical) -"sHf" = ( -/obj/effect/decal/cleanable/dirt, -/obj/structure/cable, -/obj/machinery/firealarm/directional/west, -/turf/open/floor/iron, -/area/station/maintenance/disposal/incinerator) "sHg" = ( /obj/structure/cable, /obj/effect/decal/cleanable/dirt, @@ -54433,12 +54494,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/engineering/lobby) -"sIA" = ( -/obj/structure/filingcabinet/filingcabinet, -/obj/effect/turf_decal/bot_red, -/obj/machinery/firealarm/directional/east, -/turf/open/floor/iron/textured_large, -/area/station/cargo/sorting) "sIJ" = ( /obj/machinery/light/small/directional/north{ bulb_power = 0.8 @@ -54966,12 +55021,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/commons/locker) -"sSn" = ( -/obj/effect/turf_decal/siding/purple, -/obj/machinery/light/dim/directional/west, -/obj/machinery/firealarm/directional/west, -/turf/open/floor/iron/white, -/area/station/science/ordnance/testlab) "sSL" = ( /obj/structure/disposalpipe/segment{ dir = 9 @@ -55051,6 +55100,10 @@ }, /turf/open/floor/engine, /area/station/hallway/secondary/entry) +"sTS" = ( +/obj/effect/landmark/firealarm_sanity, +/turf/open/openspace, +/area/station/security/warden) "sUc" = ( /obj/item/bodypart/arm/left, /turf/open/floor/plating/airless, @@ -55346,13 +55399,15 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos) -"sYV" = ( -/obj/effect/turf_decal/tile/neutral, -/obj/effect/spawner/random/structure/table, -/obj/machinery/airalarm/directional/south, -/obj/item/stack/medical/bruise_pack, -/turf/open/floor/iron, -/area/station/commons/fitness/recreation) +"sYZ" = ( +/obj/machinery/duct, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 1 + }, +/obj/machinery/light/directional/west, +/obj/machinery/firealarm/directional/west, +/turf/open/floor/iron/freezer, +/area/station/commons/toilet/restrooms) "sZl" = ( /obj/effect/turf_decal/trimline/blue/filled/line, /obj/structure/cable, @@ -55515,6 +55570,14 @@ }, /turf/open/floor/plating, /area/station/science/xenobiology) +"tbV" = ( +/obj/effect/mapping_helpers/airlock/access/all/service/kitchen, +/obj/machinery/door/airlock{ + name = "Kitchen" + }, +/obj/structure/cable, +/turf/open/floor/iron/kitchen, +/area/station/service/kitchen) "tbZ" = ( /obj/structure/chair/comfy/brown{ dir = 4; @@ -56171,6 +56234,13 @@ }, /turf/open/floor/carpet/executive, /area/station/command/heads_quarters/captain/private) +"toN" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/machinery/vending/wallmed/directional/west, +/turf/open/floor/iron, +/area/station/hallway/primary/central) "toT" = ( /obj/machinery/telecomms/bus/preset_two, /turf/open/floor/circuit/green/telecomms/mainframe, @@ -56447,14 +56517,6 @@ /obj/effect/spawner/random/trash/garbage, /turf/open/floor/plating, /area/station/maintenance/central/greater) -"ttP" = ( -/obj/effect/turf_decal/tile/neutral, -/obj/effect/spawner/random/entertainment/arcade{ - dir = 1 - }, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/iron, -/area/station/commons/fitness/recreation) "ttT" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable, @@ -56611,11 +56673,6 @@ /obj/effect/turf_decal/caution/stand_clear, /turf/open/floor/engine, /area/station/command/corporate_dock) -"txq" = ( -/obj/machinery/camera/autoname/directional/south, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/iron/textured, -/area/station/engineering/storage/tech) "txw" = ( /obj/structure/table, /obj/effect/spawner/round_default_module, @@ -57278,6 +57335,15 @@ dir = 8 }, /area/station/command/meeting_room) +"tIk" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/vending/wallmed/directional/west, +/turf/open/floor/iron, +/area/station/hallway/primary/central) "tIr" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable, @@ -57327,23 +57393,6 @@ /obj/machinery/digital_clock/directional/south, /turf/open/floor/iron, /area/station/hallway/primary/central) -"tJn" = ( -/obj/machinery/door/airlock{ - name = "Law Office" - }, -/obj/effect/mapping_helpers/airlock/access/all/service/lawyer, -/obj/effect/turf_decal/siding/wood{ - dir = 8 - }, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/disposalpipe/segment{ - dir = 8 - }, -/obj/machinery/door/firedoor, -/turf/open/floor/wood, -/area/station/service/lawoffice) "tJx" = ( /obj/structure/chair/plastic{ dir = 4 @@ -57410,6 +57459,10 @@ /obj/machinery/door/firedoor, /turf/open/floor/iron, /area/station/engineering/atmos) +"tKm" = ( +/obj/machinery/firealarm/directional/west, +/turf/open/floor/circuit/green, +/area/station/ai_monitored/command/nuke_storage) "tKX" = ( /obj/structure/table/reinforced, /obj/item/storage/toolbox/mechanical{ @@ -57745,11 +57798,6 @@ /obj/structure/window/reinforced/spawner/directional/east, /turf/open/openspace, /area/station/engineering/storage/tech) -"tPr" = ( -/obj/structure/sign/poster/random/directional/north, -/obj/effect/landmark/firealarm_sanity, -/turf/open/openspace, -/area/station/science/research) "tPJ" = ( /obj/machinery/light_switch/directional/west, /obj/structure/disposalpipe/segment, @@ -57817,6 +57865,16 @@ }, /turf/open/floor/glass, /area/station/command/meeting_room) +"tQX" = ( +/obj/structure/closet/radiation{ + anchored = 1 + }, +/obj/effect/turf_decal/trimline/yellow/filled/line{ + dir = 4 + }, +/obj/machinery/firealarm/directional/east, +/turf/open/floor/iron, +/area/station/engineering/main) "tQY" = ( /obj/effect/turf_decal/tile/yellow{ dir = 4 @@ -57983,6 +58041,15 @@ dir = 1 }, /area/station/service/hydroponics/garden) +"tTS" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/machinery/photocopier/prebuilt, +/obj/machinery/camera/autoname/directional/north, +/obj/machinery/firealarm/directional/north, +/turf/open/floor/wood, +/area/station/service/library) "tUb" = ( /obj/structure/railing{ dir = 4 @@ -58203,17 +58270,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/circuit/green, /area/station/ai_monitored/command/nuke_storage) -"tXs" = ( -/obj/effect/turf_decal/trimline/blue/filled/line, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment{ - dir = 8 - }, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/iron/white, -/area/station/medical/paramedic) "tXM" = ( /obj/structure/disposalpipe/segment{ dir = 8 @@ -58427,6 +58483,13 @@ /obj/item/radio/intercom/directional/west, /turf/open/floor/iron, /area/station/hallway/primary/central) +"ubl" = ( +/obj/structure/stairs/east, +/obj/effect/landmark/firealarm_sanity, +/turf/open/floor/iron/stairs/medium{ + dir = 8 + }, +/area/station/medical/storage) "ubm" = ( /turf/closed/wall/r_wall, /area/station/security/prison/work) @@ -58989,6 +59052,10 @@ /obj/effect/turf_decal/tile/bar/opposingcorners, /turf/open/floor/iron, /area/station/service/bar) +"ulU" = ( +/obj/effect/landmark/firealarm_sanity, +/turf/open/openspace, +/area/station/service/bar) "ulV" = ( /obj/machinery/door/airlock/grunge{ name = "Chapel" @@ -59147,20 +59214,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/service/hydroponics) -"upq" = ( -/obj/structure/table/reinforced, -/obj/machinery/coffeemaker{ - pixel_y = 5 - }, -/obj/effect/turf_decal/tile/red/anticorner/contrasted{ - dir = 1 - }, -/obj/structure/disposalpipe/segment{ - dir = 6 - }, -/obj/machinery/firealarm/directional/west, -/turf/open/floor/iron/half, -/area/station/security/breakroom) "ups" = ( /obj/docking_port/stationary/escape_pod, /turf/open/space/basic, @@ -59384,10 +59437,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/wood/tile, /area/station/service/bar) -"uss" = ( -/obj/effect/landmark/firealarm_sanity, -/turf/open/floor/plating, -/area/station/maintenance/central/greater) "usF" = ( /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -59489,6 +59538,14 @@ /obj/machinery/door/firedoor, /turf/open/floor/wood/parquet, /area/station/service/theater) +"uuh" = ( +/obj/effect/turf_decal/tile/brown/half/contrasted{ + dir = 1 + }, +/obj/machinery/requests_console/auto_name/directional/north, +/obj/effect/mapping_helpers/requests_console/assistance, +/turf/open/floor/iron, +/area/station/cargo/storage) "uuu" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -59543,8 +59600,7 @@ /turf/open/floor/iron/white, /area/station/medical/treatment_center) "uvn" = ( -/obj/structure/table, -/obj/item/flashlight/lamp, +/obj/structure/filingcabinet/chestdrawer, /turf/open/floor/iron/dark, /area/station/medical/morgue) "uvx" = ( @@ -59645,12 +59701,6 @@ }, /turf/open/floor/iron/dark, /area/station/science/ordnance) -"uyc" = ( -/obj/machinery/light/cold/directional/west, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/machinery/firealarm/directional/west, -/turf/open/floor/iron/dark, -/area/station/ai_monitored/turret_protected/aisat/foyer) "uyj" = ( /obj/structure/cable, /obj/machinery/door/airlock/atmos/glass{ @@ -59910,6 +59960,23 @@ dir = 9 }, /area/station/command/emergency_closet) +"uCp" = ( +/obj/machinery/door/airlock/research/glass{ + name = "Xenobiology Space Bridge" + }, +/obj/structure/cable, +/obj/effect/mapping_helpers/airlock/access/all/science/xenobio, +/obj/machinery/door/firedoor, +/obj/effect/turf_decal/trimline/purple/filled/arrow_ccw{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/purple/filled/arrow_ccw{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/white/smooth_large, +/area/station/science/xenobiology/hallway) "uCr" = ( /obj/structure/table, /obj/machinery/fax{ @@ -59999,12 +60066,6 @@ }, /turf/open/floor/iron, /area/station/security/office) -"uDQ" = ( -/obj/machinery/door/airlock/research{ - name = "Restroom" - }, -/turf/open/floor/iron/showroomfloor, -/area/station/science/research) "uDZ" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -60200,15 +60261,6 @@ /obj/machinery/recharger, /turf/open/floor/iron/textured, /area/station/security/warden) -"uId" = ( -/obj/machinery/computer/bank_machine{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/effect/turf_decal/bot_white, -/obj/machinery/status_display/evac/directional/south, -/turf/open/floor/iron/dark, -/area/station/ai_monitored/command/nuke_storage) "uIj" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 1 @@ -60568,10 +60620,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/misc/asteroid, /area/station/maintenance/department/science) -"uOv" = ( -/obj/effect/landmark/firealarm_sanity, -/turf/open/openspace, -/area/station/service/bar) "uOx" = ( /obj/structure/disposalpipe/segment{ dir = 6 @@ -60793,15 +60841,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron, /area/station/security) -"uTS" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/disposal/bin, -/obj/structure/disposalpipe/trunk{ - dir = 4 - }, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/wood/large, -/area/station/cargo/boutique) "uUj" = ( /obj/machinery/door/airlock/highsecurity{ name = "AI Chamber" @@ -60833,6 +60872,17 @@ /obj/structure/sign/poster/contraband/random/directional/west, /turf/open/floor/plating, /area/station/maintenance/department/medical) +"uUt" = ( +/obj/machinery/door/poddoor/shutters/window/preopen{ + dir = 8; + id = "xbprotect"; + name = "Security Shutters" + }, +/obj/structure/cable, +/obj/machinery/door/firedoor, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "uUx" = ( /obj/machinery/dna_infuser, /obj/item/infuser_book, @@ -60917,6 +60967,10 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron, /area/station/cargo/storage) +"uWb" = ( +/obj/effect/landmark/firealarm_sanity, +/turf/open/openspace, +/area/station/hallway/primary/central) "uWj" = ( /obj/effect/landmark/start/chaplain, /obj/machinery/holopad, @@ -61155,13 +61209,6 @@ "vaC" = ( /turf/open/floor/catwalk_floor/iron_dark, /area/station/command/corporate_dock) -"vaS" = ( -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/machinery/vending/wallmed/directional/west, -/turf/open/floor/iron, -/area/station/hallway/primary/central) "vaU" = ( /obj/item/toy/plush/lizard_plushie/space/green{ name = "Delaminates-The-Supermatter" @@ -61249,6 +61296,23 @@ /obj/structure/closet/wardrobe/white/medical, /turf/open/floor/iron/white, /area/station/medical/paramedic) +"vdD" = ( +/obj/effect/turf_decal/siding/purple{ + dir = 1 + }, +/obj/machinery/door/firedoor/border_only{ + dir = 8 + }, +/turf/open/floor/iron/white/smooth_corner, +/area/station/science/research) +"vdJ" = ( +/obj/structure/cable, +/obj/effect/turf_decal/trimline/blue/filled/line{ + dir = 4 + }, +/obj/machinery/firealarm/directional/east, +/turf/open/floor/iron/white, +/area/station/medical/treatment_center) "vdO" = ( /obj/effect/turf_decal/tile/dark_red/opposingcorners, /obj/machinery/light_switch/directional/north, @@ -61325,10 +61389,6 @@ }, /turf/open/floor/catwalk_floor/iron_dark/telecomms, /area/station/ai_monitored/turret_protected/ai) -"vft" = ( -/obj/effect/landmark/firealarm_sanity, -/turf/open/openspace, -/area/station/security/warden) "vfy" = ( /obj/machinery/door/airlock/medical/glass{ name = "Pharmacy" @@ -61643,14 +61703,6 @@ }, /turf/open/floor/iron, /area/station/service/hydroponics) -"vkU" = ( -/obj/machinery/door/airlock/security/glass{ - name = "Prison Wing" - }, -/obj/effect/mapping_helpers/airlock/access/all/security/armory, -/obj/effect/turf_decal/tile/red/fourcorners, -/turf/open/floor/iron, -/area/station/security/warden) "vla" = ( /obj/effect/turf_decal/siding/wood{ dir = 8 @@ -61798,6 +61850,12 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron/white, /area/station/science/research) +"vog" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable, +/obj/machinery/door/firedoor, +/turf/open/floor/plating, +/area/station/security/warden) "voq" = ( /obj/structure/closet/crate/secure/science, /obj/effect/spawner/random/entertainment/money_medium, @@ -62100,10 +62158,6 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron/white, /area/station/science/lobby) -"vuI" = ( -/obj/effect/landmark/firealarm_sanity, -/turf/open/openspace, -/area/station/hallway/primary/central) "vuZ" = ( /obj/structure/bookcase/random/reference, /turf/open/floor/wood/parquet, @@ -62136,16 +62190,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central) -"vvQ" = ( -/obj/effect/turf_decal/trimline/blue/filled/line{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment, -/obj/machinery/light/cold/directional/west, -/obj/machinery/firealarm/directional/west, -/turf/open/floor/iron/white, -/area/station/medical/treatment_center) "vvY" = ( /obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ dir = 9 @@ -62600,6 +62644,13 @@ /obj/machinery/atmospherics/components/unary/vent_pump/siphon/monitored/plasma_output, /turf/open/floor/engine/plasma, /area/station/engineering/atmos) +"vED" = ( +/obj/structure/closet/secure_closet/warden, +/obj/item/gun/energy/laser, +/obj/item/radio/intercom/directional/north, +/obj/machinery/firealarm/directional/east, +/turf/open/floor/carpet/red, +/area/station/security/warden) "vEE" = ( /obj/structure/cable, /obj/effect/decal/cleanable/dirt, @@ -63184,14 +63235,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/white/smooth_large, /area/station/science/research) -"vNO" = ( -/obj/effect/turf_decal/trimline/yellow/filled/line{ - dir = 1 - }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, -/obj/machinery/firealarm/directional/north, -/turf/open/floor/iron, -/area/station/engineering/gravity_generator) "vNT" = ( /obj/machinery/computer/slot_machine, /obj/effect/decal/cleanable/dirt/dust, @@ -63229,18 +63272,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/hallway/primary/central) -"vOk" = ( -/obj/effect/mapping_helpers/airlock/access/all/engineering/general, -/obj/machinery/door/airlock/engineering/glass{ - name = "Supermatter Engine Room" - }, -/obj/structure/cable, -/obj/machinery/door/firedoor, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable/layer1, -/turf/open/floor/engine, -/area/station/engineering/supermatter/room) "vOs" = ( /obj/machinery/airalarm/directional/south, /obj/structure/tank_holder/extinguisher, @@ -63367,6 +63398,15 @@ "vQB" = ( /turf/closed/wall, /area/station/cargo/boutique) +"vQR" = ( +/obj/effect/turf_decal/tile/neutral/half{ + dir = 8 + }, +/obj/machinery/vending/wallmed/directional/west, +/turf/open/floor/iron/edge{ + dir = 8 + }, +/area/station/hallway/secondary/exit/departure_lounge) "vQT" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -64080,12 +64120,6 @@ /obj/structure/sign/poster/random/directional/west, /turf/open/floor/plating, /area/station/maintenance/department/medical) -"wdU" = ( -/obj/structure/reagent_dispensers/fueltank, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/firealarm/directional/west, -/turf/open/floor/iron, -/area/station/commons/storage/primary) "wdV" = ( /obj/structure/cable, /obj/effect/decal/cleanable/dirt/dust, @@ -64278,16 +64312,14 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central) -"wit" = ( -/obj/effect/turf_decal/tile/red/anticorner/contrasted{ +"wiy" = ( +/obj/machinery/washing_machine, +/obj/effect/turf_decal/tile/blue/opposingcorners{ dir = 1 }, -/obj/machinery/digital_clock/directional/north, -/obj/item/kirbyplants/random, -/obj/machinery/camera/autoname/directional/west, -/obj/machinery/firealarm/directional/west, -/turf/open/floor/iron, -/area/station/security/brig/entrance) +/obj/machinery/firealarm/directional/south, +/turf/open/floor/iron/cafeteria, +/area/station/commons/locker) "wiA" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -64528,6 +64560,15 @@ /obj/effect/turf_decal/stripes, /turf/open/floor/iron/dark, /area/station/engineering/atmospherics_engine) +"wmN" = ( +/obj/effect/turf_decal/stripes{ + dir = 8 + }, +/obj/structure/cable, +/obj/structure/cable/layer1, +/obj/machinery/firealarm/directional/west, +/turf/open/floor/engine, +/area/station/engineering/supermatter/room) "wmO" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/glass/reinforced, @@ -64663,6 +64704,13 @@ /obj/effect/turf_decal/box, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat/teleporter) +"wpG" = ( +/obj/structure/railing, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/door/firedoor/border_only, +/obj/effect/landmark/firealarm_sanity, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/lobby) "wpH" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/crayon, @@ -64685,13 +64733,6 @@ }, /turf/closed/wall/r_wall, /area/station/engineering/atmos) -"wpQ" = ( -/obj/machinery/camera/autoname/directional/east, -/obj/machinery/firealarm/directional/east, -/turf/open/floor/iron/dark/side{ - dir = 4 - }, -/area/station/command/corporate_showroom) "wpU" = ( /obj/machinery/door/airlock/medical/glass{ name = "Waiting Room" @@ -64722,11 +64763,6 @@ /obj/structure/lattice/catwalk, /turf/open/openspace/telecomms, /area/station/science/xenobiology) -"wqH" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/firealarm/directional/east, -/turf/open/floor/plating, -/area/station/service/theater) "wqK" = ( /obj/structure/table, /obj/item/circular_saw, @@ -64865,6 +64901,14 @@ }, /turf/open/floor/iron, /area/station/command/heads_quarters/ce) +"wsX" = ( +/obj/machinery/duct, +/obj/structure/cable, +/obj/effect/turf_decal/tile/dark_green/opposingcorners, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/firealarm/directional/east, +/turf/open/floor/iron, +/area/station/hallway/secondary/service) "wtf" = ( /obj/machinery/camera/autoname/directional/north{ network = list("ss13","rd") @@ -65082,6 +65126,21 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white/smooth_large, /area/station/science/xenobiology/hallway) +"wwe" = ( +/obj/structure/table, +/obj/item/storage/toolbox/mechanical, +/obj/item/geiger_counter{ + pixel_x = 7; + pixel_y = 3 + }, +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 9 + }, +/obj/machinery/airalarm/directional/west, +/obj/machinery/camera/autoname/directional/north, +/obj/machinery/firealarm/directional/north, +/turf/open/floor/iron/dark, +/area/station/security/checkpoint/engineering) "wwj" = ( /obj/effect/landmark/event_spawn, /obj/structure/cable, @@ -65165,21 +65224,6 @@ }, /turf/open/floor/carpet/executive, /area/station/command/meeting_room) -"wxO" = ( -/obj/machinery/disposal/bin{ - desc = "A pneumatic waste disposal unit. This one leads into space!"; - name = "deathsposal unit" - }, -/obj/effect/turf_decal/stripes/end{ - dir = 1 - }, -/obj/machinery/light/directional/south, -/obj/structure/disposalpipe/trunk{ - dir = 8 - }, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/iron/white/textured_large, -/area/station/science/xenobiology) "wxQ" = ( /obj/machinery/computer/operating{ dir = 8 @@ -65259,6 +65303,10 @@ /obj/item/pai_card, /turf/open/floor/iron, /area/station/hallway/primary/central) +"wyK" = ( +/obj/effect/landmark/firealarm_sanity, +/turf/open/floor/plating, +/area/station/maintenance/central/greater) "wyZ" = ( /obj/machinery/atmospherics/pipe/bridge_pipe/green/visible{ dir = 4 @@ -65587,18 +65635,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/dark, /area/station/security/execution/education) -"wDU" = ( -/obj/structure/reagent_dispensers/fueltank, -/obj/machinery/airalarm/directional/south, -/obj/effect/turf_decal/tile/yellow/anticorner/contrasted, -/obj/machinery/light_switch/directional/east{ - pixel_y = 5 - }, -/obj/machinery/firealarm/directional/east{ - pixel_y = -5 - }, -/turf/open/floor/iron, -/area/station/commons/storage/tools) "wDW" = ( /obj/machinery/modular_computer/preset/id{ dir = 1 @@ -65744,6 +65780,12 @@ }, /turf/open/floor/iron/dark, /area/station/command/heads_quarters/rd) +"wFR" = ( +/obj/structure/railing/corner, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/firealarm_sanity, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/lobby) "wFS" = ( /obj/machinery/portable_atmospherics/canister, /obj/effect/turf_decal/bot, @@ -65902,6 +65944,15 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/department/engine) +"wKJ" = ( +/obj/structure/showcase/cyborg/old{ + dir = 8; + pixel_x = 9; + pixel_y = 2 + }, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/catwalk_floor/iron_dark, +/area/station/ai_monitored/turret_protected/aisat/foyer) "wKO" = ( /turf/open/floor/glass, /area/station/maintenance/department/medical) @@ -66192,6 +66243,16 @@ }, /turf/open/floor/iron/dark, /area/station/service/chapel) +"wPk" = ( +/obj/structure/transport/linear/public{ + base_icon_state = "catwalk"; + icon = 'icons/obj/smooth_structures/catwalk.dmi'; + icon_state = "catwalk-255" + }, +/obj/effect/turf_decal/caution/stand_clear, +/obj/effect/landmark/firealarm_sanity, +/turf/open/floor/plating/elevatorshaft, +/area/station/cargo/storage) "wPn" = ( /obj/structure/girder, /turf/open/floor/plating, @@ -66200,16 +66261,6 @@ /obj/effect/landmark/atmospheric_sanity/ignore_area, /turf/closed/wall/r_wall, /area/station/ai_monitored/turret_protected/ai_upload_foyer) -"wPD" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/structure/table, -/obj/machinery/light/directional/south, -/obj/item/radio/intercom/directional/south, -/obj/item/storage/box/bandages, -/turf/open/floor/iron, -/area/station/command/gateway) "wPE" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -66219,6 +66270,14 @@ }, /turf/open/floor/iron, /area/station/security/office) +"wPP" = ( +/obj/effect/turf_decal/trimline/blue/filled/line{ + dir = 4 + }, +/obj/structure/cable, +/obj/machinery/firealarm/directional/east, +/turf/open/floor/iron/white, +/area/station/medical/medbay/central) "wPU" = ( /obj/machinery/light/small/directional/west, /turf/open/misc/asteroid, @@ -66283,17 +66342,6 @@ }, /turf/open/floor/wood, /area/station/command/heads_quarters/hos) -"wRi" = ( -/obj/machinery/computer/crew{ - dir = 1 - }, -/obj/effect/turf_decal/trimline/blue/filled/line, -/obj/machinery/camera/autoname/directional/south{ - network = list("ss13","medbay") - }, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/iron/white, -/area/station/medical/paramedic) "wRm" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating/airless, @@ -66758,26 +66806,6 @@ /obj/effect/turf_decal/tile/blue/half/contrasted, /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) -"wZK" = ( -/obj/structure/table/wood/fancy/red, -/obj/effect/turf_decal/siding/wood, -/obj/machinery/recharger{ - pixel_x = 16; - pixel_y = 3 - }, -/obj/item/folder/red{ - pixel_x = 2; - pixel_y = 9 - }, -/obj/item/stamp/head/hos{ - pixel_y = 11; - pixel_x = 2 - }, -/obj/machinery/computer/records/security/laptop{ - dir = 1 - }, -/turf/open/floor/wood, -/area/station/command/heads_quarters/hos) "wZR" = ( /obj/machinery/telecomms/message_server/preset, /turf/open/floor/circuit/green/telecomms/mainframe, @@ -66800,20 +66828,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/maintenance/disposal/incinerator) -"xao" = ( -/obj/structure/railing{ - dir = 5 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/door/firedoor/border_only{ - dir = 4 - }, -/obj/machinery/door/firedoor/border_only{ - dir = 1 - }, -/obj/effect/landmark/firealarm_sanity, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/lobby) "xas" = ( /obj/effect/turf_decal/trimline/blue/filled/line, /obj/effect/turf_decal/siding/blue{ @@ -66893,11 +66907,6 @@ /obj/effect/turf_decal/stripes, /turf/open/floor/engine, /area/station/engineering/supermatter/room) -"xaY" = ( -/obj/item/radio/intercom/directional/north, -/obj/machinery/modular_computer/preset/id, -/turf/open/floor/iron/dark, -/area/station/command/heads_quarters/hos) "xbi" = ( /obj/effect/landmark/start/depsec/engineering, /obj/effect/turf_decal/trimline/red/filled/line, @@ -66944,6 +66953,18 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, /area/station/maintenance/department/science) +"xbB" = ( +/obj/machinery/disposal/bin, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/disposalpipe/trunk{ + dir = 8 + }, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/iron/dark/textured_edge{ + dir = 1 + }, +/area/station/medical/pharmacy) "xbC" = ( /obj/effect/turf_decal/siding/purple{ dir = 4 @@ -67112,15 +67133,6 @@ /obj/effect/spawner/random/maintenance, /turf/open/floor/plating, /area/station/maintenance/department/science) -"xeP" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/disposal/bin, -/obj/structure/disposalpipe/trunk{ - dir = 8 - }, -/obj/machinery/firealarm/directional/north, -/turf/open/floor/wood/parquet, -/area/station/cargo/boutique) "xeS" = ( /turf/open/floor/iron, /area/station/commons/storage/primary) @@ -67159,6 +67171,15 @@ dir = 8 }, /area/station/engineering/atmos) +"xfE" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/disposal/bin, +/obj/structure/disposalpipe/trunk{ + dir = 4 + }, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/wood/large, +/area/station/cargo/boutique) "xfJ" = ( /obj/machinery/door/window/brigdoor/right/directional/west{ req_access = list("xenobiology") @@ -67494,14 +67515,6 @@ /obj/machinery/firealarm/directional/north, /turf/open/floor/iron/dark/textured, /area/station/hallway/secondary/exit/departure_lounge) -"xlX" = ( -/obj/machinery/duct, -/obj/structure/cable, -/obj/effect/turf_decal/tile/dark_green/opposingcorners, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/firealarm/directional/east, -/turf/open/floor/iron, -/area/station/hallway/secondary/service) "xlY" = ( /obj/structure/bookcase/random/reference, /turf/open/floor/wood, @@ -67896,6 +67909,14 @@ /obj/machinery/firealarm/directional/west, /turf/open/floor/catwalk_floor, /area/station/cargo/storage) +"xtG" = ( +/obj/machinery/rnd/production/techfab/department/service, +/obj/machinery/firealarm/directional/west, +/obj/machinery/light/directional/south, +/obj/effect/turf_decal/tile/dark_green/opposingcorners, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/iron, +/area/station/hallway/secondary/service) "xtH" = ( /obj/machinery/power/apc/auto_name/directional/west, /obj/effect/turf_decal/tile/red/half/contrasted{ @@ -68037,6 +68058,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white/smooth_half, /area/station/medical/pharmacy) +"xvZ" = ( +/obj/effect/landmark/firealarm_sanity, +/turf/open/openspace, +/area/station/maintenance/central/greater) "xwe" = ( /obj/effect/turf_decal/sand/plating, /obj/effect/turf_decal/stripes/full, @@ -68062,12 +68087,6 @@ /obj/structure/railing, /turf/open/openspace, /area/station/engineering/main) -"xwn" = ( -/obj/machinery/light/warm/directional/south, -/obj/effect/turf_decal/siding/wood, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/wood/tile, -/area/station/service/bar) "xws" = ( /turf/closed/wall, /area/station/engineering/supermatter/room) @@ -68462,6 +68481,25 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/wood/parquet, /area/station/cargo/boutique) +"xCE" = ( +/obj/structure/window/spawner/directional/east, +/obj/structure/table, +/obj/item/reagent_containers/spray/cleaner{ + pixel_x = -14 + }, +/obj/item/storage/medkit/regular{ + pixel_y = 5 + }, +/obj/effect/turf_decal/tile/blue/anticorner/contrasted{ + dir = 4 + }, +/obj/structure/cable, +/obj/structure/disposalpipe/trunk/multiz{ + dir = 8 + }, +/obj/machinery/vending/wallmed/directional/north, +/turf/open/floor/iron/white, +/area/station/security/medical) "xCI" = ( /obj/structure/broken_flooring/side/directional/east, /obj/effect/decal/cleanable/dirt/dust, @@ -68702,15 +68740,10 @@ /obj/structure/railing, /turf/open/floor/iron, /area/station/engineering/atmos) -"xHj" = ( -/obj/effect/turf_decal/stripes{ - dir = 8 - }, -/obj/structure/cable, -/obj/structure/cable/layer1, -/obj/machinery/firealarm/directional/west, -/turf/open/floor/engine, -/area/station/engineering/supermatter/room) +"xHf" = ( +/obj/effect/landmark/firealarm_sanity, +/turf/open/openspace, +/area/station/medical/medbay/central) "xHA" = ( /obj/effect/turf_decal/stripes/corner, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ @@ -68778,6 +68811,11 @@ /obj/structure/window/fulltile, /turf/open/misc/asteroid, /area/station/asteroid) +"xIR" = ( +/obj/structure/cable, +/obj/machinery/vending/wallmed/directional/north, +/turf/open/floor/iron/white, +/area/station/science/research) "xIV" = ( /turf/closed/wall/r_wall, /area/station/engineering/supermatter) @@ -68868,13 +68906,6 @@ /obj/item/tank/internals/oxygen, /turf/open/floor/iron/white/textured, /area/station/medical/treatment_center) -"xKt" = ( -/obj/machinery/camera/autoname/directional/south{ - network = list("ss13","rd") - }, -/obj/item/radio/intercom/directional/south, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/ordnance/testlab) "xKx" = ( /mob/living/basic/mothroach, /turf/open/misc/asteroid, @@ -68932,6 +68963,16 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white, /area/station/medical/treatment_center) +"xLR" = ( +/obj/effect/turf_decal/tile/red/anticorner/contrasted{ + dir = 1 + }, +/obj/machinery/digital_clock/directional/north, +/obj/item/kirbyplants/random, +/obj/machinery/camera/autoname/directional/west, +/obj/machinery/firealarm/directional/west, +/turf/open/floor/iron, +/area/station/security/brig/entrance) "xMg" = ( /obj/machinery/shower/directional/south, /obj/effect/spawner/random/trash/soap, @@ -69627,15 +69668,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/white, /area/station/medical/chemistry/minisat) -"xZW" = ( -/obj/effect/turf_decal/tile/neutral/half{ - dir = 8 - }, -/obj/machinery/vending/wallmed/directional/west, -/turf/open/floor/iron/edge{ - dir = 8 - }, -/area/station/hallway/secondary/exit/departure_lounge) "xZX" = ( /obj/machinery/power/port_gen/pacman, /obj/structure/cable, @@ -70128,6 +70160,9 @@ /obj/structure/window/spawner/directional/east, /turf/open/misc/grass, /area/station/ai_monitored/turret_protected/aisat/foyer) +"yin" = ( +/turf/open/water/no_planet_atmos/deep, +/area/station/service/hydroponics/garden) "yit" = ( /obj/structure/transport/linear/public, /turf/open/floor/plating/elevatorshaft, @@ -70138,10 +70173,6 @@ }, /turf/open/floor/carpet/black, /area/station/command/heads_quarters/hos) -"yiM" = ( -/obj/machinery/firealarm/directional/south, -/turf/open/floor/iron/dark, -/area/station/engineering/supermatter/room) "yiN" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -70218,17 +70249,6 @@ }, /turf/open/floor/iron, /area/station/command/bridge) -"yjW" = ( -/obj/machinery/fax{ - fax_name = "Psychology Office"; - name = "Psychology Office Fax Machine" - }, -/obj/structure/table/wood, -/obj/machinery/light/directional/south, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/wood/parquet, -/area/station/medical/psychology) "ykc" = ( /obj/structure/cable, /obj/item/trash/chips, @@ -83139,7 +83159,7 @@ kbY awi rnk bay -vvQ +rKH xsM tMO qhu @@ -83155,7 +83175,7 @@ wrU wrU dcx kZO -kap +fGj tpl kKc gRp @@ -83415,7 +83435,7 @@ xOQ qOF xOQ wwj -che +srO fma eCd dHU @@ -83662,7 +83682,7 @@ uhe qOF gVn xLN -dek +vdJ uRT ykv bzo @@ -84141,7 +84161,7 @@ jch oey dhN uDB -sgR +uuh uyL vSt umh @@ -84174,7 +84194,7 @@ pzx jgH yds kFT -mTZ +mmi hQK dPg fvo @@ -84400,7 +84420,7 @@ tka uDB lAL lAL -fuc +heZ uyL uyL ezP @@ -85150,7 +85170,7 @@ mmy uYI wMn cpB -plz +xCE luz hqN eSS @@ -85475,7 +85495,7 @@ iuV cEy dHk jyx -wRi +cTX rnk gtK oaP @@ -85697,7 +85717,7 @@ fXZ gli gli gli -gNu +oDo gli gli hgi @@ -85943,7 +85963,7 @@ exT uBI jCX hvA -hFu +wPk pJL jCX etV @@ -85989,7 +86009,7 @@ iKD nOx gTI ltB -dGr +ivD rnk gtK oqj @@ -86464,7 +86484,7 @@ sdc dro uyL uUF -bKP +cFF vQB vQB vQB @@ -86987,7 +87007,7 @@ mIA izd ccT iDB -uTS +xfE rnk uyC paa @@ -87017,7 +87037,7 @@ vkn pGM cBb dAr -tXs +asP rnk paa rnk @@ -87238,7 +87258,7 @@ mwR dHW vQB yae -aSv +nZL vQB geO chF @@ -87251,7 +87271,7 @@ oUd oUd rnk uVi -cdV +ubl mAi wJy qfB @@ -88023,7 +88043,7 @@ oUd rnk owr lDl -rbY +xbB qfB rdE wTW @@ -88229,7 +88249,7 @@ fAR keQ ftK jza -upq +rOe pWB jiy mJx @@ -88515,7 +88535,7 @@ sUn kRM wBw rKW -sIA +hGC uWl iDs fad @@ -89039,7 +89059,7 @@ lYe cis thW vQB -xeP +hCc dtx dtx dtx @@ -89058,7 +89078,7 @@ hjW dGs rdP qfB -eTH +oiC goI tuY xza @@ -89266,7 +89286,7 @@ mxv hSW fyA rRK -wit +xLR lfp tRX rjL @@ -90594,9 +90614,9 @@ tIH tIH tIH iuv -ggl -tIH -tIH +rqc +yin +yin kAg afW wUc @@ -90851,9 +90871,9 @@ ckn wnj tIH mWf -tIH -lFZ -sWn +iak +cPz +eVl kAg uZx sRH @@ -91093,7 +91113,7 @@ cOR ufV jVI noF -wPD +dtI bAw ign iIB @@ -91108,7 +91128,7 @@ nvD pNa nvD oQk -nvD +dlg fRv nvD kAg @@ -91355,7 +91375,7 @@ bAw kxZ fMZ hBi -wDU +qVe hov wjW aly @@ -91627,7 +91647,7 @@ dGf uXt kAg kAg -bYH +rPk aod bxx lsC @@ -91828,7 +91848,7 @@ smZ msz oXd cyS -oYm +ifP cyS sWp kgT @@ -92139,7 +92159,7 @@ kAg auo fvg rDs -agu +aEd nMT kYB sGk @@ -92356,9 +92376,9 @@ ygw ygw ygw ygw -bVB -tJn -bVB +eJM +gqB +eJM jAG exz qER @@ -92615,7 +92635,7 @@ qgE rkA hiW okd -ojj +dGO jAG oed oed @@ -93137,7 +93157,7 @@ vhT fYj mff jpW -kPb +bGF rjX mHu tHF @@ -94676,7 +94696,7 @@ eEa kmu kmu xJe -vaS +toN wSi kmu rqj @@ -94695,7 +94715,7 @@ jrX lIr oEo otA -xlX +wsX bcX vMC brS @@ -94721,7 +94741,7 @@ oKy rbH dMU kGF -xZW +vQR yiO tiT pCJ @@ -95708,7 +95728,7 @@ rjg lTv tlE nwr -jLA +mnj xdj pWa kZw @@ -96270,7 +96290,7 @@ uir aaB nHK cLf -kmZ +dUc cLf cLf cLf @@ -96527,7 +96547,7 @@ amZ aaB nHK cLf -kmZ +dUc cLf cLf cLf @@ -96737,7 +96757,7 @@ aQL aQL aQL aQL -ank +eRy aQL aQL aQL @@ -96784,7 +96804,7 @@ ewX aaB nHK cLf -kmZ +dUc cLf cLf cLf @@ -97517,7 +97537,7 @@ aQL vAp qSq lLW -nFu +tbV qxr qxr qxr @@ -98502,7 +98522,7 @@ cLf cLf bqX cQP -aBe +gpT eon sZK sZK @@ -99065,7 +99085,7 @@ mds bmp vvC qQK -wqH +ako gjI vnr qPr @@ -99579,7 +99599,7 @@ vAE tDa fXR fXR -hLy +wiy bmp pjI vrF @@ -99825,7 +99845,7 @@ aGL aGL cgr xiy -sYV +rwG xQH mcA kqD @@ -100360,7 +100380,7 @@ gyM doH jIc xhy -jjb +bmO bmp rGv qbA @@ -101113,7 +101133,7 @@ xdq smT xQH xQH -qMl +cIM gGs uzH rnB @@ -101625,7 +101645,7 @@ uIU ufr kZw rhP -ttP +fQm xQH xQH cWD @@ -101837,7 +101857,7 @@ cLf jEY vWK vWK -uyc +sjB juh srs dWb @@ -101847,7 +101867,7 @@ iPH iuU srs bsZ -oyq +aMg iRp jEY jEY @@ -101891,7 +101911,7 @@ akl clG tXi utH -phH +sYZ sGV pik xzK @@ -103425,7 +103445,7 @@ nxG nxG nxG hjJ -mGU +tIk glH iAE xAm @@ -103450,7 +103470,7 @@ hmj xeS kmb jWE -wdU +gmX hbf dct hqk @@ -103708,7 +103728,7 @@ nSH oqz kXz oqz -oaJ +jlJ dct hqk jFc @@ -104736,7 +104756,7 @@ uLY teG sHg sHg -gtC +cYq wKY iFq jFc @@ -104926,7 +104946,7 @@ jWj lNE gRq gRq -jWM +oTh eAW eAW dPY @@ -105763,7 +105783,7 @@ pEf sbd soB sbd -txq +bcm lHm dct umt @@ -106021,7 +106041,7 @@ hYF qgY nAi ruq -ohx +qgc qPp bcr qVH @@ -106498,7 +106518,7 @@ tZF kcN xGB ixU -uDQ +beA kdg xOU xOU @@ -106541,7 +106561,7 @@ bcr cEc mht koe -smW +jUz qWS uFb gWo @@ -107273,7 +107293,7 @@ kQv lfx thf tJx -kQt +cwR nMI jQl niB @@ -107516,11 +107536,11 @@ oBP xAd kHG obA -mDK -iUJ +lNV +svL cPt ixU -cJM +xIR dfM pBn cPo @@ -108297,7 +108317,7 @@ hfB eIo smE xCw -rAz +dqU thf thf uzv @@ -109636,7 +109656,7 @@ uFb gLq lrk ykG -vNO +dgG mKc pGo ykG @@ -109875,7 +109895,7 @@ dpU jco oss vEZ -iaa +emO vEZ vEZ hmz @@ -110151,7 +110171,7 @@ chV rDD ykG ykG -lcE +arq ykG ykG cpG @@ -111181,7 +111201,7 @@ xCf suq bzQ ciE -iLH +kjI vdZ rgI kyh @@ -111668,7 +111688,7 @@ fTX sJD eKa rVZ -fNH +ozx fTX uBz qYt @@ -111942,7 +111962,7 @@ ybD ybD ybD ybD -pnO +tQX iJt oWE ybD @@ -112200,7 +112220,7 @@ jnY jnY jnY uFC -vOk +kcc uFC jnY jnY @@ -112458,7 +112478,7 @@ bup bup fOi cHe -xHj +wmN gyq gyq gyq @@ -116060,7 +116080,7 @@ hVB dvX ktc ncv -yiM +jld uFC vkO eIk @@ -121673,7 +121693,7 @@ jQS lcX jQS hKN -hrq +jVY hBF cnt hbV @@ -121681,7 +121701,7 @@ hbV hbV hbV kQa -lAX +pJt uhz jQS oPs @@ -121931,13 +121951,13 @@ jQS jQS jQS jQS -lYw +aoP jQS tMz krz tMz jQS -oei +kmo jQS jQS jQS @@ -123217,7 +123237,7 @@ kOL kOL xTa fyS -gUI +koK udH onm jJS @@ -128854,13 +128874,13 @@ cLf cLf cLf cLf -kmZ +dUc rYo rYo cAC rYo rYo -kmZ +dUc cLf cLf cLf @@ -130396,13 +130416,13 @@ cLf cLf cLf cLf -kmZ +dUc rYo rYo fxp rYo rYo -kmZ +dUc cLf cLf cLf @@ -147118,11 +147138,11 @@ aZg aZg vxX gNV -cPp -isP +bMZ +tKm lib qmf -uId +iSw gNV vxX vxX @@ -147379,7 +147399,7 @@ rwu eiI hvV kkK -mYx +pha gNV vxX vxX @@ -149427,7 +149447,7 @@ xXo sMV oZQ oZQ -iHN +aof oZQ oZQ oZQ @@ -149656,7 +149676,7 @@ lrV rQY kex dOG -xaY +oxe gYH vrU uDZ @@ -149677,7 +149697,7 @@ iaN dlY iaN sdc -iHN +aof oZQ qNz xXo @@ -149715,7 +149735,7 @@ laf kuy bVY lgA -yjW +eXW fnh mhc fnh @@ -149909,13 +149929,13 @@ jOV mIW mIW mIW -eYS +vED lLO ioZ dOG wum tYI -wZK +rpM sap wus gFI @@ -150164,7 +150184,7 @@ baH wSc jYh hKM -lLa +hEX mIW mIW xZO @@ -150174,7 +150194,7 @@ bFe fir icp mlq -mNc +lJT dOG gAQ eBa @@ -150217,7 +150237,7 @@ kYT bGk bGk bGk -cou +lsT bGk nNo imI @@ -150421,7 +150441,7 @@ aOp wSc tfZ mIW -vkU +mZK mIW qir loT @@ -150677,7 +150697,7 @@ wSc wSc wSc jYh -ppU +vog rrn edH kOn @@ -150740,7 +150760,7 @@ fqt jIn ryt oZX -irD +xHf evQ evQ evQ @@ -150934,7 +150954,7 @@ wSc wSc wSc jKc -ppU +vog mQo mQo eWB @@ -151191,7 +151211,7 @@ wSc wSc wSc eJT -ppU +vog bnr cYS iRR @@ -151448,7 +151468,7 @@ wSc wSc wSc jYh -ppU +vog idB mQo kUG @@ -151479,7 +151499,7 @@ vxX sdc oZQ oZQ -iHN +aof oZQ oZQ kUd @@ -151705,7 +151725,7 @@ wSc uhC nvR uEX -ppU +vog fPB ciy eLe @@ -152533,12 +152553,12 @@ evQ evQ evQ igq -elm +hfV fow cQK wZw dYr -jCR +wPP tLs uqh eCW @@ -152737,7 +152757,7 @@ vxX vxX vxX mIW -vft +sTS thT thT hED @@ -153057,7 +153077,7 @@ gYT xdQ eCR xck -ejk +jpv xhJ qvV aOm @@ -156649,7 +156669,7 @@ vAo jCP sZF pLP -epI +kEs uXD vxX vxX @@ -157127,7 +157147,7 @@ vxX vxX gYW hbQ -nnc +saY gYW qIP gYW @@ -158448,7 +158468,7 @@ mJV jCP sZF pLP -epI +kEs uXD gMk vxX @@ -159714,11 +159734,11 @@ tZL reD qDQ vkR -fWU +lRN hCs -sal +kKU cmw -gtY +xtG lIr sYs vPn @@ -161018,7 +161038,7 @@ yaM ulL mGW mGW -vuI +uWb mGW iZz hzF @@ -161523,7 +161543,7 @@ acA xIN rDg rDg -uOv +ulU rDg rDg rDg @@ -161984,7 +162004,7 @@ iXk iXk bBm jxS -dGi +cjK jxS njZ gUB @@ -161995,7 +162015,7 @@ ttt uCo xXh xnF -ouQ +qMf ttt ttt ttt @@ -162058,7 +162078,7 @@ uxt swU tkD uxt -rLE +prB uxt oqN pLn @@ -162564,7 +162584,7 @@ mGW mGW iZz hzF -hfQ +atb eXi lIv okL @@ -163841,7 +163861,7 @@ nAm rDg rDg dyV -xwn +rvp hRB sYD iZz @@ -164079,15 +164099,15 @@ vxX vxX vxX gYW -uss +wyK tuR wxh -axO +xvZ gYW apQ tYw tYw -bVa +oPD apQ icl ggu @@ -164297,7 +164317,7 @@ iXk iXk cZE cZE -fCI +sAD cZE jIl kOl @@ -164860,7 +164880,7 @@ shl juZ lpu apQ -mCc +tTS dzY olR pUy @@ -165075,7 +165095,7 @@ vYv fEU pFd reS -fre +dpb owl owl owl @@ -165330,8 +165350,8 @@ iub dSG tZA tZA -wpQ -syT +jcQ +eIM owl owl owl @@ -166932,7 +166952,7 @@ vxX vxX gMk vDa -lHx +rBU oFk suV hRO @@ -167891,7 +167911,7 @@ bFS bFS wOo bSE -iVg +ciZ prw oVG aSM @@ -168918,7 +168938,7 @@ upF dVu tMV aOQ -gUK +gIq faK scg faK @@ -169428,7 +169448,7 @@ hhX hhX cxg srs -mWu +pqd bNI wHJ wHJ @@ -169440,7 +169460,7 @@ wHJ wHJ wHJ riQ -iop +wKJ srs mxt hhX @@ -169452,13 +169472,13 @@ vxX gvF gvF gvF -bJc -chM +wFR +mMO tqD tqD tqD -chM -gQu +mMO +fhP gvF vxX bKL @@ -169688,7 +169708,7 @@ mQE mlY mQE wHJ -lQH +hHO osK feV feV @@ -169709,13 +169729,13 @@ fYe jam bjb fft -pdi +wpG oAs gOc gOc gOc nzn -xao +jqf oWg gMk fXf @@ -170713,7 +170733,7 @@ hhX cxg mQE mQE -gwF +qoC yaw wHJ dqA @@ -170736,7 +170756,7 @@ mNZ mNZ gvF hAx -mNR +pof wny gOc gOc @@ -170982,7 +171002,7 @@ lmo xAR wHJ tww -ffT +jlL sJT ogb vxX @@ -173052,7 +173072,7 @@ lJq raz eUj obA -tPr +oJr vRA oXa gak @@ -173100,7 +173120,7 @@ bkk bkk bkk bkk -hoh +wwe nlI nlI miL @@ -173565,7 +173585,7 @@ evr vfJ raz obA -eBD +gbR omL wME acY @@ -173822,7 +173842,7 @@ riv vpK raz obA -mil +dOl nmj iJS fTN @@ -174128,7 +174148,7 @@ isT rRt isT dUi -gLa +ohe rls vos tFW @@ -174136,7 +174156,7 @@ tFW tFW rhK aWD -oWu +ohA qXm tfC nfP @@ -175372,14 +175392,14 @@ aLe cCb dwV vRA -ehq +qfr vRA vRA vRA sPD oZT jKg -kGT +jqG jxF vjZ mxq @@ -175631,7 +175651,7 @@ jxa jxa jxa jxa -oVj +vdD prh jxF sPD @@ -175888,7 +175908,7 @@ rHF mHf xfK jxa -qGd +kBo uWt kdg lJC @@ -176449,7 +176469,7 @@ pMJ ybD qHp wtH -hkb +nSN mGP jjI mee @@ -176665,12 +176685,12 @@ kdg sFa kzC jqk -qQi +pve uMT rQO uXP uXP -qJv +nLg osr rlw gMk @@ -176949,7 +176969,7 @@ oVF qXF kRT iZa -ffP +ahz iVk xoh mTw @@ -177463,7 +177483,7 @@ lpW lpW uqn iZa -svB +esV qdV qdV qdV @@ -177722,7 +177742,7 @@ iZa iZa lBZ qdV -rcq +oBo qdV dYo fWg @@ -177966,7 +177986,7 @@ uab qhG awM cQr -sHf +mtT pXL kOI eRl @@ -177975,7 +177995,7 @@ btZ djW oas muw -deR +bGU iZa hHS kHt @@ -178455,7 +178475,7 @@ iSz uba vfJ vfJ -rPV +coF wYI elT elT @@ -178470,7 +178490,7 @@ iFN iFN vxX rlw -asP +eGM rlw vxX dsP @@ -178486,7 +178506,7 @@ vEE jpH iZa jDi -smz +qtA nvC uIj jgs @@ -180004,7 +180024,7 @@ ivx ivx ivx wkG -eqZ +lLm iFN iFN iFN @@ -180261,7 +180281,7 @@ moe wkG wkG wkG -xKt +rzI moe vxX vxX @@ -180270,7 +180290,7 @@ vxX vxX rlw wvS -dPe +uCp uXP uXP iTF @@ -182073,7 +182093,7 @@ hhX hhX hhX sqL -faF +lQA rlw uVI uVI @@ -182313,9 +182333,9 @@ jVV jVV fDj fDj -sSn +qIt jYT -dqJ +jwF fDj fDj jVV @@ -184644,7 +184664,7 @@ hhX jQS tjq lSA -adQ +nKV jQS hhX hhX @@ -186437,7 +186457,7 @@ wBd hAL dBj jQS -sue +kSq ubn gYI ybO @@ -187465,7 +187485,7 @@ wBd hAL jQS jQS -mNw +uUt gMy gwx jQS @@ -187475,7 +187495,7 @@ wmO jQS xDf gtE -qtm +dsB jQS jQS cku @@ -187978,7 +187998,7 @@ jVV wBd rWL jQS -ibb +gBW qXj avA nVm @@ -187990,7 +188010,7 @@ wmO xGG uBm vUJ -wxO +cVF jQS hAL tLO @@ -188498,7 +188518,7 @@ cWL tMz jQS wmO -kgt +iaP jgA jQS tMz @@ -188753,7 +188773,7 @@ jEt aMf rdn xSW -dJI +oHh wnA wnA wnA @@ -189529,7 +189549,7 @@ rxC awy jpe wnA -ltO +iGg jQS jQS jQS @@ -189783,7 +189803,7 @@ jQS tbU byC tbU -oia +dKo tbU byC tbU @@ -190040,7 +190060,7 @@ jQS nCm nCm nCm -kgM +rOD nCm nCm nCm diff --git a/_maps/shuttles/emergency_monastery.dmm b/_maps/shuttles/emergency_monastery.dmm index bada195eb480..e1c8d5a97b57 100644 --- a/_maps/shuttles/emergency_monastery.dmm +++ b/_maps/shuttles/emergency_monastery.dmm @@ -60,7 +60,7 @@ "bd" = ( /obj/structure/lattice, /obj/structure/grille/broken, -/turf/open/space, +/turf/open/space/basic, /area/shuttle/escape) "be" = ( /obj/machinery/light/small/directional/west, @@ -142,7 +142,7 @@ /obj/structure/window/reinforced/spawner/directional/east, /obj/structure/window/reinforced/spawner/directional/south, /obj/structure/lattice, -/turf/open/space, +/turf/open/space/basic, /area/shuttle/escape) "cu" = ( /obj/structure/table/wood, @@ -159,10 +159,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/plating, /area/shuttle/escape) -"cH" = ( -/obj/structure/window/reinforced/spawner/directional/south, -/turf/open/space, -/area/shuttle/escape) "cT" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 1 @@ -199,11 +195,6 @@ /obj/structure/cable, /turf/open/floor/iron/dark, /area/shuttle/escape) -"dp" = ( -/obj/structure/window/reinforced/spawner/directional/east, -/obj/structure/lattice, -/turf/open/space, -/area/shuttle/escape) "du" = ( /obj/machinery/door/airlock/external/ruin, /turf/open/floor/plating, @@ -230,7 +221,7 @@ "dX" = ( /obj/structure/window/reinforced/spawner/directional/west, /obj/structure/window/reinforced/spawner/directional/north, -/turf/open/space, +/turf/open/space/basic, /area/shuttle/escape) "dY" = ( /obj/structure/table/wood, @@ -302,7 +293,7 @@ "fm" = ( /obj/structure/window/reinforced/spawner/directional/west, /obj/structure/window/reinforced/spawner/directional/south, -/turf/open/space, +/turf/open/space/basic, /area/shuttle/escape) "fn" = ( /obj/effect/spawner/xmastree, @@ -341,7 +332,7 @@ /obj/structure/window/reinforced/spawner/directional/east, /obj/structure/lattice, /obj/structure/window/reinforced/spawner/directional/south, -/turf/open/space, +/turf/open/space/basic, /area/shuttle/escape) "fT" = ( /obj/structure/table/wood, @@ -462,7 +453,7 @@ "iw" = ( /obj/structure/lattice, /obj/structure/grille, -/turf/open/space, +/turf/open/space/basic, /area/shuttle/escape) "iB" = ( /obj/machinery/light/small/directional/west, @@ -671,7 +662,7 @@ "kJ" = ( /obj/structure/lattice, /obj/structure/window/reinforced/spawner/directional/west, -/turf/open/space, +/turf/open/space/basic, /area/shuttle/escape) "kM" = ( /obj/structure/table/wood/fancy, @@ -697,11 +688,6 @@ /obj/machinery/meter, /turf/open/floor/plating, /area/shuttle/escape) -"ln" = ( -/obj/structure/window/reinforced/spawner/directional/east, -/obj/structure/window/reinforced/spawner/directional/south, -/turf/open/space, -/area/shuttle/escape) "lB" = ( /turf/open/floor/iron/chapel{ dir = 8 @@ -729,14 +715,6 @@ }, /turf/open/floor/iron, /area/shuttle/escape) -"ml" = ( -/obj/structure/window/reinforced/spawner/directional/west, -/turf/open/space, -/area/shuttle/escape) -"mm" = ( -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/shuttle/escape) "mn" = ( /obj/structure/chair/wood, /obj/item/radio/intercom/chapel{ @@ -1315,10 +1293,6 @@ }, /turf/open/floor/mineral/plastitanium/red, /area/shuttle/escape/brig) -"uP" = ( -/obj/structure/window/reinforced/spawner/directional/east, -/turf/open/space, -/area/shuttle/escape) "uX" = ( /obj/machinery/power/smes, /turf/open/floor/plating, @@ -2793,10 +2767,6 @@ /obj/effect/station_crash/devastating, /turf/open/floor/iron/dark, /area/shuttle/escape) -"OL" = ( -/obj/structure/lattice, -/turf/open/space, -/area/shuttle/escape) "OM" = ( /obj/item/cultivator, /turf/open/floor/grass, @@ -4287,7 +4257,7 @@ nr nr nr nr -uP +hq hq JG JG @@ -4989,9 +4959,9 @@ JG JG PB ti -OL -uP -ln +PB +hq +gl zE zE AJ @@ -5065,7 +5035,7 @@ JG JG JG iw -OL +PB iw iw iw @@ -5149,8 +5119,8 @@ JG iw JG JG -dp -uP +rZ +hq zE Zf zE @@ -5229,7 +5199,7 @@ JG JG JG bd -OL +PB bT zE zE @@ -5311,7 +5281,7 @@ aH iw iw iw -cH +qA zE zE jc @@ -5388,8 +5358,8 @@ JG JG "} (21,1,1) = {" -uP -uP +hq +hq hq rZ hq @@ -5798,7 +5768,7 @@ JG JG "} (26,1,1) = {" -cH +qA zE ox bb @@ -6217,7 +6187,7 @@ LK zE LK dX -ml +IM fm zE zE @@ -6294,9 +6264,9 @@ JG JG IM IM -ml -ml -ml +IM +IM +IM IM JG JG @@ -6384,7 +6354,7 @@ JG JG JG JG -ml +IM fm zE zE @@ -6635,8 +6605,8 @@ JG JG JG JG -ml -ml +IM +IM jS zE ko @@ -6721,7 +6691,7 @@ JG JG JG kJ -mm +ti zE jc jc @@ -6803,7 +6773,7 @@ JG JG JG PB -mm +ti zE zE zE @@ -6884,8 +6854,8 @@ JG JG JG JG -OL -mm +PB +ti kJ IM IM diff --git a/_maps/virtual_domains/meta_central.dmm b/_maps/virtual_domains/meta_central.dmm index 43314f959b1d..8c17d14812a4 100644 --- a/_maps/virtual_domains/meta_central.dmm +++ b/_maps/virtual_domains/meta_central.dmm @@ -262,6 +262,14 @@ /obj/effect/turf_decal/caution/red, /turf/open/floor/iron, /area/virtual_domain) +"ch" = ( +/obj/structure/table/wood, +/obj/machinery/light/directional/south, +/obj/item/papercutter{ + pixel_x = -4 + }, +/turf/open/floor/wood, +/area/virtual_domain) "cj" = ( /obj/item/radio/intercom/directional/east, /obj/effect/turf_decal/tile/neutral{ @@ -3690,6 +3698,19 @@ }, /turf/open/floor/iron, /area/virtual_domain) +"Fa" = ( +/obj/structure/table/reinforced, +/obj/item/clothing/glasses/night{ + pixel_x = 5; + pixel_y = 7 + }, +/obj/item/clothing/glasses/night, +/obj/item/clothing/glasses/night{ + pixel_x = -5; + pixel_y = -3 + }, +/turf/template_noop, +/area/virtual_domain/safehouse) "Fc" = ( /obj/machinery/door/firedoor, /obj/effect/turf_decal/tile/neutral{ @@ -4406,19 +4427,6 @@ /obj/item/clothing/mask/facehugger/dead, /turf/open/floor/plating, /area/virtual_domain) -"Lq" = ( -/obj/structure/table/reinforced, -/obj/item/clothing/glasses/night/colorless{ - pixel_x = 5; - pixel_y = 7 - }, -/obj/item/clothing/glasses/night/colorless, -/obj/item/clothing/glasses/night/colorless{ - pixel_x = -5; - pixel_y = -3 - }, -/turf/template_noop, -/area/virtual_domain/safehouse) "Ls" = ( /obj/modular_map_root/safehouse{ key = "shuttle_space" @@ -4522,15 +4530,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/wood, /area/virtual_domain) -"Mk" = ( -/obj/structure/table/wood, -/obj/machinery/light/directional/south, -/obj/item/papercutter{ - pixel_x = -4 - }, -/obj/item/paper/fluff/ids_for_dummies, -/turf/open/floor/wood, -/area/virtual_domain) "Ml" = ( /obj/effect/decal/cleanable/crayon/x, /turf/closed/wall/rust, @@ -6727,7 +6726,7 @@ uS uS ML DP -Mk +ch uS ND AP @@ -7277,7 +7276,7 @@ oD pB hX zQ -Lq +Fa hX hX hX diff --git a/_maps/virtual_domains/psyker_shuffle.dmm b/_maps/virtual_domains/psyker_shuffle.dmm index 5f303d4ae047..bc77f996ee6f 100644 --- a/_maps/virtual_domains/psyker_shuffle.dmm +++ b/_maps/virtual_domains/psyker_shuffle.dmm @@ -85,7 +85,7 @@ /turf/open/indestructible/dark, /area/virtual_domain) "B" = ( -/turf/open/space, +/turf/open/space/basic, /area/space/virtual_domain) "F" = ( /obj/structure/closet/crate/internals, diff --git a/biome.json b/biome.json index 9b05fad5eeab..8f792f2b57b0 100644 --- a/biome.json +++ b/biome.json @@ -56,8 +56,7 @@ "suspicious": { "noArrayIndexKey": "off", "noExplicitAny": "off", - "noImplicitAnyLet": "off", - "noAssignInExpressions": "warn" + "noImplicitAnyLet": "off" } } }, diff --git a/code/__DEFINES/achievements.dm b/code/__DEFINES/achievements.dm index 502f2c94d884..518369c1911c 100644 --- a/code/__DEFINES/achievements.dm +++ b/code/__DEFINES/achievements.dm @@ -70,6 +70,7 @@ #define MAFIA_MEDAL_DETECTIVE "Detective" #define MAFIA_MEDAL_PSYCHOLOGIST "Psychologist" #define MAFIA_MEDAL_CHAPLAIN "Chaplain" +#define MAFIA_MEDAL_CORONER "Coroner" #define MAFIA_MEDAL_MD "Medical Doctor" #define MAFIA_MEDAL_OFFICER "Security Officer" #define MAFIA_MEDAL_LAWYER "Lawyer" diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index 0fa62223bdab..8098f4844e25 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -82,7 +82,7 @@ /atom/proc/Admin_Coordinates_Readable(area_name, admin_jump_ref) var/turf/turf_at_coords = Safe_COORD_Location() - return turf_at_coords ? "[area_name ? "[get_area_name(turf_at_coords, TRUE)] " : " "]([turf_at_coords.x],[turf_at_coords.y],[turf_at_coords.z])[admin_jump_ref ? " [ADMIN_JMP(turf_at_coords)]" : ""]" : "nonexistent location" + return turf_at_coords ? "[area_name ? "[get_area_name(turf_at_coords, TRUE)] " : ""]([turf_at_coords.x],[turf_at_coords.y],[turf_at_coords.z])[admin_jump_ref ? " [ADMIN_JMP(turf_at_coords)]" : ""]" : "nonexistent location" /atom/proc/Safe_COORD_Location() var/atom/drop_atom = drop_location() diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index a3647e69b03f..9a2390557d83 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -457,3 +457,9 @@ GLOBAL_LIST_INIT(human_invader_antagonists, list( #define BATTLE_ROYALE_CAMERA_NET "battle_royale_camera_net" #define MALF_MAX_PP 400 + +//Uplink spawn loc +#define UPLINK_PDA "PDA" +#define UPLINK_RADIO "Radio" +#define UPLINK_PEN "Pen" //like a real spy! +#define UPLINK_IMPLANT "Implant" diff --git a/code/__DEFINES/clothing.dm b/code/__DEFINES/clothing.dm index a6370218fd40..805d3eccb38e 100644 --- a/code/__DEFINES/clothing.dm +++ b/code/__DEFINES/clothing.dm @@ -42,3 +42,29 @@ /// How much integrity does a shirt lose every time we bite it? #define MOTH_EATING_CLOTHING_DAMAGE 15 + +//Suit/Skirt +/// Preference: Jumpsuit +#define PREF_SUIT "Jumpsuit" +/// Preference: Jumpskirt +#define PREF_SKIRT "Jumpskirt" + +// Types of backpack +/// Backpack type: Department themed backpack +#define DBACKPACK "Department Backpack" +/// Backpack type: Department themed duffelbag +#define DDUFFELBAG "Department Duffel Bag" +/// Backpack type: Department themed satchel +#define DSATCHEL "Department Satchel" +/// Backpack type: Department themed messenger bag +#define DMESSENGER "Department Messenger Bag" +/// Backpack type: Grey backpack +#define GBACKPACK "Grey Backpack" +/// Backpack type: Grey duffelbag +#define GDUFFELBAG "Grey Duffel Bag" +/// Backpack type: Grey satchel +#define GSATCHEL "Grey Satchel" +/// Backpack type: Grey messenger bag +#define GMESSENGER "Grey Messenger Bag" +/// Backpack type: Leather satchel +#define LSATCHEL "Leather Satchel" diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index b5ea83cd26eb..0e961b3153b4 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -233,6 +233,21 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list( /// Ammo box will have a different sprite for any ammo at all, and no ammo, -full -empty #define AMMO_BOX_FULL_EMPTY 2 +// Ammo box multiload defines +/// Ammo box does not accept multiload in or out, e.g. ammo box CANNOT transfer multiple casings in one action, either IN or OUT. +#define AMMO_BOX_MULTILOAD_NONE 0 +/// Ammo box accepts multiload going in, e.g. ammo box can transfer multiple casings IN at once. +#define AMMO_BOX_MULTILOAD_IN (1 << 0) +/// Ammo box accepts multiload going out, e.g. ammo box can transfer multiple casings OUT at once. +#define AMMO_BOX_MULTILOAD_OUT (1 << 1) +/// Ammo box accepts multiload in AND out, e.g. ammo box can transfer multiple casings IN at once *and* OUT at once. +#define AMMO_BOX_MULTILOAD_BOTH AMMO_BOX_MULTILOAD_IN | AMMO_BOX_MULTILOAD_OUT + +DEFINE_BITFIELD(ammo_box_multiload, list( + "LOAD_IN" = AMMO_BOX_MULTILOAD_IN, + "LOAD_OUT" = AMMO_BOX_MULTILOAD_OUT, +)) + #define SUPPRESSED_NONE 0 #define SUPPRESSED_QUIET 1 ///standard suppressed #define SUPPRESSED_VERY 2 /// no message diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm index 1df2f39cc1b1..378a86aceeba 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm @@ -105,7 +105,7 @@ /// Return to prevent the movable from talking into the radio. #define COMPONENT_CANNOT_USE_RADIO (1<<0) -/// Sent from /atom/movable/proc/say_quote() after say verb is chosen and before spans are applied. +/// Sent from /atom/movable/proc/generate_messagepart() generating a quoted message, after say verb is chosen and before spans are applied. #define COMSIG_MOVABLE_SAY_QUOTE "movable_say_quote" // Used to access COMSIG_MOVABLE_SAY_QUOTE argslist /// The index of args that corresponds to the actual message diff --git a/code/__DEFINES/dcs/signals/signals_cytology.dm b/code/__DEFINES/dcs/signals/signals_cytology.dm index 70fbe29c4e09..fce8e8a2714a 100644 --- a/code/__DEFINES/dcs/signals/signals_cytology.dm +++ b/code/__DEFINES/dcs/signals/signals_cytology.dm @@ -1,4 +1,5 @@ //Cytology signals ///Sent from /datum/biological_sample/proc/reset_sample #define COMSIG_SAMPLE_GROWTH_COMPLETED "sample_growth_completed" - +///Sent from /datum/biological_sample/proc/succeed_growing : (atom/grown_thing) +#define COMSIG_SAMPLE_DEPOSITED "sample_deposited" diff --git a/code/__DEFINES/dcs/signals/signals_food.dm b/code/__DEFINES/dcs/signals/signals_food.dm index 113826a44863..121942aab7bb 100644 --- a/code/__DEFINES/dcs/signals/signals_food.dm +++ b/code/__DEFINES/dcs/signals/signals_food.dm @@ -50,6 +50,8 @@ #define COMPONENT_HANDLED_GRILLING (1<<0) ///Called when an object is turned into another item through grilling ontop of a griddle #define COMSIG_ITEM_GRILLED "item_grill_completed" +///Sent to the newly spawned object when it's grilled on a griddle. +#define COMSIG_ITEM_GRILLED_RESULT "item_grilled_result" ///Called when the object is grilled by the grill (not to be confused by the griddle, but oh gee the two should be merged in one) #define COMSIG_ITEM_BARBEQUE_GRILLED "item_barbeque_grilled" @@ -67,6 +69,8 @@ #define COMPONENT_BAKING_BAD_RESULT (1<<2) ///Called when an object is turned into another item through baking in an oven #define COMSIG_ITEM_BAKED "item_bake_completed" +///Sent to the newly spawned object when it's baked in an oven. +#define COMSIG_ITEM_BAKED_RESULT "item_baked_result" //Drink diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm index 932437398685..1f5f19ba6103 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm @@ -14,6 +14,8 @@ #define COMSIG_ORGAN_SURGICALLY_REMOVED "organ_surgically_removed" /// Called when an organ gets surgically removed (mob/living/user, mob/living/carbon/new_owner, target_zone, obj/item/tool) #define COMSIG_ORGAN_SURGICALLY_INSERTED "organ_surgically_inserted" +/// Called when an organ finishes inserting into a bodypart (obj/item/bodypart/limb, movement_flags) +#define COMSIG_ORGAN_BODYPART_INSERTED "organ_bodypart_inserted" ///Called when movement intent is toggled. #define COMSIG_MOVE_INTENT_TOGGLED "move_intent_toggled" @@ -25,6 +27,8 @@ #define COMSIG_LIVING_ENTER_STAMCRIT "living_enter_stamcrit" ///from /obj/structure/door/crush(): (mob/living/crushed, /obj/machinery/door/crushing_door) #define COMSIG_LIVING_DOORCRUSHED "living_doorcrush" + /// Stop the door from causing wounds (damage still applies though) + #define DOORCRUSH_NO_WOUND (1<<0) ///from base of mob/living/resist() (/mob/living) #define COMSIG_LIVING_RESIST "living_resist" ///from base of mob/living/ignite_mob() (/mob/living) diff --git a/code/__DEFINES/dcs/signals/signals_object.dm b/code/__DEFINES/dcs/signals/signals_object.dm index 997e4fb88e01..844d72bc62ff 100644 --- a/code/__DEFINES/dcs/signals/signals_object.dm +++ b/code/__DEFINES/dcs/signals/signals_object.dm @@ -359,6 +359,12 @@ #define COMPONENT_CANCEL_SAWING_OFF (1<<0) #define COMSIG_GUN_SAWN_OFF "gun_sawn_off" +///called in /obj/item/firing_pin/proc/gun_insert(mob/living/user, obj/item/gun/new_gun): (obj/item/firing_pin/pin, mob/living/user) +#define COMSIG_GUN_PIN_INSERTED "gun_pin_inserted" + +///called in /obj/item/firing_pin/proc/gun_remove(mob/living/user): (obj/item/firing_pin/pin, mob/living/user) +#define COMSIG_GUN_PIN_REMOVED "gun_pin_removed" + // Jetpack things // Please kill me diff --git a/code/__DEFINES/dcs/signals/signals_reagent.dm b/code/__DEFINES/dcs/signals/signals_reagent.dm index 7e2954e7d220..157f7058a4c4 100644 --- a/code/__DEFINES/dcs/signals/signals_reagent.dm +++ b/code/__DEFINES/dcs/signals/signals_reagent.dm @@ -6,8 +6,6 @@ #define COMSIG_ATOM_EXPOSE_REAGENTS "atom_expose_reagents" /// Prevents the atom from being exposed to reagents if returned on [COMSIG_ATOM_EXPOSE_REAGENTS] #define COMPONENT_NO_EXPOSE_REAGENTS (1<<0) -///from base of atom/expose_reagents(): (/list, /datum/reagents, methods, volume_modifier, show_message) -#define COMSIG_ATOM_AFTER_EXPOSE_REAGENTS "atom_after_expose_reagents" ///from base of [/datum/reagent/proc/expose_atom]: (/datum/reagent, reac_volume) #define COMSIG_ATOM_EXPOSE_REAGENT "atom_expose_reagent" ///from base of [/datum/reagent/proc/expose_atom]: (/atom, reac_volume) @@ -36,8 +34,6 @@ ///from base of [/datum/reagents/proc/process]: (num_reactions) #define COMSIG_REAGENTS_REACTION_STEP "reagents_time_step" -///from base of [/atom/proc/expose_reagents]: (/atom, /list, methods, volume_modifier, show_message) -#define COMSIG_REAGENTS_EXPOSE_ATOM "reagents_expose_atom" ///from base of [/obj/proc/expose_reagents]: (/obj, /list, methods, volume_modifier, show_message) #define COMSIG_REAGENTS_EXPOSE_OBJ "reagents_expose_obj" ///from base of [/mob/living/proc/expose_reagents]: (/mob/living, /list, methods, volume_modifier, show_message, touch_protection) diff --git a/code/__DEFINES/exosuit_fab.dm b/code/__DEFINES/exosuit_fab.dm index 4fd921bdeb77..4cc21f210d61 100644 --- a/code/__DEFINES/exosuit_fab.dm +++ b/code/__DEFINES/exosuit_fab.dm @@ -35,12 +35,10 @@ #define EXOSUIT_MODULE_MARAUDER (1<<10) /// Module is compatible with Paddy models #define EXOSUIT_MODULE_PADDY (1<<11) -/// Module is compatible with Justice models -#define EXOSUIT_MODULE_JUSTICE (1<<12) /// Module is compatible with "Working" Exosuit models - Ripley and Clarke #define EXOSUIT_MODULE_WORKING (EXOSUIT_MODULE_RIPLEY | EXOSUIT_MODULE_CLARKE) /// Module is compatible with "Combat" Exosuit models - Gygax, H.O.N.K, Durand and Phazon, or any Exosuit with an empty Concealed Weapon Bay -#define EXOSUIT_MODULE_COMBAT (EXOSUIT_MODULE_GYGAX | EXOSUIT_MODULE_HONK | EXOSUIT_MODULE_DURAND | EXOSUIT_MODULE_PHAZON | EXOSUIT_MODULE_SAVANNAH | EXOSUIT_MODULE_RETICENCE | EXOSUIT_MODULE_MARAUDER | EXOSUIT_MODULE_PADDY | EXOSUIT_MODULE_JUSTICE | EXOSUIT_MODULE_CONCEALED_WEP_BAY) +#define EXOSUIT_MODULE_COMBAT (EXOSUIT_MODULE_GYGAX | EXOSUIT_MODULE_HONK | EXOSUIT_MODULE_DURAND | EXOSUIT_MODULE_PHAZON | EXOSUIT_MODULE_SAVANNAH | EXOSUIT_MODULE_RETICENCE | EXOSUIT_MODULE_MARAUDER | EXOSUIT_MODULE_PADDY | EXOSUIT_MODULE_CONCEALED_WEP_BAY) /// Module is compatible with "Medical" Exosuit modelsm - Odysseus #define EXOSUIT_MODULE_MEDICAL EXOSUIT_MODULE_ODYSSEUS diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm index 1c0f10b0daf9..5876bd610615 100644 --- a/code/__DEFINES/layers.dm +++ b/code/__DEFINES/layers.dm @@ -13,8 +13,8 @@ #define PLANE_SPACE -21 #define PLANE_SPACE_PARALLAX -20 -#define GRAVITY_PULSE_PLANE -12 -#define GRAVITY_PULSE_RENDER_TARGET "*GRAVPULSE_RENDER_TARGET" +#define DISPLACEMENT_PLANE -12 +#define DISPLACEMENT_RENDER_TARGET "*DISPLACEMENT_RENDER_TARGET" #define RENDER_PLANE_TRANSPARENT -11 //Transparent plane that shows openspace underneath the floor @@ -47,56 +47,59 @@ #define O_LIGHTING_VISUAL_RENDER_TARGET "*O_LIGHT_VISUAL_PLANE" // Render plate used by overlay lighting to mask turf lights -#define TURF_LIGHTING_PLATE 12 +#define RENDER_PLANE_TURF_LIGHTING 12 #define EMISSIVE_PLANE 13 /// This plane masks out lighting to create an "emissive" effect, ie for glowing lights in otherwise dark areas. -#define EMISSIVE_RENDER_PLATE 14 -#define EMISSIVE_RENDER_TARGET "*EMISSIVE_PLANE" +#define RENDER_PLANE_EMISSIVE 14 +#define EMISSIVE_RENDER_TARGET "*RENDER_PLANE_EMISSIVE" // Ensures all the render targets that point at the emissive plate layer correctly #define EMISSIVE_Z_BELOW_LAYER 1 #define EMISSIVE_FLOOR_LAYER 2 #define EMISSIVE_SPACE_LAYER 3 #define EMISSIVE_WALL_LAYER 4 -#define EMISSIVE_BLOOM_MASK_PLATE 15 -#define EMISSIVE_BLOOM_MASK_TARGET "*EMISSIVE_BLOOM_MASK_PLATE" -#define EMISSIVE_BLOOM_PLATE 16 +#define RENDER_PLANE_EMISSIVE_BLOOM_MASK 15 +#define EMISSIVE_BLOOM_MASK_RENDER_TARGET "*RENDER_PLANE_EMISSIVE_BLOOM_MASK" +#define RENDER_PLANE_EMISSIVE_BLOOM 16 -//-------------------- Game plane assembly --------------------- - -#define RENDER_PLANE_GAME 17 -/// If fov is enabled we'll draw game to this and do shit to it -#define RENDER_PLANE_GAME_MASKED 18 -/// The bit of the game plane that is let alone is sent here -#define RENDER_PLANE_GAME_UNMASKED 19 +#define RENDER_PLANE_SPECULAR_MASK 17 +#define SPECULAR_MASK_RENDER_TARGET "*RENDER_PLANE_SPECULAR_MASK" //-------------------- Lighting --------------------- +/// Main game plane to which everything renders, which then is multiplied by light +/// Should not be lit directly as it is sourced for emissive bloom +#define RENDER_PLANE_UNLIT_GAME 19 + #define RENDER_PLANE_LIGHTING 20 /// Masks the lighting plane with turfs, so we never light up the void /// Failing that, masks emissives and the overlay lighting plane -#define LIGHT_MASK_PLANE 21 -#define LIGHT_MASK_RENDER_TARGET "*LIGHT_MASK_PLANE" +#define RENDER_PLANE_LIGHT_MASK 21 +#define LIGHT_MASK_RENDER_TARGET "*RENDER_PLANE_LIGHT_MASK" + +/// We cannot render speculars to ABOVE_LIGHTING, as then they give it alpha and end up masking things in darkness +/// So we need to render it directly to RENDER_PLANE_GAME above RENDER_PLANE_LIGHTING +#define RENDER_PLANE_SPECULAR 22 -///Things that should render ignoring lighting -#define ABOVE_LIGHTING_PLANE 22 +/// Things that should render ignoring lighting +#define ABOVE_LIGHTING_PLANE 23 -#define WEATHER_GLOW_PLANE 23 +#define WEATHER_GLOW_PLANE 24 ///---------------- MISC ----------------------- ///Pipecrawling images -#define PIPECRAWL_IMAGES_PLANE 24 +#define PIPECRAWL_IMAGES_PLANE 25 ///AI Camera Static -#define CAMERA_STATIC_PLANE 25 +#define CAMERA_STATIC_PLANE 26 ///Anything that wants to be part of the game plane, but also wants to draw above literally everything else -#define HIGH_GAME_PLANE 26 +#define HIGH_GAME_PLANE 27 -#define FULLSCREEN_PLANE 27 +#define FULLSCREEN_PLANE 28 ///--------------- FULLSCREEN RUNECHAT BUBBLES ------------ @@ -116,7 +119,12 @@ // The largest plane here must still be less than RENDER_PLANE_GAME //-------------------- Rendering --------------------- -#define LIT_GAME_RENDER_PLATE 40 +#define RENDER_PLANE_GAME 40 +/// If fov is enabled we'll draw game to this and do shit to it +#define RENDER_PLANE_GAME_MASKED 41 +/// The bit of the game plane that is let alone is sent here +#define RENDER_PLANE_GAME_UNMASKED 42 + #define RENDER_PLANE_NON_GAME 45 // Only VERY special planes should be here, as they are above not just the game, but the UI planes as well. @@ -151,6 +159,9 @@ // NOTICE: we break from the pattern of increasing in steps of like 0.01 here // Because TOPDOWN_LAYER is 10000 and that's enough to floating point our modifications away +// Must be equal to the offset of the highest topdown layer +#define TOPDOWN_LAYER_COUNT 18 + //lower than LOW_FLOOR_LAYER, for turfs with stuff on the edge that should be covered by other turfs #define LOWER_FLOOR_LAYER (1 + TOPDOWN_LAYER) #define LOW_FLOOR_LAYER (2 + TOPDOWN_LAYER) @@ -170,7 +181,7 @@ #define ABOVE_OPEN_TURF_LAYER (15 + TOPDOWN_LAYER) #define LOWER_RUNE_LAYER (16 + TOPDOWN_LAYER) #define RUNE_LAYER (17 + TOPDOWN_LAYER) -#define CLEANABLE_FLOOR_OBJECT_LAYER (21 + TOPDOWN_LAYER) +#define CLEANABLE_FLOOR_OBJECT_LAYER (18 + TOPDOWN_LAYER) //Placeholders in case the game plane and possibly other things between it and the floor plane are ever made into topdown planes @@ -186,6 +197,8 @@ // GAME_PLANE layers #define BULLET_HOLE_LAYER 2.06 #define ABOVE_NORMAL_TURF_LAYER 2.08 +#define FLOOR_EMISSIVE_START_LAYER 2.09 +#define FLOOR_EMISSIVE_END_LAYER 2.26 #define GAS_PIPE_HIDDEN_LAYER 2.35 //layer = initial(layer) + piping_layer / 1000 in atmospherics/update_icon() to determine order of pipe overlap #define WIRE_BRIDGE_LAYER 2.44 #define WIRE_TERMINAL_LAYER 2.45 @@ -228,6 +241,7 @@ #define BELOW_MOB_LAYER 3.7 #define LOW_MOB_LAYER 3.75 #define LYING_MOB_LAYER 3.8 +#define ABOVE_LYING_MOB_LAYER 3.85 #define VEHICLE_LAYER 3.9 #define MOB_BELOW_PIGGYBACK_LAYER 3.94 //#define MOB_LAYER 4 //For easy recordkeeping; this is a byond define diff --git a/code/__DEFINES/lighting.dm b/code/__DEFINES/lighting.dm index 03bc07e29f54..98c4cdae3d3f 100644 --- a/code/__DEFINES/lighting.dm +++ b/code/__DEFINES/lighting.dm @@ -80,12 +80,29 @@ #define _EMISSIVE_COLOR(val) list(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, val,0,0,0) #define _EMISSIVE_COLOR_NO_BLOOM(val) list(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,val,0,0) +#define _SPECULAR_COLOR(val) list(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,val,0) /// The color matrix applied to all emissive overlays. Should be solely dependent on alpha and not have RGB overlap with [EM_BLOCK_COLOR]. #define EMISSIVE_COLOR _EMISSIVE_COLOR(1) #define EMISSIVE_COLOR_NO_BLOOM _EMISSIVE_COLOR_NO_BLOOM(1) +#define SPECULAR_COLOR _SPECULAR_COLOR(1) /// A globally cached version of [EMISSIVE_COLOR] for quick access. GLOBAL_LIST_INIT(emissive_color, EMISSIVE_COLOR) GLOBAL_LIST_INIT(emissive_color_no_bloom, EMISSIVE_COLOR_NO_BLOOM) +GLOBAL_LIST_INIT(specular_color, SPECULAR_COLOR) + +// Types of emissives +/// Emissive that will not have bloom applied to it, encoded into the green channel +#define EMISSIVE_NO_BLOOM 0 +/// Emissive that will get bloom applied to it, encoded into the red channel +#define EMISSIVE_BLOOM 1 +/// Mimics a highly reflective surface, will not have any glow by itself but will amplify any lighting applied to it, encoded into the blue channel +#define EMISSIVE_SPECULAR 2 + +/// Light cutoff of specular emissives, controls how sharp a light must be before it starts reflecting +#define SPECULAR_EMISSIVE_CUTOFF 0.3 +/// Controls how bright specular emissives sourced from overlay lights are +/// Keep in mind that overlay lights are also affected by the specular cutoff, so the maximum light value achievable is (contrast - cutoff) +#define SPECULAR_EMISSIVE_OVERLAY_CONTRAST 1.4 #define _EM_BLOCK_COLOR(val) list(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,val, 0,0,0,0) /// The color matrix applied to all emissive blockers. Should be solely dependent on alpha and not have RGB overlap with [EMISSIVE_COLOR]. diff --git a/code/__DEFINES/mecha.dm b/code/__DEFINES/mecha.dm index fad05151e374..602a34d76c4f 100644 --- a/code/__DEFINES/mecha.dm +++ b/code/__DEFINES/mecha.dm @@ -78,25 +78,3 @@ /// bitflags for do_after checks on mechs #define MECH_DO_AFTER_DIR_CHANGE_FLAG (1 << 0) #define MECH_DO_AFTER_ADJACENCY_FLAG (1 << 1) - -/// Defines for Justice mech -#define JUSTICE_IDLE "idle" -#define JUSTICE_CHARGE "charge" -#define JUSTICE_INVISIBILITY "invisibility" -#define JUSTICE_INVISIBILITY_ATTACK "invisibility attack" -#define JUSTICE_FATALITY "fatality" - -#define JUSTICE_ENGINE_ACTIVE "active" -#define JUSTICE_ENGINE_ACTIVATING "activating" -#define JUSTICE_ENGINE_ONCOOLDOWN "oncooldown" -#define JUSTICE_ENGINE_DEACTIVATING "deactivating" -#define JUSTICE_ENGINE_DEACTIVE "deactive" - -#define COMSIG_JUSTICE_ATTACK_AOE "justice_attack_aoe" -#define COMSIG_JUSTICE_CHARGE_BUTTON_DOWN "justice_charge_button_down" - -#define COMSIG_JUSTICE_INVISIBILITY_ACTIVATE "justice_invisibility_activate" - #define COMPONENT_CANCEL_JUSTICE_INVISIBILITY_ACTIVATE (1<<0) -#define COMSIG_JUSTICE_INVISIBILITY_DEACTIVATE "justice_invisibility_deactivate" - #define COMPONENT_CANCEL_JUSTICE_INVISIBILITY_DEACTIVATE (1<<0) - diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index c99eacb7bcbc..8c22b65f7247 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -236,6 +236,9 @@ #define HUMAN_MAX_OXYLOSS 3 #define HUMAN_CRIT_MAX_OXYLOSS (SSMOBS_DT/3) +/// Combined brute and burn damage states on a human's head after which they become disfigured +#define HUMAN_DISFIGURATION_HEAD_DAMAGE_STATES 3 + #define HEAT_DAMAGE_LEVEL_1 1 //Amount of damage applied when your body temperature just passes the 360.15k safety point #define HEAT_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when your body temperature passes the 400K point #define HEAT_DAMAGE_LEVEL_3 4 //Amount of damage applied when your body temperature passes the 460K point and you are on fire @@ -255,6 +258,7 @@ //Brain Damage defines #define BRAIN_DAMAGE_MILD 20 +#define BRAIN_DAMAGE_ASYNC_BLINKING 60 #define BRAIN_DAMAGE_SEVERE 100 #define BRAIN_DAMAGE_DEATH 200 @@ -465,7 +469,7 @@ #define APPRENTICE_AGE_MIN 29 //youngest an apprentice can be #define SHOES_SLOWDOWN 0 //How much shoes slow you down by default. Negative values speed you up #define POCKET_STRIP_DELAY (4 SECONDS) //time taken to search somebody's pockets -#define DOOR_CRUSH_DAMAGE 15 //the amount of damage that airlocks deal when they crush you +#define DOOR_CRUSH_DAMAGE 20 //the amount of damage that airlocks deal when they crush you #define HUNGER_FACTOR 0.05 //factor at which mob nutrition decreases #define ETHEREAL_DISCHARGE_RATE (1e-3 * STANDARD_ETHEREAL_CHARGE) // Rate at which ethereal stomach charge decreases @@ -820,7 +824,7 @@ GLOBAL_LIST_INIT(layers_to_offset, list( // BACK_LAYER (backpacks are big) // BODYPARTS_HIGH_LAYER (arms) // BODY_LAYER (body markings (full body), underwear (full body)) - "[EYES_LAYER]" = EYES_LAYER, // looks fine with but no need to filter it, so we can save on perf (eyes and eyelids) + // EYES_LAYER, // BODY_ADJ_LAYER (external organs like wings) // BODY_BEHIND_LAYER (external organs like wings) // BODY_FRONT_LAYER (external organs like wings) @@ -918,6 +922,8 @@ GLOBAL_LIST_INIT(layers_to_offset, list( #define VOMIT_CATEGORY_DEFAULT (MOB_VOMIT_MESSAGE | MOB_VOMIT_HARM | MOB_VOMIT_STUN) /// The vomit you've all come to know and love, but with a little extra "spice" (blood) #define VOMIT_CATEGORY_BLOOD (VOMIT_CATEGORY_DEFAULT | MOB_VOMIT_BLOOD) +/// The bloody vomit, but without the stunning +#define VOMIT_CATEGORY_BLOOD_STUNLESS (VOMIT_CATEGORY_BLOOD & ~MOB_VOMIT_STUN) /// Another vomit variant that causes you to get knocked down instead of just only getting a stun. Standard otherwise. #define VOMIT_CATEGORY_KNOCKDOWN (MOB_VOMIT_MESSAGE | MOB_VOMIT_HARM | MOB_VOMIT_KNOCKDOWN) diff --git a/code/__DEFINES/movement.dm b/code/__DEFINES/movement.dm index 9706819610f5..28d5be84c521 100644 --- a/code/__DEFINES/movement.dm +++ b/code/__DEFINES/movement.dm @@ -144,9 +144,5 @@ GLOBAL_VAR_INIT(glide_size_multiplier, 1.0) #define INERTIA_FORCE_SPACEMOVE_REDUCTION 0.75 NEWTONS /// How much inertia we must have to not be able to instantly stop after having something to grab #define INERTIA_FORCE_SPACEMOVE_GRAB 1.5 NEWTONS -/// How much inertia is required for the impacted object to be thrown at the wall -#define INERTIA_FORCE_THROW_FLOOR 10 NEWTONS -/// How much inertia is required past the floor to add 1 strength -#define INERTIA_FORCE_PER_THROW_FORCE 5 NEWTONS // Results in maximum speed of 1 tile per tick, capped at about 2/3rds of maximum force #define INERTIA_SPEED_COEF 0.375 diff --git a/code/__DEFINES/obj_flags.dm b/code/__DEFINES/obj_flags.dm index 8b0aad161c2b..1828f736a898 100644 --- a/code/__DEFINES/obj_flags.dm +++ b/code/__DEFINES/obj_flags.dm @@ -51,6 +51,8 @@ #define NO_BLOOD_ON_ITEM (1 << 19) /// Whether this item should skip the /datum/component/fantasy applied on spawn on the RPG event. Used on things like stacks #define SKIP_FANTASY_ON_SPAWN (1<<20) +/// If an item has had its /datum/element/weapon_description initialized or not. +#define WEAPON_DESCRIPTION_INITIALIZED (1<<21) // Flags for the clothing_flags var on /obj/item/clothing diff --git a/code/__DEFINES/research.dm b/code/__DEFINES/research.dm index f56ab891fa7f..f3b2cf819489 100644 --- a/code/__DEFINES/research.dm +++ b/code/__DEFINES/research.dm @@ -56,6 +56,14 @@ #define CELL_LINE_TABLE_BUTTERFLY "cell_line_butterfly_table" #define CELL_LINE_TABLE_MEGA_ARACHNID "cell_line_table_mega_arachnid" +//! Biopsy cell line organ types +#define CELL_LINE_ORGAN_HEART "cell_line_organ_heart" +#define CELL_LINE_ORGAN_LUNGS "cell_line_organ_lungs" +#define CELL_LINE_ORGAN_LIVER "cell_line_organ_liver" +#define CELL_LINE_ORGAN_STOMACH "cell_line_organ_stomach" + +#define CELL_LINE_ORGAN_HEART_CURSED "cell_line_organ_heart_cursed" + //! All cell virus types #define CELL_VIRUS_TABLE_GENERIC "cell_virus_generic_table" #define CELL_VIRUS_TABLE_GENERIC_MOB "cell_virus_generic_mob_table" diff --git a/code/__DEFINES/research/anomalies.dm b/code/__DEFINES/research/anomalies.dm index 8198ed6755cb..f0dabae02509 100644 --- a/code/__DEFINES/research/anomalies.dm +++ b/code/__DEFINES/research/anomalies.dm @@ -10,9 +10,9 @@ #define MAX_CORES_ECTOPLASMIC 8 ///Defines for the different types of explosion a flux anomaly can have -#define FLUX_NO_EXPLOSION 0 -#define FLUX_EXPLOSIVE 1 -#define FLUX_LOW_EXPLOSIVE 2 +#define FLUX_NO_EMP 0 +#define FLUX_EMP 1 +#define FLUX_LIGHT_EMP 2 /// Chance of anomalies moving every process tick #define ANOMALY_MOVECHANCE 45 diff --git a/code/__DEFINES/research/research_categories.dm b/code/__DEFINES/research/research_categories.dm index cd7a216bc9c9..3f6428eb7317 100644 --- a/code/__DEFINES/research/research_categories.dm +++ b/code/__DEFINES/research/research_categories.dm @@ -134,7 +134,6 @@ #define RND_CATEGORY_MECHFAB_PHAZON "/Phazon" #define RND_CATEGORY_MECHFAB_CLARKE "/Clarke" #define RND_CATEGORY_MECHFAB_SAVANNAH_IVANOV "/Savannah-Ivanov" -#define RND_CATEGORY_MECHFAB_JUSTICE "/Justice" #define RND_SUBCATEGORY_MECHFAB_CHASSIS "/Chassis" #define RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT "/Supported Equipment" #define RND_SUBCATEGORY_MECHFAB_CONTROL_INTERFACES "/Control Interfaces" diff --git a/code/__DEFINES/rust_g.dm b/code/__DEFINES/rust_g.dm index d2928195a507..048ea0bd0b75 100644 --- a/code/__DEFINES/rust_g.dm +++ b/code/__DEFINES/rust_g.dm @@ -138,6 +138,36 @@ */ #define rustg_dmi_icon_states(fname) RUSTG_CALL(RUST_G, "dmi_icon_states")(fname) +/** + * The below functions involve dmi metadata represented in the following format: + * list( + * "width": number, + * "height": number, + * "states": list([STATE_DATA], ...) + * ) + * + * STATE_DATA format: + * list( + * "name": string, + * "dirs": 1 | 4 | 8, + * "delays"?: list(number, ...), + * "rewind"?: TRUE | FALSE, + * "movement"?: TRUE | FALSE, + * "loop"?: number + * ) + */ + +/** + * Get the dmi metadata of the file located at `fname`. + * Returns a list in the metadata format listed above, or an error message. + */ +#define rustg_dmi_read_metadata(fname) json_decode(RUSTG_CALL(RUST_G, "dmi_read_metadata")(fname)) +/** + * Inject dmi metadata into a png file located at `path`. + * `metadata` must be a json_encode'd list in the metadata format listed above. + */ +#define rustg_dmi_inject_metadata(path, metadata) RUSTG_CALL(RUST_G, "dmi_inject_metadata")(path, metadata) + #define rustg_file_read(fname) RUSTG_CALL(RUST_G, "file_read")(fname) #define rustg_file_exists(fname) (RUSTG_CALL(RUST_G, "file_exists")(fname) == "true") #define rustg_file_write(text, fname) RUSTG_CALL(RUST_G, "file_write")(text, fname) @@ -198,13 +228,21 @@ #define rustg_http_request_blocking(method, url, body, headers, options) RUSTG_CALL(RUST_G, "http_request_blocking")(method, url, body, headers, options) #define rustg_http_request_async(method, url, body, headers, options) RUSTG_CALL(RUST_G, "http_request_async")(method, url, body, headers, options) #define rustg_http_check_request(req_id) RUSTG_CALL(RUST_G, "http_check_request")(req_id) +/// This is basically just `rustg_http_request_async` if you don't care about the response. +/// This will either return "ok" or an error, as this does not create a job. +#define rustg_http_request_fire_and_forget(method, url, body, headers, options) RUSTG_CALL(RUST_G, "http_request_fire_and_forget")(method, url, body, headers, options) -/// Generates a spritesheet at: [file_path][spritesheet_name]_[size_id].png +/// Generates a spritesheet at: [file_path][spritesheet_name]_[size_id].[png or dmi] /// The resulting spritesheet arranges icons in a random order, with the position being denoted in the "sprites" return value. /// All icons have the same y coordinate, and their x coordinate is equal to `icon_width * position`. /// /// hash_icons is a boolean (0 or 1), and determines if the generator will spend time creating hashes for the output field dmi_hashes. -/// These hashes can be heplful for 'smart' caching (see rustg_iconforge_cache_valid), but require extra computation. +/// These hashes can be helpful for 'smart' caching (see rustg_iconforge_cache_valid), but require extra computation. +/// +/// generate_dmi is a boolean (0 or 1), and determines if the generator will save the sheet as a DMI or stripped PNG file. +/// DMI files can be used to replace bulk Insert() operations, PNGs are more useful for asset transport or UIs. DMI generation is slower due to more metadata. +/// flatten is a boolean (0 or 1), and determines if the DMI output will be flattened to a single frame/dir if unscoped (null/0 dir or frame values). +/// PNGs are always flattened, regardless of argument. /// /// Spritesheet will contain all sprites listed within "sprites". /// "sprites" format: @@ -220,9 +258,15 @@ /// ) /// TRANSFORM_OBJECT format: /// list("type" = RUSTG_ICONFORGE_BLEND_COLOR, "color" = "#ff0000", "blend_mode" = ICON_MULTIPLY) -/// list("type" = RUSTG_ICONFORGE_BLEND_ICON, "icon" = [SPRITE_OBJECT], "blend_mode" = ICON_OVERLAY) +/// list("type" = RUSTG_ICONFORGE_BLEND_ICON, "icon" = [SPRITE_OBJECT], "blend_mode" = ICON_OVERLAY, "x" = 1, "y" = 1) // offsets optional /// list("type" = RUSTG_ICONFORGE_SCALE, "width" = 32, "height" = 32) /// list("type" = RUSTG_ICONFORGE_CROP, "x1" = 1, "y1" = 1, "x2" = 32, "y2" = 32) // (BYOND icons index from 1,1 to the upper bound, inclusive) +/// list("type" = RUSTG_ICONFORGE_MAP_COLORS, "rr" = 0.5, "rg" = 0.5, "rb" = 0.5, "ra" = 1, "gr" = 1, "gg" = 1, "gb" = 1, "ga" = 1, ...) // alpha arguments and rgba0 optional +/// list("type" = RUSTG_ICONFORGE_FLIP, "dir" = SOUTH) +/// list("type" = RUSTG_ICONFORGE_TURN, "angle" = 90.0) +/// list("type" = RUSTG_ICONFORGE_SHIFT, "dir" = EAST, "offset" = 10, "wrap" = FALSE) +/// list("type" = RUSTG_ICONFORGE_SWAP_COLOR, "src_color" = "#ff0000", "dst_color" = "#00ff00") // alpha bits supported +/// list("type" = RUSTG_ICONFORGE_DRAW_BOX, "color" = "#ff0000", "x1" = 1, "y1" = 1, "x2" = 32, "y2" = 32) // alpha bits supported. color can be null/omitted for transparency. x2 and y2 will default to x1 and y1 if omitted /// /// Returns a SpritesheetResult as JSON, containing fields: /// list( @@ -233,9 +277,9 @@ /// "error" = "[A string, empty if there were no errors.]" /// ) /// In the case of an unrecoverable panic from within Rust, this function ONLY returns a string containing the error. -#define rustg_iconforge_generate(file_path, spritesheet_name, sprites, hash_icons) RUSTG_CALL(RUST_G, "iconforge_generate")(file_path, spritesheet_name, sprites, "[hash_icons]") +#define rustg_iconforge_generate(file_path, spritesheet_name, sprites, hash_icons, generate_dmi, flatten) RUSTG_CALL(RUST_G, "iconforge_generate")(file_path, spritesheet_name, sprites, "[hash_icons]", "[generate_dmi]", "[flatten]") /// Returns a job_id for use with rustg_iconforge_check() -#define rustg_iconforge_generate_async(file_path, spritesheet_name, sprites, hash_icons) RUSTG_CALL(RUST_G, "iconforge_generate_async")(file_path, spritesheet_name, sprites, "[hash_icons]") +#define rustg_iconforge_generate_async(file_path, spritesheet_name, sprites, hash_icons, generate_dmi, flatten) RUSTG_CALL(RUST_G, "iconforge_generate_async")(file_path, spritesheet_name, sprites, "[hash_icons]", "[generate_dmi]", "[flatten]") /// Returns the status of an async job_id, or its result if it is completed. See RUSTG_JOB DEFINEs. #define rustg_iconforge_check(job_id) RUSTG_CALL(RUST_G, "iconforge_check")("[job_id]") /// Clears all cached DMIs and images, freeing up memory. @@ -256,7 +300,7 @@ /// Provided a /datum/greyscale_config typepath, JSON string containing the greyscale config, and path to a DMI file containing the base icons, /// Loads that config into memory for later use by rustg_iconforge_gags(). The config_path is the unique identifier used later. /// JSON Config schema: https://hackmd.io/@tgstation/GAGS-Layer-Types -/// Unsupported features: color_matrix layer type, 'or' blend_mode. May not have BYOND parity with animated icons or varying dirs between layers. +/// Adding dirs or frames (via blending larger icons) to icons with more than 1 dir or 1 frame is not supported. /// Returns "OK" if successful, otherwise, returns a string containing the error. #define rustg_iconforge_load_gags_config(config_path, config_json, config_icon_path) RUSTG_CALL(RUST_G, "iconforge_load_gags_config")("[config_path]", config_json, config_icon_path) /// Given a config_path (previously loaded by rustg_iconforge_load_gags_config), and a string of hex colors formatted as "#ff00ff#ffaa00" @@ -272,6 +316,12 @@ #define RUSTG_ICONFORGE_BLEND_ICON "BlendIcon" #define RUSTG_ICONFORGE_CROP "Crop" #define RUSTG_ICONFORGE_SCALE "Scale" +#define RUSTG_ICONFORGE_MAP_COLORS "MapColors" +#define RUSTG_ICONFORGE_FLIP "Flip" +#define RUSTG_ICONFORGE_TURN "Turn" +#define RUSTG_ICONFORGE_SHIFT "Shift" +#define RUSTG_ICONFORGE_SWAP_COLOR "SwapColor" +#define RUSTG_ICONFORGE_DRAW_BOX "DrawBox" #define RUSTG_JOB_NO_RESULTS_YET "NO RESULTS YET" #define RUSTG_JOB_NO_SUCH_JOB "NO SUCH JOB" @@ -298,6 +348,39 @@ */ #define rustg_noise_poisson_map(seed, width, length, radius) RUSTG_CALL(RUST_G, "noise_poisson_map")(seed, width, length, radius) +/** + * Register a list of nodes into a rust library. This list of nodes must have been serialized in a json. + * Node {// Index of this node in the list of nodes + * unique_id: usize, + * // Position of the node in byond + * x: usize, + * y: usize, + * z: usize, + * // Indexes of nodes connected to this one + * connected_nodes_id: Vec} + * It is important that the node with the unique_id 0 is the first in the json, unique_id 1 right after that, etc. + * It is also important that all unique ids follow. {0, 1, 2, 4} is not a correct list and the registering will fail + * Nodes should not link across z levels. + * A node cannot link twice to the same node and shouldn't link itself either + */ +#define rustg_register_nodes_astar(json) RUSTG_CALL(RUST_G, "register_nodes_astar")(json) + +/** + * Add a new node to the static list of nodes. Same rule as registering_nodes applies. + * This node unique_id must be equal to the current length of the static list of nodes + */ +#define rustg_add_node_astar(json) RUSTG_CALL(RUST_G, "add_node_astar")(json) + +/** + * Remove every link to the node with unique_id. Replace that node by null + */ +#define rustg_remove_node_astar(unique_id) RUSTG_CALL(RUST_G, "remove_node_astar")("[unique_id]") + +/** + * Compute the shortest path between start_node and goal_node using A*. Heuristic used is simple geometric distance + */ +#define rustg_generate_path_astar(start_node_id, goal_node_id) RUSTG_CALL(RUST_G, "generate_path_astar")("[start_node_id]", "[goal_node_id]") + /* * Takes in a string and json_encode()"d lists to produce a sanitized string. * This function operates on whitelists, there is currently no way to blacklist. @@ -362,8 +445,17 @@ #define rustg_time_milliseconds(id) text2num(RUSTG_CALL(RUST_G, "time_milliseconds")(id)) #define rustg_time_reset(id) RUSTG_CALL(RUST_G, "time_reset")(id) +/// Returns the current timestamp (in local time), formatted with the given format string. +/// See https://docs.rs/chrono/latest/chrono/format/strftime/index.html for documentation on the formatting syntax. +#define rustg_formatted_timestamp(format) RUSTG_CALL(RUST_G, "formatted_timestamp")(format) + +/// Returns the current timestamp (with the given UTC offset in hours), formatted with the given format string. +/// See https://docs.rs/chrono/latest/chrono/format/strftime/index.html for documentation on the formatting syntax. +#define rustg_formatted_timestamp_tz(format, offset) RUSTG_CALL(RUST_G, "formatted_timestamp")(format, offset) + /// Returns the timestamp as a string -#define rustg_unix_timestamp(...) (RUSTG_CALL(RUST_G, "unix_timestamp")()) +/proc/rustg_unix_timestamp() + return RUSTG_CALL(RUST_G, "unix_timestamp")() #define rustg_raw_read_toml_file(path) json_decode(RUSTG_CALL(RUST_G, "toml_file_to_json")(path) || "null") @@ -391,10 +483,3 @@ #define url_decode(text) rustg_url_decode(text) #endif -/// Returns the current timestamp (in local time), formatted with the given format string. -/// See https://docs.rs/chrono/latest/chrono/format/strftime/index.html for documentation on the formatting syntax. -#define rustg_formatted_timestamp(format) RUSTG_CALL(RUST_G, "formatted_timestamp")(format) - -/// Returns the current timestamp (with the given UTC offset in hours), formatted with the given format string. -/// See https://docs.rs/chrono/latest/chrono/format/strftime/index.html for documentation on the formatting syntax. -#define rustg_formatted_timestamp_tz(format, offset) RUSTG_CALL(RUST_G, "formatted_timestamp")(format, offset) diff --git a/code/__DEFINES/say.dm b/code/__DEFINES/say.dm index 3405fc117b12..097a2592e647 100644 --- a/code/__DEFINES/say.dm +++ b/code/__DEFINES/say.dm @@ -5,6 +5,8 @@ #define RADIO_EXTENSION "department specific" #define RADIO_KEY "department specific key" #define LANGUAGE_EXTENSION "language specific" +///This is a mob that is forcing us to say something, so we can use the mob typing the text for bans rather than the one speaking. +#define MANNEQUIN_CONTROLLED "mannequin controlled" /// Message mod which contains a list of bonus "mutual understanding" to allow arbitrary understanding of any speech #define LANGUAGE_MUTUAL_BONUS "language mutual bonus" #define SAY_MOD_VERB "say_mod_verb" @@ -46,7 +48,10 @@ #define MODE_KEY_PUPPET "j" #define MODE_ALIEN "alientalk" +#define MODE_KEY_ALIEN "a" + #define MODE_HOLOPAD "holopad" +#define MODE_KEY_HOLOPAD "h" #define MODE_CHANGELING "changeling" #define MODE_KEY_CHANGELING "g" @@ -119,6 +124,9 @@ #define MSG_AUDIBLE (1<<1) +// Say mode message handling return flags, exist for readability. +/// Say mode has handled the message. +#define SAYMODE_MESSAGE_HANDLED (1<<0) // Used in visible_message_flags, audible_message_flags and runechat_flags /// Automatically applies emote related spans/fonts/formatting to the message diff --git a/code/__DEFINES/skills.dm b/code/__DEFINES/skills.dm index 5a945d7ec579..5de91c1fa8d4 100644 --- a/code/__DEFINES/skills.dm +++ b/code/__DEFINES/skills.dm @@ -47,6 +47,9 @@ ///The base modifier a boulder's size grants to the mining skill. #define MINING_SKILL_BOULDER_SIZE_XP 10 +///The base modifier for how much experience is earned from misc athletics interactions +#define ATHLETICS_SKILL_MISC_EXP 5 + // Skillchip categories //Various skillchip categories. Use these when setting which categories a skillchip restricts being paired with //while using the SKILLCHIP_RESTRICTED_CATEGORIES flag diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index 802bf04212d8..6e9c8f0fee7f 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -941,6 +941,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_NO_WORN_ICON "no_worn_icon" /// Items with this trait will not appear when examined. #define TRAIT_EXAMINE_SKIP "examine_skip" +/// Objects with this trait cannot be repaired with duct tape +#define TRAIT_DUCT_TAPE_UNREPAIRABLE "duct_tape_unrepairable" //quirk traits #define TRAIT_ALCOHOL_TOLERANCE "alcohol_tolerance" @@ -1048,6 +1050,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_MODPC_HALVED_DOWNLOAD_SPEED "modpc_halved_download_speed" ///Dictates whether a user (source) is interacting with the frame of a stationary modular computer or the pc inside it. Needed for circuits I guess. #define TRAIT_MODPC_INTERACTING_WITH_FRAME "modpc_interacting_with_frame" +///Allows isnerting IDs into the second id slot +#define TRAIT_MODPC_TWO_ID_SLOTS "modpc_two_id_slots" /// If present on a [/mob/living/carbon], will make them appear to have a medium level disease on health HUDs. #define TRAIT_DISEASELIKE_SEVERITY_MEDIUM "diseaselike_severity_medium" @@ -1549,4 +1553,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// Trait that makes mobs with it immune to mining gear AOE attacks #define TRAIT_MINING_AOE_IMMUNE "mining_aoe_immune" +/// Trait that allows an item to perform holy rites akin to a nullrod +#define TRAIT_NULLROD_ITEM "nullrod_item" + // END TRAIT DEFINES diff --git a/code/__DEFINES/visual_helpers.dm b/code/__DEFINES/visual_helpers.dm index bb54c5d6b0b7..fda7f6648092 100644 --- a/code/__DEFINES/visual_helpers.dm +++ b/code/__DEFINES/visual_helpers.dm @@ -18,7 +18,7 @@ base_pixel_z = z; #define _SET_BASE_PIXEL_VISUAL_NO_OFFSET(w, z) \ - base_pixel_z = w; \ + base_pixel_w = w; \ base_pixel_z = z; /// Much like [SET_BASE_PIXEL], except it will not effect pixel offsets in mapping programs diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index cb4eb9b724a1..ba0cc6f96759 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -1344,3 +1344,17 @@ while(islist(result)) result = pick(result) return result + +/** Takes in two weighted lists and outputs a third list containing the elements of both inputs with their weights blended according to a given proportion. + * Not exact and may have rounding errors, will round to nearest 1/1000. + * */ +/proc/blend_weighted_lists(list/listA, list/listB, blend) + var/list/joined_list = listA | listB + + listA = counterlist_normalise(listA) + listB = counterlist_normalise(listB) + + for(var/element in joined_list) + joined_list[element] = round((listA[element] * (1 - blend) + listB[element] * (blend)) * 1000) + + return joined_list diff --git a/code/__HELPERS/chat.dm b/code/__HELPERS/chat.dm index 669a5f38fc46..5be492d9ef08 100644 --- a/code/__HELPERS/chat.dm +++ b/code/__HELPERS/chat.dm @@ -95,5 +95,10 @@ it will be sent to all connected chats. /// Sends a message to everyone within the list, as well as all observers. /proc/relay_to_list_and_observers(message, list/mob_list, source, message_type = null) for(var/mob/creature as anything in mob_list) - to_chat(creature, message, type = message_type) + to_chat( + creature, + message, + type = message_type, + avoid_highlighting = (creature == source), + ) send_to_observers(message, source) diff --git a/code/__HELPERS/icon_smoothing.dm b/code/__HELPERS/icon_smoothing.dm index 2f3355205e1b..733fd9e4f721 100644 --- a/code/__HELPERS/icon_smoothing.dm +++ b/code/__HELPERS/icon_smoothing.dm @@ -307,7 +307,7 @@ xxx xxx xxx SOUTH_JUNCTION|WEST_JUNCTION|SOUTHWEST_JUNCTION, SOUTH_JUNCTION|EAST_JUNCTION|SOUTHEAST_JUNCTION, ) - icon_state = "[base_icon_state]-[smoothing_junction]-d" + icon_state = "[base_icon_state]-[smoothing_junction]-diagonal" if(new_junction == old_junction || fixed_underlay) // Mutable underlays? return diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index 86817a55440d..ba9d701b03ae 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -1171,27 +1171,60 @@ GLOBAL_LIST_EMPTY(transformation_animation_objects) animate(pixel_x = initialpixelx + rand(-pixelshiftx,pixelshiftx), pixel_y = initialpixely + rand(-pixelshifty,pixelshifty), time = shake_interval) animate(pixel_x = initialpixelx, pixel_y = initialpixely, time = shake_interval) +/// Returns rustg-parsed metadata for an icon, universal icon, or DMI file, using cached values where possible +/// Returns null if passed object is not a filepath or icon with a valid DMI file +/proc/icon_metadata(file) + var/static/list/icon_metadata_cache = list() + if(istype(file, /datum/universal_icon)) + var/datum/universal_icon/u_icon = file + file = u_icon.icon_file + var/file_string = "[file]" + if(!istext(file) && !(isfile(file) && length(file_string))) + return null + var/list/cached_metadata = icon_metadata_cache[file_string] + if(islist(cached_metadata)) + return cached_metadata + var/list/metadata_result = rustg_dmi_read_metadata(file_string) + if(!islist(metadata_result) || !length(metadata_result)) + CRASH("Error while reading DMI metadata for path '[file_string]': [metadata_result]") + else + icon_metadata_cache[file_string] = metadata_result + return metadata_result + /// Checks whether a given icon state exists in a given icon file. If `file` and `state` both exist, /// this will return `TRUE` - otherwise, it will return `FALSE`. /// /// If you want a stack trace to be output when the given state/file doesn't exist, use /// `/proc/icon_exists_or_scream()`. /proc/icon_exists(file, state) - var/static/list/icon_states_cache = list() if(isnull(file) || isnull(state)) return FALSE //This is common enough that it shouldn't panic, imo. - if(isnull(icon_states_cache[file])) - icon_states_cache[file] = list() - var/file_string = "[file]" - if(isfile(file) && length(file_string)) // ensure that it's actually a file, and not a runtime icon - for(var/istate in json_decode(rustg_dmi_icon_states(file_string))) - icon_states_cache[file][istate] = TRUE - else // Otherwise, we have to use the slower BYOND proc - for(var/istate in icon_states(file)) - icon_states_cache[file][istate] = TRUE - - return !isnull(icon_states_cache[file][state]) + if(isnull(GLOB.icon_states_cache_lookup[file])) + compile_icon_states_cache(file) + return !isnull(GLOB.icon_states_cache_lookup[file][state]) + +/// Cached, rustg-based alternative to icon_states() +/proc/icon_states_fast(file) + if(isnull(file)) + return null + if(isnull(GLOB.icon_states_cache[file])) + compile_icon_states_cache(file) + return GLOB.icon_states_cache[file] + +/proc/compile_icon_states_cache(file) + GLOB.icon_states_cache[file] = list() + GLOB.icon_states_cache_lookup[file] = list() + // Try to use rustg first + var/list/metadata = icon_metadata(file) + if(islist(metadata) && islist(metadata["states"])) + for(var/list/state_data as anything in metadata["states"]) + GLOB.icon_states_cache[file] += state_data["name"] + GLOB.icon_states_cache_lookup[file][state_data["name"]] = TRUE + else // Otherwise, we have to use the slower BYOND proc + for(var/istate in icon_states(file)) + GLOB.icon_states_cache[file] += istate + GLOB.icon_states_cache_lookup[file][istate] = TRUE /// Functions the same as `/proc/icon_exists()`, but with the addition of a stack trace if the /// specified file or state doesn't exist. @@ -1238,6 +1271,31 @@ GLOBAL_LIST_EMPTY(transformation_animation_objects) /// Returns a list containing the width and height of an icon file /proc/get_icon_dimensions(icon_path) + if(istype(icon_path, /datum/universal_icon)) + var/datum/universal_icon/u_icon = icon_path + icon_path = u_icon.icon_file + // Icons can be a real file(), a rsc backed file(), a dynamic rsc (dyn.rsc) reference (known as a cache reference in byond docs), or an /icon which is pointing to one of those. + // Runtime generated dynamic icons are an unbounded concept cache identity wise, the same icon can exist millions of ways and holding them in a list as a key can lead to unbounded memory usage if called often by consumers. + // Check distinctly that this is something that has this unspecified concept, and thus that we should not cache. + if (!istext(icon_path) && (!isfile(icon_path) || !length("[icon_path]"))) + var/icon/my_icon = icon(icon_path) + return list("width" = my_icon.Width(), "height" = my_icon.Height()) + if (isnull(GLOB.icon_dimensions[icon_path])) + // Used cached icon metadata + var/list/metadata = icon_metadata(icon_path) + var/list/result = null + if(islist(metadata) && isnum(metadata["width"]) && isnum(metadata["height"])) + result = list("width" = metadata["width"], "height" = metadata["height"]) + // Otherwise, we have to use the slower BYOND proc + else + var/icon/my_icon = icon(icon_path) + result = list("width" = my_icon.Width(), "height" = my_icon.Height()) + GLOB.icon_dimensions[icon_path] = result + + return GLOB.icon_dimensions[icon_path] + +/// Returns a list containing the width and height of an icon file, without using rustg for pure function calls +/proc/get_icon_dimensions_pure(icon_path) // Icons can be a real file(), a rsc backed file(), a dynamic rsc (dyn.rsc) reference (known as a cache reference in byond docs), or an /icon which is pointing to one of those. // Runtime generated dynamic icons are an unbounded concept cache identity wise, the same icon can exist millions of ways and holding them in a list as a key can lead to unbounded memory usage if called often by consumers. // Check distinctly that this is something that has this unspecified concept, and thus that we should not cache. diff --git a/code/__HELPERS/lighting.dm b/code/__HELPERS/lighting.dm index 0cc3f8ef5ea6..9cf4839a1ff9 100644 --- a/code/__HELPERS/lighting.dm +++ b/code/__HELPERS/lighting.dm @@ -1,17 +1,30 @@ +#define TOPDOWN_TO_EMISSIVE_LAYER(layer) LERP(FLOOR_EMISSIVE_START_LAYER, FLOOR_EMISSIVE_END_LAYER, (layer - (TOPDOWN_LAYER + 1)) / TOPDOWN_LAYER_COUNT) + /// Produces a mutable appearance glued to the [EMISSIVE_PLANE] dyed to be the [EMISSIVE_COLOR]. -/proc/emissive_appearance(icon, icon_state = "", atom/offset_spokesman, layer = FLOAT_LAYER, alpha = 255, appearance_flags = NONE, offset_const, apply_bloom = TRUE) +/proc/emissive_appearance(icon, icon_state = "", atom/offset_spokesman, layer, alpha = 255, appearance_flags = NONE, offset_const, effect_type = EMISSIVE_BLOOM) + if (isnull(layer)) + if(IS_TOPDOWN_PLANE(offset_spokesman.plane)) + layer = TOPDOWN_TO_EMISSIVE_LAYER(offset_spokesman.layer) + else + layer = FLOAT_LAYER var/mutable_appearance/appearance = mutable_appearance(icon, icon_state, layer, offset_spokesman, EMISSIVE_PLANE, 255, appearance_flags | EMISSIVE_APPEARANCE_FLAGS, offset_const) if(alpha == 255) - if (apply_bloom) - appearance.color = GLOB.emissive_color - else - appearance.color = GLOB.emissive_color_no_bloom + switch(effect_type) + if(EMISSIVE_NO_BLOOM) + appearance.color = GLOB.emissive_color_no_bloom + if (EMISSIVE_BLOOM) + appearance.color = GLOB.emissive_color + if (EMISSIVE_SPECULAR) + appearance.color = GLOB.specular_color else var/alpha_ratio = alpha/255 - if (apply_bloom) - appearance.color = _EMISSIVE_COLOR(alpha_ratio) - else - appearance.color = _EMISSIVE_COLOR_NO_BLOOM(alpha_ratio) + switch(effect_type) + if(EMISSIVE_NO_BLOOM) + appearance.color = _EMISSIVE_COLOR_NO_BLOOM(alpha_ratio) + if (EMISSIVE_BLOOM) + appearance.color = _EMISSIVE_COLOR(alpha_ratio) + if (EMISSIVE_SPECULAR) + appearance.color = _SPECULAR_COLOR(alpha_ratio) //Test to make sure emissives with broken or missing icon states are created if(PERFORM_ALL_TESTS(focus_only/invalid_emissives)) @@ -27,6 +40,10 @@ blocker.icon = make_blocker.icon blocker.icon_state = make_blocker.icon_state // blocker.layer = FLOAT_LAYER // Implied, FLOAT_LAYER is default for appearances + // If we keep this on a FLOAT_LAYER on a topdown object it'll render ontop of everything + // So we need to force it to render at a saner layer + if(IS_TOPDOWN_PLANE(make_blocker.plane)) + blocker.layer = TOPDOWN_TO_EMISSIVE_LAYER(make_blocker.layer) blocker.appearance_flags |= make_blocker.appearance_flags | EMISSIVE_APPEARANCE_FLAGS blocker.dir = make_blocker.dir if(make_blocker.alpha == 255) @@ -41,7 +58,12 @@ return blocker /// Produces a mutable appearance glued to the [EMISSIVE_PLANE] dyed to be the [EM_BLOCK_COLOR]. -/proc/emissive_blocker(icon, icon_state = "", atom/offset_spokesman, layer = FLOAT_LAYER, alpha = 255, appearance_flags = NONE, offset_const) +/proc/emissive_blocker(icon, icon_state = "", atom/offset_spokesman, layer, alpha = 255, appearance_flags = NONE, offset_const) + if (isnull(layer)) + if(IS_TOPDOWN_PLANE(offset_spokesman.plane)) + layer = TOPDOWN_TO_EMISSIVE_LAYER(offset_spokesman.layer) + else + layer = FLOAT_LAYER var/mutable_appearance/appearance = mutable_appearance(icon, icon_state, layer, offset_spokesman, EMISSIVE_PLANE, alpha, appearance_flags | EMISSIVE_APPEARANCE_FLAGS, offset_const) if(alpha == 255) appearance.color = GLOB.em_block_color @@ -77,3 +99,5 @@ var/atom/movable/vis_cast = make_blocker vis_cast.vis_contents += hand_back return hand_back + +#undef TOPDOWN_TO_EMISSIVE_LAYER diff --git a/code/__HELPERS/logging/talk.dm b/code/__HELPERS/logging/talk.dm index 6cfae068cb62..cae932806f19 100644 --- a/code/__HELPERS/logging/talk.dm +++ b/code/__HELPERS/logging/talk.dm @@ -1,3 +1,28 @@ +/** + * Helper for logging chat messages that may or may not have a custom say verb, + * or be a pure radio emote outright. + * + * This proc reads the `message_mods` to determine + * in what ways the given message should be logged, + * and forwards it to other logging procs as such. + * Arguments: + * * message - The message being logged + * * message_mods - A list of message modifiers, i.e. whispering/singing. + * * tag - tag that indicates the type of text(announcement, telepathy, etc) + * * log_globally - boolean checking whether or not we write this log to the log file + * * forced_by - source that forced the dialogue if any + */ +/atom/proc/log_sayverb_talk(message, list/message_mods = list(), tag = null, log_globally = TRUE, forced_by = null) + // If it's just the custom say verb, log it to emotes. + if(message_mods[MODE_CUSTOM_SAY_ERASE_INPUT]) + log_talk(message_mods[MODE_CUSTOM_SAY_EMOTE], LOG_RADIO_EMOTE, tag, log_globally, forced_by) + return + + if(message_mods[WHISPER_MODE]) + log_talk(message, LOG_WHISPER, tag, log_globally, forced_by, message_mods[MODE_CUSTOM_SAY_EMOTE]) + else + log_talk(message, LOG_SAY, tag, log_globally, forced_by, message_mods[MODE_CUSTOM_SAY_EMOTE]) + /** * Helper for logging chat messages or other logs with arbitrary inputs (e.g. announcements) * diff --git a/code/__HELPERS/names.dm b/code/__HELPERS/names.dm index 227d2abff453..20d22015f36b 100644 --- a/code/__HELPERS/names.dm +++ b/code/__HELPERS/names.dm @@ -395,3 +395,11 @@ GLOBAL_DATUM(syndicate_code_response_regex, /regex) if(breaks.Find(given_name)) return FALSE return TRUE + +/// Build a list of strings containing the numbers 1-99 as both arabic and roman numerals +/proc/generate_number_strings() + var/list/L[198] + for(var/i in 1 to 99) + L += "[i]" + L += "\Roman[i]" + return L diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 62273fbb7c2f..59e0b6bd5a60 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -158,8 +158,7 @@ GLOBAL_LIST_INIT(achievements_unlocked, list()) var/json_file = file("[GLOB.log_directory]/newscaster.json") var/list/file_data = list() var/pos = 1 - for(var/V in GLOB.news_network.network_channels) - var/datum/feed_channel/channel = V + for(var/datum/feed_channel/channel as anything in GLOB.news_network.network_channels) if(!istype(channel)) stack_trace("Non-channel in newscaster channel list") continue @@ -666,7 +665,7 @@ GLOBAL_LIST_INIT(achievements_unlocked, list()) button_icon_state = "round_end" show_to_observers = FALSE -/datum/action/report/Trigger(trigger_flags) +/datum/action/report/Trigger(mob/clicker, trigger_flags) if(owner && GLOB.common_report && SSticker.current_state == GAME_STATE_FINISHED) SSticker.show_roundend_report(owner.client) diff --git a/code/__HELPERS/time.dm b/code/__HELPERS/time.dm index 49de184a9158..59e95ad8e85f 100644 --- a/code/__HELPERS/time.dm +++ b/code/__HELPERS/time.dm @@ -8,22 +8,22 @@ return time2text(wtime, format, NO_TIMEZONE) ///returns the current IC station time in a world.time format -/proc/station_time(display_only = FALSE, wtime=world.time) - return ((((wtime - SSticker.round_start_time) * SSticker.station_time_rate_multiplier) + SSticker.gametime_offset) % 864000) - (display_only? GLOB.timezoneOffset : 0) +/proc/station_time(wtime = world.time) + return (((wtime - SSticker.round_start_time) * SSticker.station_time_rate_multiplier) + SSticker.gametime_offset) % (24 HOURS) ///returns the current IC station time in a human readable format /proc/station_time_timestamp(format = "hh:mm:ss", wtime) - return time2text(station_time(TRUE, wtime), format, NO_TIMEZONE) + return time2text(station_time(wtime), format, NO_TIMEZONE) /proc/station_time_debug(force_set) if(isnum(force_set)) SSticker.gametime_offset = force_set return - SSticker.gametime_offset = rand(0, 864000) //hours in day * minutes in hour * seconds in minute * deciseconds in second + SSticker.gametime_offset = rand(0, 24 HOURS) //hours in day * minutes in hour * seconds in minute * deciseconds in second if(prob(50)) - SSticker.gametime_offset = FLOOR(SSticker.gametime_offset, 3600) + SSticker.gametime_offset = FLOOR(SSticker.gametime_offset, 1 HOURS) else - SSticker.gametime_offset = CEILING(SSticker.gametime_offset, 3600) + SSticker.gametime_offset = CEILING(SSticker.gametime_offset, 1 HOURS) ///returns timestamp in a sql and a not-quite-compliant ISO 8601 friendly format. Do not use for SQL, use NOW() instead /proc/ISOtime(timevar) @@ -129,7 +129,7 @@ GLOBAL_VAR_INIT(rollovercheck_last_timeofday, 0) * the timezone is the time value offset from the local time. It's to be applied outside time2text() to get the AM/PM right. */ /proc/time_to_twelve_hour(time, format = "hh:mm:ss", timezone = TIMEZONE_UTC) - time = MODULUS(time + (timezone - GLOB.timezoneOffset) HOURS, 24 HOURS) + time = MODULUS(time + (timezone * (1 HOURS)), 24 HOURS) var/am_pm = "AM" if(time > 12 HOURS) am_pm = "PM" diff --git a/code/__HELPERS/turfs.dm b/code/__HELPERS/turfs.dm index 1aa7fcd65d07..902bfbf585ef 100644 --- a/code/__HELPERS/turfs.dm +++ b/code/__HELPERS/turfs.dm @@ -236,7 +236,7 @@ Turf and target are separate in case you want to teleport some distance from a t var/pixel_y_offset = checked_atom.pixel_y + checked_atom.pixel_z + atom_matrix.get_y_shift() //Irregular objects - var/list/icon_dimensions = get_icon_dimensions(checked_atom.icon) + var/list/icon_dimensions = get_icon_dimensions_pure(checked_atom.icon) var/checked_atom_icon_height = icon_dimensions["height"] var/checked_atom_icon_width = icon_dimensions["width"] if(checked_atom_icon_height != ICON_SIZE_Y || checked_atom_icon_width != ICON_SIZE_X) diff --git a/code/_globalvars/arcade.dm b/code/_globalvars/arcade.dm index 281b9b40208e..4510867575a7 100644 --- a/code/_globalvars/arcade.dm +++ b/code/_globalvars/arcade.dm @@ -44,7 +44,7 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( /obj/item/restraints/handcuffs/fake = 2, /obj/item/grenade/chem_grenade/glitter/pink = 1, /obj/item/grenade/chem_grenade/glitter/blue = 1, - /obj/item/grenade/chem_grenade/glitter/white = 1, + /obj/item/grenade/chem_grenade/glitter = 1, /obj/item/toy/eightball = 2, /obj/item/toy/windup_toolbox = 2, /obj/item/toy/clockwork_watch = 2, diff --git a/code/_globalvars/lists/clothing.dm b/code/_globalvars/lists/clothing.dm new file mode 100644 index 000000000000..674a32664a7e --- /dev/null +++ b/code/_globalvars/lists/clothing.dm @@ -0,0 +1,11 @@ +GLOBAL_LIST_INIT(backpacklist, list( + DBACKPACK, + DDUFFELBAG, + DSATCHEL, + DMESSENGER, + GBACKPACK, + GDUFFELBAG, + GSATCHEL, + GMESSENGER, + LSATCHEL, +)) diff --git a/code/_globalvars/lists/color.dm b/code/_globalvars/lists/color.dm index 1a195798f465..22bb20a4cfc6 100644 --- a/code/_globalvars/lists/color.dm +++ b/code/_globalvars/lists/color.dm @@ -25,3 +25,35 @@ GLOBAL_LIST_INIT(carp_colors, list( COLOR_CARP_PALE_GREEN = 7, COLOR_CARP_SILVER = 1, // The rare silver carp )) + +/// List of possible ethereal colours +GLOBAL_LIST_INIT(color_list_ethereal, list( + "Blue" = "#3399ff", + "Bright Yellow" = "#ffff99", + "Burnt Orange" = "#cc4400", + "Cyan Blue" = "#00ffff", + "Dark Blue" = "#6666ff", + "Dark Fuschia" = "#cc0066", + "Dark Green" = "#37835b", + "Dark Red" = "#9c3030", + "Dull Yellow" = "#fbdf56", + "Faint Blue" = "#b3d9ff", + "Faint Green" = "#ddff99", + "Faint Red" = "#ffb3b3", + "Green" = "#97ee63", + "Orange" = "#ffa64d", + "Pink" = "#ff99cc", + "Purple" = "#ee82ee", + "Red" = "#ff4d4d", + "Seafoam Green" = "#00fa9a", + "White" = "#f2f2f2", +)) + +/// List of possible lustrous ethereal colours +GLOBAL_LIST_INIT(color_list_lustrous, list( + "Cyan Blue" = "#00ffff", + "Sky Blue" = "#37c0ff", + "Blue" = "#3374ff", + "Dark Blue" = "#5b5beb", + "Bright Red" = "#fa2d2d", +)) diff --git a/code/_globalvars/lists/communication.dm b/code/_globalvars/lists/communication.dm new file mode 100644 index 000000000000..c13cf6c03b34 --- /dev/null +++ b/code/_globalvars/lists/communication.dm @@ -0,0 +1,13 @@ +GLOBAL_LIST_INIT(admiral_messages, list( + "Error: No comment given.", + "null", + "Do you know how expensive these stations are?", + "I was sleeping, thanks a lot.", + "It's a good day to die!", + "No.", + "Stand and fight you cowards!", + "Stop being paranoid.", + "Stop wasting my time.", + "Whatever's broken just build a new one.", + "You knew the risks coming in.", +)) diff --git a/code/_globalvars/lists/department.dm b/code/_globalvars/lists/department.dm new file mode 100644 index 000000000000..2ec4a15d4183 --- /dev/null +++ b/code/_globalvars/lists/department.dm @@ -0,0 +1,7 @@ +GLOBAL_LIST_INIT(security_depts_prefs, sort_list(list( + SEC_DEPT_ENGINEERING, + SEC_DEPT_MEDICAL, + SEC_DEPT_NONE, + SEC_DEPT_SCIENCE, + SEC_DEPT_SUPPLY, +))) diff --git a/code/_globalvars/lists/disposals.dm b/code/_globalvars/lists/disposals.dm new file mode 100644 index 000000000000..f543343f3ed0 --- /dev/null +++ b/code/_globalvars/lists/disposals.dm @@ -0,0 +1,52 @@ +// Reference list for disposal sort junctions. Set the sortType variable on disposal sort junctions to +// the index of the sort department that you want. For example, sortType set to 2 will reroute all packages +// tagged for the Cargo Bay. + +/* List of sortType codes for mapping reference +0 Waste +1 Disposals - All unwrapped items and untagged parcels get picked up by a junction with this sortType. Usually leads to the recycler. +2 Cargo Bay +3 QM Office +4 Engineering +5 CE Office +6 Atmospherics +7 Security +8 HoS Office +9 Medbay +10 CMO Office +11 Chemistry +12 Research +13 RD Office +14 Robotics +15 HoP Office +16 Library +17 Chapel +18 Theatre +19 Bar +20 Kitchen +21 Hydroponics +22 Janitor +23 Genetics +24 Experimentor Lab +25 Ordnance +26 Dormitories +27 Virology +28 Xenobiology +29 Law Office +30 Detective's Office +*/ + +//The whole system for the sorttype var is determined based on the order of this list, +//disposals must always be 1, since anything that's untagged will automatically go to disposals, or sorttype = 1 --Superxpdude + +//If you don't want to fuck up disposals, add to this list, and don't change the order. +//If you insist on changing the order, you'll have to change every sort junction to reflect the new order. --Pete + +GLOBAL_LIST_INIT(TAGGERLOCATIONS, list("Disposals", + "Cargo Bay", "QM Office", "Engineering", "CE Office", + "Atmospherics", "Security", "HoS Office", "Medbay", + "CMO Office", "Chemistry", "Research", "RD Office", + "Robotics", "HoP Office", "Library", "Chapel", "Theatre", + "Bar", "Kitchen", "Hydroponics", "Janitor Closet","Genetics", + "Experimentor Lab", "Ordnance", "Dormitories", "Virology", + "Xenobiology", "Law Office","Detective's Office")) diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm deleted file mode 100644 index 4acd977438dc..000000000000 --- a/code/_globalvars/lists/flavor_misc.dm +++ /dev/null @@ -1,280 +0,0 @@ -GLOBAL_LIST_INIT(color_list_ethereal, list( - "Blue" = "#3399ff", - "Bright Yellow" = "#ffff99", - "Burnt Orange" = "#cc4400", - "Cyan Blue" = "#00ffff", - "Dark Blue" = "#6666ff", - "Dark Fuschia" = "#cc0066", - "Dark Green" = "#37835b", - "Dark Red" = "#9c3030", - "Dull Yellow" = "#fbdf56", - "Faint Blue" = "#b3d9ff", - "Faint Green" = "#ddff99", - "Faint Red" = "#ffb3b3", - "Green" = "#97ee63", - "Orange" = "#ffa64d", - "Pink" = "#ff99cc", - "Purple" = "#ee82ee", - "Red" = "#ff4d4d", - "Seafoam Green" = "#00fa9a", - "White" = "#f2f2f2", -)) - -GLOBAL_LIST_INIT(color_list_lustrous, list( - "Cyan Blue" = "#00ffff", - "Sky Blue" = "#37c0ff", - "Blue" = "#3374ff", - "Dark Blue" = "#5b5beb", - "Bright Red" = "#fa2d2d", -)) - -GLOBAL_LIST_INIT(ghost_forms_with_directions_list, list( - "catghost", - "ghost_black", - "ghost_blazeit", - "ghost_blue", - "ghost_camo", - "ghost_cyan", - "ghost_dblue", - "ghost_dcyan", - "ghost_dgreen", - "ghost_dpink", - "ghost_dred", - "ghost_dyellow", - "ghost_fire", - "ghost_funkypurp", - "ghost_green", - "ghost_grey", - "ghost_mellow", - "ghost_pink", - "ghost_pinksherbert", - "ghost_purpleswirl", - "ghost_rainbow", - "ghost_red", - "ghost_yellow", - "ghost", - "ghostian", - "ghostian2", - "ghostking", - "skeleghost", -)) -//stores the ghost forms that support directional sprites - -GLOBAL_LIST_INIT(ghost_forms_with_accessories_list, list( - "ghost_black", - "ghost_blazeit", - "ghost_blue", - "ghost_camo", - "ghost_cyan", - "ghost_dblue", - "ghost_dcyan", - "ghost_dgreen", - "ghost_dpink", - "ghost_dred", - "ghost_dyellow", - "ghost_fire", - "ghost_funkypurp", - "ghost_green", - "ghost_grey", - "ghost_mellow", - "ghost_pink", - "ghost_pinksherbert", - "ghost_purpleswirl", - "ghost_rainbow", - "ghost_red", - "ghost_yellow", - "ghost", - "skeleghost", -)) -//stores the ghost forms that support hair and other such things - -GLOBAL_LIST_INIT(security_depts_prefs, sort_list(list( - SEC_DEPT_ENGINEERING, - SEC_DEPT_MEDICAL, - SEC_DEPT_NONE, - SEC_DEPT_SCIENCE, - SEC_DEPT_SUPPLY, -))) - - //Backpacks -#define DBACKPACK "Department Backpack" -#define DDUFFELBAG "Department Duffel Bag" -#define DSATCHEL "Department Satchel" -#define DMESSENGER "Department Messenger Bag" -#define GBACKPACK "Grey Backpack" -#define GDUFFELBAG "Grey Duffel Bag" -#define GSATCHEL "Grey Satchel" -#define GMESSENGER "Grey Messenger Bag" -#define LSATCHEL "Leather Satchel" -GLOBAL_LIST_INIT(backpacklist, list( - DBACKPACK, - DDUFFELBAG, - DSATCHEL, - DMESSENGER, - GBACKPACK, - GDUFFELBAG, - GSATCHEL, - GMESSENGER, - LSATCHEL, -)) - - //Suit/Skirt -#define PREF_SUIT "Jumpsuit" -#define PREF_SKIRT "Jumpskirt" - -//Uplink spawn loc -#define UPLINK_PDA "PDA" -#define UPLINK_RADIO "Radio" -#define UPLINK_PEN "Pen" //like a real spy! -#define UPLINK_IMPLANT "Implant" - - //Female Uniforms -GLOBAL_LIST_EMPTY(female_clothing_icons) - -GLOBAL_LIST_INIT(scarySounds, list( - 'sound/effects/footstep/clownstep1.ogg', - 'sound/effects/footstep/clownstep2.ogg', - 'sound/effects/glass/glassbr1.ogg', - 'sound/effects/glass/glassbr2.ogg', - 'sound/effects/glass/glassbr3.ogg', - 'sound/items/tools/welder.ogg', - 'sound/items/tools/welder2.ogg', - 'sound/machines/airlock/airlock.ogg', - 'sound/mobs/non-humanoids/hiss/hiss1.ogg', - 'sound/mobs/non-humanoids/hiss/hiss2.ogg', - 'sound/mobs/non-humanoids/hiss/hiss3.ogg', - 'sound/mobs/non-humanoids/hiss/hiss4.ogg', - 'sound/mobs/non-humanoids/hiss/hiss5.ogg', - 'sound/mobs/non-humanoids/hiss/hiss6.ogg', - 'sound/items/weapons/armbomb.ogg', - 'sound/items/weapons/taser.ogg', - 'sound/items/weapons/thudswoosh.ogg', - 'sound/items/weapons/shove.ogg', -)) - - -// Reference list for disposal sort junctions. Set the sortType variable on disposal sort junctions to -// the index of the sort department that you want. For example, sortType set to 2 will reroute all packages -// tagged for the Cargo Bay. - -/* List of sortType codes for mapping reference -0 Waste -1 Disposals - All unwrapped items and untagged parcels get picked up by a junction with this sortType. Usually leads to the recycler. -2 Cargo Bay -3 QM Office -4 Engineering -5 CE Office -6 Atmospherics -7 Security -8 HoS Office -9 Medbay -10 CMO Office -11 Chemistry -12 Research -13 RD Office -14 Robotics -15 HoP Office -16 Library -17 Chapel -18 Theatre -19 Bar -20 Kitchen -21 Hydroponics -22 Janitor -23 Genetics -24 Experimentor Lab -25 Ordnance -26 Dormitories -27 Virology -28 Xenobiology -29 Law Office -30 Detective's Office -*/ - -//The whole system for the sorttype var is determined based on the order of this list, -//disposals must always be 1, since anything that's untagged will automatically go to disposals, or sorttype = 1 --Superxpdude - -//If you don't want to fuck up disposals, add to this list, and don't change the order. -//If you insist on changing the order, you'll have to change every sort junction to reflect the new order. --Pete - -GLOBAL_LIST_INIT(TAGGERLOCATIONS, list("Disposals", - "Cargo Bay", "QM Office", "Engineering", "CE Office", - "Atmospherics", "Security", "HoS Office", "Medbay", - "CMO Office", "Chemistry", "Research", "RD Office", - "Robotics", "HoP Office", "Library", "Chapel", "Theatre", - "Bar", "Kitchen", "Hydroponics", "Janitor Closet","Genetics", - "Experimentor Lab", "Ordnance", "Dormitories", "Virology", - "Xenobiology", "Law Office","Detective's Office")) - -GLOBAL_LIST_INIT(station_prefixes, world.file2list("strings/station_prefixes.txt")) - -GLOBAL_LIST_INIT(station_names, world.file2list("strings/station_names.txt")) - -GLOBAL_LIST_INIT(station_suffixes, world.file2list("strings/station_suffixes.txt")) - -GLOBAL_LIST_INIT(greek_letters, world.file2list("strings/greek_letters.txt")) - -GLOBAL_LIST_INIT(phonetic_alphabet, world.file2list("strings/phonetic_alphabet.txt")) - -GLOBAL_LIST_INIT(numbers_as_words, world.file2list("strings/numbers_as_words.txt")) - -GLOBAL_LIST_INIT(wisdoms, world.file2list("strings/wisdoms.txt")) - -/proc/generate_number_strings() - var/list/L[198] - for(var/i in 1 to 99) - L += "[i]" - L += "\Roman[i]" - return L - -GLOBAL_LIST_INIT(station_numerals, greek_letters + phonetic_alphabet + numbers_as_words + generate_number_strings()) - -GLOBAL_LIST_INIT(admiral_messages, list( - "Error: No comment given.", - "null", - "Do you know how expensive these stations are?", - "I was sleeping, thanks a lot.", - "It's a good day to die!", - "No.", - "Stand and fight you cowards!", - "Stop being paranoid.", - "Stop wasting my time.", - "Whatever's broken just build a new one.", - "You knew the risks coming in.", -)) - -GLOBAL_LIST_INIT(junkmail_messages, world.file2list("strings/junkmail.txt")) - -// All valid inputs to status display post_status -GLOBAL_LIST_INIT(status_display_approved_pictures, list( - "blank", - "shuttle", - "default", - "biohazard", - "lockdown", - "greenalert", - "bluealert", - "redalert", - "deltaalert", - "radiation", - "currentalert", //For automatic set of status display on current level -)) - -// Members of status_display_approved_pictures that are actually states and not alert values -GLOBAL_LIST_INIT(status_display_state_pictures, list( - "blank", - "shuttle", -)) - -GLOBAL_LIST_INIT(fishing_tips, world.file2list("strings/fishing_tips.txt")) - -/// 1000 element long list containing the 1000 most common words in the English language. -/// Indexed by word, value is the rank of the word in the list. So accessing it is fasta. -GLOBAL_LIST_INIT(most_common_words, init_common_words()) - -/proc/init_common_words() - . = list() - var/i = 1 - for(var/word in world.file2list("strings/1000_most_common.txt")) - .[word] = i - i += 1 diff --git a/code/_globalvars/lists/ghost.dm b/code/_globalvars/lists/ghost.dm new file mode 100644 index 000000000000..42db2c830ee5 --- /dev/null +++ b/code/_globalvars/lists/ghost.dm @@ -0,0 +1,59 @@ +/// Stores the ghost forms that support directional sprites +GLOBAL_LIST_INIT(ghost_forms_with_directions_list, list( + "catghost", + "ghost_black", + "ghost_blazeit", + "ghost_blue", + "ghost_camo", + "ghost_cyan", + "ghost_dblue", + "ghost_dcyan", + "ghost_dgreen", + "ghost_dpink", + "ghost_dred", + "ghost_dyellow", + "ghost_fire", + "ghost_funkypurp", + "ghost_green", + "ghost_grey", + "ghost_mellow", + "ghost_pink", + "ghost_pinksherbert", + "ghost_purpleswirl", + "ghost_rainbow", + "ghost_red", + "ghost_yellow", + "ghost", + "ghostian", + "ghostian2", + "ghostking", + "skeleghost", +)) + +/// Stores the ghost forms that support hair and other such things +GLOBAL_LIST_INIT(ghost_forms_with_accessories_list, list( + "ghost_black", + "ghost_blazeit", + "ghost_blue", + "ghost_camo", + "ghost_cyan", + "ghost_dblue", + "ghost_dcyan", + "ghost_dgreen", + "ghost_dpink", + "ghost_dred", + "ghost_dyellow", + "ghost_fire", + "ghost_funkypurp", + "ghost_green", + "ghost_grey", + "ghost_mellow", + "ghost_pink", + "ghost_pinksherbert", + "ghost_purpleswirl", + "ghost_rainbow", + "ghost_red", + "ghost_yellow", + "ghost", + "skeleghost", +)) diff --git a/code/_globalvars/lists/icons.dm b/code/_globalvars/lists/icons.dm index ff60e6bc8d92..fd51a76c5f4d 100644 --- a/code/_globalvars/lists/icons.dm +++ b/code/_globalvars/lists/icons.dm @@ -1,2 +1,8 @@ /// Cache of the width and height of icon files, to avoid repeating the same expensive operation GLOBAL_LIST_EMPTY(icon_dimensions) +/// Cache of the states of icon files +GLOBAL_LIST_EMPTY(icon_states_cache) +/// Cache of the states of icon files, stored associatively with TRUE for lookup +GLOBAL_LIST_EMPTY(icon_states_cache_lookup) +/// Female Uniforms +GLOBAL_LIST_EMPTY(female_clothing_icons) diff --git a/code/_globalvars/lists/names.dm b/code/_globalvars/lists/names.dm index f9f70a2c7069..a564d55c4203 100644 --- a/code/_globalvars/lists/names.dm +++ b/code/_globalvars/lists/names.dm @@ -1,47 +1,44 @@ GLOBAL_LIST_INIT(ai_names, world.file2list("strings/names/ai.txt")) -GLOBAL_LIST_INIT(wizard_first, world.file2list("strings/names/wizardfirst.txt")) -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(cargorilla_names, world.file2list("strings/names/cargorilla.txt")) +GLOBAL_LIST_INIT(carp_names, world.file2list("strings/names/carp.txt")) +GLOBAL_LIST_INIT(clown_names, world.file2list("strings/names/clown.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(cyberauth_names, world.file2list("strings/names/cyberauth.txt")) +GLOBAL_LIST_INIT(ethereal_names, world.file2list("strings/names/ethereal.txt")) GLOBAL_LIST_INIT(first_names_female, world.file2list("strings/names/first_female.txt")) +GLOBAL_LIST_INIT(first_names_male, world.file2list("strings/names/first_male.txt")) +GLOBAL_LIST_INIT(first_names, world.file2list("strings/names/first.txt")) +GLOBAL_LIST_INIT(golem_names, world.file2list("strings/names/golem.txt")) +GLOBAL_LIST_INIT(guardian_fantasy_surnames, world.file2list("strings/names/guardian_tarot.txt")) +GLOBAL_LIST_INIT(guardian_first_names, world.file2list("strings/names/guardian_descriptions.txt")) +GLOBAL_LIST_INIT(guardian_tech_surnames, world.file2list("strings/names/guardian_gamepieces.txt")) +GLOBAL_LIST_INIT(hacker_aliases, world.file2list("strings/names/hackers.txt")) +GLOBAL_LIST_INIT(hive_names, world.file2list("strings/names/hive_names.txt")) GLOBAL_LIST_INIT(last_names, world.file2list("strings/names/last.txt")) -GLOBAL_LIST_INIT(clown_names, world.file2list("strings/names/clown.txt")) -GLOBAL_LIST_INIT(mime_names, world.file2list("strings/names/mime.txt")) -GLOBAL_LIST_INIT(religion_names, world.file2list("strings/names/religion.txt")) -GLOBAL_LIST_INIT(carp_names, world.file2list("strings/names/carp.txt")) -GLOBAL_LIST_INIT(lizard_names_male, world.file2list("strings/names/lizard_male.txt")) GLOBAL_LIST_INIT(lizard_names_female, world.file2list("strings/names/lizard_female.txt")) -GLOBAL_LIST_INIT(golem_names, world.file2list("strings/names/golem.txt")) +GLOBAL_LIST_INIT(lizard_names_male, world.file2list("strings/names/lizard_male.txt")) +GLOBAL_LIST_INIT(martial_prefix, world.file2list("strings/names/martial_prefix.txt")) +GLOBAL_LIST_INIT(megacarp_first_names, world.file2list("strings/names/megacarp1.txt")) +GLOBAL_LIST_INIT(megacarp_last_names, world.file2list("strings/names/megacarp2.txt")) +GLOBAL_LIST_INIT(mime_names, world.file2list("strings/names/mime.txt")) GLOBAL_LIST_INIT(moth_first, world.file2list("strings/names/moth_first.txt")) GLOBAL_LIST_INIT(moth_last, world.file2list("strings/names/moth_last.txt")) +GLOBAL_LIST_INIT(nightmare_names, world.file2list("strings/names/nightmare.txt")) +GLOBAL_LIST_INIT(ninja_names, world.file2list("strings/names/ninjaname.txt")) +GLOBAL_LIST_INIT(ninja_titles, world.file2list("strings/names/ninjatitle.txt")) +GLOBAL_LIST_INIT(operative_aliases, world.file2list("strings/names/operative_alias.txt")) GLOBAL_LIST_INIT(plasmaman_names, world.file2list("strings/names/plasmaman.txt")) -GLOBAL_LIST_INIT(ethereal_names, world.file2list("strings/names/ethereal.txt")) GLOBAL_LIST_INIT(posibrain_names, world.file2list("strings/names/posibrain.txt")) -GLOBAL_LIST_INIT(nightmare_names, world.file2list("strings/names/nightmare.txt")) -GLOBAL_LIST_INIT(megacarp_first_names, world.file2list("strings/names/megacarp1.txt")) -GLOBAL_LIST_INIT(megacarp_last_names, world.file2list("strings/names/megacarp2.txt")) -GLOBAL_LIST_INIT(cyberauth_names, world.file2list("strings/names/cyberauth.txt")) -GLOBAL_LIST_INIT(hacker_aliases, world.file2list("strings/names/hackers.txt")) +GLOBAL_LIST_INIT(religion_names, world.file2list("strings/names/religion.txt")) +GLOBAL_LIST_INIT(station_names, world.file2list("strings/station_names.txt")) +GLOBAL_LIST_INIT(station_numerals, greek_letters + phonetic_alphabet + numbers_as_words + generate_number_strings()) +GLOBAL_LIST_INIT(station_prefixes, world.file2list("strings/station_prefixes.txt")) +GLOBAL_LIST_INIT(station_suffixes, world.file2list("strings/station_suffixes.txt")) GLOBAL_LIST_INIT(syndicate_monkey_names, world.file2list("strings/names/syndicate_monkey.txt")) -GLOBAL_LIST_INIT(cargorilla_names, world.file2list("strings/names/cargorilla.txt")) -GLOBAL_LIST_INIT(guardian_first_names, world.file2list("strings/names/guardian_descriptions.txt")) -GLOBAL_LIST_INIT(guardian_tech_surnames, world.file2list("strings/names/guardian_gamepieces.txt")) -GLOBAL_LIST_INIT(guardian_fantasy_surnames, world.file2list("strings/names/guardian_tarot.txt")) -GLOBAL_LIST_INIT(operative_aliases, world.file2list("strings/names/operative_alias.txt")) +GLOBAL_LIST_INIT(vampire_house_names, world.file2list("strings/names/vampire_house_names.txt")) GLOBAL_LIST_INIT(voidwalker_names, world.file2list("strings/names/voidwalker.txt")) +GLOBAL_LIST_INIT(wizard_first, world.file2list("strings/names/wizardfirst.txt")) +GLOBAL_LIST_INIT(wizard_second, world.file2list("strings/names/wizardsecond.txt")) -GLOBAL_LIST_INIT(verbs, world.file2list("strings/names/verbs.txt")) -GLOBAL_LIST_INIT(ing_verbs, world.file2list("strings/names/ing_verbs.txt")) -GLOBAL_LIST_INIT(martial_prefix, world.file2list("strings/names/martial_prefix.txt")) -GLOBAL_LIST_INIT(adverbs, world.file2list("strings/names/adverbs.txt")) -GLOBAL_LIST_INIT(adjectives, world.file2list("strings/names/adjectives.txt")) -GLOBAL_LIST_INIT(gross_adjectives, world.file2list("strings/names/gross_adjectives.txt")) -GLOBAL_LIST_INIT(dream_strings, world.file2list("strings/dreamstrings.txt")) -GLOBAL_LIST_INIT(vampire_house_names, world.file2list("strings/names/vampire_house_names.txt")) -GLOBAL_LIST_INIT(greek_alphabet, world.file2list("strings/greek_alphabet.txt")) -GLOBAL_LIST_INIT(hive_names, world.file2list("strings/names/hive_names.txt")) //loaded on startup because of " //would include in rsc if ' was used diff --git a/code/_globalvars/lists/sound.dm b/code/_globalvars/lists/sound.dm new file mode 100644 index 000000000000..a8fc4ab698c7 --- /dev/null +++ b/code/_globalvars/lists/sound.dm @@ -0,0 +1,20 @@ +GLOBAL_LIST_INIT(scarySounds, list( + 'sound/effects/footstep/clownstep1.ogg', + 'sound/effects/footstep/clownstep2.ogg', + 'sound/effects/glass/glassbr1.ogg', + 'sound/effects/glass/glassbr2.ogg', + 'sound/effects/glass/glassbr3.ogg', + 'sound/items/tools/welder.ogg', + 'sound/items/tools/welder2.ogg', + 'sound/machines/airlock/airlock.ogg', + 'sound/mobs/non-humanoids/hiss/hiss1.ogg', + 'sound/mobs/non-humanoids/hiss/hiss2.ogg', + 'sound/mobs/non-humanoids/hiss/hiss3.ogg', + 'sound/mobs/non-humanoids/hiss/hiss4.ogg', + 'sound/mobs/non-humanoids/hiss/hiss5.ogg', + 'sound/mobs/non-humanoids/hiss/hiss6.ogg', + 'sound/items/weapons/armbomb.ogg', + 'sound/items/weapons/taser.ogg', + 'sound/items/weapons/thudswoosh.ogg', + 'sound/items/weapons/shove.ogg', +)) diff --git a/code/_globalvars/lists/status_display.dm b/code/_globalvars/lists/status_display.dm new file mode 100644 index 000000000000..66ec47d9964f --- /dev/null +++ b/code/_globalvars/lists/status_display.dm @@ -0,0 +1,20 @@ +// All valid inputs to status display post_status +GLOBAL_LIST_INIT(status_display_approved_pictures, list( + "blank", + "shuttle", + "default", + "biohazard", + "lockdown", + "greenalert", + "bluealert", + "redalert", + "deltaalert", + "radiation", + "currentalert", //For automatic set of status display on current level +)) + +// Members of status_display_approved_pictures that are actually states and not alert values +GLOBAL_LIST_INIT(status_display_state_pictures, list( + "blank", + "shuttle", +)) diff --git a/code/_globalvars/lists/strings.dm b/code/_globalvars/lists/strings.dm new file mode 100644 index 000000000000..80cc4816c1e4 --- /dev/null +++ b/code/_globalvars/lists/strings.dm @@ -0,0 +1,16 @@ +GLOBAL_LIST_INIT(adjectives, world.file2list("strings/names/adjectives.txt")) +GLOBAL_LIST_INIT(adverbs, world.file2list("strings/names/adverbs.txt")) +GLOBAL_LIST_INIT(dream_strings, world.file2list("strings/dreamstrings.txt")) +GLOBAL_LIST_INIT(fishing_tips, world.file2list("strings/fishing_tips.txt")) +GLOBAL_LIST_INIT(greek_letters, world.file2list("strings/greek_letters.txt")) +GLOBAL_LIST_INIT(gross_adjectives, world.file2list("strings/names/gross_adjectives.txt")) +GLOBAL_LIST_INIT(ing_verbs, world.file2list("strings/names/ing_verbs.txt")) +GLOBAL_LIST_INIT(junkmail_messages, world.file2list("strings/junkmail.txt")) +GLOBAL_LIST_INIT(most_common_words, world.file2list("strings/1000_most_common.txt")) +GLOBAL_LIST_INIT(numbers_as_words, world.file2list("strings/numbers_as_words.txt")) +GLOBAL_LIST_INIT(phonetic_alphabet, world.file2list("strings/phonetic_alphabet.txt")) +GLOBAL_LIST_INIT(verbs, world.file2list("strings/names/verbs.txt")) +GLOBAL_LIST_INIT(wisdoms, world.file2list("strings/wisdoms.txt")) + +//loaded on startup because of " +//would include in rsc if ' was used diff --git a/code/_globalvars/lists/xenobiology.dm b/code/_globalvars/lists/xenobiology.dm index 0e587e891b44..5b61e4e054c5 100644 --- a/code/_globalvars/lists/xenobiology.dm +++ b/code/_globalvars/lists/xenobiology.dm @@ -85,7 +85,29 @@ GLOBAL_LIST_INIT_TYPED(cell_line_tables, /list, list( /datum/micro_organism/cell_line/snake = 1, /datum/micro_organism/cell_line/walking_mushroom = 2, /datum/micro_organism/cell_line/axolotl = 1, - ) + ), + CELL_LINE_ORGAN_HEART = list( + /datum/micro_organism/cell_line/organs/heart = 3, + /datum/micro_organism/cell_line/organs/heart/evolved = 1, + ), + CELL_LINE_ORGAN_HEART_CURSED = list( + /datum/micro_organism/cell_line/organs/heart/corrupt = 1, + /datum/micro_organism/cell_line/organs/heart/sacred = 1, + ), + CELL_LINE_ORGAN_LUNGS = list( + /datum/micro_organism/cell_line/organs/lungs = 3, + /datum/micro_organism/cell_line/organs/lungs/evolved = 1, + ), + CELL_LINE_ORGAN_LIVER = list( + /datum/micro_organism/cell_line/organs/liver = 3, + /datum/micro_organism/cell_line/organs/liver/evolved = 1, + /datum/micro_organism/cell_line/organs/liver/bloody = 1, + /datum/micro_organism/cell_line/organs/liver/distillery = 1, + ), + CELL_LINE_ORGAN_STOMACH = list( + /datum/micro_organism/cell_line/organs/stomach = 3, + /datum/micro_organism/cell_line/organs/stomach/evolved = 1, + ), )) ///Assoc list of cell virus define | assoc list of datum | cell_virus diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 9309e7e4cf95..6a5a131c95cd 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -145,6 +145,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( ), /obj = list( "TRAIT_CONTRABAND" = TRAIT_CONTRABAND, + "TRAIT_DUCT_TAPE_UNREPAIRABLE" = TRAIT_DUCT_TAPE_UNREPAIRABLE, "TRAIT_SPEED_POTIONED" = TRAIT_SPEED_POTIONED, "TRAIT_WALLMOUNTED" = TRAIT_WALLMOUNTED, ), @@ -665,6 +666,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_NO_SIDE_KICK" = TRAIT_NO_SIDE_KICK, "TRAIT_NODROP" = TRAIT_NODROP, "TRAIT_NO_WORN_ICON" = TRAIT_NO_WORN_ICON, + "TRAIT_NULLROD_ITEM" = TRAIT_NULLROD_ITEM, "TRAIT_OMNI_BAIT" = TRAIT_OMNI_BAIT, "TRAIT_PLANT_WILDMUTATE" = TRAIT_PLANT_WILDMUTATE, "TRAIT_POISONOUS_BAIT" = TRAIT_POISONOUS_BAIT, @@ -739,6 +741,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( ), /obj/item/modular_computer = list( "TRAIT_MODPC_HALVED_DOWNLOAD_SPEED" = TRAIT_MODPC_HALVED_DOWNLOAD_SPEED, + "TRAIT_MODPC_TWO_ID_SLOTS" = TRAIT_MODPC_TWO_ID_SLOTS, "TRAIT_PDA_CAN_EXPLODE" = TRAIT_PDA_CAN_EXPLODE, "TRAIT_PDA_MESSAGE_MENU_RIGGED" = TRAIT_PDA_MESSAGE_MENU_RIGGED, ), diff --git a/code/_globalvars/traits/admin_tooling.dm b/code/_globalvars/traits/admin_tooling.dm index 5b878b47e68f..c81ee3cd4d57 100644 --- a/code/_globalvars/traits/admin_tooling.dm +++ b/code/_globalvars/traits/admin_tooling.dm @@ -28,6 +28,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( ), /obj = list( "TRAIT_CONTRABAND" = TRAIT_CONTRABAND, + "TRAIT_DUCT_TAPE_UNREPAIRABLE" = TRAIT_DUCT_TAPE_UNREPAIRABLE, "TRAIT_SPEED_POTIONED" = TRAIT_SPEED_POTIONED, ), /mob = list( diff --git a/code/_onclick/hud/action_button.dm b/code/_onclick/hud/action_button.dm index 69186dead8a5..88508c11e476 100644 --- a/code/_onclick/hud/action_button.dm +++ b/code/_onclick/hud/action_button.dm @@ -56,7 +56,7 @@ var/list/modifiers = params2list(params) if(LAZYACCESS(modifiers, ALT_CLICK)) - linked_action?.begin_creating_bind(usr) + linked_action?.begin_creating_bind(src, usr) return TRUE if(LAZYACCESS(modifiers, SHIFT_CLICK)) var/datum/hud/our_hud = usr.hud_used @@ -68,7 +68,7 @@ var/trigger_flags if(LAZYACCESS(modifiers, RIGHT_CLICK)) trigger_flags |= TRIGGER_SECONDARY_ACTION - linked_action.Trigger(trigger_flags = trigger_flags) + linked_action.Trigger(usr, trigger_flags = trigger_flags) return TRUE // Entered and Exited won't fire while you're dragging something, because you're still "holding" it diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index 1b4a043678a7..ec7d26d4da09 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -824,7 +824,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." name = "Revival" desc = "Someone is trying to revive you. Re-enter your corpse if you want to be revived!" icon_state = "template" - timeout = 300 + timeout = 30 SECONDS clickable_glow = TRUE /atom/movable/screen/alert/revival/Click() diff --git a/code/_onclick/hud/parallax/parallax.dm b/code/_onclick/hud/parallax/parallax.dm index 075556145078..74f16c1a64a1 100644 --- a/code/_onclick/hud/parallax/parallax.dm +++ b/code/_onclick/hud/parallax/parallax.dm @@ -62,13 +62,8 @@ var/turf/screen_location = get_turf(screenmob) if(SSmapping.level_trait(screen_location?.z, ZTRAIT_NOPARALLAX)) - for(var/atom/movable/screen/plane_master/white_space as anything in get_true_plane_masters(PLANE_SPACE)) - white_space.hide_plane(screenmob) return FALSE - for(var/atom/movable/screen/plane_master/white_space as anything in get_true_plane_masters(PLANE_SPACE)) - white_space.unhide_plane(screenmob) - if (SSlag_switch.measures[DISABLE_PARALLAX] && !HAS_TRAIT(viewmob, TRAIT_BYPASS_MEASURES)) return FALSE diff --git a/code/_onclick/hud/rendering/plane_masters/_plane_master.dm b/code/_onclick/hud/rendering/plane_masters/_plane_master.dm index bebf872f8ebe..a29a76fa9cee 100644 --- a/code/_onclick/hud/rendering/plane_masters/_plane_master.dm +++ b/code/_onclick/hud/rendering/plane_masters/_plane_master.dm @@ -31,7 +31,7 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master) //--rendering relay vars-- /// list of planes we will relay this plane's render to - var/list/render_relay_planes = list(RENDER_PLANE_GAME) + var/list/render_relay_planes = list(RENDER_PLANE_UNLIT_GAME) /// blend mode to apply to the render relay in case you dont want to use the plane_masters blend_mode var/blend_mode_override /// list of current relays this plane is utilizing to render diff --git a/code/_onclick/hud/rendering/plane_masters/plane_master_subtypes.dm b/code/_onclick/hud/rendering/plane_masters/plane_master_subtypes.dm index a588ab791c9b..0599f56df347 100644 --- a/code/_onclick/hud/rendering/plane_masters/plane_master_subtypes.dm +++ b/code/_onclick/hud/rendering/plane_masters/plane_master_subtypes.dm @@ -60,12 +60,12 @@
If you want something to look as if it has parallax on it, draw it to this plane." plane = PLANE_SPACE appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR - render_relay_planes = list(RENDER_PLANE_GAME, LIGHT_MASK_PLANE) + render_relay_planes = list(RENDER_PLANE_UNLIT_GAME, RENDER_PLANE_LIGHT_MASK) critical = PLANE_CRITICAL_FUCKO_PARALLAX // goes funny when touched. no idea why I don't trust byond /atom/movable/screen/plane_master/parallax_white/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) . = ..() - add_relay_to(GET_NEW_PLANE(EMISSIVE_RENDER_PLATE, offset), relay_layer = EMISSIVE_SPACE_LAYER) + add_relay_to(GET_NEW_PLANE(RENDER_PLANE_EMISSIVE, offset), relay_layer = EMISSIVE_SPACE_LAYER) ///Contains space parallax /atom/movable/screen/plane_master/parallax @@ -106,7 +106,7 @@ // Hacky shit to ensure parallax works in perf mode /atom/movable/screen/plane_master/parallax/outside_bounds(mob/relevant) if(offset == 0) - remove_relay_from(GET_NEW_PLANE(RENDER_PLANE_GAME, 0)) + remove_relay_from(GET_NEW_PLANE(RENDER_PLANE_UNLIT_GAME, 0)) is_outside_bounds = TRUE // I'm sorry :( return // If we can't render, and we aren't the bottom layer, don't render us @@ -121,7 +121,7 @@ /atom/movable/screen/plane_master/parallax/inside_bounds(mob/relevant) if(offset == 0) - add_relay_to(GET_NEW_PLANE(RENDER_PLANE_GAME, 0)) + add_relay_to(GET_NEW_PLANE(RENDER_PLANE_UNLIT_GAME, 0)) is_outside_bounds = FALSE return // Always readd, just in case we lost it @@ -161,33 +161,33 @@ /atom/movable/screen/plane_master/parallax/proc/narsie_unsummoned() animate(src, color = null, time = 8 SECONDS) -/atom/movable/screen/plane_master/gravpulse - name = "Gravpulse" - documentation = "Ok so this one's fun. Basically, we want to be able to distort the game plane when a grav annom is around.\ +/atom/movable/screen/plane_master/displacement + name = "Displacement" + documentation = "Ok so this one's fun. Basically, we want to be able to distort the game plane when a grav annom or similar is around.\
So we draw the pattern we want to use to this plane, and it's then used as a render target by a distortion filter on the game plane.\
Note the blend mode and lack of relay targets. This plane exists only to distort, it's never rendered anywhere." mouse_opacity = MOUSE_OPACITY_TRANSPARENT - plane = GRAVITY_PULSE_PLANE + plane = DISPLACEMENT_PLANE appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR blend_mode = BLEND_ADD - render_target = GRAVITY_PULSE_RENDER_TARGET + render_target = DISPLACEMENT_RENDER_TARGET render_relay_planes = list() // We start out hidden as we do not need to render when there's no distortion on our level start_hidden = TRUE -/atom/movable/screen/plane_master/gravpulse/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) +/atom/movable/screen/plane_master/displacement/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) . = ..() RegisterSignal(GLOB, SIGNAL_ADDTRAIT(TRAIT_DISTORTION_IN_USE(offset)), PROC_REF(distortion_enabled)) RegisterSignal(GLOB, SIGNAL_REMOVETRAIT(TRAIT_DISTORTION_IN_USE(offset)), PROC_REF(distortion_disabled)) if(HAS_TRAIT(GLOB, TRAIT_DISTORTION_IN_USE(offset))) distortion_enabled() -/atom/movable/screen/plane_master/gravpulse/proc/distortion_enabled(datum/source) +/atom/movable/screen/plane_master/displacement/proc/distortion_enabled(datum/source) SIGNAL_HANDLER var/mob/our_mob = home?.our_hud?.mymob unhide_plane(our_mob) -/atom/movable/screen/plane_master/gravpulse/proc/distortion_disabled(datum/source) +/atom/movable/screen/plane_master/displacement/proc/distortion_disabled(datum/source) SIGNAL_HANDLER hide_plane() @@ -196,30 +196,30 @@ name = "Floor" documentation = "The well, floor. This is mostly used as a sorting mechanism, but it also lets us create a \"border\" around the game world plane, so its drop shadow will actually work." plane = FLOOR_PLANE - render_relay_planes = list(RENDER_PLANE_GAME, LIGHT_MASK_PLANE) + render_relay_planes = list(RENDER_PLANE_UNLIT_GAME, RENDER_PLANE_LIGHT_MASK) /atom/movable/screen/plane_master/transparent_floor name = "Transparent Floor" documentation = "Really just openspace, stuff that is a turf but has no color or alpha whatsoever.\
We use this to draw to just the light mask plane, cause if it's not there we get holes of blackness over openspace" plane = TRANSPARENT_FLOOR_PLANE - render_relay_planes = list(LIGHT_MASK_PLANE) + render_relay_planes = list(RENDER_PLANE_LIGHT_MASK) // Needs to be critical or it uh, it'll look white critical = PLANE_CRITICAL_DISPLAY|PLANE_CRITICAL_NO_RELAY /atom/movable/screen/plane_master/floor/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) . = ..() - add_relay_to(GET_NEW_PLANE(EMISSIVE_RENDER_PLATE, offset), relay_layer = EMISSIVE_FLOOR_LAYER, relay_color = GLOB.em_block_color) + add_relay_to(GET_NEW_PLANE(RENDER_PLANE_EMISSIVE, offset), relay_layer = EMISSIVE_FLOOR_LAYER, relay_color = GLOB.em_block_color) /atom/movable/screen/plane_master/wall name = "Wall" documentation = "Holds all walls. We render this onto the game world. Separate so we can use this + space and floor planes as a guide for where byond blackness is NOT." plane = WALL_PLANE - render_relay_planes = list(RENDER_PLANE_GAME_WORLD, LIGHT_MASK_PLANE) + render_relay_planes = list(RENDER_PLANE_GAME_WORLD, RENDER_PLANE_LIGHT_MASK) /atom/movable/screen/plane_master/wall/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) . = ..() - add_relay_to(GET_NEW_PLANE(EMISSIVE_RENDER_PLATE, offset), relay_layer = EMISSIVE_WALL_LAYER, relay_color = GLOB.em_block_color) + add_relay_to(GET_NEW_PLANE(RENDER_PLANE_EMISSIVE, offset), relay_layer = EMISSIVE_WALL_LAYER, relay_color = GLOB.em_block_color) /atom/movable/screen/plane_master/game name = "Game" @@ -292,7 +292,7 @@ documentation = "Contains all lighting drawn to turfs. Not so complex, draws directly onto the lighting plate." plane = LIGHTING_PLANE appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR - render_relay_planes = list(TURF_LIGHTING_PLATE) + render_relay_planes = list(RENDER_PLANE_TURF_LIGHTING) blend_mode_override = BLEND_ADD mouse_opacity = MOUSE_OPACITY_TRANSPARENT critical = PLANE_CRITICAL_DISPLAY @@ -315,20 +315,27 @@ /atom/movable/screen/plane_master/o_light_visual/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) . = ..() // I'd love for this to be HSL but filters don't work with blend modes - add_relay_to(GET_NEW_PLANE(TURF_LIGHTING_PLATE, offset), BLEND_MULTIPLY, relay_color = list( + add_relay_to(GET_NEW_PLANE(RENDER_PLANE_TURF_LIGHTING, offset), BLEND_MULTIPLY, relay_color = list( -1, -1, -1, 0, -1, -1, -1, 0, -1, -1, -1, 0, 0, 0, 0, OVERLAY_LIGHTING_WEIGHT, 1, 1, 1, 0, )) + add_relay_to(GET_NEW_PLANE(RENDER_PLANE_SPECULAR, offset), relay_color = list( + SPECULAR_EMISSIVE_OVERLAY_CONTRAST, 0, 0, 0, + 0, SPECULAR_EMISSIVE_OVERLAY_CONTRAST, 0, 0, + 0, 0, SPECULAR_EMISSIVE_OVERLAY_CONTRAST, 0, + 0, 0, 0, 1, + -SPECULAR_EMISSIVE_CUTOFF, -SPECULAR_EMISSIVE_CUTOFF, -SPECULAR_EMISSIVE_CUTOFF, 0, + )) /atom/movable/screen/plane_master/above_lighting name = "Above lighting" plane = ABOVE_LIGHTING_PLANE documentation = "Anything on the game plane that needs a space to draw on that will be above the lighting plane.\
Mostly little alerts and effects, also sometimes contains things that are meant to look as if they glow." - render_relay_planes = list(LIT_GAME_RENDER_PLATE) + render_relay_planes = list(RENDER_PLANE_GAME) /atom/movable/screen/plane_master/weather_glow name = "Weather Glow" @@ -336,7 +343,7 @@ plane = WEATHER_GLOW_PLANE start_hidden = TRUE critical = PLANE_CRITICAL_DISPLAY - render_relay_planes = list(LIT_GAME_RENDER_PLATE) + render_relay_planes = list(RENDER_PLANE_GAME) /atom/movable/screen/plane_master/weather_glow/set_home(datum/plane_master_group/home) . = ..() @@ -361,11 +368,14 @@ /atom/movable/screen/plane_master/emissive/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) . = ..() /// Okay, so what we're doing here is making all emissives convert to white for actual emissive masking (i.e. adding light so objects glow) - add_relay_to(GET_NEW_PLANE(EMISSIVE_RENDER_PLATE, offset), relay_color = list(1,1,1,0, 1,1,1,0, 1,1,1,0, 0,0,0,1, 0,0,0,0)) + add_relay_to(GET_NEW_PLANE(RENDER_PLANE_EMISSIVE, offset), relay_color = list(1,1,1,0, 1,1,1,0, 0,0,0,0, 0,0,0,1, 0,0,0,0)) /// But for the bloom plate we convert only the red color into full white, this way we can have emissives in green channel unaffected by bloom /// which allows us to selectively bloom only a part of our emissives - add_relay_to(GET_NEW_PLANE(EMISSIVE_BLOOM_PLATE, offset), relay_color = list(255,255,255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0)) - add_relay_to(GET_NEW_PLANE(EMISSIVE_BLOOM_MASK_PLATE, offset), relay_color = list(1,1,1,1, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0)) + add_relay_to(GET_NEW_PLANE(RENDER_PLANE_EMISSIVE_BLOOM, offset), relay_color = list(255,255,255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0)) + add_relay_to(GET_NEW_PLANE(RENDER_PLANE_EMISSIVE_BLOOM_MASK, offset), relay_color = list(1,1,1,1, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0)) + // Blue channel is dedicated to specular, i.e. our bootleg implementation of shiny objects + // We map it onto alpha so we can use the mask plate in an alpha mask filter to cut out only the shiny bits + add_relay_to(GET_NEW_PLANE(RENDER_PLANE_SPECULAR_MASK, offset), relay_color = list(0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0, 1,1,1,0)) /atom/movable/screen/plane_master/pipecrawl name = "Pipecrawl" @@ -373,7 +383,7 @@
Has a few effects and a funky color matrix designed to make things a bit more visually readable." plane = PIPECRAWL_IMAGES_PLANE start_hidden = TRUE - render_relay_planes = list(LIT_GAME_RENDER_PLATE) + render_relay_planes = list(RENDER_PLANE_GAME) /atom/movable/screen/plane_master/pipecrawl/Initialize(mapload, datum/hud/hud_owner) . = ..() @@ -389,7 +399,7 @@ documentation = "Holds camera static images. Usually only visible to people who can well, see static.\
We use images rather then vis contents because they're lighter on maptick, and maptick sucks butt." plane = CAMERA_STATIC_PLANE - render_relay_planes = list(LIT_GAME_RENDER_PLATE) + render_relay_planes = list(RENDER_PLANE_GAME) /atom/movable/screen/plane_master/camera_static/show_to(mob/mymob) . = ..() @@ -428,7 +438,7 @@
Really only exists for its layering potential, we don't use this for any vfx" plane = HIGH_GAME_PLANE mouse_opacity = MOUSE_OPACITY_TRANSPARENT - render_relay_planes = list(LIT_GAME_RENDER_PLATE) + render_relay_planes = list(RENDER_PLANE_GAME) /atom/movable/screen/plane_master/ghost name = "Ghost" diff --git a/code/_onclick/hud/rendering/render_plate.dm b/code/_onclick/hud/rendering/render_plate.dm index 415539a66f1a..701aa4732a61 100644 --- a/code/_onclick/hud/rendering/render_plate.dm +++ b/code/_onclick/hud/rendering/render_plate.dm @@ -29,161 +29,6 @@ name = "Default rendering plate" multiz_scaled = FALSE -///this plate renders the final screen to show to the player -/atom/movable/screen/plane_master/rendering_plate/master - name = "Master rendering plate" - documentation = "The endpoint of all plane masters, you can think of this as the final \"view\" we draw.\ -
If offset is not 0 this will be drawn to the transparent plane of the floor above, but otherwise this is drawn to nothing, or shown to the player." - plane = RENDER_PLANE_MASTER - render_relay_planes = list() - -/atom/movable/screen/plane_master/rendering_plate/master/show_to(mob/mymob) - . = ..() - if(!.) - return - if(offset == 0) - return - // Non 0 offset render plates will relay up to the transparent plane above them, assuming they're not on the same z level as their target of course - var/datum/hud/hud = home.our_hud - // show_to can be called twice successfully with no hide_from call. Ensure no runtimes off the registers from this - if(hud) - RegisterSignal(hud, COMSIG_HUD_OFFSET_CHANGED, PROC_REF(on_offset_change), override = TRUE) - offset_change(hud?.current_plane_offset || 0) - -/atom/movable/screen/plane_master/rendering_plate/master/hide_from(mob/oldmob) - . = ..() - if(offset == 0) - return - var/datum/hud/hud = home.our_hud - if(hud) - UnregisterSignal(hud, COMSIG_HUD_OFFSET_CHANGED, PROC_REF(on_offset_change)) - -/atom/movable/screen/plane_master/rendering_plate/master/proc/on_offset_change(datum/source, old_offset, new_offset) - SIGNAL_HANDLER - offset_change(new_offset) - -/atom/movable/screen/plane_master/rendering_plate/master/proc/offset_change(new_offset) - if(new_offset == offset) // If we're on our own z layer, relay to nothing, just draw - remove_relay_from(GET_NEW_PLANE(RENDER_PLANE_TRANSPARENT, offset - 1)) - else // Otherwise, regenerate the relay - add_relay_to(GET_NEW_PLANE(RENDER_PLANE_TRANSPARENT, offset - 1)) - -///renders general in charachter game objects -/atom/movable/screen/plane_master/rendering_plate/game_plate - name = "Game rendering plate" - documentation = "Holds all objects that are ahhh, in character? is maybe the best way to describe it.\ -
We apply a displacement effect from the gravity pulse plane too, so we can warp the game world.\ -
If we have fov enabled we'll relay this onto two different rendering plates to apply fov effects to only a portion. If not, we just draw straight to master" - plane = RENDER_PLANE_GAME - render_relay_planes = list(LIT_GAME_RENDER_PLATE) - -/atom/movable/screen/plane_master/rendering_plate/game_plate/Initialize(mapload, datum/hud/hud_owner) - . = ..() - add_relay_to(GET_NEW_PLANE(EMISSIVE_BLOOM_PLATE, offset), blend_override = BLEND_MULTIPLY) - RegisterSignal(GLOB, SIGNAL_ADDTRAIT(TRAIT_DISTORTION_IN_USE(offset)), PROC_REF(distortion_enabled)) - RegisterSignal(GLOB, SIGNAL_REMOVETRAIT(TRAIT_DISTORTION_IN_USE(offset)), PROC_REF(distortion_disabled)) - if(HAS_TRAIT(GLOB, TRAIT_DISTORTION_IN_USE(offset))) - distortion_enabled() - -/atom/movable/screen/plane_master/rendering_plate/game_plate/proc/distortion_enabled(datum/source) - SIGNAL_HANDLER - add_filter("displacer", 1, displacement_map_filter(render_source = OFFSET_RENDER_TARGET(GRAVITY_PULSE_RENDER_TARGET, offset), size = 10)) - -/atom/movable/screen/plane_master/rendering_plate/game_plate/proc/distortion_disabled(datum/source) - SIGNAL_HANDLER - remove_filter("displacer") - -/atom/movable/screen/plane_master/rendering_plate/game_plate/show_to(mob/mymob) - . = ..() - if(!. || !mymob) - return . - RegisterSignal(mymob, SIGNAL_ADDTRAIT(TRAIT_FOV_APPLIED), PROC_REF(fov_enabled), override = TRUE) - RegisterSignal(mymob, SIGNAL_REMOVETRAIT(TRAIT_FOV_APPLIED), PROC_REF(fov_disabled), override = TRUE) - if(HAS_TRAIT(mymob, TRAIT_FOV_APPLIED)) - fov_enabled(mymob) - else - fov_disabled(mymob) - -/atom/movable/screen/plane_master/rendering_plate/game_plate/proc/fov_enabled(mob/source) - SIGNAL_HANDLER - add_relay_to(GET_NEW_PLANE(RENDER_PLANE_GAME_UNMASKED, offset)) - add_relay_to(GET_NEW_PLANE(RENDER_PLANE_GAME_MASKED, offset)) - remove_relay_from(GET_NEW_PLANE(LIT_GAME_RENDER_PLATE, offset)) - -/atom/movable/screen/plane_master/rendering_plate/game_plate/proc/fov_disabled(mob/source) - SIGNAL_HANDLER - remove_relay_from(GET_NEW_PLANE(RENDER_PLANE_GAME_UNMASKED, offset)) - remove_relay_from(GET_NEW_PLANE(RENDER_PLANE_GAME_MASKED, offset)) - add_relay_to(GET_NEW_PLANE(LIT_GAME_RENDER_PLATE, offset)) - -///renders the parts of the plate unmasked by fov -/atom/movable/screen/plane_master/rendering_plate/unmasked_game_plate - name = "Unmasked Game rendering plate" - documentation = "Holds the bits of the game plate that aren't impacted by fov.\ -
We use an alpha mask to cut out the bits we plan on dealing with elsewhere" - plane = RENDER_PLANE_GAME_UNMASKED - render_relay_planes = list(LIT_GAME_RENDER_PLATE) - -/atom/movable/screen/plane_master/rendering_plate/unmasked_game_plate/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) - . = ..() - add_filter("fov_handled", 1, alpha_mask_filter(render_source = OFFSET_RENDER_TARGET(FIELD_OF_VISION_BLOCKER_RENDER_TARGET, offset), flags = MASK_INVERSE)) - -/atom/movable/screen/plane_master/rendering_plate/unmasked_game_plate/show_to(mob/mymob) - . = ..() - if(!. || !mymob) - return . - RegisterSignal(mymob, SIGNAL_ADDTRAIT(TRAIT_FOV_APPLIED), PROC_REF(fov_enabled), override = TRUE) - RegisterSignal(mymob, SIGNAL_REMOVETRAIT(TRAIT_FOV_APPLIED), PROC_REF(fov_disabled), override = TRUE) - if(HAS_TRAIT(mymob, TRAIT_FOV_APPLIED)) - fov_enabled(mymob) - else - fov_disabled(mymob) - -/atom/movable/screen/plane_master/rendering_plate/unmasked_game_plate/proc/fov_enabled(mob/source) - SIGNAL_HANDLER - if(force_hidden == FALSE) - return - unhide_plane(source) - -/atom/movable/screen/plane_master/rendering_plate/unmasked_game_plate/proc/fov_disabled(mob/source) - SIGNAL_HANDLER - hide_plane(source) - -///renders the parts of the plate masked by fov -/atom/movable/screen/plane_master/rendering_plate/masked_game_plate - name = "FOV Game rendering plate" - documentation = "Contains the bits of the game plate that are hidden by some form of fov\ -
Applies a color matrix to dim and create contrast, alongside a blur. Goal is only half being able to see stuff" - plane = RENDER_PLANE_GAME_MASKED - render_relay_planes = list(LIT_GAME_RENDER_PLATE) - -/atom/movable/screen/plane_master/rendering_plate/masked_game_plate/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) - . = ..() - add_filter("fov_blur", 1, gauss_blur_filter(1.8)) - add_filter("fov_handled_space", 2, alpha_mask_filter(render_source = OFFSET_RENDER_TARGET(FIELD_OF_VISION_BLOCKER_RENDER_TARGET, offset))) - add_filter("fov_matrix", 3, color_matrix_filter(list(0.5,-0.15,-0.15,0, -0.15,0.5,-0.15,0, -0.15,-0.15,0.5,0, 0,0,0,1, 0,0,0,0))) - -/atom/movable/screen/plane_master/rendering_plate/masked_game_plate/show_to(mob/mymob) - . = ..() - if(!. || !mymob) - return . - RegisterSignal(mymob, SIGNAL_ADDTRAIT(TRAIT_FOV_APPLIED), PROC_REF(fov_enabled), override = TRUE) - RegisterSignal(mymob, SIGNAL_REMOVETRAIT(TRAIT_FOV_APPLIED), PROC_REF(fov_disabled), override = TRUE) - if(HAS_TRAIT(mymob, TRAIT_FOV_APPLIED)) - fov_enabled(mymob) - else - fov_disabled(mymob) - -/atom/movable/screen/plane_master/rendering_plate/masked_game_plate/proc/fov_enabled(mob/source) - SIGNAL_HANDLER - if(force_hidden == FALSE) - return - unhide_plane(source) - -/atom/movable/screen/plane_master/rendering_plate/masked_game_plate/proc/fov_disabled(mob/source) - SIGNAL_HANDLER - hide_plane(source) - // Blackness renders weird when you view down openspace, because of transforms and borders and such // This is a consequence of not using lummy's grouped transparency, but I couldn't get that to work without totally fucking up // Sight flags, and shooting vis_contents usage to the moon. So we're doin it different. @@ -217,6 +62,108 @@ if(istype(mymob) && mymob.canon_client?.prefs?.read_preference(/datum/preference/toggle/ambient_occlusion)) add_filter("AO", 1, drop_shadow_filter(x = 0, y = -2, size = 4, color = "#04080FAA")) +/atom/movable/screen/plane_master/rendering_plate/unlit_game_plate + name = "Unlit Game rendering plate" + documentation = "Feeds the bits of the game plate which want to be effected by lighting into RENDER_PLANE_GAME and the emissive bloom pipeline (the reason this exists)." + plane = RENDER_PLANE_UNLIT_GAME + render_relay_planes = list(RENDER_PLANE_GAME) + +/atom/movable/screen/plane_master/rendering_plate/unlit_game_plate/Initialize(mapload, datum/hud/hud_owner) + . = ..() + add_relay_to(GET_NEW_PLANE(RENDER_PLANE_EMISSIVE_BLOOM, offset), blend_override = BLEND_MULTIPLY) + +/atom/movable/screen/plane_master/rendering_plate/turf_lighting + name = "Turf lighting post-processing plate" + documentation = "Used by overlay lighting, and possibly over plates, to mask out turf lighting." + plane = RENDER_PLANE_TURF_LIGHTING + render_relay_planes = list(RENDER_PLANE_LIGHTING) + blend_mode = BLEND_ADD + critical = PLANE_CRITICAL_DISPLAY + +/atom/movable/screen/plane_master/rendering_plate/turf_lighting/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) + . = ..() + /// We get affected by cutoff but not by the contrast that overlay lights get + /// So flashlights seem to reflect "better" + add_relay_to(GET_NEW_PLANE(RENDER_PLANE_SPECULAR, offset), relay_color = list( + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + -SPECULAR_EMISSIVE_CUTOFF, -SPECULAR_EMISSIVE_CUTOFF, -SPECULAR_EMISSIVE_CUTOFF, 0, + )) + +/atom/movable/screen/plane_master/rendering_plate/emissive_slate + name = "Emissive Plate" + documentation = "This system works by exploiting BYONDs color matrix filter to use layers to handle emissive blockers.\ +
Emissive overlays are pasted with an atom color that converts them to be entirely some specific color.\ +
Emissive blockers are pasted with an atom color that converts them to be entirely some different color.\ +
Emissive overlays and emissive blockers are put onto the same plane (This one).\ +
The layers for the emissive overlays and emissive blockers cause them to mask eachother similar to normal BYOND objects.\ +
A color matrix filter is applied to the emissive plane to mask out anything that isn't whatever the emissive color is.\ +
This is then used to alpha mask the lighting plane." + plane = RENDER_PLANE_EMISSIVE + appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + render_target = EMISSIVE_RENDER_TARGET + render_relay_planes = list() + critical = PLANE_CRITICAL_DISPLAY + +/atom/movable/screen/plane_master/rendering_plate/emissive_slate/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) + . = ..() + add_filter("em_block_masking", 2, color_matrix_filter(GLOB.em_mask_matrix)) + if(offset != 0) + add_relay_to(GET_NEW_PLANE(RENDER_PLANE_EMISSIVE, offset - 1), relay_layer = EMISSIVE_Z_BELOW_LAYER) + +/atom/movable/screen/plane_master/rendering_plate/emissive_bloom_mask + name = "Emissive bloom mask plate" + documentation = "A holder plate used purely as a way to full-white bloom emissives before applying them as a mask onto the emissive bloom plate." + plane = RENDER_PLANE_EMISSIVE_BLOOM_MASK + appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + render_relay_planes = list() + render_target = EMISSIVE_BLOOM_MASK_RENDER_TARGET + critical = PLANE_CRITICAL_DISPLAY + +/atom/movable/screen/plane_master/rendering_plate/emissive_bloom + name = "Emissive bloom plate" + documentation = "Plate used to bloom emissives before adding them onto the overlay lighting plane. We do this by multiplying the game plate\ + onto a fullbright emissive, then alpha masking it by emissive's color to solve the problem of blockers, both alone and covered by emissives." + plane = RENDER_PLANE_EMISSIVE_BLOOM + appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + blend_mode = BLEND_ADD + render_relay_planes = list(O_LIGHTING_VISUAL_PLANE) + critical = PLANE_CRITICAL_DISPLAY + +/atom/movable/screen/plane_master/rendering_plate/emissive_bloom/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) + . = ..() + add_filter("emissive_mask", 1, alpha_mask_filter(render_source = OFFSET_RENDER_TARGET(EMISSIVE_BLOOM_MASK_RENDER_TARGET, offset))) + add_filter("emissive_bloom", 2, bloom_filter(threshold = COLOR_BLACK, size = 2, offset = 1)) + +/atom/movable/screen/plane_master/rendering_plate/specular_mask + name = "Specular mask plate" + documentation = "Plate used to generate the specular mask for the specular plate effect." + plane = RENDER_PLANE_SPECULAR_MASK + appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + render_target = SPECULAR_MASK_RENDER_TARGET + render_relay_planes = list() + critical = PLANE_CRITICAL_DISPLAY + +/atom/movable/screen/plane_master/rendering_plate/specular + name = "Specular plate" + documentation = "Plate used to artificially increase lighting on certain pixels to poorly mimic shiny surfaces." + plane = RENDER_PLANE_SPECULAR + appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + blend_mode = BLEND_ADD + render_relay_planes = list(RENDER_PLANE_GAME) + critical = PLANE_CRITICAL_DISPLAY + +/atom/movable/screen/plane_master/rendering_plate/specular/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) + . = ..() + add_filter("specular_mask", 1, alpha_mask_filter(render_source = OFFSET_RENDER_TARGET(SPECULAR_MASK_RENDER_TARGET, offset))) + ///Contains all lighting objects /atom/movable/screen/plane_master/rendering_plate/lighting name = "Lighting plate" @@ -231,7 +178,7 @@ blend_mode_override = BLEND_MULTIPLY mouse_opacity = MOUSE_OPACITY_TRANSPARENT critical = PLANE_CRITICAL_DISPLAY - render_relay_planes = list(LIT_GAME_RENDER_PLATE) + render_relay_planes = list(RENDER_PLANE_GAME) /// A list of light cutoffs we're actively using, (mass, r, g, b) to avoid filter churn var/list/light_cutoffs @@ -312,28 +259,6 @@ add_filter("light_cutdown", 3, color_matrix_filter(list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, -(ratio + red),-(ratio+green),-(ratio+blue),0))) add_filter("light_cutup", 4, color_matrix_filter(list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, ratio+red,ratio+green,ratio+blue,0))) -/atom/movable/screen/plane_master/rendering_plate/emissive_slate - name = "Emissive Plate" - documentation = "This system works by exploiting BYONDs color matrix filter to use layers to handle emissive blockers.\ -
Emissive overlays are pasted with an atom color that converts them to be entirely some specific color.\ -
Emissive blockers are pasted with an atom color that converts them to be entirely some different color.\ -
Emissive overlays and emissive blockers are put onto the same plane (This one).\ -
The layers for the emissive overlays and emissive blockers cause them to mask eachother similar to normal BYOND objects.\ -
A color matrix filter is applied to the emissive plane to mask out anything that isn't whatever the emissive color is.\ -
This is then used to alpha mask the lighting plane." - plane = EMISSIVE_RENDER_PLATE - appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - render_target = EMISSIVE_RENDER_TARGET - render_relay_planes = list() - critical = PLANE_CRITICAL_DISPLAY - -/atom/movable/screen/plane_master/rendering_plate/emissive_slate/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) - . = ..() - add_filter("em_block_masking", 2, color_matrix_filter(GLOB.em_mask_matrix)) - if(offset != 0) - add_relay_to(GET_NEW_PLANE(EMISSIVE_RENDER_PLATE, offset - 1), relay_layer = EMISSIVE_Z_BELOW_LAYER) - /atom/movable/screen/plane_master/rendering_plate/light_mask name = "Light Mask" documentation = "Any part of this plane that is transparent will be black below it on the game rendering plate.\ @@ -341,7 +266,7 @@
We relay copies of the space, floor and wall planes to it, so we can use them as masks. Then we just boost any existing alpha to 100% and we're done.\
If we ever switch to a sight setup that shows say, mobs but not floors, we instead mask just overlay lighting and emissives.\
This avoids dumb seethrough without breaking stuff like thermals." - plane = LIGHT_MASK_PLANE + plane = RENDER_PLANE_LIGHT_MASK appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR // Fullwhite where there's anything, no color otherwise color = list(255,255,255,255, 255,255,255,255, 255,255,255,255, 255,255,255,255, 0,0,0,0) @@ -349,7 +274,7 @@ render_target = LIGHT_MASK_RENDER_TARGET // We blend against the game plane, so she's gotta multiply! blend_mode = BLEND_MULTIPLY - render_relay_planes = list(LIT_GAME_RENDER_PLATE) + render_relay_planes = list(RENDER_PLANE_GAME) /atom/movable/screen/plane_master/rendering_plate/light_mask/show_to(mob/mymob) . = ..() @@ -361,24 +286,141 @@ /atom/movable/screen/plane_master/rendering_plate/light_mask/hide_from(mob/oldmob) . = ..() - var/atom/movable/screen/plane_master/emissive = home.get_plane(GET_NEW_PLANE(EMISSIVE_RENDER_PLATE, offset)) + var/atom/movable/screen/plane_master/emissive = home.get_plane(GET_NEW_PLANE(RENDER_PLANE_EMISSIVE, offset)) emissive.remove_filter("lighting_mask") - remove_relay_from(GET_NEW_PLANE(LIT_GAME_RENDER_PLATE, offset)) + remove_relay_from(GET_NEW_PLANE(RENDER_PLANE_GAME, offset)) UnregisterSignal(oldmob, COMSIG_MOB_SIGHT_CHANGE) /atom/movable/screen/plane_master/rendering_plate/light_mask/proc/handle_sight(datum/source, new_sight, old_sight) // If we can see something that shows "through" blackness, and we can't see turfs, disable our draw to the game plane // And instead mask JUST the overlay lighting plane, since that will look fuckin wrong - var/atom/movable/screen/plane_master/emissive = home.get_plane(GET_NEW_PLANE(EMISSIVE_RENDER_PLATE, offset)) + var/atom/movable/screen/plane_master/emissive = home.get_plane(GET_NEW_PLANE(RENDER_PLANE_EMISSIVE, offset)) if(new_sight & SEE_AVOID_TURF_BLACKNESS && !(new_sight & SEE_TURFS)) - remove_relay_from(GET_NEW_PLANE(LIT_GAME_RENDER_PLATE, offset)) + remove_relay_from(GET_NEW_PLANE(RENDER_PLANE_GAME, offset)) emissive.add_filter("lighting_mask", 1, alpha_mask_filter(render_source = OFFSET_RENDER_TARGET(LIGHT_MASK_RENDER_TARGET, offset))) // If we CAN'T see through the black, then draw er down brother! else emissive.remove_filter("lighting_mask") // We max alpha here, so our darkness is actually.. dark // Can't do it before cause it fucks with the filter - add_relay_to(GET_NEW_PLANE(LIT_GAME_RENDER_PLATE, offset), relay_color = list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, 0,0,0,1)) + add_relay_to(GET_NEW_PLANE(RENDER_PLANE_GAME, offset), relay_color = list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, 0,0,0,1)) + +///renders in character game objects +/atom/movable/screen/plane_master/rendering_plate/game_plate + name = "Game rendering plate" + documentation = "Holds all objects that are ahhh, in character? is maybe the best way to describe it.\ +
We apply a displacement effect from the gravity pulse plane too, so we can warp the game world.\ +
If we have fov enabled we'll relay this onto two different rendering plates to apply fov effects to only a portion. If not, we just draw straight to master.\ +
It's also the step where we finally build lighting into the visual pipeline" + plane = RENDER_PLANE_GAME + render_relay_planes = list(RENDER_PLANE_MASTER) + critical = PLANE_CRITICAL_DISPLAY + +/atom/movable/screen/plane_master/rendering_plate/game_plate/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) + . = ..() + RegisterSignal(GLOB, SIGNAL_ADDTRAIT(TRAIT_DISTORTION_IN_USE(offset)), PROC_REF(distortion_enabled)) + RegisterSignal(GLOB, SIGNAL_REMOVETRAIT(TRAIT_DISTORTION_IN_USE(offset)), PROC_REF(distortion_disabled)) + if(HAS_TRAIT(GLOB, TRAIT_DISTORTION_IN_USE(offset))) + distortion_enabled() + +/atom/movable/screen/plane_master/rendering_plate/game_plate/proc/distortion_enabled(datum/source) + SIGNAL_HANDLER + add_filter("displacer", 1, displacement_map_filter(render_source = OFFSET_RENDER_TARGET(DISPLACEMENT_RENDER_TARGET, offset), size = 10)) + +/atom/movable/screen/plane_master/rendering_plate/game_plate/proc/distortion_disabled(datum/source) + SIGNAL_HANDLER + remove_filter("displacer") + +/atom/movable/screen/plane_master/rendering_plate/game_plate/show_to(mob/mymob) + . = ..() + if(!. || !mymob) + return . + RegisterSignal(mymob, SIGNAL_ADDTRAIT(TRAIT_FOV_APPLIED), PROC_REF(fov_enabled), override = TRUE) + RegisterSignal(mymob, SIGNAL_REMOVETRAIT(TRAIT_FOV_APPLIED), PROC_REF(fov_disabled), override = TRUE) + if(HAS_TRAIT(mymob, TRAIT_FOV_APPLIED)) + fov_enabled(mymob) + else + fov_disabled(mymob) + +/atom/movable/screen/plane_master/rendering_plate/game_plate/proc/fov_enabled(mob/source) + SIGNAL_HANDLER + add_relay_to(GET_NEW_PLANE(RENDER_PLANE_GAME_UNMASKED, offset)) + add_relay_to(GET_NEW_PLANE(RENDER_PLANE_GAME_MASKED, offset)) + remove_relay_from(GET_NEW_PLANE(RENDER_PLANE_MASTER, offset)) + +/atom/movable/screen/plane_master/rendering_plate/game_plate/proc/fov_disabled(mob/source) + SIGNAL_HANDLER + remove_relay_from(GET_NEW_PLANE(RENDER_PLANE_GAME_UNMASKED, offset)) + remove_relay_from(GET_NEW_PLANE(RENDER_PLANE_GAME_MASKED, offset)) + add_relay_to(GET_NEW_PLANE(RENDER_PLANE_MASTER, offset)) + +///renders the parts of the plate unmasked by fov +/atom/movable/screen/plane_master/rendering_plate/unmasked_game_plate + name = "Unmasked Game rendering plate" + documentation = "Holds the bits of the game plate that aren't impacted by fov.\ +
We use an alpha mask to cut out the bits we plan on dealing with elsewhere" + plane = RENDER_PLANE_GAME_UNMASKED + render_relay_planes = list(RENDER_PLANE_MASTER) + +/atom/movable/screen/plane_master/rendering_plate/unmasked_game_plate/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) + . = ..() + add_filter("fov_handled", 1, alpha_mask_filter(render_source = OFFSET_RENDER_TARGET(FIELD_OF_VISION_BLOCKER_RENDER_TARGET, offset), flags = MASK_INVERSE)) + +/atom/movable/screen/plane_master/rendering_plate/unmasked_game_plate/show_to(mob/mymob) + . = ..() + if(!. || !mymob) + return . + RegisterSignal(mymob, SIGNAL_ADDTRAIT(TRAIT_FOV_APPLIED), PROC_REF(fov_enabled), override = TRUE) + RegisterSignal(mymob, SIGNAL_REMOVETRAIT(TRAIT_FOV_APPLIED), PROC_REF(fov_disabled), override = TRUE) + if(HAS_TRAIT(mymob, TRAIT_FOV_APPLIED)) + fov_enabled(mymob) + else + fov_disabled(mymob) + +/atom/movable/screen/plane_master/rendering_plate/unmasked_game_plate/proc/fov_enabled(mob/source) + SIGNAL_HANDLER + if(force_hidden == FALSE) + return + unhide_plane(source) + +/atom/movable/screen/plane_master/rendering_plate/unmasked_game_plate/proc/fov_disabled(mob/source) + SIGNAL_HANDLER + hide_plane(source) + +///renders the parts of the plate masked by fov +/atom/movable/screen/plane_master/rendering_plate/masked_game_plate + name = "FOV Game rendering plate" + documentation = "Contains the bits of the game plate that are hidden by some form of fov\ +
Applies a color matrix to dim and create contrast, alongside a blur. Goal is only half being able to see stuff" + plane = RENDER_PLANE_GAME_MASKED + render_relay_planes = list(RENDER_PLANE_MASTER) + +/atom/movable/screen/plane_master/rendering_plate/masked_game_plate/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) + . = ..() + add_filter("fov_blur", 1, gauss_blur_filter(1.8)) + add_filter("fov_handled_space", 2, alpha_mask_filter(render_source = OFFSET_RENDER_TARGET(FIELD_OF_VISION_BLOCKER_RENDER_TARGET, offset))) + add_filter("fov_matrix", 3, color_matrix_filter(list(0.5,-0.15,-0.15,0, -0.15,0.5,-0.15,0, -0.15,-0.15,0.5,0, 0,0,0,1, 0,0,0,0))) + +/atom/movable/screen/plane_master/rendering_plate/masked_game_plate/show_to(mob/mymob) + . = ..() + if(!. || !mymob) + return . + RegisterSignal(mymob, SIGNAL_ADDTRAIT(TRAIT_FOV_APPLIED), PROC_REF(fov_enabled), override = TRUE) + RegisterSignal(mymob, SIGNAL_REMOVETRAIT(TRAIT_FOV_APPLIED), PROC_REF(fov_disabled), override = TRUE) + if(HAS_TRAIT(mymob, TRAIT_FOV_APPLIED)) + fov_enabled(mymob) + else + fov_disabled(mymob) + +/atom/movable/screen/plane_master/rendering_plate/masked_game_plate/proc/fov_enabled(mob/source) + SIGNAL_HANDLER + if(force_hidden == FALSE) + return + unhide_plane(source) + +/atom/movable/screen/plane_master/rendering_plate/masked_game_plate/proc/fov_disabled(mob/source) + SIGNAL_HANDLER + hide_plane(source) ///render plate for OOC stuff like ghosts, hud-screen effects, etc /atom/movable/screen/plane_master/rendering_plate/non_game @@ -387,46 +429,44 @@ plane = RENDER_PLANE_NON_GAME render_relay_planes = list(RENDER_PLANE_MASTER) -/atom/movable/screen/plane_master/rendering_plate/emissive_bloom_mask - name = "Emissive bloom mask plate" - documentation = "A holder plate used purely as a way to full-white bloom emissives before applying them as a mask onto the emissive bloom plate." - plane = EMISSIVE_BLOOM_MASK_PLATE - appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR - mouse_opacity = MOUSE_OPACITY_TRANSPARENT +///this plate renders the final screen to show to the player +/atom/movable/screen/plane_master/rendering_plate/master + name = "Master rendering plate" + documentation = "The endpoint of all plane masters, you can think of this as the final \"view\" we draw.\ +
If offset is not 0 this will be drawn to the transparent plane of the floor above, but otherwise this is drawn to nothing, or shown to the player." + plane = RENDER_PLANE_MASTER render_relay_planes = list() - render_target = EMISSIVE_BLOOM_MASK_TARGET - critical = PLANE_CRITICAL_DISPLAY -/atom/movable/screen/plane_master/rendering_plate/emissive_bloom - name = "Emissive bloom plate" - documentation = "Plate used to bloom emissives before adding them onto the overlay lighting plane. We do this by multiplying the game plate\ - onto a fullbright emissive, then alpha masking it by emissive's color to solve the problem of blockers, both alone and covered by emissives." - plane = EMISSIVE_BLOOM_PLATE - appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - blend_mode = BLEND_ADD - render_relay_planes = list(O_LIGHTING_VISUAL_PLANE) - critical = PLANE_CRITICAL_DISPLAY +/atom/movable/screen/plane_master/rendering_plate/master/show_to(mob/mymob) + . = ..() + if(!.) + return + if(offset == 0) + return + // Non 0 offset render plates will relay up to the transparent plane above them, assuming they're not on the same z level as their target of course + var/datum/hud/hud = home.our_hud + // show_to can be called twice successfully with no hide_from call. Ensure no runtimes off the registers from this + if(hud) + RegisterSignal(hud, COMSIG_HUD_OFFSET_CHANGED, PROC_REF(on_offset_change), override = TRUE) + offset_change(hud?.current_plane_offset || 0) -/atom/movable/screen/plane_master/rendering_plate/emissive_bloom/Initialize(mapload, datum/hud/hud_owner, datum/plane_master_group/home, offset) +/atom/movable/screen/plane_master/rendering_plate/master/hide_from(mob/oldmob) . = ..() - add_filter("emissive_mask", 1, alpha_mask_filter(render_source = OFFSET_RENDER_TARGET(EMISSIVE_BLOOM_MASK_TARGET, offset))) - add_filter("emissive_bloom", 2, bloom_filter(threshold = COLOR_BLACK, size = 2, offset = 1)) + if(offset == 0) + return + var/datum/hud/hud = home.our_hud + if(hud) + UnregisterSignal(hud, COMSIG_HUD_OFFSET_CHANGED, PROC_REF(on_offset_change)) -/atom/movable/screen/plane_master/rendering_plate/turf_lighting - name = "Turf lighting post-processing plate" - documentation = "Used by overlay lighting, and possibly over plates, to mask out turf lighting." - plane = TURF_LIGHTING_PLATE - render_relay_planes = list(RENDER_PLANE_LIGHTING) - blend_mode = BLEND_ADD - critical = PLANE_CRITICAL_DISPLAY +/atom/movable/screen/plane_master/rendering_plate/master/proc/on_offset_change(datum/source, old_offset, new_offset) + SIGNAL_HANDLER + offset_change(new_offset) -/atom/movable/screen/plane_master/rendering_plate/lit_game - name = "Lit game rendering plate" - documentation = "Plate which is used to multiply the game rendering plate by lighting visuals and rendering fullbright stuff. Exists so we can fetch fullbright game plate for emissive VFX." - plane = LIT_GAME_RENDER_PLATE - render_relay_planes = list(RENDER_PLANE_MASTER) - critical = PLANE_CRITICAL_DISPLAY +/atom/movable/screen/plane_master/rendering_plate/master/proc/offset_change(new_offset) + if(new_offset == offset) // If we're on our own z layer, relay to nothing, just draw + remove_relay_from(GET_NEW_PLANE(RENDER_PLANE_TRANSPARENT, offset - 1)) + else // Otherwise, regenerate the relay + add_relay_to(GET_NEW_PLANE(RENDER_PLANE_TRANSPARENT, offset - 1)) /** * Plane master proc called in Initialize() that creates relay objects, and sets them up as needed diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm index 02f45a541508..62dba374b79a 100644 --- a/code/controllers/subsystem.dm +++ b/code/controllers/subsystem.dm @@ -291,7 +291,7 @@ /datum/controller/subsystem/stat_entry(msg) if(can_fire && !(SS_NO_FIRE & flags) && init_stage <= Master.init_stage_completed) - msg = "[round(cost,1)]ms|[round(tick_usage,1)]%([round(tick_overrun,1)]%)|[round(ticks,0.1)]\t[msg]" + msg = "[round(cost,1)]ms|[round(tick_usage,1)]%([round(tick_overrun,1)]%)|[round(ticks,0.1)] [msg]" else msg = "OFFLINE\t[msg]" return msg diff --git a/code/controllers/subsystem/admin_verbs.dm b/code/controllers/subsystem/admin_verbs.dm index 645a447c4854..74b86a3c5cb0 100644 --- a/code/controllers/subsystem/admin_verbs.dm +++ b/code/controllers/subsystem/admin_verbs.dm @@ -22,7 +22,8 @@ SUBSYSTEM_DEF(admin_verbs) admin_verbs_by_type = SSadmin_verbs.admin_verbs_by_type /datum/controller/subsystem/admin_verbs/stat_entry(msg) - return "[..()] | V: [length(admin_verbs_by_type)]" + msg = "V:[length(admin_verbs_by_type)]" + return ..() /datum/controller/subsystem/admin_verbs/proc/process_pending_admins() var/list/pending_admins = admins_pending_subsytem_init diff --git a/code/controllers/subsystem/ai_controllers.dm b/code/controllers/subsystem/ai_controllers.dm index 397062ddd80c..355a06ff3a5a 100644 --- a/code/controllers/subsystem/ai_controllers.dm +++ b/code/controllers/subsystem/ai_controllers.dm @@ -21,7 +21,7 @@ SUBSYSTEM_DEF(ai_controllers) /datum/controller/subsystem/ai_controllers/stat_entry(msg) var/list/planning_list = GLOB.ai_controllers_by_status[planning_status] - msg = "Planning AIs:[length(planning_list)]/[round(our_cost,1)]%" + msg = "\n Planning AIs:[length(planning_list)]/[round(our_cost,1)]%" return ..() /datum/controller/subsystem/ai_controllers/fire(resumed) diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm index b0e0846d5ee7..df9a53e82e11 100644 --- a/code/controllers/subsystem/air.dm +++ b/code/controllers/subsystem/air.dm @@ -63,7 +63,7 @@ SUBSYSTEM_DEF(air) /datum/controller/subsystem/air/stat_entry(msg) - msg += "C:{" + msg += "\n Cost:{" msg += "AT:[round(cost_turfs,1)]|" msg += "HS:[round(cost_hotspots,1)]|" msg += "EG:[round(cost_groups,1)]|" @@ -75,7 +75,7 @@ SUBSYSTEM_DEF(air) msg += "RB:[round(cost_rebuilds,1)]|" msg += "AJ:[round(cost_adjacent,1)]|" msg += "} " - msg += "AT:[active_turfs.len]|" + msg += "\n Count:{AT:[active_turfs.len]|" msg += "HS:[hotspots.len]|" msg += "EG:[excited_groups.len]|" msg += "HP:[high_pressure_delta.len]|" @@ -87,6 +87,7 @@ SUBSYSTEM_DEF(air) msg += "EP:[expansion_queue.len]|" msg += "AJ:[adjacent_rebuild.len]|" msg += "AT/MS:[round((cost ? active_turfs.len/cost : 0),0.1)]" + msg += "}" return ..() diff --git a/code/controllers/subsystem/area_contents.dm b/code/controllers/subsystem/area_contents.dm index 054de9d8efcf..11e07eac55bf 100644 --- a/code/controllers/subsystem/area_contents.dm +++ b/code/controllers/subsystem/area_contents.dm @@ -22,7 +22,7 @@ SUBSYSTEM_DEF(area_contents) total_to_clear += length(to_clear.turfs_to_uncontain_by_zlevel[area_zlevel]) if (length(to_clear.turfs_by_zlevel) >= area_zlevel) //this should always be true, but stat_entry is no place for runtimes. fire() can handle that total_clearing_from += length(to_clear.turfs_by_zlevel[area_zlevel]) - msg = "A:[length(currentrun)] MR:[length(marked_for_clearing)] TC:[total_to_clear] CF:[total_clearing_from]" + msg = "\n A:[length(currentrun)] MR:[length(marked_for_clearing)] TC:[total_to_clear] CF:[total_clearing_from]" return ..() diff --git a/code/controllers/subsystem/asset_loading.dm b/code/controllers/subsystem/asset_loading.dm index ecdf406894a0..1129ae94c155 100644 --- a/code/controllers/subsystem/asset_loading.dm +++ b/code/controllers/subsystem/asset_loading.dm @@ -13,12 +13,14 @@ SUBSYSTEM_DEF(asset_loading) while(length(generate_queue)) var/datum/asset/to_load = generate_queue[generate_queue.len] + last_queue_len = length(generate_queue) + generate_queue.len-- + to_load.queued_generation() if(MC_TICK_CHECK) return - last_queue_len = length(generate_queue) - generate_queue.len-- + // We just emptied the queue if(last_queue_len && !length(generate_queue)) // Clean up cached icons, freeing memory. diff --git a/code/controllers/subsystem/dbcore.dm b/code/controllers/subsystem/dbcore.dm index c98009ed9d9b..e1a43605613a 100644 --- a/code/controllers/subsystem/dbcore.dm +++ b/code/controllers/subsystem/dbcore.dm @@ -88,7 +88,7 @@ SUBSYSTEM_DEF(dbcore) log_config("ERROR: POOLING_MAX_SQL_CONNECTIONS ([max_sql_connections]) is set lower than POOLING_MIN_SQL_CONNECTIONS ([min_sql_connections]). Please check your config or the code defaults for sanity") /datum/controller/subsystem/dbcore/stat_entry(msg) - msg = "P:[length(all_queries)]|Active:[length(queries_active)]|Standby:[length(queries_standby)]" + msg = "\n P:[length(all_queries)]|Active:[length(queries_active)]|Standby:[length(queries_standby)]" return ..() /// Resets the tracking numbers on the subsystem. Used by SStime_track. diff --git a/code/controllers/subsystem/economy.dm b/code/controllers/subsystem/economy.dm index c146887ba299..bbc72ee44704 100644 --- a/code/controllers/subsystem/economy.dm +++ b/code/controllers/subsystem/economy.dm @@ -247,6 +247,32 @@ SUBSYSTEM_DEF(economy) var/obj/machinery/vending/vending = prices_to_update[i] vending.reset_prices(vending.product_records, vending.coin_records + vending.hidden_records) +/** + * Reassign the prices of the vending machine as a result of the inflation value, as provided by SSeconomy + * + * This rebuilds both /datum/data/vending_products lists for premium and standard products based on their most relevant pricing values. + * Arguments: + * * recordlist - the list of standard product datums in the vendor to refresh their prices. + * * premiumlist - the list of premium product datums in the vendor to refresh their prices. + */ +/obj/machinery/vending/proc/reset_prices(list/recordlist, list/premiumlist) + var/inflation_value = HAS_TRAIT(SSeconomy, TRAIT_MARKET_CRASHING) ? SSeconomy.inflation_value() : 1 + default_price = round(initial(default_price) * inflation_value) + extra_price = round(initial(extra_price) * inflation_value) + + for(var/datum/data/vending_product/record as anything in recordlist) + var/obj/item/potential_product = record.product_path + var/custom_price = round(initial(potential_product.custom_price) * inflation_value) + record.price = custom_price | default_price + for(var/datum/data/vending_product/premium_record as anything in premiumlist) + var/obj/item/potential_product = premium_record.product_path + var/premium_custom_price = round(initial(potential_product.custom_premium_price) * inflation_value) + var/custom_price = initial(potential_product.custom_price) + if(!premium_custom_price && custom_price) //For some ungodly reason, some premium only items only have a custom_price + premium_record.price = extra_price + round(custom_price * inflation_value) + else + premium_record.price = premium_custom_price || extra_price + /datum/controller/subsystem/economy/proc/inflict_moneybags(datum/bank_account/moneybags) if(!moneybags) return FALSE diff --git a/code/controllers/subsystem/explosions.dm b/code/controllers/subsystem/explosions.dm index 57af71f11c36..c885c8826280 100644 --- a/code/controllers/subsystem/explosions.dm +++ b/code/controllers/subsystem/explosions.dm @@ -45,7 +45,7 @@ SUBSYSTEM_DEF(explosions) /datum/controller/subsystem/explosions/stat_entry(msg) - msg += "C:{" + msg += "\n Cost:{" msg += "LT:[round(cost_lowturf,1)]|" msg += "MT:[round(cost_medturf,1)]|" msg += "HT:[round(cost_highturf,1)]|" @@ -59,7 +59,7 @@ SUBSYSTEM_DEF(explosions) msg += "} " - msg += "AMT:{" + msg += "\n Count:{" msg += "LT:[lowturf.len]|" msg += "MT:[medturf.len]|" msg += "HT:[highturf.len]|" @@ -72,7 +72,7 @@ SUBSYSTEM_DEF(explosions) msg += "TO:[throwturf.len]" msg += "HTO:[held_throwturf.len]" - msg += "} " + msg += "}" return ..() /datum/controller/subsystem/explosions/proc/is_exploding() diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index 844f52a860f6..bb1475a4f50e 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -63,19 +63,19 @@ SUBSYSTEM_DEF(garbage) var/list/counts = list() for (var/list/L in queues) counts += length(L) - msg += "Q:[counts.Join(",")]|D:[delslasttick]|G:[gcedlasttick]|" + msg += "\n Queue:[counts.Join(",")]|Dels:[delslasttick]|GCs:[gcedlasttick]|" msg += "GR:" if (!(delslasttick+gcedlasttick)) msg += "n/a|" else msg += "[round((gcedlasttick/(delslasttick+gcedlasttick))*100, 0.01)]%|" - msg += "TD:[totaldels]|TG:[totalgcs]|" + msg += "\n TD:[totaldels]|TG:[totalgcs]|" if (!(totaldels+totalgcs)) msg += "n/a|" else msg += "TGR:[round((totalgcs/(totaldels+totalgcs))*100, 0.01)]%" - msg += " P:[pass_counts.Join(",")]" + msg += "\n P:[pass_counts.Join(",")]" msg += "|F:[fail_counts.Join(",")]" return ..() diff --git a/code/controllers/subsystem/input.dm b/code/controllers/subsystem/input.dm index 66097a4077cb..11b75be8af75 100644 --- a/code/controllers/subsystem/input.dm +++ b/code/controllers/subsystem/input.dm @@ -94,6 +94,5 @@ VERB_MANAGER_SUBSYSTEM_DEF(input) current_clicks = 0 /datum/controller/subsystem/verb_manager/input/stat_entry(msg) - . = ..() - . += "M/S:[round(movements_per_second,0.01)] | C/S:[round(clicks_per_second,0.01)] ([round(delayed_clicks_per_second,0.01)] | CD: [round(average_click_delay / (1 SECONDS),0.01)])" - + msg = "\n M/S:[round(movements_per_second,0.01)] | C/S:[round(clicks_per_second,0.01)] ([round(delayed_clicks_per_second,0.01)] | CD: [round(average_click_delay / (1 SECONDS),0.01)])" + return ..() diff --git a/code/controllers/subsystem/ipintel.dm b/code/controllers/subsystem/ipintel.dm index d61789deb692..6ba87c02780c 100644 --- a/code/controllers/subsystem/ipintel.dm +++ b/code/controllers/subsystem/ipintel.dm @@ -41,7 +41,8 @@ SUBSYSTEM_DEF(ipintel) )) /datum/controller/subsystem/ipintel/stat_entry(msg) - return "[..()] | M: [CONFIG_GET(number/ipintel_rate_minute) - rate_limit_minute]" + msg = "M:[CONFIG_GET(number/ipintel_rate_minute) - rate_limit_minute]" + return ..() /datum/controller/subsystem/ipintel/proc/is_enabled() diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm index f73eb7f1c034..2bff25b00a59 100644 --- a/code/controllers/subsystem/lighting.dm +++ b/code/controllers/subsystem/lighting.dm @@ -16,7 +16,7 @@ SUBSYSTEM_DEF(lighting) #endif /datum/controller/subsystem/lighting/stat_entry(msg) - msg = "L:[length(sources_queue)]|C:[length(corners_queue)]|O:[length(objects_queue)]" + msg = "\n Sources:[length(sources_queue)]|Corners:[length(corners_queue)]|Objects:[length(objects_queue)]" return ..() diff --git a/code/controllers/subsystem/machines.dm b/code/controllers/subsystem/machines.dm index 1038926bf7cd..e3e0b0357a0d 100644 --- a/code/controllers/subsystem/machines.dm +++ b/code/controllers/subsystem/machines.dm @@ -86,7 +86,7 @@ SUBSYSTEM_DEF(machines) propagate_network(power_cable, power_cable.powernet) /datum/controller/subsystem/machines/stat_entry(msg) - msg = "M:[length(all_machines)]|MT:[length(machines_by_type)]|PM:[length(processing)]|PN:[length(powernets)]" + msg = "\n M:[length(all_machines)]|MT:[length(machines_by_type)]|PM:[length(processing)]|PN:[length(powernets)]" return ..() /datum/controller/subsystem/machines/fire(resumed = FALSE) diff --git a/code/controllers/subsystem/networks/id_access.dm b/code/controllers/subsystem/networks/id_access.dm index 43d5ea2b61a1..dd3299078712 100644 --- a/code/controllers/subsystem/networks/id_access.dm +++ b/code/controllers/subsystem/networks/id_access.dm @@ -457,7 +457,7 @@ SUBSYSTEM_DEF(id_access) if (ishuman(id_card.loc)) var/mob/living/carbon/human/owner = id_card.loc - owner.sec_hud_set_ID() + owner.update_ID_card() /** * Removes a trim from a ID card. @@ -478,7 +478,7 @@ SUBSYSTEM_DEF(id_access) if (ishuman(id_card.loc)) var/mob/living/carbon/human/owner = id_card.loc - owner.sec_hud_set_ID() + owner.update_ID_card() /** * Adds the accesses associated with a trim to an ID card. diff --git a/code/controllers/subsystem/networks/radio.dm b/code/controllers/subsystem/networks/radio.dm index 578b69b0d0ed..6d880cedeb30 100644 --- a/code/controllers/subsystem/networks/radio.dm +++ b/code/controllers/subsystem/networks/radio.dm @@ -11,6 +11,15 @@ SUBSYSTEM_DEF(radio) saymodes[SM.key] = SM return ..() +/// Gets the say mode associated with the given key, if available to the given user. +/datum/controller/subsystem/radio/proc/get_available_say_mode(mob/living/user, key) + var/datum/saymode/selected_saymode = SSradio.saymodes[key] + if(isnull(selected_saymode)) + return + if(!selected_saymode.can_be_used_by(user)) + return + return selected_saymode + /datum/controller/subsystem/radio/proc/add_object(obj/device, new_frequency as num, filter = null as text|null) var/f_text = num2text(new_frequency) var/datum/radio_frequency/frequency = frequencies[f_text] diff --git a/code/controllers/subsystem/polling.dm b/code/controllers/subsystem/polling.dm index 1577672caf12..1477fa7e7c36 100644 --- a/code/controllers/subsystem/polling.dm +++ b/code/controllers/subsystem/polling.dm @@ -328,7 +328,7 @@ SUBSYSTEM_DEF(polling) QDEL_IN(finishing_poll, 0.5 SECONDS) /datum/controller/subsystem/polling/stat_entry(msg) - msg += "Active: [length(currently_polling)] | Total: [total_polls]" + msg = "\n Active: [length(currently_polling)] | Total: [total_polls]" var/datum/candidate_poll/soonest_to_complete = get_next_poll_to_finish() if(soonest_to_complete) msg += " | Next: [DisplayTimeText(soonest_to_complete.time_left())] ([length(soonest_to_complete.signed_up)] candidates)" diff --git a/code/controllers/subsystem/processing/greyscale.dm b/code/controllers/subsystem/processing/greyscale.dm index 4b77aa3e7b4b..f88b960e869f 100644 --- a/code/controllers/subsystem/processing/greyscale.dm +++ b/code/controllers/subsystem/processing/greyscale.dm @@ -1,7 +1,6 @@ /// Disable to use builtin DM-based generation. /// IconForge is 250x times faster but requires storing the icons in tmp/ and may result in higher asset transport. /// Note that the builtin GAGS editor still uses the 'legacy' generation to allow for debugging. -/// IconForge also does not support the color matrix layer type or the 'or' blend_mode, however both are currently unused. #define USE_RUSTG_ICONFORGE_GAGS PROCESSING_SUBSYSTEM_DEF(greyscale) diff --git a/code/controllers/subsystem/radiation.dm b/code/controllers/subsystem/radiation.dm index 6a9cc631cf52..a129c2a34641 100644 --- a/code/controllers/subsystem/radiation.dm +++ b/code/controllers/subsystem/radiation.dm @@ -26,7 +26,7 @@ SUBSYSTEM_DEF(radiation) processing.Cut(1, 2) /datum/controller/subsystem/radiation/stat_entry(msg) - msg = "[msg] | Pulses: [processing.len]" + msg = "Pulses:[processing.len]" return ..() /datum/controller/subsystem/radiation/proc/pulse(atom/source, datum/radiation_pulse_information/pulse_information) diff --git a/code/controllers/subsystem/spatial_gridmap.dm b/code/controllers/subsystem/spatial_gridmap.dm index f4f1036593a7..f2d6c20554fb 100644 --- a/code/controllers/subsystem/spatial_gridmap.dm +++ b/code/controllers/subsystem/spatial_gridmap.dm @@ -104,6 +104,9 @@ SUBSYSTEM_DEF(spatial_grid) ///how many pregenerated /mob/oranges_ear instances currently exist. this should hopefully never exceed its starting value var/number_of_oranges_ears = NUMBER_OF_PREGENERATED_ORANGES_EARS + ///for debugging, stores a list of grids with colors to paint atoms with + var/list/cells_with_color + /datum/controller/subsystem/spatial_grid/Initialize() cells_on_x_axis = SPATIAL_GRID_CELLS_PER_SIDE(world.maxx) cells_on_y_axis = SPATIAL_GRID_CELLS_PER_SIDE(world.maxy) @@ -843,6 +846,31 @@ SUBSYSTEM_DEF(spatial_grid) the average client distance is: [average_client_distance], the average hearable_distance is [average_hearable_distance], \ and the average atmos distance is [average_atmos_distance] ") +//A debugging proc that colors objects based on what grid they belong to +/datum/controller/subsystem/spatial_grid/proc/paint_grids() + cells_with_color = list() + for(var/list/z_level_grid as anything in grids_by_z_level) + for(var/list/cell_row as anything in z_level_grid) + for(var/datum/spatial_grid_cell/cell as anything in cell_row) + cells_with_color[cell] = RANDOM_COLOUR + for(var/atom/thing in world.contents) + var/datum/spatial_grid_cell/things_cell = get_cell_of(thing) + if(!things_cell) + continue + thing.add_atom_colour(cells_with_color[things_cell], ADMIN_COLOUR_PRIORITY) + if(ismovable(thing)) + RegisterSignal(thing, COMSIG_MOVABLE_MOVED, PROC_REF(update_color)) + CHECK_TICK + +//A debugging proc that colors objects based on what grid they belong to +/datum/controller/subsystem/spatial_grid/proc/update_color(atom/movable/thing) + SIGNAL_HANDLER + + var/datum/spatial_grid_cell/things_cell = get_cell_of(thing) + if(!isdatum(things_cell)) + return + thing.add_atom_colour(cells_with_color[things_cell], ADMIN_COLOUR_PRIORITY) + #undef BOUNDING_BOX_MAX #undef BOUNDING_BOX_MIN diff --git a/code/controllers/subsystem/statpanel.dm b/code/controllers/subsystem/statpanel.dm index e139ff8a8135..d7d4b38793d4 100644 --- a/code/controllers/subsystem/statpanel.dm +++ b/code/controllers/subsystem/statpanel.dm @@ -195,7 +195,7 @@ SUBSYSTEM_DEF(statpanels) list("World Time:", "[world.time]"), list("Globals:", GLOB.stat_entry(), text_ref(GLOB)), list("[config]:", config.stat_entry(), text_ref(config)), - list("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%)) (Internal Tick Usage: [round(MAPTICK_LAST_INTERNAL_TICK_USAGE,0.1)]%)"), + list("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%))\n (Internal Tick Usage: [round(MAPTICK_LAST_INTERNAL_TICK_USAGE,0.1)]%)"), list("Master Controller:", Master.stat_entry(), text_ref(Master)), list("Failsafe Controller:", Failsafe.stat_entry(), text_ref(Failsafe)), list("","") diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 60898e26bbc1..1450bab9b0d7 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -142,13 +142,15 @@ SUBSYSTEM_DEF(ticker) GLOB.syndicate_code_response_regex = codeword_match - start_at = world.time + (CONFIG_GET(number/lobby_countdown) * 10) + start_at = world.time + (CONFIG_GET(number/lobby_countdown) * (1 SECONDS)) + round_start_time = start_at // May be changed later, but prevents the time from jumping back when the round actually starts if(CONFIG_GET(flag/randomize_shift_time)) - gametime_offset = rand(0, 23) HOURS + gametime_offset = rand(0, 23) * (1 HOURS) else if(CONFIG_GET(flag/shift_time_realtime)) - gametime_offset = world.timeofday + gametime_offset = world.timeofday + GLOB.timezoneOffset + station_time_rate_multiplier = 1 else - gametime_offset = (CONFIG_GET(number/shift_time_start_hour) HOURS) + gametime_offset = (CONFIG_GET(number/shift_time_start_hour) * (1 HOURS)) return SS_INIT_SUCCESS /datum/controller/subsystem/ticker/fire() diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm index 2b2d9393287a..20fe4eb47b60 100644 --- a/code/controllers/subsystem/timer.dm +++ b/code/controllers/subsystem/timer.dm @@ -55,7 +55,7 @@ SUBSYSTEM_DEF(timer) bucket_resolution = world.tick_lag /datum/controller/subsystem/timer/stat_entry(msg) - msg = "B:[bucket_count] P:[length(second_queue)] H:[length(hashes)] C:[length(clienttime_timers)] S:[length(timer_id_dict)] RST:[bucket_reset_count]" + msg = "\n B:[bucket_count] P:[length(second_queue)] H:[length(hashes)] C:[length(clienttime_timers)] S:[length(timer_id_dict)] RST:[bucket_reset_count]" return ..() /datum/controller/subsystem/timer/proc/dump_timer_buckets(full = TRUE) diff --git a/code/controllers/subsystem/tts.dm b/code/controllers/subsystem/tts.dm index 9d3f7d6b76f5..1106318e021c 100644 --- a/code/controllers/subsystem/tts.dm +++ b/code/controllers/subsystem/tts.dm @@ -45,7 +45,7 @@ SUBSYSTEM_DEF(tts) return ..() /datum/controller/subsystem/tts/stat_entry(msg) - msg = "Active:[length(in_process_http_messages)]|Standby:[length(queued_http_messages?.L)]|Avg:[average_tts_messages_time]" + msg = "\n Active:[length(in_process_http_messages)]|Standby:[length(queued_http_messages?.L)]|Avg:[average_tts_messages_time]" return ..() /proc/cmp_word_length_asc(datum/tts_request/a, datum/tts_request/b) diff --git a/code/controllers/subsystem/unplanned_controllers.dm b/code/controllers/subsystem/unplanned_controllers.dm index a53061aa504e..49fbcb2e83b5 100644 --- a/code/controllers/subsystem/unplanned_controllers.dm +++ b/code/controllers/subsystem/unplanned_controllers.dm @@ -23,7 +23,7 @@ SUBSYSTEM_DEF(unplanned_controllers) return ..() /datum/controller/subsystem/unplanned_controllers/stat_entry(msg) - msg = "Planning AIs:[length(GLOB.unplanned_controllers[target_status])]" + msg = "\n Planning AIs:[length(GLOB.unplanned_controllers[target_status])]" return ..() /datum/controller/subsystem/unplanned_controllers/fire(resumed) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 5dd3f537bfc2..776c787f0a4a 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -461,7 +461,7 @@ SUBSYSTEM_DEF(vote) /datum/action/vote/IsAvailable(feedback = FALSE) return TRUE // Democracy is always available to the free people -/datum/action/vote/Trigger(trigger_flags) +/datum/action/vote/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return diff --git a/code/controllers/subsystem/wardrobe.dm b/code/controllers/subsystem/wardrobe.dm index 55288bc025ac..2593595bdf63 100644 --- a/code/controllers/subsystem/wardrobe.dm +++ b/code/controllers/subsystem/wardrobe.dm @@ -66,10 +66,9 @@ SUBSYSTEM_DEF(wardrobe) /datum/controller/subsystem/wardrobe/stat_entry(msg) var/total_provided = max(stock_hit + stock_miss, 1) var/current_max_store = (one_go_master * cache_intensity) + (overflow_lienency * length(canon_minimum)) - msg += " P:[length(canon_minimum)] Q:[length(order_list)] S:[length(preloaded_stock)] I:[cache_intensity] O:[overflow_lienency]" - msg += " H:[stock_hit] M:[stock_miss] T:[total_provided] H/T:[PERCENT(stock_hit / total_provided)]% M/T:[PERCENT(stock_miss / total_provided)]%" - msg += " MAX:[current_max_store]" - msg += " ID:[inspect_delay] NI:[last_inspect_time + inspect_delay]" + msg += "\n P:[length(canon_minimum)] Q:[length(order_list)] S:[length(preloaded_stock)] I:[cache_intensity] O:[overflow_lienency] MAX:[current_max_store]" + msg += "\n H:[stock_hit] M:[stock_miss] T:[total_provided] H/T:[PERCENT(stock_hit / total_provided)]% M/T:[PERCENT(stock_miss / total_provided)]%" + msg += "\n ID:[inspect_delay] NI:[last_inspect_time + inspect_delay]" return ..() /datum/controller/subsystem/wardrobe/fire(resumed=FALSE) diff --git a/code/datums/achievements/mafia_achievements.dm b/code/datums/achievements/mafia_achievements.dm index 31462f7a0ce2..22c911305cce 100644 --- a/code/datums/achievements/mafia_achievements.dm +++ b/code/datums/achievements/mafia_achievements.dm @@ -23,10 +23,16 @@ /datum/award/achievement/mafia/chaplain name = "Chaplain Victory" - desc = "Useless... until the one night the thoughtfeeder confidently claims themselves as detective. Mafia's true bullshit detector." + desc = "The curse finally broken." database_id = MAFIA_MEDAL_CHAPLAIN icon_state = "town" +/datum/award/achievement/mafia/coroner + name = "Coroner Victory" + desc = "Useless... until the one night the thoughtfeeder confidently claims themselves as detective. Mafia's true bullshit detector." + database_id = MAFIA_MEDAL_CORONER + icon_state = "town" + /datum/award/achievement/mafia/md name = "Medical Doctor Victory" desc = "Congratulations on learning how to not talk!" diff --git a/code/datums/actions/action.dm b/code/datums/actions/action.dm index 12d46c02e4a3..65c314d4fc97 100644 --- a/code/datums/actions/action.dm +++ b/code/datums/actions/action.dm @@ -162,7 +162,7 @@ /// Actually triggers the effects of the action. /// Called when the on-screen button is clicked, for example. -/datum/action/proc/Trigger(trigger_flags) +/datum/action/proc/Trigger(mob/clicker, trigger_flags) if(!(trigger_flags & TRIGGER_FORCE_AVAILABLE) && !IsAvailable(feedback = TRUE)) return FALSE if(SEND_SIGNAL(src, COMSIG_ACTION_TRIGGER, src) & COMPONENT_ACTION_BLOCK_TRIGGER) @@ -432,15 +432,15 @@ /datum/action/proc/is_action_active(atom/movable/screen/movable/action_button/current_button) return FALSE -/datum/action/proc/begin_creating_bind(mob/user) - if(!user != owner) +/datum/action/proc/begin_creating_bind(atom/movable/screen/movable/action_button/current_button, mob/user) + if(!current_button || user != owner) return if(!isnull(full_key)) full_key = null - update_button_status(src) + update_button_status(current_button) return full_key = tgui_input_keycombo(user, "Please bind a key for this action.") - update_button_status(src) + update_button_status(current_button) /datum/action/proc/keydown(mob/source, key, client/client, full_key) SIGNAL_HANDLER diff --git a/code/datums/actions/cooldown_action.dm b/code/datums/actions/cooldown_action.dm index c45fbda9fed5..9f1bd18f29da 100644 --- a/code/datums/actions/cooldown_action.dm +++ b/code/datums/actions/cooldown_action.dm @@ -215,14 +215,14 @@ for(var/datum/action/cooldown/cd_action in owner.actions) cd_action.disable() -/datum/action/cooldown/Trigger(trigger_flags, atom/target) +/datum/action/cooldown/Trigger(mob/clicker, trigger_flags, atom/target) . = ..() if(!.) return FALSE if(!owner) return FALSE - var/mob/user = usr || owner + var/mob/user = clicker || owner // If our cooldown action is a click_to_activate action: // The actual action is activated on whatever the user clicks on - diff --git a/code/datums/actions/innate_action.dm b/code/datums/actions/innate_action.dm index b907ba619579..53899ddf2285 100644 --- a/code/datums/actions/innate_action.dm +++ b/code/datums/actions/innate_action.dm @@ -12,7 +12,7 @@ /// If we're a click action, the text shown on disable var/disable_text -/datum/action/innate/Trigger(trigger_flags) +/datum/action/innate/Trigger(mob/clicker, trigger_flags) if(!..()) return FALSE // We're a click action, trigger just sets it as active or not diff --git a/code/datums/actions/item_action.dm b/code/datums/actions/item_action.dm index e5fa0cf561d8..1de226b68320 100644 --- a/code/datums/actions/item_action.dm +++ b/code/datums/actions/item_action.dm @@ -23,7 +23,7 @@ else qdel(GetComponent(/datum/component/action_item_overlay)) -/datum/action/item_action/Trigger(trigger_flags) +/datum/action/item_action/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return FALSE diff --git a/code/datums/actions/mobs/adjust_vision.dm b/code/datums/actions/mobs/adjust_vision.dm index 009bd7b1c018..4a6270d321b2 100644 --- a/code/datums/actions/mobs/adjust_vision.dm +++ b/code/datums/actions/mobs/adjust_vision.dm @@ -30,7 +30,7 @@ UnregisterSignal(remove_from, COMSIG_MOB_UPDATE_SIGHT) . = ..() -/datum/action/adjust_vision/Trigger(trigger_flags) +/datum/action/adjust_vision/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return diff --git a/code/datums/actions/mobs/blood_warp.dm b/code/datums/actions/mobs/blood_warp.dm index d65c941f5df4..0cf7f42fd9d5 100644 --- a/code/datums/actions/mobs/blood_warp.dm +++ b/code/datums/actions/mobs/blood_warp.dm @@ -3,7 +3,7 @@ button_icon = 'icons/effects/blood.dmi' button_icon_state = "floor1" desc = "Allows you to teleport to blood at a clicked position." - cooldown_time = 0 + cooldown_time = 0 SECONDS /// The range of turfs to try to jaunt to from around the target var/pick_range = 5 /// The range of turfs if a client is using this ability diff --git a/code/datums/actions/mobs/personality_commune.dm b/code/datums/actions/mobs/personality_commune.dm index 8481d451fb1d..592e675e3c9f 100644 --- a/code/datums/actions/mobs/personality_commune.dm +++ b/code/datums/actions/mobs/personality_commune.dm @@ -22,7 +22,7 @@ return ..() -/datum/action/personality_commune/Trigger(trigger_flags) +/datum/action/personality_commune/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return FALSE diff --git a/code/datums/beam.dm b/code/datums/beam.dm index c2dd73a5a525..0a044e6b7a56 100644 --- a/code/datums/beam.dm +++ b/code/datums/beam.dm @@ -80,13 +80,7 @@ */ /datum/beam/proc/Start() visuals = new beam_type() - visuals.icon = icon - visuals.icon_state = icon_state - visuals.color = beam_color - visuals.vis_flags = VIS_INHERIT_PLANE|VIS_INHERIT_LAYER - visuals.emissive = emissive - visuals.layer = beam_layer - visuals.update_appearance() + set_up_effect(visuals, icon_state) Draw() RegisterSignals(origin, list(COMSIG_MOVABLE_MOVED, COMSIG_QDELETING), PROC_REF(redrawing)) RegisterSignals(target, list(COMSIG_MOVABLE_MOVED, COMSIG_QDELETING), PROC_REF(redrawing)) @@ -146,15 +140,14 @@ var/obj/effect/ebeam/segment = new beam_type(origin_turf, src) elements += segment - //Assign our single visual ebeam to each ebeam's vis_contents //ends are cropped by a transparent box icon of length-N pixel size laid over the visuals obj if(N+32>length) //went past the target, we draw a box of space to cut away from the beam sprite so the icon actually ends at the center of the target sprite - var/icon/II = new(icon, icon_state)//this means we exclude the overshooting object from the visual contents which does mean those visuals don't show up for the final bit of the beam... - II.DrawBox(null,1,(length-N),32,32)//in the future if you want to improve this, remove the drawbox and instead use a 513 filter to cut away at the final object's icon - segment.icon = II + var/icon/terminal_icon = new(icon, icon_state)//this means we exclude the overshooting object from the visual contents which does mean those visuals don't show up for the final bit of the beam... + terminal_icon.DrawBox(null,1,(length-N),32,32)//in the future if you want to improve this, remove the drawbox and instead use a 513 filter to cut away at the final object's icon + segment.icon = terminal_icon segment.color = beam_color else - segment.vis_contents += visuals + set_subsegment_appearance(segment) segment.transform = rot_matrix //Calculate pixel offsets (If necessary) @@ -184,6 +177,50 @@ segment.pixel_y = origin_py + Pixel_y CHECK_TICK +/datum/beam/proc/set_up_effect(obj/effect/ebeam/beam_effect, effect_icon_state) + beam_effect.icon = icon + beam_effect.icon_state = effect_icon_state + beam_effect.color = beam_color + beam_effect.vis_flags = VIS_INHERIT_PLANE|VIS_INHERIT_LAYER + beam_effect.emissive = emissive + beam_effect.layer = beam_layer + beam_effect.update_appearance() + +///sets the sprite of the segment, using the more performant viscontents by default +/datum/beam/proc/set_subsegment_appearance(obj/effect/ebeam/segment) + //Assign our single visual ebeam to each ebeam's vis_contents + segment.vis_contents += visuals + +//for when you don't want each segment to look identital +/datum/beam/varied + //how many variants do we have in addition to the unnumbered state we use as a base icon state and terminal segment + var/icon_state_variants = 1 + +/datum/beam/varied/New( + origin, + target, + icon = 'icons/effects/beam.dmi', + icon_state = "b_beam", + time = INFINITY, + max_distance = INFINITY, + beam_type = /obj/effect/ebeam, + beam_color = null, + emissive = TRUE, + override_origin_pixel_x = null, + override_origin_pixel_y = null, + override_target_pixel_x = null, + override_target_pixel_y = null, + beam_layer = ABOVE_ALL_MOB_LAYER, + icon_state_variants = 1 + ) + . = ..() + + src.icon_state_variants = icon_state_variants + +/datum/beam/varied/set_subsegment_appearance(obj/effect/ebeam/segment) + //we use reall ass icon states here. + set_up_effect(segment, "[icon_state][rand(1, icon_state_variants)]") + /obj/effect/ebeam mouse_opacity = MOUSE_OPACITY_TRANSPARENT layer = ABOVE_ALL_MOB_LAYER @@ -298,8 +335,14 @@ override_origin_pixel_y = null, override_target_pixel_x = null, override_target_pixel_y = null, - layer = ABOVE_ALL_MOB_LAYER + layer = ABOVE_ALL_MOB_LAYER, + icon_state_variants = 0, ) - var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type, beam_color, emissive, override_origin_pixel_x, override_origin_pixel_y, override_target_pixel_x, override_target_pixel_y, layer) + var/datum/beam/newbeam + + if(icon_state_variants <= 0) + newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type, beam_color, emissive, override_origin_pixel_x, override_origin_pixel_y, override_target_pixel_x, override_target_pixel_y, layer) + else + newbeam = new /datum/beam/varied(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type, beam_color, emissive, override_origin_pixel_x, override_origin_pixel_y, override_target_pixel_x, override_target_pixel_y, layer, icon_state_variants) INVOKE_ASYNC(newbeam, TYPE_PROC_REF(/datum/beam/, Start)) return newbeam diff --git a/code/datums/brain_damage/creepy_trauma.dm b/code/datums/brain_damage/creepy_trauma.dm index 3e3c4bd61532..99cbaab630d0 100644 --- a/code/datums/brain_damage/creepy_trauma.dm +++ b/code/datums/brain_damage/creepy_trauma.dm @@ -12,8 +12,8 @@ var/datum/antagonist/obsessed/antagonist var/viewing = FALSE //it's a lot better to store if the owner is watching the obsession than checking it twice between two procs - var/total_time_creeping = 0 //just for round end fun - var/time_spent_away = 0 + var/total_time_creeping = 0 SECONDS //just for round end fun + var/time_spent_away = 0 SECONDS var/obsession_hug_count = 0 /datum/brain_trauma/special/obsessed/on_gain() @@ -50,15 +50,15 @@ if(viewing) owner.add_mood_event("creeping", /datum/mood_event/creeping, obsession.name) total_time_creeping += seconds_per_tick SECONDS - time_spent_away = 0 + time_spent_away = 0 SECONDS if(attachedobsessedobj)//if an objective needs to tick down, we can do that since traumas coexist with the antagonist datum attachedobsessedobj.timer -= seconds_per_tick SECONDS //mob subsystem ticks every 2 seconds(?), remove 20 deciseconds from the timer. sure, that makes sense. else out_of_view() /datum/brain_trauma/special/obsessed/proc/out_of_view() - time_spent_away += 20 - if(time_spent_away > 1800) //3 minutes + time_spent_away += 2 SECONDS + if(time_spent_away > 3 MINUTES) //3 minutes owner.add_mood_event("creeping", /datum/mood_event/notcreepingsevere, obsession.name) else owner.add_mood_event("creeping", /datum/mood_event/notcreeping, obsession.name) diff --git a/code/datums/brain_damage/imaginary_friend.dm b/code/datums/brain_damage/imaginary_friend.dm index 449b0ec06574..617f590e5fbd 100644 --- a/code/datums/brain_damage/imaginary_friend.dm +++ b/code/datums/brain_damage/imaginary_friend.dm @@ -223,7 +223,6 @@ /mob/eye/imaginary_friend/send_speech(message, range = IMAGINARY_FRIEND_SPEECH_RANGE, obj/source = src, bubble_type = bubble_icon, list/spans = list(), datum/language/message_language = null, list/message_mods = list(), forced = null) message = get_message_mods(message, message_mods) - message = capitalize(message) if(message_mods[RADIO_EXTENSION] == MODE_ADMIN) SSadmin_verbs.dynamic_invoke_verb(client, /datum/admin_verb/cmd_admin_say, message) @@ -236,6 +235,9 @@ if(check_emote(message, forced)) return + message = check_for_custom_say_emote(message, message_mods) + message = capitalize(message) + if(message_mods[MODE_SING]) var/randomnote = pick("♩", "♪", "♫") message = "[randomnote] [capitalize(message)] [randomnote]" @@ -246,21 +248,17 @@ var/eavesdrop_range = 0 - if (message_mods[MODE_CUSTOM_SAY_ERASE_INPUT]) - message = message_mods[MODE_CUSTOM_SAY_EMOTE] - log_message(message, LOG_RADIO_EMOTE) - else + if(!(message_mods[MODE_CUSTOM_SAY_ERASE_INPUT])) if(message_mods[WHISPER_MODE] == MODE_WHISPER) - log_talk(message, LOG_WHISPER, tag="imaginary friend", forced_by = forced, custom_say_emote = message_mods[MODE_CUSTOM_SAY_EMOTE]) spans |= SPAN_ITALICS eavesdrop_range = EAVESDROP_EXTRA_RANGE range = WHISPER_RANGE - else - log_talk(message, LOG_SAY, tag="imaginary friend", forced_by = forced, custom_say_emote = message_mods[MODE_CUSTOM_SAY_EMOTE]) - var/quoted_message = say_quote(apply_message_emphasis(message), spans, message_mods) - var/rendered = "[span_name("[name]")] [quoted_message]" - var/dead_rendered = "[span_name("[name] (Imaginary friend of [owner])")] [quoted_message]" + log_sayverb_talk(message, message_mods, tag = "imaginary friend", forced_by = forced) + + var/messagepart = generate_messagepart(message, spans, message_mods) + var/rendered = "[span_name("[name]")] [messagepart]" + var/dead_rendered = "[span_name("[name] (Imaginary friend of [owner])")] [messagepart]" var/language = message_language || owner.get_selected_language() Hear(rendered, src, language, message, null, null, null, spans, message_mods) // We always hear what we say diff --git a/code/datums/components/anti_magic.dm b/code/datums/components/anti_magic.dm index a96ad73e93dd..29855ac6c476 100644 --- a/code/datums/components/anti_magic.dm +++ b/code/datums/components/anti_magic.dm @@ -7,10 +7,12 @@ var/charges /// The inventory slot the object must be located at in order to activate var/inventory_flags - /// The callback invoked when we have been drained a antimagic charge - var/datum/callback/drain_antimagic + /// The callback invoked when we block magic + var/datum/callback/block_magic /// The callback invoked when twe have been depleted of all charges var/datum/callback/expiration + /// Callback to invoke to see if we can block magic + var/datum/callback/check_blocking /// Whether we should, on equipping, alert the caster that this item can block any of their spells /// This changes between true and false on equip and drop, don't set it outright to something var/alert_caster_on_equip = TRUE @@ -25,8 +27,9 @@ * * antimagic_flags (optional) A bitflag with the types of magic resistance on the object * * charges (optional) The amount of times the object can protect the user from magic * * inventory_flags (optional) The inventory slot the object must be located at in order to activate - * * drain_antimagic (optional) The proc that is triggered when an object has been drained a antimagic charge + * * block_magic (optional) The proc that is triggered when an object blocks magic * * expiration (optional) The proc that is triggered when the object is depleted of charges + * * check_blocking (optional) The proc that is triggered to check if we can block magic * * * antimagic bitflags: (see code/__DEFINES/magic.dm) * * MAGIC_RESISTANCE - Default magic resistance that blocks normal magic (wizard, spells, staffs) @@ -37,8 +40,9 @@ antimagic_flags = MAGIC_RESISTANCE, charges = INFINITY, inventory_flags = ALL, - datum/callback/drain_antimagic, + datum/callback/block_magic, datum/callback/expiration, + datum/callback/check_blocking, ) @@ -67,11 +71,12 @@ src.antimagic_flags = antimagic_flags src.charges = charges src.inventory_flags = inventory_flags - src.drain_antimagic = drain_antimagic + src.block_magic = block_magic src.expiration = expiration + src.check_blocking = check_blocking /datum/component/anti_magic/Destroy(force) - drain_antimagic = null + block_magic = null expiration = null return ..() @@ -124,6 +129,9 @@ /datum/component/anti_magic/proc/block_receiving_magic(mob/living/carbon/source, casted_magic_flags, charge_cost, list/antimagic_sources) SIGNAL_HANDLER + if(check_blocking && !check_blocking.Invoke()) + return NONE + // We do not block this type of magic, good day if(!(casted_magic_flags & antimagic_flags)) return NONE @@ -135,8 +143,8 @@ // Block success! Add this parent to the list of antimagic sources antimagic_sources += parent + block_magic?.Invoke(source, parent) if((charges != INFINITY) && charge_cost > 0) - drain_antimagic?.Invoke(source, parent) charges -= charge_cost if(charges <= 0) expiration?.Invoke(source, parent) diff --git a/code/datums/components/aquarium.dm b/code/datums/components/aquarium.dm index 576852a471ef..fd442427bbb9 100644 --- a/code/datums/components/aquarium.dm +++ b/code/datums/components/aquarium.dm @@ -617,7 +617,7 @@ "fish_happiness" = fish.get_happiness_value(), "fish_icon" = fish::icon, "fish_icon_state" = fish::icon_state, - "fish_health" = fish.health, + "fish_alive" = fish.status == FISH_ALIVE, )) continue .["propData"] += list(list( diff --git a/code/datums/components/bakeable.dm b/code/datums/components/bakeable.dm index 5d54bbd81703..a7296eb1202c 100644 --- a/code/datums/components/bakeable.dm +++ b/code/datums/components/bakeable.dm @@ -29,6 +29,18 @@ if(positive_result) ADD_TRAIT(parent, TRAIT_BAKEABLE, REF(src)) + + var/obj/item/item_target = parent + if(!PERFORM_ALL_TESTS(focus_only/check_materials_when_processed) || !positive_result || !item_target.custom_materials) + return + + var/atom/result = new bake_result + if(!item_target.compare_materials(result)) + var/warning = "custom_materials of [result.type] when baked compared to just spawned don't match" + var/what_it_should_be = item_target.get_materials_english_list() + stack_trace("[warning]. custom_materials should be [what_it_should_be].") + qdel(result) + // Inherit the new values passed to the component /datum/component/bakeable/InheritComponent(datum/component/bakeable/new_comp, original, bake_result, required_bake_time, positive_result, use_large_steam_sprite) if(!original) @@ -113,6 +125,7 @@ ignored_mobs = asomnia_hadders, ) SEND_SIGNAL(parent, COMSIG_ITEM_BAKED, baked_result) + SEND_SIGNAL(baked_result, COMSIG_ITEM_BAKED_RESULT, parent) qdel(parent) ///Gives info about the items baking status so you can see if its almost done diff --git a/code/datums/components/blob_minion.dm b/code/datums/components/blob_minion.dm index a17fd4b4a15d..75eee8410d25 100644 --- a/code/datums/components/blob_minion.dm +++ b/code/datums/components/blob_minion.dm @@ -172,11 +172,17 @@ /// We only speak telepathically to blobs /datum/component/blob_minion/proc/on_try_speech(mob/living/minion, message, ignore_spam, forced) SIGNAL_HANDLER - minion.log_talk(message, LOG_SAY, tag = "blob hivemind telepathy") - var/spanned_message = minion.say_quote(message) + INVOKE_ASYNC(src, PROC_REF(send_blob_telepathy), minion, message) + return COMPONENT_CANNOT_SPEAK + +/datum/component/blob_minion/proc/send_blob_telepathy(mob/living/minion, message) + var/list/message_mods = list() + // Note: check_for_custom_say_emote can sleep. + var/adjusted_message = minion.check_for_custom_say_emote(message, message_mods) + minion.log_sayverb_talk(message, message_mods, tag = "blob hivemind telepathy") + var/spanned_message = minion.generate_messagepart(adjusted_message, message_mods = message_mods) var/rendered = span_blob("\[Blob Telepathy\] [minion.real_name] [spanned_message]") relay_to_list_and_observers(rendered, GLOB.blob_telepathy_mobs, minion, MESSAGE_TYPE_RADIO) - return COMPONENT_CANNOT_SPEAK /// Called when a blob minion is transformed into something else, hopefully a spore into a zombie /datum/component/blob_minion/proc/on_transformed(mob/living/minion, mob/living/replacement) diff --git a/code/datums/components/crafting/equipment.dm b/code/datums/components/crafting/equipment.dm index cc57f4c1641f..84c031afe114 100644 --- a/code/datums/components/crafting/equipment.dm +++ b/code/datums/components/crafting/equipment.dm @@ -151,7 +151,7 @@ /datum/crafting_recipe/flashlight_eyes name = "Flashlight Eyes" result = /obj/item/organ/eyes/robotic/flashlight - time = 10 + time = 1 SECONDS reqs = list( /obj/item/flashlight = 2, /obj/item/restraints/handcuffs/cable = 1 @@ -225,7 +225,7 @@ /datum/crafting_recipe/ghettojetpack name = "Improvised Jetpack" result = /obj/item/tank/jetpack/improvised - time = 30 + time = 3 SECONDS reqs = list( /obj/item/tank/internals/oxygen = 2, /obj/item/extinguisher = 1, @@ -262,7 +262,7 @@ /datum/crafting_recipe/rebar_quiver name = "Rebar Storage Quiver" result = /obj/item/storage/bag/rebar_quiver - time = 10 + time = 1 SECONDS reqs = list( /obj/item/tank/internals/oxygen = 1, /obj/item/stack/cable_coil = 15, @@ -273,7 +273,7 @@ /datum/crafting_recipe/arrow_quiver name = "Archery Quiver" result = /obj/item/storage/bag/quiver/lesser - time = 10 + time = 1 SECONDS reqs = list( /obj/item/stack/sheet/leather = 4, /obj/item/stack/sheet/cardboard = 4 diff --git a/code/datums/components/crafting/guncrafting.dm b/code/datums/components/crafting/guncrafting.dm index 67e84083a5b4..42d21ba12bfc 100644 --- a/code/datums/components/crafting/guncrafting.dm +++ b/code/datums/components/crafting/guncrafting.dm @@ -70,6 +70,7 @@ /obj/item/weaponcrafting/gunkit/tesla name = "tesla cannon parts kit (lethal)" desc = "A suitcase containing the necessary gun parts to construct a tesla cannon around a stabilized flux anomaly. Handle with care." + icon_state = "weaponskit_tesla" /obj/item/weaponcrafting/gunkit/xray name = "x-ray laser gun parts kit (lethal)" diff --git a/code/datums/components/earprotection.dm b/code/datums/components/earprotection.dm index 6dfa7d9568ba..542a1d0c60f3 100644 --- a/code/datums/components/earprotection.dm +++ b/code/datums/components/earprotection.dm @@ -3,10 +3,10 @@ mobtype = /mob/living/carbon proctype = PROC_REF(reducebang) var/reduce_amount = 1 + valid_slots = ITEM_SLOT_EARS | ITEM_SLOT_HEAD -/datum/component/wearertargeting/earprotection/Initialize(valid_slots, reduce_amount = 1) +/datum/component/wearertargeting/earprotection/Initialize(reduce_amount = 1) . = ..() - src.valid_slots = valid_slots if(reduce_amount) src.reduce_amount = reduce_amount diff --git a/code/datums/components/echolocation.dm b/code/datums/components/echolocation.dm index 915b99843ce5..a40c14306290 100644 --- a/code/datums/components/echolocation.dm +++ b/code/datums/components/echolocation.dm @@ -127,7 +127,7 @@ /datum/component/echolocation/proc/show_image(image/input_appearance, atom/input, current_time) var/image/final_image = image(input_appearance) - //final_image.layer += FOV_EFFECT_LAYER + final_image.layer += EFFECTS_LAYER final_image.plane = FULLSCREEN_PLANE final_image.loc = images_are_static ? get_turf(input) : input final_image.dir = input.dir diff --git a/code/datums/components/fearful/effects.dm b/code/datums/components/fearful/effects.dm index a46f922bd5f1..b2b4458cbfa1 100644 --- a/code/datums/components/fearful/effects.dm +++ b/code/datums/components/fearful/effects.dm @@ -108,6 +108,8 @@ var/active_attack = FALSE /// Breath loop used during a panic attack var/datum/looping_sound/breathing/breath_loop + /// Timer that will stop our panic attack + var/panic_end_timer = null /datum/terror_handler/panic/New(mob/living/new_owner, datum/component/fearful/new_component) . = ..() @@ -116,12 +118,13 @@ /datum/terror_handler/panic/Destroy(force) owner.remove_fov_trait(type, FOV_270_DEGREES) QDEL_NULL(breath_loop) + deltimer(panic_end_timer) return ..() /datum/terror_handler/panic/tick(seconds_per_tick, terror_buildup) . = ..() if (owner.stat >= UNCONSCIOUS) - active_attack = FALSE + stop_panic_attack() active = FALSE owner.remove_fov_trait(type, FOV_270_DEGREES) return @@ -154,12 +157,14 @@ owner.emote("gasp") owner.Knockdown(0.5 SECONDS) breath_loop.start() - addtimer(CALLBACK(src, PROC_REF(stop_panic_attack)), rand(3 SECONDS, 5 SECONDS)) + panic_end_timer = addtimer(CALLBACK(src, PROC_REF(stop_panic_attack)), rand(3 SECONDS, 5 SECONDS), TIMER_UNIQUE|TIMER_STOPPABLE) owner.visible_message(span_warning("[owner] drops to the floor for a moment, clutching their chest."), span_alert("Your heart lurches in your chest. You can't take much more of this!")) return PANIC_ATTACK_TERROR_AMOUNT /datum/terror_handler/panic/proc/stop_panic_attack() breath_loop.stop() active_attack = FALSE + deltimer(panic_end_timer) + panic_end_timer = null #undef FEAR_SCALING diff --git a/code/datums/components/fish_growth.dm b/code/datums/components/fish_growth.dm index f4c835045e88..380a82912b85 100644 --- a/code/datums/components/fish_growth.dm +++ b/code/datums/components/fish_growth.dm @@ -72,8 +72,7 @@ var/obj/item/fish/fishie = result fishie.breeding_wait = source.breeding_wait fishie.last_feeding = source.last_feeding - var/health_percent = source.health / initial(source.health) - fishie.adjust_health(fishie.health * health_percent) + fishie.update_integrity(fishie.max_integrity * source.get_integrity_percentage()) else result = new result_type (location) if(location != source.loc) diff --git a/code/datums/components/food/edible.dm b/code/datums/components/food/edible.dm index 21bb8a49f97e..8a9255d3a188 100644 --- a/code/datums/components/food/edible.dm +++ b/code/datums/components/food/edible.dm @@ -327,7 +327,7 @@ Behavior that's still missing from this component that original food items had t var/volume = ROUND_UP(original_atom.reagents.maximum_volume / chosen_processing_option[TOOL_PROCESSING_AMOUNT]) this_food.create_reagents(volume, this_food.reagents?.flags) - original_atom.reagents.copy_to(this_food, original_atom.reagents.total_volume / chosen_processing_option[TOOL_PROCESSING_AMOUNT], 1) + original_atom.reagents.trans_to(this_food, original_atom.reagents.total_volume / chosen_processing_option[TOOL_PROCESSING_AMOUNT], copy_only = TRUE) if(original_atom.name != initial(original_atom.name)) this_food.name = "slice of [original_atom.name]" diff --git a/code/datums/components/fullauto.dm b/code/datums/components/fullauto.dm index 61a216666770..bf19c5b16727 100644 --- a/code/datums/components/fullauto.dm +++ b/code/datums/components/fullauto.dm @@ -28,9 +28,12 @@ var/windup_spindown = 3 SECONDS ///Timer for tracking the spindown reset timings var/timerid + ///Looping sound while firing. + var/datum/looping_sound/autofire_sound_loop COOLDOWN_DECLARE(next_shot_cd) -/datum/component/automatic_fire/Initialize(autofire_shot_delay, windup_autofire, windup_autofire_reduction_multiplier, windup_autofire_cap, windup_spindown, allow_akimbo = TRUE) + +/datum/component/automatic_fire/Initialize(autofire_shot_delay, windup_autofire, windup_autofire_reduction_multiplier, windup_autofire_cap, windup_spindown, allow_akimbo = TRUE, firing_sound_loop) . = ..() if(!isgun(parent)) return COMPONENT_INCOMPATIBLE @@ -48,8 +51,12 @@ var/mob/user = gun.loc wake_up(src, user) + if(firing_sound_loop) + autofire_sound_loop = new firing_sound_loop(parent) + /datum/component/automatic_fire/Destroy() + QDEL_NULL(autofire_sound_loop) autofire_off() return ..() @@ -191,6 +198,8 @@ START_PROCESSING(SSprojectiles, src) RegisterSignal(clicker, COMSIG_CLIENT_MOUSEDRAG, PROC_REF(on_mouse_drag)) + if(autofire_sound_loop) + autofire_sound_loop.start(shooter) /datum/component/automatic_fire/proc/on_mouse_up(datum/source, atom/object, turf/location, control, params) SIGNAL_HANDLER @@ -217,6 +226,9 @@ target_loc = null mouse_parameters = null + if(autofire_sound_loop) + autofire_sound_loop.stop() + /datum/component/automatic_fire/proc/on_mouse_drag(client/source, atom/src_object, atom/over_object, turf/src_location, turf/over_location, src_control, over_control, params) SIGNAL_HANDLER if(isnull(over_location)) //This happens when the mouse is over an inventory or screen object, or on entering deep darkness, for example. @@ -238,7 +250,6 @@ target_loc = get_turf(over_object) mouse_parameters = params - /datum/component/automatic_fire/proc/process_shot() if(autofire_stat != AUTOFIRE_STAT_FIRING) return FALSE diff --git a/code/datums/components/grillable.dm b/code/datums/components/grillable.dm index dd23854fee98..53042e2e3881 100644 --- a/code/datums/components/grillable.dm +++ b/code/datums/components/grillable.dm @@ -34,6 +34,17 @@ src.use_large_steam_sprite = use_large_steam_sprite src.added_reagents = added_reagents + var/obj/item/item_parent = parent + if(!PERFORM_ALL_TESTS(focus_only/check_materials_when_processed) || !positive_result || !item_parent.custom_materials || isstack(parent)) + return + + var/atom/result = new cook_result + if(!item_parent.compare_materials(result)) + var/warning = "custom_materials of [result.type] when grilled compared to just spawned don't match" + var/what_it_should_be = item_parent.get_materials_english_list() + stack_trace("[warning]. custom_materials should be [what_it_should_be].") + qdel(result) + /datum/component/grillable/RegisterWithParent() RegisterSignal(parent, COMSIG_ITEM_GRILL_PLACED, PROC_REF(on_grill_placed)) RegisterSignal(parent, COMSIG_ITEM_GRILL_TURNED_ON, PROC_REF(on_grill_turned_on)) @@ -153,6 +164,7 @@ grilled_result.reagents.add_reagent_list(added_reagents) SEND_SIGNAL(parent, COMSIG_ITEM_GRILLED, grilled_result) + SEND_SIGNAL(grilled_result, COMSIG_ITEM_GRILLED_RESULT, parent) if(who_placed_us) ADD_TRAIT(grilled_result, TRAIT_FOOD_CHEF_MADE, who_placed_us) diff --git a/code/datums/components/manual_blinking.dm b/code/datums/components/manual_blinking.dm index 59e963b27ca6..aed2c531e3d9 100644 --- a/code/datums/components/manual_blinking.dm +++ b/code/datums/components/manual_blinking.dm @@ -5,7 +5,9 @@ var/warn_grace = FALSE var/warn_dying = FALSE var/last_blink - var/check_every = 20 SECONDS + /// How long can you not blink before you get a warning? + var/warning_delay = 20 SECONDS + /// Delay between getting a warning and you starting to take eye damage var/grace_period = 6 SECONDS /// Organ damage taken per tick var/damage_rate = 1 @@ -15,12 +17,12 @@ var/display_message = TRUE var/list/valid_emotes = list(/datum/emote/living/carbon/human/blink, /datum/emote/living/carbon/human/blink_r) -/datum/component/manual_blinking/Initialize(damage_rate = 1, check_every = 20 SECONDS, grace_period = 6 SECONDS, display_message = TRUE) +/datum/component/manual_blinking/Initialize(damage_rate = 1, warning_delay = 20 SECONDS, grace_period = 6 SECONDS, display_message = TRUE) if(!iscarbon(parent)) return COMPONENT_INCOMPATIBLE src.damage_rate = damage_rate - src.check_every = check_every + src.warning_delay = warning_delay src.grace_period = grace_period src.display_message = display_message @@ -70,12 +72,12 @@ STOP_PROCESSING(SSdcs, src) /datum/component/manual_blinking/process() - if(world.time > (last_blink + check_every + grace_period)) + if(world.time > (last_blink + warning_delay + grace_period)) if(!warn_dying) to_chat(parent, span_userdanger("Your eyes begin to wither, you need to blink!")) warn_dying = TRUE parent_eyes.apply_organ_damage(damage_rate) - else if(world.time > (last_blink + check_every)) + else if(world.time > (last_blink + warning_delay)) if(!warn_grace) to_chat(parent, span_danger("You feel a need to blink!")) warn_grace = TRUE diff --git a/code/datums/components/punchcooldown.dm b/code/datums/components/punchcooldown.dm index 22a212d4512a..72220a91cab4 100644 --- a/code/datums/components/punchcooldown.dm +++ b/code/datums/components/punchcooldown.dm @@ -3,7 +3,7 @@ signals = list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_LIVING_HAND_ITEM_ATTACK) mobtype = /mob/living/carbon proctype = PROC_REF(reducecooldown) - valid_slots = list(ITEM_SLOT_GLOVES) + valid_slots = ITEM_SLOT_GLOVES ///The warcry this generates var/warcry = "AT" diff --git a/code/datums/components/sitcomlaughter.dm b/code/datums/components/sitcomlaughter.dm index bc69a08b80c9..835a82cee422 100644 --- a/code/datums/components/sitcomlaughter.dm +++ b/code/datums/components/sitcomlaughter.dm @@ -1,5 +1,5 @@ /datum/component/wearertargeting/sitcomlaughter - valid_slots = list(ITEM_SLOT_HANDS, ITEM_SLOT_BELT, ITEM_SLOT_ID, ITEM_SLOT_LPOCKET, ITEM_SLOT_RPOCKET, ITEM_SLOT_SUITSTORE, ITEM_SLOT_DEX_STORAGE) + valid_slots = ITEM_SLOT_HANDS | ITEM_SLOT_BELT | ITEM_SLOT_ID | ITEM_SLOT_LPOCKET | ITEM_SLOT_RPOCKET | ITEM_SLOT_SUITSTORE | ITEM_SLOT_DEX_STORAGE signals = list(COMSIG_MOB_HIT_BY_SPLAT, COMSIG_ON_CARBON_SLIP, COMSIG_POST_TILT_AND_CRUSH, COMSIG_MOB_CLUMSY_SHOOT_FOOT) proctype = PROC_REF(EngageInComedy) mobtype = /mob/living diff --git a/code/datums/components/slippery.dm b/code/datums/components/slippery.dm index 370b3406ff9f..edc48a512d22 100644 --- a/code/datums/components/slippery.dm +++ b/code/datums/components/slippery.dm @@ -33,8 +33,8 @@ var/datum/callback/on_slip_callback /// If parent is an item, this is the person currently holding/wearing the parent (or the parent if no one is holding it) var/mob/living/holder - /// Whitelist of item slots the parent can be equipped in that make the holder slippery. If null or empty, it will always make the holder slippery. - var/list/slot_whitelist = list(ITEM_SLOT_OCLOTHING, ITEM_SLOT_ICLOTHING, ITEM_SLOT_GLOVES, ITEM_SLOT_FEET, ITEM_SLOT_HEAD, ITEM_SLOT_MASK, ITEM_SLOT_BELT, ITEM_SLOT_NECK) + /// Whitelist bitfields of item slots bitflags the parent can be equipped in that make the holder slippery. If null or empty, it will always make the holder slippery. + var/slot_whitelist = ITEM_SLOT_OCLOTHING | ITEM_SLOT_ICLOTHING | ITEM_SLOT_GLOVES | ITEM_SLOT_FEET | ITEM_SLOT_HEAD | ITEM_SLOT_MASK | ITEM_SLOT_BELT | ITEM_SLOT_NECK ///what we give to connect_loc by default, makes slippable mobs moving over us slip var/static/list/default_connections = list( COMSIG_ATOM_ENTERED = PROC_REF(Slip), @@ -191,7 +191,7 @@ /datum/component/slippery/proc/on_equip(datum/source, mob/equipper, slot) SIGNAL_HANDLER - if((!LAZYLEN(slot_whitelist) || (slot in slot_whitelist)) && isliving(equipper)) + if((!slot || (slot & slot_whitelist)) && isliving(equipper)) holder = equipper qdel(GetComponent(/datum/component/connect_loc_behalf)) AddComponent(/datum/component/connect_loc_behalf, holder, mob_connections) diff --git a/code/datums/components/style/style.dm b/code/datums/components/style/style.dm index 9de22c1772ef..2e8fb5cd07c1 100644 --- a/code/datums/components/style/style.dm +++ b/code/datums/components/style/style.dm @@ -139,16 +139,15 @@ /datum/component/style/proc/add_action(action, amount) if(length(actions) > 9) actions.Cut(1, 2) + var/action_id = 0 if(length(actions)) var/last_action = actions[length(actions)] if(action == actions[last_action]) amount *= 0.5 - var/id - while(!id || (id in actions)) - id = "action[rand(1, 1000)]" - actions[id] = action + action_id = text2num(last_action) + 1 + actions["[action_id]"] = action change_points(amount) - addtimer(CALLBACK(src, PROC_REF(remove_action), id), 10 SECONDS) + addtimer(CALLBACK(src, PROC_REF(remove_action), action_id), 10 SECONDS) /datum/component/style/proc/remove_action(action_id) actions -= action_id @@ -197,7 +196,7 @@ rank = rank_changed meter.maptext = "[format_rank_string(rank)][generate_multiplier()][generate_actions()]" - meter.maptext_y = 94 - 12 * length(actions) + meter.maptext_y = initial(meter.maptext_y) - 12 * length(actions) update_meter(point_to_rank(), go_back) /datum/component/style/proc/update_meter(new_rank, go_back) diff --git a/code/datums/components/style/style_meter.dm b/code/datums/components/style/style_meter.dm index eb9ca3653fc8..7b399927e33e 100644 --- a/code/datums/components/style/style_meter.dm +++ b/code/datums/components/style/style_meter.dm @@ -127,11 +127,11 @@ icon_state = "style_meter_background" icon = 'icons/hud/style_meter.dmi' mouse_opacity = MOUSE_OPACITY_TRANSPARENT - screen_loc = "WEST,CENTER:16" - maptext_height = 120 + screen_loc = "WEST,CENTER-1:19" + maptext_height = 160 maptext_width = 105 maptext_x = 5 - maptext_y = 94 + maptext_y = 124 maptext = "" layer = SCREENTIP_LAYER diff --git a/code/datums/components/tactical.dm b/code/datums/components/tactical.dm index 17309b888eac..80ea33f24451 100644 --- a/code/datums/components/tactical.dm +++ b/code/datums/components/tactical.dm @@ -44,6 +44,7 @@ RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved)) RegisterSignal(user, COMSIG_HUMAN_GET_VISIBLE_NAME, PROC_REF(on_name_inquiry)) RegisterSignal(user, COMSIG_HUMAN_GET_FORCED_NAME, PROC_REF(on_name_inquiry)) + // This forces a name update on the user, so we don't need to call name update ourselves ADD_TRAIT(user, TRAIT_UNKNOWN, REF(src)) current_slot = slot diff --git a/code/datums/components/tether.dm b/code/datums/components/tether.dm index d04716a0af0a..cbbd2b1c18f7 100644 --- a/code/datums/components/tether.dm +++ b/code/datums/components/tether.dm @@ -15,7 +15,7 @@ var/datum/beam/tether_beam /// Tether module if we were created by one var/obj/item/mod/module/tether/parent_module - /// Source, if any, for TRAIT_TETHER_ATTACHED we add + /// Ref of source, if any, for TRAIT_TETHER_ATTACHED we add var/tether_trait_source /// If TRUE, only add TRAIT_TETHER_ATTACHED to our parent var/no_target_trait @@ -24,6 +24,9 @@ parent_module = null, tether_trait_source = null, no_target_trait = FALSE) if(!ismovable(parent) || !istype(tether_target) || !tether_target.loc) return COMPONENT_INCOMPATIBLE + if(isatom(tether_trait_source)) + stack_trace("Tried to add a [src.type] with a tether_trait_source that is a hard ref! Use REF() first before passing!") + return COMPONENT_INCOMPATIBLE src.tether_target = tether_target src.embed_target = embed_target diff --git a/code/datums/components/wearertargeting.dm b/code/datums/components/wearertargeting.dm index 44c16aa72bd1..fa04ebb3918e 100644 --- a/code/datums/components/wearertargeting.dm +++ b/code/datums/components/wearertargeting.dm @@ -1,7 +1,9 @@ // A dummy parent type used for easily making components that target an item's wearer rather than the item itself. /datum/component/wearertargeting - var/list/valid_slots = list() + /// Bitflag value of valid slots. + /// You can find all slot bitflags in code/__DEFINES/inventory.dm + var/valid_slots = NONE var/list/signals = list() var/proctype = GLOBAL_PROC_REF(pass) var/mobtype = /mob/living @@ -15,7 +17,7 @@ /datum/component/wearertargeting/proc/on_equip(datum/source, mob/equipper, slot) SIGNAL_HANDLER - if((slot in valid_slots) && istype(equipper, mobtype)) + if((valid_slots & slot) && istype(equipper, mobtype)) RegisterSignals(equipper, signals, proctype, TRUE) else UnregisterSignal(equipper, signals) diff --git a/code/datums/drift_handler.dm b/code/datums/drift_handler.dm index 559ea9e13ca8..53133025657f 100644 --- a/code/datums/drift_handler.dm +++ b/code/datums/drift_handler.dm @@ -209,8 +209,6 @@ /datum/drift_handler/proc/attempt_halt(movement_dir, continuous_move, atom/backup) if ((backup.density || !backup.CanPass(parent, get_dir(backup, parent))) && (get_dir(parent, backup) == movement_dir || parent.loc == backup.loc)) - if (drift_force >= INERTIA_FORCE_THROW_FLOOR) - parent.throw_at(backup, 1, floor(1 + (drift_force - INERTIA_FORCE_THROW_FLOOR) / INERTIA_FORCE_PER_THROW_FORCE), spin = FALSE) return FALSE if (drift_force < INERTIA_FORCE_SPACEMOVE_GRAB || isnull(drifting_loop)) diff --git a/code/datums/elements/above_mob_drop.dm b/code/datums/elements/above_mob_drop.dm new file mode 100644 index 000000000000..552f6c863a1e --- /dev/null +++ b/code/datums/elements/above_mob_drop.dm @@ -0,0 +1,21 @@ +/// Element that makes mob drops appear above their corpses until moved or picked up +/datum/element/above_mob_drop + element_flags = ELEMENT_BESPOKE + argument_hash_start_idx = 2 + /// Layer to which items are initially changed + var/target_layer = ABOVE_LYING_MOB_LAYER + +/datum/element/above_mob_drop/Attach(datum/target, target_layer = ABOVE_LYING_MOB_LAYER) + . = ..() + if (!ismovable(target)) + return ELEMENT_INCOMPATIBLE + src.target_layer = target_layer + var/atom/movable/owner = target + owner.layer = target_layer + RegisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved)) + +/datum/element/above_mob_drop/proc/on_moved(atom/movable/source) + SIGNAL_HANDLER + if (source.layer == target_layer) + source.layer = initial(source.layer) + Detach(source) diff --git a/code/datums/elements/climbable.dm b/code/datums/elements/climbable.dm index eb3bc611b29d..2a928900b8e9 100644 --- a/code/datums/elements/climbable.dm +++ b/code/datums/elements/climbable.dm @@ -99,7 +99,7 @@ if(istype(buckle_target)) if(buckle_target.is_buckle_possible(user)) buckle_target.buckle_mob(user) - user.mind?.adjust_experience(/datum/skill/athletics, 5) //Get a bit fitter with every climb. + user.mind?.adjust_experience(/datum/skill/athletics, round(ATHLETICS_SKILL_MISC_EXP/(fitness_level || 1), 1)) //Get a bit fitter with every climb. But it has diminishing returns at a certain point. else to_chat(user, span_warning("You fail to climb onto [climbed_thing].")) LAZYREMOVEASSOC(current_climbers, climbed_thing, user) diff --git a/code/datums/elements/decals/blood.dm b/code/datums/elements/decals/blood.dm index 801a0bd7b520..16a338888932 100644 --- a/code/datums/elements/decals/blood.dm +++ b/code/datums/elements/decals/blood.dm @@ -37,7 +37,7 @@ blood_splatter.color = _color var/mutable_appearance/emissive_splatter = null if (emissive_alpha) - emissive_splatter = emissive_appearance('icons/effects/blood.dmi', "itemblood", as_item, alpha = emissive_alpha) + emissive_splatter = emissive_appearance('icons/effects/blood.dmi', "itemblood", as_item, alpha = emissive_alpha, effect_type = EMISSIVE_NO_BLOOM) emissive_splatter.blend_mode = BLEND_INSET_OVERLAY if (uses_filter) blood_splatter.appearance_flags |= KEEP_APART diff --git a/code/datums/elements/dryable.dm b/code/datums/elements/dryable.dm index 16c5a8c1a5dd..3d7842b30891 100644 --- a/code/datums/elements/dryable.dm +++ b/code/datums/elements/dryable.dm @@ -14,6 +14,17 @@ RegisterSignal(target, COMSIG_ITEM_DRIED, PROC_REF(finish_drying)) ADD_TRAIT(target, TRAIT_DRYABLE, ELEMENT_TRAIT(type)) + var/atom/atom_target = target + if(!PERFORM_ALL_TESTS(focus_only/check_materials_when_processed) || !atom_target.custom_materials || !dry_result || isstack(atom_target)) + return + + var/atom/result = new dry_result + if(!atom_target.compare_materials(result)) + var/warning = "custom_materials of [result.type] when dried compared to just spawned don't match" + var/what_it_should_be = atom_target.get_materials_english_list() + stack_trace("[warning]. custom_materials should be [what_it_should_be].") + qdel(result) + /datum/element/dryable/Detach(datum/target) . = ..() diff --git a/code/datums/elements/fish_safe_storage.dm b/code/datums/elements/fish_safe_storage.dm index a5eb5c561316..92416789148e 100644 --- a/code/datums/elements/fish_safe_storage.dm +++ b/code/datums/elements/fish_safe_storage.dm @@ -51,5 +51,5 @@ ///Keep delaying hunger and breeding while in stasis, and also heal them. fish.last_feeding += seconds_per_tick SECONDS fish.breeding_wait += seconds_per_tick SECONDS - if(fish.health < initial(fish.health) * 0.65) - fish.adjust_health(fish.health + 0.75 * seconds_per_tick) + if(fish.get_health_percentage() < 0.65) + fish.repair_damage(0.75 * seconds_per_tick) diff --git a/code/datums/elements/food/microwavable.dm b/code/datums/elements/food/microwavable.dm index 86f0b2083b89..325f7fe865d0 100644 --- a/code/datums/elements/food/microwavable.dm +++ b/code/datums/elements/food/microwavable.dm @@ -3,15 +3,15 @@ element_flags = ELEMENT_BESPOKE argument_hash_start_idx = 2 /// The typepath we default to if we were passed no microwave result - var/atom/default_typepath = /obj/item/food/badrecipe + var/atom/default_typepath /// Resulting atom typepath on a completed microwave. var/atom/result_typepath /// Reagents that should be added to the result var/list/added_reagents -/datum/element/microwavable/Attach(datum/target, microwave_type, list/reagents) +/datum/element/microwavable/Attach(obj/item/target, microwave_type, list/reagents, skip_matcheck = FALSE) . = ..() - if(!isitem(target)) + if(!istype(target)) return ELEMENT_INCOMPATIBLE result_typepath = microwave_type || default_typepath @@ -23,6 +23,16 @@ if(!ispath(result_typepath, default_typepath)) RegisterSignal(target, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) + if(!PERFORM_ALL_TESTS(focus_only/check_materials_when_processed) || skip_matcheck || !target.custom_materials || isstack(target)) + return + + var/atom/result = new result_typepath + if(!target.compare_materials(result)) + var/warning = "custom_materials of [result.type] when microwaved compared to just spawned don't match" + var/what_it_should_be = target.get_materials_english_list() + stack_trace("[warning]. custom_materials should be [what_it_should_be].") + qdel(result) + /datum/element/microwavable/Detach(datum/source) UnregisterSignal(source, list(COMSIG_ITEM_MICROWAVE_ACT, COMSIG_ATOM_EXAMINE)) return ..() @@ -44,8 +54,6 @@ result.set_custom_materials(source.custom_materials) var/efficiency = istype(used_microwave) ? used_microwave.efficiency : 1 - SEND_SIGNAL(result, COMSIG_ITEM_MICROWAVE_COOKED, source, efficiency) - SEND_SIGNAL(source, COMSIG_ITEM_MICROWAVE_COOKED_FROM, result, efficiency) if(IS_EDIBLE(result) && (result_typepath != default_typepath)) BLACKBOX_LOG_FOOD_MADE(result.type) @@ -62,6 +70,10 @@ if(microwaver && microwaver.mind) ADD_TRAIT(result, TRAIT_FOOD_CHEF_MADE, REF(microwaver.mind)) + + SEND_SIGNAL(result, COMSIG_ITEM_MICROWAVE_COOKED, source, efficiency) + SEND_SIGNAL(source, COMSIG_ITEM_MICROWAVE_COOKED_FROM, result, efficiency) + qdel(source) var/recipe_result = COMPONENT_MICROWAVE_SUCCESS diff --git a/code/datums/elements/food/processable.dm b/code/datums/elements/food/processable.dm index 9ca96b3821b2..59c8c0462635 100644 --- a/code/datums/elements/food/processable.dm +++ b/code/datums/elements/food/processable.dm @@ -34,6 +34,22 @@ RegisterSignal(target, COMSIG_ATOM_TOOL_ACT(tool_behaviour), PROC_REF(try_process)) RegisterSignal(target, COMSIG_ATOM_EXAMINE, PROC_REF(OnExamine)) + if(!PERFORM_ALL_TESTS(focus_only/check_materials_when_processed) || !atom_target.custom_materials) + return + + var/atom/movable/prototype = new + prototype.set_custom_materials(atom_target.custom_materials, 1 / amount_created) + var/atom/movable/result = new result_atom_type + if(!prototype.compare_materials(result)) + var/warning = "custom_materials of [result.type] when processed compared to just spawned don't match" + var/what_it_should_be = prototype.get_materials_english_list() + //compose a text string containing the syntax and paths to use for editing the custom_materials var + if(result.custom_materials) + what_it_should_be += " (you can round values a bit)" + stack_trace("[warning]. custom_materials should be [what_it_should_be] (you can round values a bit).") + qdel(prototype) + qdel(result) + /datum/element/processable/Detach(datum/target) . = ..() UnregisterSignal(target, list(COMSIG_ATOM_TOOL_ACT(tool_behaviour), COMSIG_ATOM_EXAMINE, COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM)) diff --git a/code/datums/elements/organ_set_bonus.dm b/code/datums/elements/organ_set_bonus.dm index 3e8f030a13d3..fa6b272897a0 100644 --- a/code/datums/elements/organ_set_bonus.dm +++ b/code/datums/elements/organ_set_bonus.dm @@ -30,7 +30,7 @@ var/datum/status_effect/organ_set_bonus/set_bonus = receiver.has_status_effect(bonus_type) if(!set_bonus) set_bonus = receiver.apply_status_effect(bonus_type) - set_bonus.set_organs(set_bonus.organs + 1) + set_bonus.set_organs(set_bonus.organs + 1, target) /datum/element/organ_set_bonus/proc/on_removed(obj/item/organ/target, mob/living/carbon/loser) SIGNAL_HANDLER @@ -38,7 +38,7 @@ //get status effect or remove it var/datum/status_effect/organ_set_bonus/set_bonus = loser.has_status_effect(bonus_type) if(set_bonus) - set_bonus.set_organs(set_bonus.organs - 1) + set_bonus.set_organs(set_bonus.organs - 1, target) /datum/status_effect/organ_set_bonus id = "organ_set_bonus" @@ -66,17 +66,17 @@ /// Color priority for limb overlay var/color_overlay_priority -/datum/status_effect/organ_set_bonus/proc/set_organs(new_value) +/datum/status_effect/organ_set_bonus/proc/set_organs(new_value, obj/item/organ/organ) organs = new_value if(!organs) //initial value but won't kick in without calling the setter qdel(src) if(organs >= organs_needed) if(!bonus_active) - INVOKE_ASYNC(src, PROC_REF(enable_bonus)) + INVOKE_ASYNC(src, PROC_REF(enable_bonus), organ) else if(bonus_active) - INVOKE_ASYNC(src, PROC_REF(disable_bonus)) + INVOKE_ASYNC(src, PROC_REF(disable_bonus), organ) -/datum/status_effect/organ_set_bonus/proc/enable_bonus() +/datum/status_effect/organ_set_bonus/proc/enable_bonus(obj/item/organ/inserted_organ) SHOULD_CALL_PARENT(TRUE) if(required_biotype) if(!(owner.mob_biotypes & required_biotype)) @@ -113,7 +113,7 @@ carbon_owner.update_body() return TRUE -/datum/status_effect/organ_set_bonus/proc/disable_bonus() +/datum/status_effect/organ_set_bonus/proc/disable_bonus(obj/item/organ/removed_organ) SHOULD_CALL_PARENT(TRUE) bonus_active = FALSE @@ -150,7 +150,7 @@ /datum/status_effect/organ_set_bonus/proc/texture_limb(atom/source, obj/item/bodypart/limb) SIGNAL_HANDLER - // Not updating because enable/disable_bonus() call it down the line, and calls coming from comsigs update the owner's body themselves + // Not updating because enable/disable_bonus(obj/item/organ/removed_organ) call it down the line, and calls coming from comsigs update the owner's body themselves limb.add_bodypart_overlay(new limb_overlay(), update = FALSE) if(color_overlay_priority) limb.add_color_override(COLOR_WHITE, color_overlay_priority) diff --git a/code/datums/elements/strippable.dm b/code/datums/elements/strippable.dm index 7f4d9f972040..f7d364cf397d 100644 --- a/code/datums/elements/strippable.dm +++ b/code/datums/elements/strippable.dm @@ -311,9 +311,6 @@ user.log_message("has stripped [key_name(source)] of [item].", LOG_ATTACK, color="red") source.log_message("has been stripped of [item] by [key_name(user)].", LOG_VICTIM, color="orange", log_globally=FALSE) - // Updates speed in case stripped speed affecting item - source.update_equipment_speed_mods() - /// A representation of the stripping UI /datum/strip_menu /// The owner who has the element /datum/element/strippable diff --git a/code/datums/elements/swimming_tile.dm b/code/datums/elements/swimming_tile.dm index eb4330549b0a..738a8d315efb 100644 --- a/code/datums/elements/swimming_tile.dm +++ b/code/datums/elements/swimming_tile.dm @@ -60,7 +60,7 @@ var/effective_stamina_entry_cost = HAS_TRAIT(floater, TRAIT_STRENGTH) ? (stamina_entry_cost + clothing_weight(floater)) : ((stamina_entry_cost + clothing_weight(floater)) / 2) //Being in high gravity doubles our effective stamina cost - var/gravity_modifier = floater.has_gravity() > STANDARD_GRAVITY ? 1 : 2 + var/gravity_modifier = floater.has_gravity() > STANDARD_GRAVITY ? 2 : 1 //If our floater has a specialized spine, include that as a factor. var/obj/item/organ/cyberimp/chest/spine/potential_spine = floater.get_organ_slot(ORGAN_SLOT_SPINE) @@ -120,7 +120,7 @@ var/effective_stamina_per_interval = HAS_TRAIT(owner, TRAIT_STRENGTH) ? stamina_per_interval : (stamina_per_interval / 2) - var/gravity_modifier = owner.has_gravity() > STANDARD_GRAVITY ? 1 : 2 + var/gravity_modifier = owner.has_gravity() > STANDARD_GRAVITY ? 2 : 1 var/under_pressure = prob(drowning_process_probability * gravity_modifier) diff --git a/code/datums/id_trim/jobs.dm b/code/datums/id_trim/jobs.dm index 4b8b63061757..e0b6a79aea26 100644 --- a/code/datums/id_trim/jobs.dm +++ b/code/datums/id_trim/jobs.dm @@ -848,6 +848,7 @@ extra_access = list( ACCESS_SURGERY, ACCESS_VIROLOGY, + ACCESS_PHARMACY, ) template_access = list( ACCESS_CAPTAIN, diff --git a/code/datums/looping_sounds/_looping_sound.dm b/code/datums/looping_sounds/_looping_sound.dm index 59b876b18722..2b2b00e19a16 100644 --- a/code/datums/looping_sounds/_looping_sound.dm +++ b/code/datums/looping_sounds/_looping_sound.dm @@ -63,6 +63,10 @@ var/direct /// Sound channel to play on, random if not provided var/sound_channel + ///If we want to reserve a random channel when we start playing sounds. Good for when there could be several sources of the same looping sound heard by the same + var/reserve_random_channel = FALSE + //If we reserve a random sound channel, store the channel number here so we can clean it up later. + var/reserved_channel /datum/looping_sound/New(_parent, start_immediately = FALSE, _direct = FALSE, _skip_starting_sounds = FALSE) if(!mid_sounds) @@ -91,6 +95,11 @@ set_parent(on_behalf_of) if(timer_id) return + + if(!sound_channel && reserve_random_channel) + sound_channel = SSsounds.reserve_sound_channel_datumless() + reserved_channel = sound_channel + on_start() /** @@ -110,6 +119,11 @@ timer_id = null loop_started = FALSE + if(reserved_channel) + sound_channel = null + SSsounds.free_sound_channel(reserved_channel) + + /// The proc that handles starting the actual core sound loop. /datum/looping_sound/proc/start_sound_loop() loop_started = TRUE @@ -165,7 +179,8 @@ pressure_affected = pressure_affected, ignore_walls = ignore_walls, falloff_distance = falloff_distance, - use_reverb = use_reverb + use_reverb = use_reverb, + channel = sound_channel || SSsounds.random_available_channel() ) /// Returns the sound we should now be playing. diff --git a/code/datums/looping_sounds/item_sounds.dm b/code/datums/looping_sounds/item_sounds.dm index dd2de0c9cd8d..e5950566d4f3 100644 --- a/code/datums/looping_sounds/item_sounds.dm +++ b/code/datums/looping_sounds/item_sounds.dm @@ -47,3 +47,15 @@ /datum/looping_sound/zipline mid_sounds = list('sound/items/weapons/zipline_mid.ogg' = 1) volume = 5 + +/datum/looping_sound/tesla_cannon + start_sound = list('sound/items/weapons/gun/tesla/tesla_start.ogg' = 1) + start_volume = 100 + start_length = 200 MILLISECONDS + mid_sounds = list('sound/items/weapons/gun/tesla/tesla_loop.ogg' = 1) + mid_length = 3.8 SECONDS + volume = 100 + end_sound = list('sound/items/weapons/gun/tesla/power_breaker_fan.ogg' = 1) + end_volume = 15 + ignore_walls = FALSE + reserve_random_channel = TRUE diff --git a/code/datums/martial/krav_maga.dm b/code/datums/martial/krav_maga.dm index 25bdd31b288d..f7a951567845 100644 --- a/code/datums/martial/krav_maga.dm +++ b/code/datums/martial/krav_maga.dm @@ -24,7 +24,7 @@ button_icon_state = "neckchop" check_flags = AB_CHECK_INCAPACITATED|AB_CHECK_HANDS_BLOCKED|AB_CHECK_CONSCIOUS -/datum/action/neck_chop/Trigger(trigger_flags) +/datum/action/neck_chop/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return @@ -43,7 +43,7 @@ button_icon_state = "legsweep" check_flags = AB_CHECK_INCAPACITATED|AB_CHECK_HANDS_BLOCKED|AB_CHECK_CONSCIOUS -/datum/action/leg_sweep/Trigger(trigger_flags) +/datum/action/leg_sweep/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return @@ -62,7 +62,7 @@ button_icon_state = "lungpunch" check_flags = AB_CHECK_INCAPACITATED|AB_CHECK_HANDS_BLOCKED|AB_CHECK_CONSCIOUS -/datum/action/lung_punch/Trigger(trigger_flags) +/datum/action/lung_punch/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return @@ -237,7 +237,7 @@ icon_state = "black" greyscale_colors = "#2f2e31" siemens_coefficient = 0 - strip_delay = 80 + strip_delay = 8 SECONDS cold_protection = HANDS min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT heat_protection = HANDS diff --git a/code/datums/martial/wrestling.dm b/code/datums/martial/wrestling.dm index 1358cc20e347..4c66f236525d 100644 --- a/code/datums/martial/wrestling.dm +++ b/code/datums/martial/wrestling.dm @@ -72,7 +72,7 @@ If you make a derivative work from this code, you must include this notification button_icon_state = "wrassle_slam" check_flags = AB_CHECK_INCAPACITATED|AB_CHECK_HANDS_BLOCKED|AB_CHECK_CONSCIOUS -/datum/action/slam/Trigger(trigger_flags) +/datum/action/slam/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return @@ -85,7 +85,7 @@ If you make a derivative work from this code, you must include this notification button_icon_state = "wrassle_throw" check_flags = AB_CHECK_INCAPACITATED|AB_CHECK_HANDS_BLOCKED|AB_CHECK_CONSCIOUS -/datum/action/throw_wrassle/Trigger(trigger_flags) +/datum/action/throw_wrassle/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return @@ -98,7 +98,7 @@ If you make a derivative work from this code, you must include this notification button_icon_state = "wrassle_kick" check_flags = AB_CHECK_INCAPACITATED|AB_CHECK_CONSCIOUS // This is supposed to be usable while cuffed but it probably isn't -/datum/action/kick/Trigger(trigger_flags) +/datum/action/kick/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return @@ -111,7 +111,7 @@ If you make a derivative work from this code, you must include this notification button_icon_state = "wrassle_strike" check_flags = AB_CHECK_INCAPACITATED|AB_CHECK_HANDS_BLOCKED|AB_CHECK_CONSCIOUS -/datum/action/strike/Trigger(trigger_flags) +/datum/action/strike/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return @@ -124,7 +124,7 @@ If you make a derivative work from this code, you must include this notification button_icon_state = "wrassle_drop" check_flags = AB_CHECK_INCAPACITATED|AB_CHECK_HANDS_BLOCKED -/datum/action/drop/Trigger(trigger_flags) +/datum/action/drop/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return diff --git a/code/datums/mood.dm b/code/datums/mood.dm index 08d493ada1ca..43fa67907751 100644 --- a/code/datums/mood.dm +++ b/code/datums/mood.dm @@ -81,9 +81,9 @@ if(MOOD_LEVEL_SAD4) adjust_sanity(-0.3 * seconds_per_tick, SANITY_INSANE) if(MOOD_LEVEL_SAD3) - adjust_sanity(-0.15 * seconds_per_tick, SANITY_INSANE) + adjust_sanity(-0.15 * seconds_per_tick, SANITY_CRAZY) if(MOOD_LEVEL_SAD2) - adjust_sanity(-0.1 * seconds_per_tick, SANITY_CRAZY) + adjust_sanity(-0.1 * seconds_per_tick, SANITY_UNSTABLE) if(MOOD_LEVEL_SAD1) adjust_sanity(-0.05 * seconds_per_tick, SANITY_UNSTABLE) if(MOOD_LEVEL_NEUTRAL) diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm index f5884d509ac1..2c5a97495509 100644 --- a/code/datums/mood_events/generic_negative_events.dm +++ b/code/datums/mood_events/generic_negative_events.dm @@ -519,7 +519,7 @@ /datum/mood_event/encountered_evil description = "I didn't want to believe it, but there are people out there that are genuinely evil." - mood_change = -4 + mood_change = -1 timeout = 1 MINUTES /datum/mood_event/smoke_in_face diff --git a/code/datums/mutations/tongue_spike.dm b/code/datums/mutations/tongue_spike.dm index c63f4cbd7032..4d908b6f9594 100644 --- a/code/datums/mutations/tongue_spike.dm +++ b/code/datums/mutations/tongue_spike.dm @@ -159,7 +159,7 @@ if(!istype(target, /obj/item/hardened_spike/chem)) qdel(src) -/datum/action/send_chems/Trigger(trigger_flags) +/datum/action/send_chems/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return FALSE diff --git a/code/datums/outfit.dm b/code/datums/outfit.dm index 4c6e42d36b03..1badba3f160a 100644 --- a/code/datums/outfit.dm +++ b/code/datums/outfit.dm @@ -213,7 +213,7 @@ if(id_trim) if(!SSid_access.apply_trim_to_card(id_card, id_trim)) WARNING("Unable to apply trim [id_trim] to [id_card] in outfit [name].") - user.sec_hud_set_ID() + user.update_ID_card() if(suit_store) EQUIP_OUTFIT_ITEM(suit_store, ITEM_SLOT_SUITSTORE) diff --git a/code/datums/quirks/negative_quirks/allergic.dm b/code/datums/quirks/negative_quirks/allergic.dm index 4628bab0c0d7..a2442adab10e 100644 --- a/code/datums/quirks/negative_quirks/allergic.dm +++ b/code/datums/quirks/negative_quirks/allergic.dm @@ -20,7 +20,8 @@ /datum/reagent/medicine/cordiolis_hepatico, /datum/reagent/medicine/synaphydramine, /datum/reagent/medicine/diphenhydramine, - /datum/reagent/medicine/sansufentanyl + /datum/reagent/medicine/sansufentanyl, + /datum/reagent/medicine/salglu_solution, ) var/allergy_string diff --git a/code/datums/quirks/negative_quirks/fluoride_stare.dm b/code/datums/quirks/negative_quirks/fluoride_stare.dm index 1bd2dd91acfc..97b9c75f3e97 100644 --- a/code/datums/quirks/negative_quirks/fluoride_stare.dm +++ b/code/datums/quirks/negative_quirks/fluoride_stare.dm @@ -28,7 +28,7 @@ /datum/quirk/item_quirk/fluoride_stare/add(client/client_source) ADD_TRAIT(quirk_holder, TRAIT_NO_EYELIDS, QUIRK_TRAIT) - quirk_holder.AddComponent(/datum/component/manual_blinking, 1, 30 SECONDS, 10 SECONDS, FALSE) + quirk_holder.AddComponent(/datum/component/manual_blinking, 0.5, 3 MINUTES, 30 SECONDS, FALSE) /datum/quirk/item_quirk/fluoride_stare/remove() REMOVE_TRAIT(quirk_holder, TRAIT_NO_EYELIDS, QUIRK_TRAIT) diff --git a/code/datums/saymode.dm b/code/datums/saymode.dm index 5e67d960b421..951c805f0af7 100644 --- a/code/datums/saymode.dm +++ b/code/datums/saymode.dm @@ -1,20 +1,40 @@ /datum/saymode + /// The symbol key used to enable this say mode. var/key + /// The corresponding say mode string. var/mode + /// Whether this say mode works with custom say emotes. + var/allows_custom_say_emotes = FALSE -//Return FALSE if you have handled the message. Otherwise, return TRUE and saycode will continue doing saycode things. -//user = whoever said the message -//message = the message -//language = the language. -/datum/saymode/proc/handle_message(mob/living/user, message, datum/language/language) +/// Checks whether this saymode can be used by the given user. May send feedback. +/datum/saymode/proc/can_be_used_by(mob/living/user) return TRUE +/** + * Handles actually modifying or forwarding our message. + * Returns `SAYMODE_[X]` flags. + * + * user - The living speaking using this say mode. + * message - The message to be said. + * spans - A list of spans to attach to the message. + * language - The language the message was said in. + * message_mods - A list of message modifiers, i.e. whispering/singing. + */ +/datum/saymode/proc/handle_message( + mob/living/user, + message, + list/spans = list(), + datum/language/language, + list/message_mods = list() +) + return NONE + + /datum/saymode/changeling key = MODE_KEY_CHANGELING mode = MODE_CHANGELING -/datum/saymode/changeling/handle_message(mob/living/user, message, datum/language/language) - //we can send the message +/datum/saymode/changeling/can_be_used_by(mob/living/user) if(!user.mind) return FALSE if(user.mind.has_antag_datum(/datum/antagonist/fallen_changeling)) @@ -26,11 +46,20 @@ if(HAS_TRAIT(user, TRAIT_CHANGELING_HIVEMIND_MUTE)) to_chat(user, span_warning("The poison in the air hinders our ability to interact with the hivemind.")) return FALSE + return TRUE - user.log_talk(message, LOG_SAY, tag="changeling [ling_sender.changelingID]") +/datum/saymode/changeling/handle_message/handle_message( + mob/living/user, + message, + list/spans = list(), + datum/language/language, + list/message_mods = list() +) + var/datum/antagonist/changeling/ling_sender = IS_CHANGELING(user) + user.log_talk(message, LOG_SAY, tag = "changeling [ling_sender.changelingID]") var/msg = span_changeling("[ling_sender.changelingID]: [message]") - //the recipients can receive the message + // Send the message to our other changelings. for(var/datum/antagonist/changeling/ling_receiver in GLOB.antagonists) if(!ling_receiver.owner) continue @@ -45,54 +74,96 @@ for(var/mob/dead/ghost as anything in GLOB.dead_mob_list) to_chat(ghost, "[FOLLOW_LINK(ghost, user)] [msg]", type = MESSAGE_TYPE_RADIO) - return FALSE + return SAYMODE_MESSAGE_HANDLED + /datum/saymode/xeno - key = "a" + key = MODE_KEY_ALIEN mode = MODE_ALIEN + allows_custom_say_emotes = TRUE -/datum/saymode/xeno/handle_message(mob/living/user, message, datum/language/language) - if(user.hivecheck()) - user.alien_talk(message) - return FALSE +/datum/saymode/xeno/can_be_used_by(mob/living/user) + if(!user.hivecheck()) + return FALSE + return TRUE + +/datum/saymode/xeno/handle_message/handle_message( + mob/living/user, + message, + list/spans = list(), + datum/language/language, + list/message_mods = list() +) + user.alien_talk(message, spans, message_mods) + return SAYMODE_MESSAGE_HANDLED /datum/saymode/vocalcords key = MODE_KEY_VOCALCORDS mode = MODE_VOCALCORDS -/datum/saymode/vocalcords/handle_message(mob/living/user, message, datum/language/language) - if(iscarbon(user)) - var/mob/living/carbon/C = user - var/obj/item/organ/vocal_cords/V = C.get_organ_slot(ORGAN_SLOT_VOICE) - if(V?.can_speak_with()) - V.handle_speech(message) //message - V.speak_with(message) //action - return FALSE +/datum/saymode/vocalcords/can_be_used_by(mob/living/user) + if(!iscarbon(user)) + return FALSE + return TRUE + +/datum/saymode/vocalcords/handle_message/handle_message( + mob/living/user, + message, + list/spans = list(), + datum/language/language, + list/message_mods = list() +) + var/mob/living/carbon/carbon_user = user + var/obj/item/organ/vocal_cords/our_vocal_cords = carbon_user.get_organ_slot(ORGAN_SLOT_VOICE) + if(our_vocal_cords?.can_speak_with()) + our_vocal_cords.handle_speech(message) //message + our_vocal_cords.speak_with(message) //action + return SAYMODE_MESSAGE_HANDLED /datum/saymode/binary //everything that uses .b (silicons, drones) key = MODE_KEY_BINARY mode = MODE_BINARY + allows_custom_say_emotes = TRUE + +/datum/saymode/binary/can_be_used_by(mob/living/user) + if(!isdrone(user) && !user.binarycheck()) + return FALSE + return TRUE -/datum/saymode/binary/handle_message(mob/living/user, message, datum/language/language) +/datum/saymode/binary/handle_message/handle_message( + mob/living/user, + message, + list/spans = list(), + datum/language/language, + list/message_mods = list() +) if(isdrone(user)) var/mob/living/basic/drone/drone_user = user - drone_user.drone_chat(message) - return FALSE - if(user.binarycheck()) - user.robot_talk(message) - return FALSE - return FALSE + drone_user.drone_chat(message, spans, message_mods) + else if(user.binarycheck()) + user.robot_talk(message, spans, message_mods) + return SAYMODE_MESSAGE_HANDLED /datum/saymode/holopad - key = "h" + key = MODE_KEY_HOLOPAD mode = MODE_HOLOPAD + allows_custom_say_emotes = TRUE -/datum/saymode/holopad/handle_message(mob/living/user, message, datum/language/language) - if(isAI(user)) - var/mob/living/silicon/ai/AI = user - AI.holopad_talk(message, language) +/datum/saymode/holopad/can_be_used_by(mob/living/user) + if(!isAI(user)) return FALSE return TRUE + +/datum/saymode/holopad/handle_message/handle_message( + mob/living/user, + message, + list/spans = list(), + datum/language/language, + list/message_mods = list() +) + var/mob/living/silicon/ai/ai_user = user + ai_user.holopad_talk(message, spans, language, message_mods) + return SAYMODE_MESSAGE_HANDLED diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index 3dcad01f284b..e06b127ecc87 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -392,12 +392,12 @@ /datum/status_effect/lightningorb/on_apply() . = ..() - owner.add_movespeed_modifier(/datum/movespeed_modifier/yellow_orb) + owner.add_movespeed_modifier(/datum/movespeed_modifier/status_effect/yellow_orb) to_chat(owner, span_notice("You feel fast!")) /datum/status_effect/lightningorb/on_remove() . = ..() - owner.remove_movespeed_modifier(/datum/movespeed_modifier/yellow_orb) + owner.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/yellow_orb) to_chat(owner, span_notice("You slow down.")) /atom/movable/screen/alert/status_effect/lightningorb @@ -454,18 +454,22 @@ status_type = STATUS_EFFECT_REPLACE show_duration = TRUE alert_type = null + ///What speed datum do we apply? + var/move_datum = /datum/movespeed_modifier/status_speed_boost /datum/status_effect/speed_boost/on_creation(mob/living/new_owner, set_duration) if(isnum(set_duration)) duration = set_duration + new_owner.do_alert_animation() + playsound(new_owner, 'sound/machines/chime.ogg', 50, FALSE, -5) . = ..() /datum/status_effect/speed_boost/on_apply() - owner.add_movespeed_modifier(/datum/movespeed_modifier/status_speed_boost, update = TRUE) + owner.add_movespeed_modifier(move_datum, update = TRUE) return ..() /datum/status_effect/speed_boost/on_remove() - owner.remove_movespeed_modifier(/datum/movespeed_modifier/status_speed_boost, update = TRUE) + owner.remove_movespeed_modifier(move_datum, update = TRUE) /datum/movespeed_modifier/status_speed_boost multiplicative_slowdown = -1 diff --git a/code/datums/weather/weather_types/rain_storm.dm b/code/datums/weather/weather_types/rain_storm.dm index 31254fd42a55..1a4da05eb2af 100644 --- a/code/datums/weather/weather_types/rain_storm.dm +++ b/code/datums/weather/weather_types/rain_storm.dm @@ -129,11 +129,11 @@ GLOB.wizard_rain_reagents |= allowed_medicine // One randomized type is allowed so the whitelist isn't spammed with subtypes - GLOB.wizard_rain_reagents |= pick(subtypesof(/datum/reagent/glitter)) GLOB.wizard_rain_reagents |= pick(subtypesof(/datum/reagent/mutationtoxin)) GLOB.wizard_rain_reagents |= pick(subtypesof(/datum/reagent/plantnutriment)) GLOB.wizard_rain_reagents |= pick(subtypesof(/datum/reagent/impurity)) GLOB.wizard_rain_reagents |= pick(subtypesof(/datum/reagent/drug)) + GLOB.wizard_rain_reagents |= pick(typesof(/datum/reagent/glitter/random)) GLOB.wizard_rain_reagents |= pick(typesof(/datum/reagent/uranium)) GLOB.wizard_rain_reagents |= pick(typesof(/datum/reagent/luminescent_fluid)) GLOB.wizard_rain_reagents |= pick(typesof(/datum/reagent/carpet)) diff --git a/code/datums/wires/vending.dm b/code/datums/wires/vending.dm index 37ed5ab5caef..6eaa0bc49024 100644 --- a/code/datums/wires/vending.dm +++ b/code/datums/wires/vending.dm @@ -93,3 +93,24 @@ vending_machine.scan_id = mend if(WIRE_SPEAKER) vending_machine.shut_up = mend + + +/** + * Shock the passed in user + * + * This checks we have power and that the passed in prob is passed, then generates some sparks + * and calls electrocute_mob on the user + * + * Arguments: + * * user - the user to shock + * * shock_chance - probability the shock happens + */ +/obj/machinery/vending/proc/shock(mob/living/user, shock_chance) + if(!istype(user) || machine_stat & (BROKEN|NOPOWER)) // unpowered, no shock + return FALSE + if(!prob(shock_chance)) + return FALSE + do_sparks(5, TRUE, src) + if(electrocute_mob(user, get_area(src), src, 0.7, dist_check = TRUE)) + return TRUE + return FALSE diff --git a/code/datums/world_topic.dm b/code/datums/world_topic.dm index 69989a3f1519..346af2651d2b 100644 --- a/code/datums/world_topic.dm +++ b/code/datums/world_topic.dm @@ -304,14 +304,8 @@ var/author_key = input["author_ckey"] var/channel_name = input["message"] - var/found_channel = FALSE - for(var/datum/feed_channel/channel as anything in GLOB.news_network.network_channels) - if(channel.channel_name == channel_name) - found_channel = TRUE - break - - // No channel with a matching name, abort - if (!found_channel) + var/datum/feed_channel/chosen_channel = GLOB.news_network.network_channels_by_name[channel_name] + if(isnull(chosen_channel)) // No channel with a matching name, abort return message_admins(span_adminnotice("Incoming cross-sector newscaster article by [author_key] in channel [channel_name].")) diff --git a/code/datums/wounds/bones.dm b/code/datums/wounds/bones.dm index f0d6fefe07c0..8103f7047f1a 100644 --- a/code/datums/wounds/bones.dm +++ b/code/datums/wounds/bones.dm @@ -279,6 +279,8 @@ if(prob(40)) victim.visible_message(span_danger("[victim]'s dislocated [limb.plaintext_zone] pops back into place!"), span_userdanger("Your dislocated [limb.plaintext_zone] pops back into place! Ow!")) remove_wound() + return DOORCRUSH_NO_WOUND + return NONE /datum/wound/blunt/bone/moderate/try_handling(mob/living/user) if(user.usable_hands <= 0 || user.pulling != victim) diff --git a/code/game/atom/_atom.dm b/code/game/atom/_atom.dm index 63cbfe69317e..10aa9c8345af 100644 --- a/code/game/atom/_atom.dm +++ b/code/game/atom/_atom.dm @@ -414,18 +414,15 @@ * - [reagents][/list]: The list of reagents the atom is being exposed to. * - [source][/datum/reagents]: The reagent holder the reagents are being sourced from. * - methods: How the atom is being exposed to the reagents. Bitflags. - * - volume_modifier: Volume multiplier. * - show_message: Whether to display anything to mobs when they are exposed. */ -/atom/proc/expose_reagents(list/reagents, datum/reagents/source, methods=TOUCH, volume_modifier=1, show_message=TRUE) - . = SEND_SIGNAL(src, COMSIG_ATOM_EXPOSE_REAGENTS, reagents, source, methods, volume_modifier, show_message) +/atom/proc/expose_reagents(list/reagents, datum/reagents/source, methods=TOUCH, show_message=TRUE) + . = SEND_SIGNAL(src, COMSIG_ATOM_EXPOSE_REAGENTS, reagents, source, methods, show_message) if(. & COMPONENT_NO_EXPOSE_REAGENTS) return - SEND_SIGNAL(source, COMSIG_REAGENTS_EXPOSE_ATOM, src, reagents, methods, volume_modifier, show_message) for(var/datum/reagent/current_reagent as anything in reagents) . |= current_reagent.expose_atom(src, reagents[current_reagent], methods) - SEND_SIGNAL(src, COMSIG_ATOM_AFTER_EXPOSE_REAGENTS, reagents, source, methods, volume_modifier, show_message) /// Are you allowed to drop this atom /atom/proc/AllowDrop() @@ -652,25 +649,25 @@ /atom/proc/StartProcessingAtom(mob/living/user, obj/item/process_item, list/chosen_option) var/processing_time = chosen_option[TOOL_PROCESSING_TIME] to_chat(user, span_notice("You start working on [src].")) - if(process_item.use_tool(src, user, processing_time, volume=50)) - var/atom/atom_to_create = chosen_option[TOOL_PROCESSING_RESULT] - var/list/atom/created_atoms = list() - var/amount_to_create = chosen_option[TOOL_PROCESSING_AMOUNT] - for(var/i = 1 to amount_to_create) - var/atom/created_atom = new atom_to_create(drop_location()) - created_atom.OnCreatedFromProcessing(user, process_item, chosen_option, src) - if(custom_materials) - created_atom.set_custom_materials(custom_materials, 1 / amount_to_create) - created_atom.pixel_x = pixel_x - created_atom.pixel_y = pixel_y - if(i > 1) - created_atom.pixel_x += rand(-8,8) - created_atom.pixel_y += rand(-8,8) - created_atoms.Add(created_atom) - to_chat(user, span_notice("You manage to create [amount_to_create] [initial(atom_to_create.gender) == PLURAL ? "[initial(atom_to_create.name)]" : "[initial(atom_to_create.name)][plural_s(initial(atom_to_create.name))]"] from [src].")) - SEND_SIGNAL(src, COMSIG_ATOM_PROCESSED, user, process_item, created_atoms) - UsedforProcessing(user, process_item, chosen_option, created_atoms) + if(!process_item.use_tool(src, user, processing_time, volume=50)) return + var/atom/atom_to_create = chosen_option[TOOL_PROCESSING_RESULT] + var/list/atom/created_atoms = list() + var/amount_to_create = chosen_option[TOOL_PROCESSING_AMOUNT] + for(var/i = 1 to amount_to_create) + var/atom/created_atom = new atom_to_create(drop_location()) + created_atom.OnCreatedFromProcessing(user, process_item, chosen_option, src) + if(custom_materials) + created_atom.set_custom_materials(custom_materials, 1 / amount_to_create) + created_atom.pixel_x = pixel_x + created_atom.pixel_y = pixel_y + if(i > 1) + created_atom.pixel_x += rand(-8,8) + created_atom.pixel_y += rand(-8,8) + created_atoms.Add(created_atom) + to_chat(user, span_notice("You manage to create [amount_to_create] [initial(atom_to_create.gender) == PLURAL ? "[initial(atom_to_create.name)]" : "[initial(atom_to_create.name)][plural_s(initial(atom_to_create.name))]"] from [src].")) + SEND_SIGNAL(src, COMSIG_ATOM_PROCESSED, user, process_item, created_atoms) + UsedforProcessing(user, process_item, chosen_option, created_atoms) /atom/proc/UsedforProcessing(mob/living/user, obj/item/used_item, list/chosen_option, list/created_atoms) qdel(src) diff --git a/code/game/atom/atom_materials.dm b/code/game/atom/atom_materials.dm index 1c227db2394e..542930919ce5 100644 --- a/code/game/atom/atom_materials.dm +++ b/code/game/atom/atom_materials.dm @@ -394,3 +394,49 @@ */ /atom/proc/get_custom_material_amount() return isnull(custom_materials) ? 0 : counterlist_sum(custom_materials) + + +/** + * A bit of leeway when comparing the amount of material of two items. + * This was made to test the material composition of items spawned via crafting/processable component and an items of the same type spawned + * via other means, since small portion of materials can be lost when rounding down values to the nearest integers and we can't do much about it. + * (eg. a slab of meat worth 100 mat points is cut in three cutlets, each 33, with the remaining 1 percent lost to rounding) + * + * right now it's 3 points per 100 units of a material. + * + */ + +#define COMPARISION_ACCEPTABLE_MATERIAL_DEVIATION 0.03 + +/// Compares the materials of two items to see if they're roughly the same. Primarily used in crafting and processing unit tests. +/atom/proc/compare_materials(atom/target) + if(length(custom_materials) != length(target.custom_materials)) + return FALSE + for(var/mat in custom_materials) + var/enemy_amount = target.custom_materials[mat] + if(!enemy_amount) //we couldn't find said material, early return so we won't perform a division by zero + return FALSE + var/ratio_difference = abs((custom_materials[mat] / enemy_amount) - 1) + if(ratio_difference > COMPARISION_ACCEPTABLE_MATERIAL_DEVIATION) + return FALSE + return TRUE + +#undef COMPARISION_ACCEPTABLE_MATERIAL_DEVIATION + +/** + * Returns a string with the materials and their respective amounts in it (eg. [list(/datum/material/meat = 100, /datum/material/plastic = 10)] ) + * also used in several unit tests. + */ +/atom/proc/get_materials_english_list() + if(!custom_materials) + return "null" + var/text = "\[list(" + var/index = 1 + var/mats_len = length(custom_materials) + for(var/datum/material/mat as anything in custom_materials) + text += "[mat.type] = [custom_materials[mat]]" + if(index < mats_len) + text += ", " + index++ + text += ")\]" + return text diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm index 0cb035ef3d96..04ba0e524395 100644 --- a/code/game/data_huds.dm +++ b/code/game/data_huds.dm @@ -262,12 +262,15 @@ Security HUDs! Basic mode shows only the job. //HOOKS -/mob/living/carbon/human/proc/sec_hud_set_ID() +/mob/living/carbon/human/proc/update_ID_card() + SIGNAL_HANDLER + var/sechud_icon_state = wear_id?.get_sechud_job_icon_state() if(!sechud_icon_state || HAS_TRAIT(src, TRAIT_UNKNOWN)) sechud_icon_state = "hudno_id" set_hud_image_state(ID_HUD, sechud_icon_state) sec_hud_set_security_status() + update_visible_name() /mob/living/proc/sec_hud_set_implants() for(var/hud_type in (list(IMPSEC_FIRST_HUD, IMPLOYAL_HUD, IMPSEC_SECOND_HUD) & hud_list)) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 47639b795979..efcc1777aab1 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -196,7 +196,7 @@ GLOBAL_LIST(admin_objective_list) //Prefilled admin assignable objective list button_icon = 'icons/obj/devices/tracker.dmi' button_icon_state = "beacon" -/datum/action/special_equipment_fallback/Trigger(trigger_flags) +/datum/action/special_equipment_fallback/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return FALSE diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index ff0cef960878..c6d3dda3f9dc 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -161,11 +161,11 @@ acid = 70 ///Needed by machine frame & flatpacker i.e the named arg board -/obj/machinery/New(loc, obj/item/circuitboard/board, ...) +/obj/machinery/New(location, obj/item/circuitboard/board, ...) if(istype(board)) circuit = board //we don't want machines that override Initialize() have the board passed as a param e.g. atmos - return ..(loc) + return ..(location) return ..() @@ -1123,7 +1123,7 @@ RefreshParts() if(shouldplaysound) - replacer_tool.play_rped_sound() + replacer_tool.play_rped_effect() return TRUE /obj/machinery/proc/display_parts(mob/user) diff --git a/code/game/machinery/civilian_bounties.dm b/code/game/machinery/civilian_bounties.dm index b463ea45c214..0b24fb8ebe10 100644 --- a/code/game/machinery/civilian_bounties.dm +++ b/code/game/machinery/civilian_bounties.dm @@ -267,14 +267,14 @@ var/holder_item = FALSE if(!isidcard(card_to_insert)) - card_to_insert = inserting_item.RemoveID() + card_to_insert = inserting_item.remove_id() holder_item = TRUE if(!card_to_insert || !user.transferItemToLoc(card_to_insert, src)) return FALSE if(target) - if(holder_item && inserting_item.InsertID(target)) + if(holder_item && inserting_item.insert_id(target)) playsound(src, 'sound/machines/terminal/terminal_insert_disc.ogg', 50, FALSE) else id_eject(user, target) diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm index 25bdf3a87d90..5dd9ec491279 100644 --- a/code/game/machinery/computer/buildandrepair.dm +++ b/code/game/machinery/computer/buildandrepair.dm @@ -124,7 +124,7 @@ if(add_cabling(user, cable, time = 0)) if(!no_sound) - replacer.play_rped_sound() + replacer.play_rped_effect() no_sound = TRUE return install_parts_from_part_replacer(user, replacer, no_sound = no_sound) // Recursive call to handle the next part @@ -137,7 +137,7 @@ if(add_glass(user, glass_sheets, time = 0)) if(!no_sound) - replacer.play_rped_sound() + replacer.play_rped_effect() return TRUE return FALSE diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index 0a41adcac98f..880313d09fb1 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -196,7 +196,7 @@ // After installing, attempts to follow up by inserting parts install_parts_from_part_replacer(user, replacer, no_sound = TRUE) if(!no_sound) - replacer.play_rped_sound() + replacer.play_rped_effect() return TRUE return FALSE diff --git a/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm b/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm index 3fcfe55a7724..745131ee0192 100644 --- a/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm @@ -31,7 +31,7 @@ /// Are we at all five organs? var/color_active = FALSE -/datum/status_effect/organ_set_bonus/fish/enable_bonus() +/datum/status_effect/organ_set_bonus/fish/enable_bonus(obj/item/organ/inserted_organ) . = ..() if(!.) return @@ -55,7 +55,7 @@ owner.mind?.adjust_experience(/datum/skill/fishing, SKILL_EXP_JOURNEYMAN, silent = TRUE) owner.grant_language(/datum/language/carptongue, ALL, type) -/datum/status_effect/organ_set_bonus/fish/disable_bonus() +/datum/status_effect/organ_set_bonus/fish/disable_bonus(obj/item/organ/removed_organ) . = ..() UnregisterSignal(owner, list( COMSIG_CARBON_GAIN_ORGAN, @@ -80,7 +80,7 @@ owner.mind?.adjust_experience(/datum/skill/fishing, -SKILL_EXP_JOURNEYMAN, silent = TRUE) owner.remove_language(/datum/language/carptongue, ALL, type) -/datum/status_effect/organ_set_bonus/fish/set_organs(new_value) +/datum/status_effect/organ_set_bonus/fish/set_organs(new_value, obj/item/organ/organ) . = ..() if (!iscarbon(owner)) return diff --git a/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm b/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm index 646290db0e2a..1d9c8bdc743e 100644 --- a/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/fly_organs.dm @@ -8,14 +8,27 @@ bonus_activate_text = null bonus_deactivate_text = null -/datum/status_effect/organ_set_bonus/fly/enable_bonus() +/datum/status_effect/organ_set_bonus/fly/enable_bonus(obj/item/organ/inserted_organ) . = ..() if(!. || !ishuman(owner)) return var/mob/living/carbon/human/new_fly = owner if(isflyperson(new_fly)) return - //okay you NEED to be a fly + // This is ugly as sin, but we're called before the organ finishes inserting into the bodypart + // so if we swap species directly the bodypart will be replaced and we'll be gone + // so we need to delay species change until we're fully inserted + RegisterSignal(inserted_organ, COMSIG_ORGAN_BODYPART_INSERTED, PROC_REF(flyify)) + +/datum/status_effect/organ_set_bonus/fly/proc/flyify(obj/item/organ/source, obj/item/bodypart/limb, movement_flags) + SIGNAL_HANDLER + var/mob/living/carbon/human/new_fly = owner + // just in case? + if(isflyperson(new_fly)) + return + // needs to be done before the species is set + UnregisterSignal(source, COMSIG_ORGAN_BODYPART_INSERTED) + // okay you NEED to be a fly to_chat(new_fly, span_danger("Too much fly DNA! Your skin begins to discolor into a horrible black as you become more fly than person!")) new_fly.set_species(/datum/species/fly) diff --git a/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm b/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm index 2e28fd94d849..4988ad4d638c 100644 --- a/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm @@ -20,7 +20,7 @@ /// Armor type attached to the owner's physiology var/datum/armor/given_armor = /datum/armor/roach_internal_armor -/datum/status_effect/organ_set_bonus/roach/enable_bonus() +/datum/status_effect/organ_set_bonus/roach/enable_bonus(obj/item/organ/inserted_organ) . = ..() if(!ishuman(owner)) return @@ -28,7 +28,7 @@ var/mob/living/carbon/human/human_owner = owner human_owner.physiology.armor = human_owner.physiology.armor.add_other_armor(given_armor) -/datum/status_effect/organ_set_bonus/roach/disable_bonus() +/datum/status_effect/organ_set_bonus/roach/disable_bonus(obj/item/organ/removed_organ) . = ..() if(!ishuman(owner) || QDELETED(owner)) return diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 4059fc3f5c88..dc86f0fc6d94 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -597,7 +597,8 @@ for(var/heading in list(NORTH,SOUTH,EAST,WEST)) if(!(unres_sides & heading)) continue - var/mutable_appearance/floorlight = mutable_appearance('icons/obj/doors/airlocks/station/overlays.dmi', "unres_[heading]", FLOAT_LAYER, src, ABOVE_LIGHTING_PLANE) + var/mutable_appearance/floorlight = mutable_appearance('icons/obj/doors/airlocks/station/overlays.dmi', "unres_[heading]", FLOAT_LAYER, src, O_LIGHTING_VISUAL_PLANE, appearance_flags = RESET_COLOR | KEEP_APART) + floorlight.color = LIGHT_COLOR_DEFAULT switch (heading) if (NORTH) floorlight.pixel_w = 0 diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index aa033e79412c..9cb7dea5cc66 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -584,24 +584,23 @@ for(var/turf/checked_turf in locs) for(var/mob/living/future_pancake in checked_turf) future_pancake.visible_message(span_warning("[src] closes on [future_pancake], crushing [future_pancake.p_them()]!"), span_userdanger("[src] closes on you and crushes you!")) - SEND_SIGNAL(future_pancake, COMSIG_LIVING_DOORCRUSHED, src) + var/sig_return = SEND_SIGNAL(future_pancake, COMSIG_LIVING_DOORCRUSHED, src) + future_pancake.add_splatter_floor(loc) + log_combat(src, future_pancake, "crushed") + var/door_wounding = (sig_return & DOORCRUSH_NO_WOUND) ? CANT_WOUND : 10 if(isalien(future_pancake)) //For xenos - future_pancake.adjustBruteLoss(DOOR_CRUSH_DAMAGE * 1.5) //Xenos go into crit after aproximately the same amount of crushes as humans. + future_pancake.apply_damage(DOOR_CRUSH_DAMAGE * 1.5, BRUTE, BODY_ZONE_CHEST, wound_bonus = door_wounding, attacking_item = src) //Xenos go into crit after aproximately the same amount of crushes as humans. future_pancake.emote("roar") else if(ismonkey(future_pancake)) //For monkeys future_pancake.emote("screech") - future_pancake.adjustBruteLoss(DOOR_CRUSH_DAMAGE) - future_pancake.Paralyze(100) + future_pancake.apply_damage(DOOR_CRUSH_DAMAGE, BRUTE, BODY_ZONE_CHEST, wound_bonus = door_wounding, attacking_item = src) + future_pancake.Paralyze(10 SECONDS) else if(ishuman(future_pancake)) //For humans - future_pancake.adjustBruteLoss(DOOR_CRUSH_DAMAGE) future_pancake.emote("scream") - future_pancake.Paralyze(100) + future_pancake.apply_damage(DOOR_CRUSH_DAMAGE, BRUTE, BODY_ZONE_CHEST, wound_bonus = door_wounding, attacking_item = src) + future_pancake.Paralyze(10 SECONDS) else //for simple_animals & borgs - future_pancake.adjustBruteLoss(DOOR_CRUSH_DAMAGE) - var/turf/location = get_turf(src) - //add_blood doesn't work for borgs/xenos, but add_blood_floor does. - future_pancake.add_splatter_floor(location) - log_combat(src, future_pancake, "crushed") + future_pancake.apply_damage(DOOR_CRUSH_DAMAGE, BRUTE, BODY_ZONE_CHEST, wound_bonus = door_wounding, attacking_item = src) for(var/obj/vehicle/sealed/mecha/mech in get_turf(src)) // Your fancy metal won't save you here! mech.take_damage(DOOR_CRUSH_DAMAGE) log_combat(src, mech, "crushed") diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index ed65cb4baf6e..8b3f9f6e5fce 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -185,6 +185,8 @@ /obj/machinery/door/firedoor/update_name(updates) . = ..() + if(!my_area || !id_tag) + return name = "[get_area_name(my_area)] [initial(name)] [id_tag]" /** diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 0c7004dde921..429b648624a2 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -119,20 +119,24 @@ switch(dir) if(NORTH,SOUTH) if(unres_sides & NORTH) - var/image/side_overlay = image(icon='icons/obj/doors/airlocks/station/overlays.dmi', icon_state="unres_n") + var/mutable_appearance/side_overlay = mutable_appearance('icons/obj/doors/airlocks/station/overlays.dmi', "unres_1", FLOAT_LAYER, src, O_LIGHTING_VISUAL_PLANE, appearance_flags = RESET_COLOR | KEEP_APART) + side_overlay.color = LIGHT_COLOR_DEFAULT side_overlay.pixel_z = dir == NORTH ? 31 : 6 . += side_overlay if(unres_sides & SOUTH) - var/image/side_overlay = image(icon='icons/obj/doors/airlocks/station/overlays.dmi', icon_state="unres_s") + var/mutable_appearance/side_overlay = mutable_appearance('icons/obj/doors/airlocks/station/overlays.dmi', "unres_2", FLOAT_LAYER, src, O_LIGHTING_VISUAL_PLANE, appearance_flags = RESET_COLOR | KEEP_APART) + side_overlay.color = LIGHT_COLOR_DEFAULT side_overlay.pixel_z = dir == NORTH ? -6 : -31 . += side_overlay if(EAST,WEST) if(unres_sides & EAST) - var/image/side_overlay = image(icon='icons/obj/doors/airlocks/station/overlays.dmi', icon_state="unres_e") + var/mutable_appearance/side_overlay = mutable_appearance('icons/obj/doors/airlocks/station/overlays.dmi', "unres_4", FLOAT_LAYER, src, O_LIGHTING_VISUAL_PLANE, appearance_flags = RESET_COLOR | KEEP_APART) + side_overlay.color = LIGHT_COLOR_DEFAULT side_overlay.pixel_w = dir == EAST ? 31 : 6 . += side_overlay if(unres_sides & WEST) - var/image/side_overlay = image(icon='icons/obj/doors/airlocks/station/overlays.dmi', icon_state="unres_w") + var/mutable_appearance/side_overlay = mutable_appearance('icons/obj/doors/airlocks/station/overlays.dmi', "unres_8", FLOAT_LAYER, src, O_LIGHTING_VISUAL_PLANE, appearance_flags = RESET_COLOR | KEEP_APART) + side_overlay.color = LIGHT_COLOR_DEFAULT side_overlay.pixel_w = dir == EAST ? -6 : -31 . += side_overlay diff --git a/code/game/machinery/drone_dispenser.dm b/code/game/machinery/drone_dispenser.dm index 82fdf1fad498..0cee62cc1e50 100644 --- a/code/game/machinery/drone_dispenser.dm +++ b/code/game/machinery/drone_dispenser.dm @@ -95,7 +95,7 @@ desc = "A suspicious machine that will create Syndicate exterminator drones when supplied with iron and glass. Disgusting." dispense_type = list(/obj/effect/mob_spawn/ghost_role/drone/syndrone) //If we're gonna be a jackass, go the full mile - 10 second recharge timer - cooldownTime = 100 + cooldownTime = 10 SECONDS end_create_message = "dispenses a suspicious drone shell." starting_amount = SHEET_MATERIAL_AMOUNT * 12.5 @@ -126,7 +126,7 @@ iron_cost = SHEET_MATERIAL_AMOUNT * 5 glass_cost = SHEET_MATERIAL_AMOUNT * 2.5 starting_amount = 0 - cooldownTime = 600 + cooldownTime = 60 SECONDS /obj/machinery/drone_dispenser/classic name = "classic drone shell dispenser" @@ -148,7 +148,7 @@ iron_cost = 0 glass_cost = 0 energy_used = 0 - cooldownTime = 10 //Only 1 second - hivebots are extremely weak + cooldownTime = 1 SECONDS //Only 1 second - hivebots are extremely weak dispense_type = list(/mob/living/basic/hivebot) begin_create_message = "closes and begins fabricating something within." end_create_message = "slams open, revealing a hivebot!" diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index d53667e61b8b..84f360f06aab 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -590,7 +590,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ holocall_to_update.user.Hear(message, speaker, message_language, raw_message, radio_freq, radio_freq_name, radio_freq_color, spans, message_mods, message_range = INFINITY) if(outgoing_call?.hologram && speaker == outgoing_call.user) - outgoing_call.hologram.say(raw_message, sanitize = FALSE) + outgoing_call.hologram.say(raw_message, spans = spans, sanitize = FALSE, language = message_language, message_mods = message_mods) if(record_mode && speaker == record_user) record_message(speaker, raw_message, message_language) diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index 977f02778590..d606556985b3 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -428,7 +428,7 @@ /datum/crafting_recipe/iv_drip name = "IV drip" result = /obj/machinery/iv_drip - time = 30 + time = 3 SECONDS tool_behaviors = list(TOOL_SCREWDRIVER) reqs = list( /obj/item/stack/rods = 2, diff --git a/code/game/machinery/machine_frame.dm b/code/game/machinery/machine_frame.dm index 4447ef140dc9..e74daa5c3ad0 100644 --- a/code/game/machinery/machine_frame.dm +++ b/code/game/machinery/machine_frame.dm @@ -258,7 +258,7 @@ play_sound = TRUE if(play_sound && !no_sound) - replacer.play_rped_sound() + replacer.play_rped_effect() return TRUE diff --git a/code/game/machinery/newscaster/newscaster_data.dm b/code/game/machinery/newscaster/newscaster_data.dm index d67e7e99365f..59b8f09db477 100644 --- a/code/game/machinery/newscaster/newscaster_data.dm +++ b/code/game/machinery/newscaster/newscaster_data.dm @@ -42,9 +42,9 @@ GLOBAL_LIST_EMPTY(request_list) ///Referece to the photo used in picture messages. var/photo_file ///What is the channel ID of the parent channel? - var/parent_ID + var/parent_id ///What number message is this? IE: The first message sent in a round including automated messages is message 1. - var/message_ID + var/message_id /datum/feed_message/proc/return_author(censor) if(censor == -1) @@ -99,37 +99,13 @@ GLOBAL_LIST_EMPTY(request_list) var/author_censor /// Is this an admin channel? Allows for actions to be taken by the admin only. var/is_admin_channel = FALSE - /// Channel ID is a random number sequence similar to account ID number that allows for us to link messages to the proper channels through the UI backend. - var/channel_ID + /// Channel ID is a unique number sequence similar to account ID number that allows for us to link messages to the proper channels through the UI backend. + var/channel_id /// Should this channel send cross-server messages? var/cross_sector = FALSE /// Is this a cross-sector channel? If so, this channel can only receive messages via topics var/receiving_cross_sector = FALSE -/datum/feed_channel/New() - . = ..() - channel_ID = random_channel_id_setup() - -/** - * This proc assigns each feed_channel a random integer, from 1-999 as a unique identifier. - * Using this value, the TGUI window has a unique identifier to attach to messages that can be used to reattach them - * to their parent channels back in dreammaker. - * Based on implementation, we're limiting ourselves to only 998 player made channels maximum. How we'd use all of them, I don't know. - */ -/datum/feed_channel/proc/random_channel_id_setup() - if(!GLOB.news_network) - return //Should only apply to channels made before setup is finished, use hardset_channel for these - if(!GLOB.news_network.channel_IDs) - GLOB.news_network.channel_IDs += rand(1,999) - return //This will almost always be the station announcements channel here. - var/channel_id - for(var/i in 1 to 10000) - channel_id = rand(1, 999) - if(!GLOB.news_network.channel_IDs["[channel_ID]"]) - break - channel_ID = channel_id - return channel_ID - /datum/feed_channel/proc/return_author(censor) if(censor == -1) censor = author_censor @@ -173,36 +149,47 @@ GLOBAL_LIST_EMPTY(request_list) /datum/feed_network /// All the feed channels that have been made on the feed network. var/list/datum/feed_channel/network_channels = list() + /// Associative list of all the feed channels that have been made on the feed network, from channel ID to channel. + var/list/datum/feed_channel/network_channels_by_id = list() + /// Associative list of all the feed channels that have been made on the feed network, from channel name to channel. + var/list/datum/feed_channel/network_channels_by_name = list() /// What is the wanted issue being sent out to all newscasters. var/datum/wanted_message/wanted_issue /// What time was the last action taken on the feed_network? var/last_action /// What does this feed network say when a message/author is redacted? var/redacted_text = "\[REDACTED\]" - /// List of all the network_channels Channel Id numbers, kept in a global easy to find place. - var/list/channel_IDs = list() + /// Channel ID to use when next making a new channel, to maintain unique IDs. + var/next_channel_id = 1 /// How many messages currently exist on this feed_network? Increments as new messages are written. var/message_count = 0 /datum/feed_network/New() - create_feed_channel(NEWSCASTER_STATION_ANNOUNCEMENTS, "SS13", "Company news, staff announcements, and all the latest information. Have a secure shift!", locked = TRUE, hardset_channel = 1000) - create_feed_channel(NEWSCASTER_SPACE_BETTING, "NtOS", "News from the SpaceBet PDA App! Download now and make your own bets!", locked = TRUE, hardset_channel = 1001) + create_feed_channel(NEWSCASTER_STATION_ANNOUNCEMENTS, "SS13", "Company news, staff announcements, and all the latest information. Have a secure shift!", locked = TRUE) + create_feed_channel(NEWSCASTER_SPACE_BETTING, "NtOS", "News from the SpaceBet PDA App! Download now and make your own bets!", locked = TRUE) wanted_issue = new /datum/wanted_message -/datum/feed_network/proc/create_feed_channel(channel_name, author, desc, locked, adminChannel = FALSE, hardset_channel = null, author_ckey = null, cross_sector = FALSE, cross_sector_delay = null, receiving_cross_sector = FALSE) - var/datum/feed_channel/newChannel = new /datum/feed_channel - newChannel.channel_name = channel_name - newChannel.author = author - newChannel.channel_desc = desc - newChannel.locked = locked - newChannel.is_admin_channel = adminChannel - newChannel.receiving_cross_sector = receiving_cross_sector - if(hardset_channel) - newChannel.channel_ID = hardset_channel - network_channels += newChannel +/datum/feed_network/proc/add_feed_channel(datum/feed_channel/new_channel) + network_channels += new_channel + network_channels_by_id["[new_channel.channel_id]"] = new_channel + network_channels_by_name["[new_channel.channel_name]"] = new_channel + +/datum/feed_network/proc/create_feed_channel(channel_name, author, desc, locked, adminChannel = FALSE, author_ckey = null, cross_sector = FALSE, cross_sector_delay = null, receiving_cross_sector = FALSE) + var/datum/feed_channel/new_channel = new /datum/feed_channel + new_channel.channel_name = channel_name + new_channel.author = author + new_channel.channel_desc = desc + new_channel.locked = locked + new_channel.is_admin_channel = adminChannel + new_channel.receiving_cross_sector = receiving_cross_sector + new_channel.channel_id = next_channel_id + next_channel_id++ + + add_feed_channel(new_channel) + if(!cross_sector) return - newChannel.cross_sector = TRUE + new_channel.cross_sector = TRUE var/list/payload = list( "author" = author, "author_ckey" = author_ckey, @@ -212,31 +199,32 @@ GLOBAL_LIST_EMPTY(request_list) send2otherserver(html_decode(station_name()), channel_name, "create_news_channel", additional_data = payload) /datum/feed_network/proc/submit_article(msg, author, channel_name, datum/picture/picture, adminMessage = FALSE, allow_comments = TRUE, update_alert = TRUE, mob/author_mob = null) - var/datum/feed_message/newMsg = new /datum/feed_message - newMsg.author = author - newMsg.body = msg - newMsg.time_stamp = "[station_time_timestamp()]" - newMsg.is_admin_message = adminMessage - newMsg.locked = !allow_comments + var/datum/feed_channel/chosen_channel = network_channels_by_name[channel_name] + if(isnull(chosen_channel)) + stack_trace("Article submitted to non-existent newscaster channel: [channel_name]") + return + + var/datum/feed_message/new_article = new /datum/feed_message + new_article.author = author + new_article.body = msg + new_article.time_stamp = "[station_time_timestamp()]" + new_article.is_admin_message = adminMessage + new_article.locked = !allow_comments message_count++ last_action++ - newMsg.creation_time = last_action - newMsg.message_ID = message_count + new_article.creation_time = last_action + new_article.message_id = message_count if(picture) - newMsg.img = picture.picture_image - newMsg.caption = picture.caption - newMsg.photo_file = save_photo(picture.picture_image) - - for(var/datum/feed_channel/channel in network_channels) - if(channel.channel_name != channel_name) - continue - - channel.messages += newMsg - newMsg.parent_ID = channel.channel_ID - if (!channel.cross_sector) - break + new_article.img = picture.picture_image + new_article.caption = picture.caption + new_article.photo_file = save_photo(picture.picture_image) + + chosen_channel.messages += new_article + new_article.parent_id = chosen_channel.channel_id + + if(chosen_channel.cross_sector) // Newscaster articles could be huge, and usefulness of first 50 symbols is dubious message_admins(span_adminnotice("Outgoing cross-sector newscaster article by [key_name(author_mob) || author] in channel [channel_name].")) var/list/payload = list( @@ -245,11 +233,10 @@ GLOBAL_LIST_EMPTY(request_list) "msg" = msg, ) send2otherserver(html_decode(station_name()), channel_name, "create_news_article", additional_data = payload) - break for(var/obj/machinery/newscaster/caster in GLOB.allCasters) caster.news_alert(channel_name, update_alert) - return newMsg + return new_article ///Submits a comment on the news network /datum/feed_network/proc/submit_comment(mob/user, comment_text, newscaster_username, datum/feed_message/current_message) diff --git a/code/game/machinery/newscaster/newscaster_machine.dm b/code/game/machinery/newscaster/newscaster_machine.dm index 58e49501e0bf..77b9c51d0128 100644 --- a/code/game/machinery/newscaster/newscaster_machine.dm +++ b/code/game/machinery/newscaster/newscaster_machine.dm @@ -196,11 +196,11 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30) //Then, breaks down the messages that have been made on those channels. if(current_channel) for(var/datum/feed_message/feed_message as anything in current_channel.messages) - var/photo_ID = null + var/photo_id = null var/list/comment_list if(feed_message.img) - user << browse_rsc(feed_message.img, "tmp_photo[feed_message.message_ID].png") - photo_ID = "tmp_photo[feed_message.message_ID].png" + user << browse_rsc(feed_message.img, "tmp_photo[feed_message.message_id].png") + photo_id = "tmp_photo[feed_message.message_id].png" for(var/datum/feed_comment/comment_message as anything in feed_message.comments) comment_list += list(list( "auth" = comment_message.author, @@ -211,16 +211,16 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30) "auth" = feed_message.author, "body" = feed_message.body, "time" = feed_message.time_stamp, - "channel_num" = feed_message.parent_ID, + "channel_num" = feed_message.parent_id, "censored_message" = feed_message.body_censor, "censored_author" = feed_message.author_censor, - "ID" = feed_message.message_ID, - "photo" = photo_ID, + "ID" = feed_message.message_id, + "photo" = photo_id, "comments" = comment_list )) - data["viewing_channel"] = current_channel?.channel_ID + data["viewing_channel"] = current_channel?.channel_id data["paper"] = paper_remaining //Here we display all the information about the current channel. data["channelName"] = current_channel?.channel_name @@ -264,7 +264,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30) "author" = channel.author, "censored" = channel.censored, "locked" = channel.locked, - "ID" = channel.channel_ID, + "ID" = channel.channel_id, )) data["channels"] = channel_list @@ -293,19 +293,20 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30) switch(action) if("setChannel") - var/prototype_channel = params["channel"] - if(isnull(prototype_channel)) + var/selected_channel_id = params["channel"] + if(isnull(selected_channel_id)) return TRUE - for(var/datum/feed_channel/potential_channel as anything in GLOB.news_network.network_channels) - if(prototype_channel == potential_channel.channel_ID) - current_channel = potential_channel + var/datum/feed_channel/potential_channel = GLOB.news_network.network_channels_by_id["[selected_channel_id]"] + if(isnull(potential_channel)) + return TRUE + current_channel = potential_channel if("createStory") if(!current_channel) balloon_alert(user, "select a channel first!") return TRUE - var/prototype_channel = params["current"] - create_story(user, channel_name = prototype_channel) + var/current_channel_id = params["current"] + create_story(user, channel_id = current_channel_id) if("togglePhoto") toggle_photo(user) @@ -352,7 +353,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30) return TRUE var/questionable_message = params["messageID"] for(var/datum/feed_message/iterated_feed_message as anything in current_channel.messages) - if(iterated_feed_message.message_ID == questionable_message) + if(iterated_feed_message.message_id == questionable_message) iterated_feed_message.toggle_censor_body() break @@ -366,7 +367,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30) return TRUE var/questionable_message = params["messageID"] for(var/datum/feed_message/iterated_feed_message in current_channel.messages) - if(iterated_feed_message.message_ID == questionable_message) + if(iterated_feed_message.message_id == questionable_message) iterated_feed_message.toggle_censor_author() break @@ -378,11 +379,13 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30) if(!(admin_access in id_card?.GetAccess())) say("Clearance not found.") return TRUE - var/prototype_channel = (params["channel"]) - for(var/datum/feed_channel/potential_channel in GLOB.news_network.network_channels) - if(prototype_channel == potential_channel.channel_ID) - current_channel = potential_channel - break + var/selected_channel_id = (params["channel"]) + if(isnull(selected_channel_id)) + return TRUE + var/datum/feed_channel/potential_channel = GLOB.news_network.network_channels_by_id["[selected_channel_id]"] + if(isnull(potential_channel)) + return TRUE + current_channel = potential_channel current_channel.toggle_censor_D_class() if("startComment") @@ -394,7 +397,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30) if(!commentable_message) return TRUE for(var/datum/feed_message/iterated_feed_message as anything in current_channel.messages) - if(iterated_feed_message.message_ID == commentable_message) + if(iterated_feed_message.message_id == commentable_message) current_message = iterated_feed_message return TRUE @@ -660,10 +663,10 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30) if(isnull(channel_locked)) return TRUE - for(var/datum/feed_channel/iterated_feed_channel as anything in GLOB.news_network.network_channels) - if(iterated_feed_channel.channel_name == channel_name) - tgui_alert(user, "ERROR: Feed channel with that name already exists on the Network.", list("Okay")) - return TRUE + var/datum/feed_channel/potential_channel = GLOB.news_network.network_channels_by_name[channel_name] + if(potential_channel) + tgui_alert(user, "ERROR: Feed channel with that name already exists on the Network.", list("Okay")) + return TRUE var/list/hard_filter_result = is_ic_filtered(channel_name) if(hard_filter_result) @@ -769,13 +772,13 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30) * Verifies that the message is being written to a real feed_channel, then provides a text input for the feed story to be written into. * Finally, it submits the message to the network, is logged globally, and clears all message-specific variables from the machine. */ -/obj/machinery/newscaster/proc/create_story(mob/user, channel_name) - for(var/datum/feed_channel/potential_channel as anything in GLOB.news_network.network_channels) - if(channel_name == potential_channel.channel_ID) - current_channel = potential_channel - break +/obj/machinery/newscaster/proc/create_story(mob/user, channel_id) + var/datum/feed_channel/potential_channel = GLOB.news_network.network_channels_by_id["[channel_id]"] + if(isnull(potential_channel)) + return + current_channel = potential_channel - if (current_channel.receiving_cross_sector) + if(current_channel.receiving_cross_sector) return var/temp_message = tgui_input_text(user, "Write your Feed story", "Network Channel Handler", feed_channel_message, max_length = MAX_BROADCAST_LEN, multiline = TRUE) diff --git a/code/game/machinery/newscaster/newspaper.dm b/code/game/machinery/newscaster/newspaper.dm index 7c1369940e7e..de706f1b5f5c 100644 --- a/code/game/machinery/newscaster/newspaper.dm +++ b/code/game/machinery/newscaster/newspaper.dm @@ -150,18 +150,22 @@ RegisterSignal(user, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(holder_updated_overlays)) RegisterSignal(user, COMSIG_HUMAN_GET_VISIBLE_NAME, PROC_REF(holder_checked_name)) user.update_appearance(UPDATE_OVERLAYS) - user.name = user.get_visible_name() if (!punctured) user.add_fov_trait(REF(src), FOV_REVERSE_270_DEGRESS) + if (ishuman(user)) + var/mob/living/carbon/human/as_human = user + as_human.update_visible_name() /// Called when you stop doing that /obj/item/newspaper/proc/on_unwielded(obj/item/source, mob/living/user) REMOVE_TRAIT(user, TRAIT_FACE_COVERED, REF(src)) UnregisterSignal(user, list(COMSIG_ATOM_UPDATE_OVERLAYS, COMSIG_HUMAN_GET_VISIBLE_NAME)) user.update_appearance(UPDATE_OVERLAYS) - user.name = user.get_visible_name() if (!punctured) user.remove_fov_trait(REF(src), FOV_REVERSE_270_DEGRESS) + if (ishuman(user)) + var/mob/living/carbon/human/as_human = user + as_human.update_visible_name() /// Called when we're being read and overlays are updated, we should show a big newspaper over the reader /obj/item/newspaper/proc/holder_updated_overlays(atom/reader, list/overlays) @@ -264,10 +268,10 @@ var/has_image = FALSE if(feed_messages.img) has_image = TRUE - user << browse_rsc(feed_messages.img, "tmp_photo[feed_messages.message_ID].png") + user << browse_rsc(feed_messages.img, "tmp_photo[feed_messages.message_id].png") channel_data["channel_messages"] += list(list( "message" = "-[feed_messages.return_body(censored_check(feed_messages.body_censor_time))]", - "photo" = (has_image ? "tmp_photo[feed_messages.message_ID].png" : null), + "photo" = (has_image ? "tmp_photo[feed_messages.message_id].png" : null), "author" = feed_messages.return_author(censored_check(feed_messages.author_censor_time)), )) data["channel_data"] = list(channel_data) diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index d5fe7413b788..7734e98b9490 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -681,7 +681,7 @@ DEFINE_BITFIELD(turret_flags, list( button_icon = 'icons/mob/actions/actions_mecha.dmi' button_icon_state = "mech_cycle_equip_off" -/datum/action/turret_toggle/Trigger(trigger_flags) +/datum/action/turret_toggle/Trigger(mob/clicker, trigger_flags) var/obj/machinery/porta_turret/P = target if(!istype(P)) return @@ -692,7 +692,7 @@ DEFINE_BITFIELD(turret_flags, list( button_icon = 'icons/mob/actions/actions_mecha.dmi' button_icon_state = "mech_eject" -/datum/action/turret_quit/Trigger(trigger_flags) +/datum/action/turret_quit/Trigger(mob/clicker, trigger_flags) var/obj/machinery/porta_turret/P = target if(!istype(P)) return diff --git a/code/game/machinery/telecomms/machines/allinone.dm b/code/game/machinery/telecomms/machines/allinone.dm index bd30c5ba0b57..63668487de75 100644 --- a/code/game/machinery/telecomms/machines/allinone.dm +++ b/code/game/machinery/telecomms/machines/allinone.dm @@ -11,6 +11,49 @@ idle_power_usage = 0 /// If this mainframe can process all syndicate chatter regardless of z level var/syndicate = FALSE + /// List of all frequencies to their name/color + var/static/alist/frequency_infos = alist( + "[FREQ_SCIENCE]" = list( + "name" = RADIO_CHANNEL_SCIENCE, + "color" = RADIO_COLOR_SCIENCE + ), + "[FREQ_MEDICAL]" = list( + "name" = RADIO_CHANNEL_MEDICAL, + "color" = RADIO_COLOR_MEDICAL + ), + "[FREQ_SUPPLY]" = list( + "name" = RADIO_CHANNEL_SUPPLY, + "color" = RADIO_COLOR_SUPPLY + ), + "[FREQ_SERVICE]" = list( + "name" = RADIO_CHANNEL_SERVICE, + "color" = RADIO_COLOR_SERVICE + ), + "[FREQ_ENTERTAINMENT]" = list( + "name" = RADIO_CHANNEL_ENTERTAINMENT, + "color" = RADIO_COLOR_ENTERTAIMENT + ), + "[FREQ_COMMON]" = list( + "name" = RADIO_CHANNEL_COMMON, + "color" = RADIO_COLOR_COMMON + ), + "[FREQ_AI_PRIVATE]" = list( + "name" = RADIO_CHANNEL_AI_PRIVATE, + "color" = RADIO_COLOR_AI_PRIVATE + ), + "[FREQ_COMMAND]" = list( + "name" = RADIO_CHANNEL_COMMAND, + "color" = RADIO_COLOR_COMMAND + ), + "[FREQ_ENGINEERING]" = list( + "name" = RADIO_CHANNEL_ENGINEERING, + "color" = RADIO_COLOR_ENGINEERING + ), + "[FREQ_SECURITY]" = list( + "name" = RADIO_CHANNEL_SECURITY, + "color" = RADIO_COLOR_SECURITY + ) + ) /obj/machinery/telecomms/allinone/nuclear name = "advanced telecommunications mainframe" @@ -35,6 +78,11 @@ if(!syndicate && !(z in signal.levels) && !(RADIO_NO_Z_LEVEL_RESTRICTION in signal.levels)) // has to be syndicate or on the right level return + var/freq_info = frequency_infos["[signal.frequency]"] + if(freq_info) + signal.data["frequency_name"] = freq_info["name"] + signal.data["frequency_color"] = freq_info["color"] + // Decompress the signal and mark it done if(syndicate) signal.levels = list(0) // Signal is broadcast to agents anywhere diff --git a/code/game/objects/effects/anomalies/anomalies_flux.dm b/code/game/objects/effects/anomalies/anomalies_flux.dm index a2dc24736005..1d823d00b60b 100644 --- a/code/game/objects/effects/anomalies/anomalies_flux.dm +++ b/code/game/objects/effects/anomalies/anomalies_flux.dm @@ -5,11 +5,11 @@ anomaly_core = /obj/item/assembly/signaler/anomaly/flux var/canshock = FALSE var/shockdamage = 20 - var/explosive = FLUX_EXPLOSIVE + var/emp_zap = FLUX_EMP -/obj/effect/anomaly/flux/Initialize(mapload, new_lifespan, explosive = FLUX_EXPLOSIVE) +/obj/effect/anomaly/flux/Initialize(mapload, new_lifespan, emp_zap = FLUX_EMP) . = ..() - src.explosive = explosive + src.emp_zap = emp_zap var/static/list/loc_connections = list( COMSIG_ATOM_ENTERED = PROC_REF(on_entered), ) @@ -42,20 +42,22 @@ M.electrocute_act(shockdamage, name, flags = SHOCK_NOGLOVES) /obj/effect/anomaly/flux/detonate() - switch(explosive) - if(FLUX_EXPLOSIVE) - explosion(src, devastation_range = 1, heavy_impact_range = 4, light_impact_range = 16, flash_range = 18) //Low devastation, but hits a lot of stuff. - if(FLUX_LOW_EXPLOSIVE) - explosion(src, heavy_impact_range = 1, light_impact_range = 4, flash_range = 6) - if(FLUX_NO_EXPLOSION) + switch(emp_zap) + if(FLUX_EMP) + empulse(src, 4, 16) + explosion(src, heavy_impact_range = 1, light_impact_range = 4, flash_range = 6) //Trashes the room a bit, might blow a small hole in the hull. + if(FLUX_LIGHT_EMP) + empulse(src, 4, 6) + explosion(src, light_impact_range = 3, flash_range = 6) + if(FLUX_NO_EMP) new /obj/effect/particle_effect/sparks(loc) -/// A flux anomaly which doesn't explode or produce a core +/// A flux anomaly which doesn't emp or produce a core /obj/effect/anomaly/flux/minor anomaly_core = null // We need to override the default arguments here to achieve the desired effect -/obj/effect/anomaly/flux/minor/Initialize(mapload, new_lifespan, explosive = FLUX_NO_EXPLOSION) +/obj/effect/anomaly/flux/minor/Initialize(mapload, new_lifespan, emp_zap = FLUX_NO_EMP) return ..() ///Bigger, meaner, immortal flux anomaly diff --git a/code/game/objects/effects/anomalies/anomalies_gravity.dm b/code/game/objects/effects/anomalies/anomalies_gravity.dm index 56a1130d4532..280e0dc1e12f 100644 --- a/code/game/objects/effects/anomalies/anomalies_gravity.dm +++ b/code/game/objects/effects/anomalies/anomalies_gravity.dm @@ -1,50 +1,4 @@ -/atom/movable/warp_effect - plane = GRAVITY_PULSE_PLANE - appearance_flags = PIXEL_SCALE|LONG_GLIDE // no tile bound so you can see it around corners and so - icon = 'icons/effects/light_overlays/light_352.dmi' - icon_state = "light" - pixel_x = -176 - pixel_y = -176 - -/atom/movable/warp_effect/Initialize(mapload) - . = ..() - var/turf/new_turf = get_turf(src) - if(new_turf) - var/new_offset = GET_TURF_PLANE_OFFSET(new_turf) - ADD_TRAIT(GLOB, TRAIT_DISTORTION_IN_USE(new_offset), ref(src)) - -/atom/movable/warp_effect/Destroy(force) - // Just in case I've forgotten how the movement api works - var/offset = GET_TURF_PLANE_OFFSET(loc) - REMOVE_TRAIT(GLOB, TRAIT_DISTORTION_IN_USE(offset), ref(src)) - return ..() - -/atom/movable/warp_effect/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change) - . = ..() - var/turf/new_turf = get_turf(src) - var/turf/old_turf = get_turf(old_loc) - if(!new_turf) - var/old_offset = GET_TURF_PLANE_OFFSET(old_turf) - REMOVE_TRAIT(GLOB, TRAIT_DISTORTION_IN_USE(old_offset), ref(src)) - return - else if(get_turf(old_loc)) - return - // If we're in a thing on a turf we COUNT as a distortion source - var/new_offset = GET_TURF_PLANE_OFFSET(new_turf) - ADD_TRAIT(GLOB, TRAIT_DISTORTION_IN_USE(new_offset), ref(src)) - -/atom/movable/warp_effect/on_changed_z_level(turf/old_turf, turf/new_turf, same_z_layer, notify_contents) - . = ..() - if(same_z_layer) - return - if(old_turf) - var/old_offset = GET_TURF_PLANE_OFFSET(old_turf) - REMOVE_TRAIT(GLOB, TRAIT_DISTORTION_IN_USE(old_offset), ref(src)) - if(new_turf) - var/new_offset = GET_TURF_PLANE_OFFSET(new_turf) - ADD_TRAIT(GLOB, TRAIT_DISTORTION_IN_USE(new_offset), ref(src)) - /obj/effect/anomaly/grav name = "gravitational anomaly" icon = 'icons/effects/effects.dmi' @@ -52,8 +6,7 @@ density = FALSE anomaly_core = /obj/item/assembly/signaler/anomaly/grav var/boing = 0 - ///Warp effect holder for displacement filter to "pulse" the anomaly - var/atom/movable/warp_effect/warp + var/object_launch_prob = 20 /obj/effect/anomaly/grav/Initialize(mapload, new_lifespan) . = ..() @@ -63,21 +16,6 @@ AddElement(/datum/element/connect_loc, loc_connections) apply_wibbly_filters(src) - warp = new(src) - vis_contents += warp - -/obj/effect/anomaly/grav/Destroy() - vis_contents -= warp - warp = null - return ..() - -/obj/effect/anomaly/grav/on_changed_z_level(turf/old_turf, turf/new_turf, same_z_layer, notify_contents) - . = ..() - if(same_z_layer) - return - if(warp) - SET_PLANE(warp, PLANE_TO_TRUE(warp.plane), new_turf) - /obj/effect/anomaly/grav/anomalyEffect(seconds_per_tick) ..() boing = 1 @@ -85,7 +23,8 @@ if(!O.anchored) step_towards(O,src) for(var/mob/living/M in range(0, src)) - gravShock(M) + if(!M.mob_negates_gravity()) + gravShock(M) for(var/mob/living/M in orange(4, src)) if(!M.mob_negates_gravity()) step_towards(M,src) @@ -93,13 +32,9 @@ if(O.anchored || HAS_TRAIT(O, TRAIT_UNDERFLOOR)) continue var/mob/living/target = locate() in view(4,src) - if(target && !target.stat) + if(target && !target.stat && prob(object_launch_prob)) O.throw_at(target, 5, 10) - //anomaly quickly contracts then slowly expands its ring - animate(warp, time = seconds_per_tick*3, transform = matrix().Scale(0.5,0.5)) - animate(time = seconds_per_tick*7, transform = matrix()) - /obj/effect/anomaly/grav/proc/on_entered(datum/source, atom/movable/AM) SIGNAL_HANDLER gravShock(AM) @@ -110,11 +45,11 @@ /obj/effect/anomaly/grav/Bumped(atom/movable/AM) gravShock(AM) -/obj/effect/anomaly/grav/proc/gravShock(mob/living/A) - if(boing && isliving(A) && !A.stat) - A.Paralyze(40) - var/atom/target = get_edge_target_turf(A, get_dir(src, get_step_away(A, src))) - A.throw_at(target, 5, 1) +/obj/effect/anomaly/grav/proc/gravShock(mob/living/living_debris) + if(boing && isliving(living_debris) && !living_debris.stat && !living_debris.mob_negates_gravity()) + living_debris.Knockdown(4 SECONDS) + var/atom/target = get_edge_target_turf(living_debris, get_dir(src, get_step_away(living_debris, src))) + living_debris.throw_at(target, 5, 1) boing = 0 /obj/effect/anomaly/grav/detonate() diff --git a/code/game/objects/effects/anomalies/anomalies_hallucination.dm b/code/game/objects/effects/anomalies/anomalies_hallucination.dm index 852e4fd998a1..ce272667ba5a 100644 --- a/code/game/objects/effects/anomalies/anomalies_hallucination.dm +++ b/code/game/objects/effects/anomalies/anomalies_hallucination.dm @@ -11,7 +11,7 @@ var/static/list/messages = list( span_warning("You feel your conscious mind fall apart!"), span_warning("Reality warps around you!"), - span_warning("Something's wispering around you!"), + span_warning("Something's whispering around you!"), span_warning("You are going insane!"), ) ///Do we spawn misleading decoys? diff --git a/code/game/objects/effects/decals/misc.dm b/code/game/objects/effects/decals/chemspray.dm similarity index 94% rename from code/game/objects/effects/decals/misc.dm rename to code/game/objects/effects/decals/chemspray.dm index 112f3b228dc4..005f7482aac1 100644 --- a/code/game/objects/effects/decals/misc.dm +++ b/code/game/objects/effects/decals/chemspray.dm @@ -95,10 +95,3 @@ reagents.expose(spraying, VAPOR) log_combat(user, spraying, "sprayed", sprayer, addition = "which had [logging_string]") - -/obj/effect/decal/fakelattice - name = "lattice" - desc = "A lightweight support lattice." - icon = 'icons/obj/smooth_structures/lattice.dmi' - icon_state = "lattice-255" - density = TRUE diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index 3087002987ef..0eebda1243c0 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -134,3 +134,7 @@ if (existing) return existing return new cleanable_type(checkturf) + +/turf/proc/spawn_glitter(glitter_colors) + var/obj/effect/decal/cleanable/glitter/new_glitter = spawn_unique_cleanable(/obj/effect/decal/cleanable/glitter) + new_glitter.color = pick_weight(glitter_colors) diff --git a/code/game/objects/effects/decals/cleanable/ants.dm b/code/game/objects/effects/decals/cleanable/ants.dm new file mode 100644 index 000000000000..b6a3fa38c3fa --- /dev/null +++ b/code/game/objects/effects/decals/cleanable/ants.dm @@ -0,0 +1,90 @@ +/obj/effect/decal/cleanable/ants + name = "space ants" + desc = "A small colony of space ants. They're normally used to the vacuum of space, so they can't climb too well." + icon = 'icons/obj/debris.dmi' + icon_state = "ants" + beauty = -150 + plane = GAME_PLANE + layer = LOW_OBJ_LAYER + decal_reagent = /datum/reagent/ants + reagent_amount = 5 + /// Sound the ants make when biting + var/bite_sound = 'sound/items/weapons/bite.ogg' + +/obj/effect/decal/cleanable/ants/Initialize(mapload) + if(mapload && reagent_amount > 2) + reagent_amount = rand((reagent_amount - 2), reagent_amount) + . = ..() + update_ant_damage() + +/obj/effect/decal/cleanable/ants/vv_edit_var(vname, vval) + . = ..() + if(vname == NAMEOF(src, bite_sound)) + update_ant_damage() + +/obj/effect/decal/cleanable/ants/handle_merge_decal(obj/effect/decal/cleanable/merger) + . = ..() + var/obj/effect/decal/cleanable/ants/ants = merger + ants.update_ant_damage() + +/obj/effect/decal/cleanable/ants/proc/update_ant_damage(ant_min_damage, ant_max_damage) + if(!ant_max_damage) + ant_max_damage = min(10, round((reagents ? reagents.get_reagent_amount(/datum/reagent/ants) : reagent_amount) * 0.1,0.1)) // 100u ants = 10 max_damage + if(!ant_min_damage) + ant_min_damage = 0.1 + var/ant_flags = (CALTROP_NOCRAWL | CALTROP_NOSTUN) /// Small amounts of ants won't be able to bite through shoes. + if(ant_max_damage > 1) + ant_flags = (CALTROP_NOCRAWL | CALTROP_NOSTUN | CALTROP_BYPASS_SHOES) + + var/datum/component/caltrop/caltrop_comp = GetComponent(/datum/component/caltrop) + if(caltrop_comp) + caltrop_comp.min_damage = ant_min_damage + caltrop_comp.max_damage = ant_max_damage + caltrop_comp.flags = ant_flags + caltrop_comp.soundfile = bite_sound + else + AddComponent(/datum/component/caltrop, min_damage = ant_min_damage, max_damage = ant_max_damage, flags = ant_flags, soundfile = bite_sound) + + update_appearance(UPDATE_ICON) + +/obj/effect/decal/cleanable/ants/update_icon_state() + if(istype(src, /obj/effect/decal/cleanable/ants/fire)) //i fucking hate this but you're forced to call parent in update_icon_state() + return ..() + if(!(flags_1 & INITIALIZED_1)) + return ..() + + var/datum/component/caltrop/caltrop_comp = GetComponent(/datum/component/caltrop) + if(!caltrop_comp) + return ..() + + switch(caltrop_comp.max_damage) + if(0 to 1) + icon_state = initial(icon_state) + if(1.1 to 4) + icon_state = "[initial(icon_state)]_2" + if(4.1 to 7) + icon_state = "[initial(icon_state)]_3" + if(7.1 to INFINITY) + icon_state = "[initial(icon_state)]_4" + return ..() + +/obj/effect/decal/cleanable/ants/update_overlays() + . = ..() + . += emissive_appearance(icon, "[icon_state]_light", src, alpha = src.alpha, effect_type = EMISSIVE_NO_BLOOM) + +/obj/effect/decal/cleanable/ants/fire_act(exposed_temperature, exposed_volume) + new /obj/effect/decal/cleanable/ants/fire(loc) + qdel(src) + +/obj/effect/decal/cleanable/ants/fire + name = "space fire ants" + desc = "A small colony no longer. We are the fire nation." + decal_reagent = /datum/reagent/ants/fire + icon_state = "fire_ants" + mergeable_decal = FALSE + +/obj/effect/decal/cleanable/ants/fire/update_ant_damage(ant_min_damage, ant_max_damage) + return ..(15, 25) + +/obj/effect/decal/cleanable/ants/fire/fire_act(exposed_temperature, exposed_volume) + return diff --git a/code/game/objects/effects/decals/cleanable/blood.dm b/code/game/objects/effects/decals/cleanable/blood.dm index b5ae997f8169..488c1b610d9c 100644 --- a/code/game/objects/effects/decals/cleanable/blood.dm +++ b/code/game/objects/effects/decals/cleanable/blood.dm @@ -119,7 +119,7 @@ . += blood_emissive(icon, icon_state) /obj/effect/decal/cleanable/blood/proc/blood_emissive(icon_to_use, icon_state_to_use) - return emissive_appearance(icon_to_use, icon_state_to_use, src, layer, 255 * emissive_alpha / alpha) + return emissive_appearance(icon_to_use, icon_state_to_use, src, alpha = 255 * emissive_alpha / alpha, effect_type = EMISSIVE_NO_BLOOM) /obj/effect/decal/cleanable/blood/lazy_init_reagents() if (reagents) @@ -459,6 +459,25 @@ /// Beyond a threshold we change to a bloodier icon state var/very_bloody = FALSE +/obj/effect/decal/cleanable/blood/trail/Initialize(mapload, list/datum/disease/diseases, list/blood_or_dna) + . = ..() + // Despite having VIS_INHERIT_PLANE, our emissives still inherit our plane offset, so we need to inherit our parent's offset to have them render correctly + if(istype(loc, /obj/effect/decal/cleanable/blood/trail_holder)) + SET_PLANE_EXPLICIT(src, initial(plane), loc) + if (emissive_alpha && !dried) + update_appearance() // correct our emissive + return + + +#ifndef UNIT_TESTS + if (mapload) + log_mapping("[src] spawned outside of a trail holder at [AREACOORD(src)]!") + return INITIALIZE_HINT_QDEL +#endif + + stack_trace("[src] spawned outside of a trail holder at [AREACOORD(src)]!") + return INITIALIZE_HINT_QDEL + /obj/effect/decal/cleanable/blood/trail/update_desc(updates) . = ..() desc = "A [dried ? "dried " : ""]trail of [get_blood_string()]." diff --git a/code/game/objects/effects/decals/cleanable/fuel.dm b/code/game/objects/effects/decals/cleanable/fuel.dm new file mode 100644 index 000000000000..e372e93c43d6 --- /dev/null +++ b/code/game/objects/effects/decals/cleanable/fuel.dm @@ -0,0 +1,113 @@ +/obj/effect/decal/cleanable/fuel_pool + name = "pool of fuel" + desc = "A pool of flammable fuel. Its probably wise to clean this off before something ignites it..." + icon_state = "fuel_pool" + beauty = -50 + clean_type = CLEAN_TYPE_BLOOD + mouse_opacity = MOUSE_OPACITY_OPAQUE + resistance_flags = UNACIDABLE | ACID_PROOF | FIRE_PROOF | FLAMMABLE //gross way of doing this but would need to disassemble fire_act call stack otherwise + /// Maximum amount of hotspots this pool can create before deleting itself + var/burn_amount = 3 + /// Is this fuel pool currently burning? + var/burning = FALSE + /// Type of hotspot fuel pool spawns upon being ignited + var/hotspot_type = /obj/effect/hotspot + +/obj/effect/decal/cleanable/fuel_pool/Initialize(mapload, burn_stacks) + . = ..() + var/static/list/loc_connections = list( + COMSIG_TURF_MOVABLE_THROW_LANDED = PROC_REF(ignition_trigger), + COMSIG_ATOM_ENTERED = PROC_REF(on_entered) + ) + AddElement(/datum/element/connect_loc, loc_connections) + for(var/obj/effect/decal/cleanable/fuel_pool/pool in get_turf(src)) //Can't use locate because we also belong to that turf + if(pool == src) + continue + pool.burn_amount = max(min(pool.burn_amount + burn_stacks, 10), 1) + return INITIALIZE_HINT_QDEL + + if(burn_stacks) + burn_amount = max(min(burn_stacks, 10), 1) + + return INITIALIZE_HINT_LATELOAD + +// Just in case of fires, do this after mapload. +/obj/effect/decal/cleanable/fuel_pool/LateInitialize() +// We don't want to burn down the create_and_destroy test area +#ifndef UNIT_TESTS + RegisterSignal(src, COMSIG_ATOM_TOUCHED_SPARKS, PROC_REF(ignition_trigger)) +#endif + +/obj/effect/decal/cleanable/fuel_pool/fire_act(exposed_temperature, exposed_volume) + . = ..() + ignite() + +/** + * Ignites the fuel pool. This should be the only way to ignite fuel pools. + */ +/obj/effect/decal/cleanable/fuel_pool/proc/ignite() + if(burning) + return + burning = TRUE + burn_process() + +/** + * Spends 1 burn_amount and spawns a hotspot. If burn_amount is equal to 0, deletes the fuel pool. + * Else, queues another call of this proc upon hotspot getting deleted and ignites other fuel pools around itself after 0.5 seconds. + * THIS SHOULD NOT BE CALLED DIRECTLY. + */ +/obj/effect/decal/cleanable/fuel_pool/proc/burn_process() + SIGNAL_HANDLER + + burn_amount -= 1 + var/obj/effect/hotspot/hotspot = new hotspot_type(get_turf(src)) + addtimer(CALLBACK(src, PROC_REF(ignite_others)), 0.5 SECONDS) + + if(!burn_amount) + qdel(src) + return + + RegisterSignal(hotspot, COMSIG_QDELETING, PROC_REF(burn_process)) + +/** + * Ignites other oil pools around itself. + */ +/obj/effect/decal/cleanable/fuel_pool/proc/ignite_others() + for(var/obj/effect/decal/cleanable/fuel_pool/oil in range(1, get_turf(src))) + oil.ignite() + +/obj/effect/decal/cleanable/fuel_pool/bullet_act(obj/projectile/hit_proj) + . = ..() + ignite() + log_combat(hit_proj.firer, src, "used [hit_proj] to ignite") + +/obj/effect/decal/cleanable/fuel_pool/attackby(obj/item/item, mob/user, list/modifiers, list/attack_modifiers) + if(item.ignition_effect(src, user)) + ignite() + log_combat(user, src, "used [item] to ignite") + return ..() + +/obj/effect/decal/cleanable/fuel_pool/proc/on_entered(datum/source, atom/movable/entered_atom) + SIGNAL_HANDLER + + if(!entered_atom.throwing) // don't light from things being thrown over us, we handle that somewhere else + ignition_trigger(source = src, enflammable_atom = entered_atom) + +/obj/effect/decal/cleanable/fuel_pool/proc/ignition_trigger(datum/source, atom/movable/enflammable_atom) + SIGNAL_HANDLER + + if(isitem(enflammable_atom)) + var/obj/item/enflamed_item = enflammable_atom + if(enflamed_item.get_temperature() > FIRE_MINIMUM_TEMPERATURE_TO_EXIST) + ignite() + return + else if(isliving(enflammable_atom)) + var/mob/living/enflamed_liver = enflammable_atom + if(enflamed_liver.on_fire) + ignite() + else if(istype(enflammable_atom, /obj/effect/particle_effect/sparks)) + ignite() + + +/obj/effect/decal/cleanable/fuel_pool/hivis + icon_state = "fuel_pool_hivis" diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/mess.dm similarity index 60% rename from code/game/objects/effects/decals/cleanable/misc.dm rename to code/game/objects/effects/decals/cleanable/mess.dm index 141d7dace9ec..d31f44a4b010 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/mess.dm @@ -294,22 +294,14 @@ GLOBAL_LIST_EMPTY(nebula_vomits) /obj/effect/decal/cleanable/glitter name = "generic glitter pile" desc = "The herpes of arts and crafts." - icon = 'icons/effects/atmospherics.dmi' - icon_state = "plasma_old" + icon = 'icons/effects/glitter.dmi' + icon_state = "glitter" gender = NEUTER mouse_opacity = MOUSE_OPACITY_TRANSPARENT -/obj/effect/decal/cleanable/glitter/pink - name = "pink glitter" - icon_state = "plasma" - -/obj/effect/decal/cleanable/glitter/white - name = "white glitter" - icon_state = "nitrous_oxide" - -/obj/effect/decal/cleanable/glitter/blue - name = "blue glitter" - icon_state = "freon" +/obj/effect/decal/cleanable/glitter/Initialize(mapload, list/datum/disease/diseases) + . = ..() + add_overlay(mutable_appearance('icons/effects/glitter.dmi', "glitter_sparkle[rand(1,9)]", appearance_flags = EMISSIVE_APPEARANCE_FLAGS)) /obj/effect/decal/cleanable/plasma name = "stabilized plasma" @@ -373,211 +365,6 @@ GLOBAL_LIST_EMPTY(nebula_vomits) . = ..() AddElement(/datum/element/swabable, CELL_LINE_TABLE_SLUDGE, CELL_VIRUS_TABLE_GENERIC, rand(2,4), 15) -/obj/effect/decal/cleanable/ants - name = "space ants" - desc = "A small colony of space ants. They're normally used to the vacuum of space, so they can't climb too well." - icon = 'icons/obj/debris.dmi' - icon_state = "ants" - beauty = -150 - plane = GAME_PLANE - layer = LOW_OBJ_LAYER - decal_reagent = /datum/reagent/ants - reagent_amount = 5 - /// Sound the ants make when biting - var/bite_sound = 'sound/items/weapons/bite.ogg' - -/obj/effect/decal/cleanable/ants/Initialize(mapload) - if(mapload && reagent_amount > 2) - reagent_amount = rand((reagent_amount - 2), reagent_amount) - . = ..() - update_ant_damage() - -/obj/effect/decal/cleanable/ants/vv_edit_var(vname, vval) - . = ..() - if(vname == NAMEOF(src, bite_sound)) - update_ant_damage() - -/obj/effect/decal/cleanable/ants/handle_merge_decal(obj/effect/decal/cleanable/merger) - . = ..() - var/obj/effect/decal/cleanable/ants/ants = merger - ants.update_ant_damage() - -/obj/effect/decal/cleanable/ants/proc/update_ant_damage(ant_min_damage, ant_max_damage) - if(!ant_max_damage) - ant_max_damage = min(10, round((reagents ? reagents.get_reagent_amount(/datum/reagent/ants) : reagent_amount) * 0.1,0.1)) // 100u ants = 10 max_damage - if(!ant_min_damage) - ant_min_damage = 0.1 - var/ant_flags = (CALTROP_NOCRAWL | CALTROP_NOSTUN) /// Small amounts of ants won't be able to bite through shoes. - if(ant_max_damage > 1) - ant_flags = (CALTROP_NOCRAWL | CALTROP_NOSTUN | CALTROP_BYPASS_SHOES) - - var/datum/component/caltrop/caltrop_comp = GetComponent(/datum/component/caltrop) - if(caltrop_comp) - caltrop_comp.min_damage = ant_min_damage - caltrop_comp.max_damage = ant_max_damage - caltrop_comp.flags = ant_flags - caltrop_comp.soundfile = bite_sound - else - AddComponent(/datum/component/caltrop, min_damage = ant_min_damage, max_damage = ant_max_damage, flags = ant_flags, soundfile = bite_sound) - - update_appearance(UPDATE_ICON) - -/obj/effect/decal/cleanable/ants/update_icon_state() - if(istype(src, /obj/effect/decal/cleanable/ants/fire)) //i fucking hate this but you're forced to call parent in update_icon_state() - return ..() - if(!(flags_1 & INITIALIZED_1)) - return ..() - - var/datum/component/caltrop/caltrop_comp = GetComponent(/datum/component/caltrop) - if(!caltrop_comp) - return ..() - - switch(caltrop_comp.max_damage) - if(0 to 1) - icon_state = initial(icon_state) - if(1.1 to 4) - icon_state = "[initial(icon_state)]_2" - if(4.1 to 7) - icon_state = "[initial(icon_state)]_3" - if(7.1 to INFINITY) - icon_state = "[initial(icon_state)]_4" - return ..() - -/obj/effect/decal/cleanable/ants/update_overlays() - . = ..() - . += emissive_appearance(icon, "[icon_state]_light", src, alpha = src.alpha) - -/obj/effect/decal/cleanable/ants/fire_act(exposed_temperature, exposed_volume) - new /obj/effect/decal/cleanable/ants/fire(loc) - qdel(src) - -/obj/effect/decal/cleanable/ants/fire - name = "space fire ants" - desc = "A small colony no longer. We are the fire nation." - decal_reagent = /datum/reagent/ants/fire - icon_state = "fire_ants" - mergeable_decal = FALSE - -/obj/effect/decal/cleanable/ants/fire/update_ant_damage(ant_min_damage, ant_max_damage) - return ..(15, 25) - -/obj/effect/decal/cleanable/ants/fire/fire_act(exposed_temperature, exposed_volume) - return - -/obj/effect/decal/cleanable/fuel_pool - name = "pool of fuel" - desc = "A pool of flammable fuel. Its probably wise to clean this off before something ignites it..." - icon_state = "fuel_pool" - beauty = -50 - clean_type = CLEAN_TYPE_BLOOD - mouse_opacity = MOUSE_OPACITY_OPAQUE - resistance_flags = UNACIDABLE | ACID_PROOF | FIRE_PROOF | FLAMMABLE //gross way of doing this but would need to disassemble fire_act call stack otherwise - /// Maximum amount of hotspots this pool can create before deleting itself - var/burn_amount = 3 - /// Is this fuel pool currently burning? - var/burning = FALSE - /// Type of hotspot fuel pool spawns upon being ignited - var/hotspot_type = /obj/effect/hotspot - -/obj/effect/decal/cleanable/fuel_pool/Initialize(mapload, burn_stacks) - . = ..() - var/static/list/loc_connections = list( - COMSIG_TURF_MOVABLE_THROW_LANDED = PROC_REF(ignition_trigger), - COMSIG_ATOM_ENTERED = PROC_REF(on_entered) - ) - AddElement(/datum/element/connect_loc, loc_connections) - for(var/obj/effect/decal/cleanable/fuel_pool/pool in get_turf(src)) //Can't use locate because we also belong to that turf - if(pool == src) - continue - pool.burn_amount = max(min(pool.burn_amount + burn_stacks, 10), 1) - return INITIALIZE_HINT_QDEL - - if(burn_stacks) - burn_amount = max(min(burn_stacks, 10), 1) - - return INITIALIZE_HINT_LATELOAD - -// Just in case of fires, do this after mapload. -/obj/effect/decal/cleanable/fuel_pool/LateInitialize() -// We don't want to burn down the create_and_destroy test area -#ifndef UNIT_TESTS - RegisterSignal(src, COMSIG_ATOM_TOUCHED_SPARKS, PROC_REF(ignition_trigger)) -#endif - -/obj/effect/decal/cleanable/fuel_pool/fire_act(exposed_temperature, exposed_volume) - . = ..() - ignite() - -/** - * Ignites the fuel pool. This should be the only way to ignite fuel pools. - */ -/obj/effect/decal/cleanable/fuel_pool/proc/ignite() - if(burning) - return - burning = TRUE - burn_process() - -/** - * Spends 1 burn_amount and spawns a hotspot. If burn_amount is equal to 0, deletes the fuel pool. - * Else, queues another call of this proc upon hotspot getting deleted and ignites other fuel pools around itself after 0.5 seconds. - * THIS SHOULD NOT BE CALLED DIRECTLY. - */ -/obj/effect/decal/cleanable/fuel_pool/proc/burn_process() - SIGNAL_HANDLER - - burn_amount -= 1 - var/obj/effect/hotspot/hotspot = new hotspot_type(get_turf(src)) - addtimer(CALLBACK(src, PROC_REF(ignite_others)), 0.5 SECONDS) - - if(!burn_amount) - qdel(src) - return - - RegisterSignal(hotspot, COMSIG_QDELETING, PROC_REF(burn_process)) - -/** - * Ignites other oil pools around itself. - */ -/obj/effect/decal/cleanable/fuel_pool/proc/ignite_others() - for(var/obj/effect/decal/cleanable/fuel_pool/oil in range(1, get_turf(src))) - oil.ignite() - -/obj/effect/decal/cleanable/fuel_pool/bullet_act(obj/projectile/hit_proj) - . = ..() - ignite() - log_combat(hit_proj.firer, src, "used [hit_proj] to ignite") - -/obj/effect/decal/cleanable/fuel_pool/attackby(obj/item/item, mob/user, list/modifiers, list/attack_modifiers) - if(item.ignition_effect(src, user)) - ignite() - log_combat(user, src, "used [item] to ignite") - return ..() - -/obj/effect/decal/cleanable/fuel_pool/proc/on_entered(datum/source, atom/movable/entered_atom) - SIGNAL_HANDLER - - if(!entered_atom.throwing) // don't light from things being thrown over us, we handle that somewhere else - ignition_trigger(source = src, enflammable_atom = entered_atom) - -/obj/effect/decal/cleanable/fuel_pool/proc/ignition_trigger(datum/source, atom/movable/enflammable_atom) - SIGNAL_HANDLER - - if(isitem(enflammable_atom)) - var/obj/item/enflamed_item = enflammable_atom - if(enflamed_item.get_temperature() > FIRE_MINIMUM_TEMPERATURE_TO_EXIST) - ignite() - return - else if(isliving(enflammable_atom)) - var/mob/living/enflamed_liver = enflammable_atom - if(enflamed_liver.on_fire) - ignite() - else if(istype(enflammable_atom, /obj/effect/particle_effect/sparks)) - ignite() - - -/obj/effect/decal/cleanable/fuel_pool/hivis - icon_state = "fuel_pool_hivis" - /obj/effect/decal/cleanable/rubble name = "rubble" desc = "A pile of rubble." diff --git a/code/game/objects/effects/decals/structure.dm b/code/game/objects/effects/decals/structure.dm new file mode 100644 index 000000000000..66935498dff3 --- /dev/null +++ b/code/game/objects/effects/decals/structure.dm @@ -0,0 +1,6 @@ +/obj/effect/decal/fakelattice + name = "lattice" + desc = "A lightweight support lattice." + icon = 'icons/obj/smooth_structures/lattice.dmi' + icon_state = "lattice-255" + density = TRUE diff --git a/code/game/objects/effects/effect_system/fluid_spread/effects_foam.dm b/code/game/objects/effects/effect_system/fluid_spread/effects_foam.dm index 4698e153607e..788740e9f323 100644 --- a/code/game/objects/effects/effect_system/fluid_spread/effects_foam.dm +++ b/code/game/objects/effects/effect_system/fluid_spread/effects_foam.dm @@ -166,7 +166,7 @@ foam_mob(foaming, seconds_per_tick) var/obj/effect/particle_effect/fluid/foam/spread_foam = new type(spread_turf, group, src) - reagents.copy_to(spread_foam, (reagents.total_volume)) + reagents.trans_to(spread_foam, reagents.total_volume, copy_only = TRUE) spread_foam.add_atom_colour(color, FIXED_COLOUR_PRIORITY) spread_foam.result_type = result_type SSfoam.queue_spread(spread_foam) @@ -199,7 +199,7 @@ /datum/effect_system/fluid_spread/foam/set_up(range = 1, amount = DIAMOND_AREA(range), atom/holder, atom/location = null, datum/reagents/carry = null, result_type = null, stop_reactions = FALSE) . = ..() - carry?.copy_to(chemholder, carry.total_volume, no_react = stop_reactions) + carry?.trans_to(chemholder, carry.total_volume, no_react = stop_reactions, copy_only = TRUE) if(!isnull(result_type)) src.result_type = result_type @@ -208,7 +208,7 @@ var/foamcolor = mix_color_from_reagents(chemholder.reagent_list) if(reagent_scale > 1) // Make room in case we were created by a particularly stuffed payload. foam.reagents.maximum_volume *= reagent_scale - chemholder.copy_to(foam, chemholder.total_volume, reagent_scale) // Foam has an amplifying effect on the reagents it is supplied with. This is balanced by the reagents being diluted as the area the foam covers increases. + chemholder.trans_to(foam, chemholder.total_volume, reagent_scale, copy_only = TRUE) // Foam has an amplifying effect on the reagents it is supplied with. This is balanced by the reagents being diluted as the area the foam covers increases. foam.add_atom_colour(foamcolor, FIXED_COLOUR_PRIORITY) if(!isnull(result_type)) foam.result_type = result_type diff --git a/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm b/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm index c5e365eee8ef..c9e68ce6ede2 100644 --- a/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm +++ b/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm @@ -86,7 +86,7 @@ smoke_mob(smoker, seconds_per_tick) var/obj/effect/particle_effect/fluid/smoke/spread_smoke = new type(spread_turf, group, src) - reagents.copy_to(spread_smoke, reagents.total_volume) + reagents.trans_to(spread_smoke, reagents.total_volume, copy_only = TRUE) spread_smoke.add_atom_colour(color, FIXED_COLOUR_PRIORITY) spread_smoke.lifetime = lifetime @@ -392,7 +392,7 @@ return FALSE var/fraction = (seconds_per_tick SECONDS) / initial(lifetime) - reagents.copy_to(smoker, reagents.total_volume, fraction, copy_methods = SMOKE_MACHINE) + reagents.trans_to(smoker, reagents.total_volume, fraction, methods = SMOKE_MACHINE, copy_only = TRUE) reagents.expose(smoker, SMOKE_MACHINE, fraction) return TRUE @@ -423,7 +423,7 @@ /datum/effect_system/fluid_spread/smoke/chem/set_up(range = 1, amount = DIAMOND_AREA(range), atom/holder, atom/location = null, datum/reagents/carry = null, silent = FALSE) . = ..() - carry?.copy_to(chemholder, carry.total_volume) + carry?.trans_to(chemholder, carry.total_volume, copy_only = TRUE) if(silent) return @@ -452,7 +452,7 @@ var/start_loc = holder ? get_turf(holder) : src.location var/mixcolor = mix_color_from_reagents(chemholder.reagent_list) var/obj/effect/particle_effect/fluid/smoke/chem/smoke = new effect_type(start_loc, new /datum/fluid_group(amount)) - chemholder.copy_to(smoke, chemholder.total_volume) + chemholder.trans_to(smoke, chemholder.total_volume, copy_only = TRUE) if(mixcolor) smoke.add_atom_colour(mixcolor, FIXED_COLOUR_PRIORITY) // give the smoke color, if it has any to begin with diff --git a/code/game/objects/effects/particles/echo.dm b/code/game/objects/effects/particles/echo.dm new file mode 100644 index 000000000000..90c3533d8ce7 --- /dev/null +++ b/code/game/objects/effects/particles/echo.dm @@ -0,0 +1,14 @@ +// Echolocation particles. +/particles/echo + icon = 'icons/effects/particles/echo.dmi' + icon_state = list("echo1" = 1, "echo2" = 1, "echo3" = 2) + width = 480 + height = 480 + count = 1000 + spawning = 0.5 + lifespan = 2 SECONDS + fade = 1 SECONDS + gravity = list(0, -0.1) + position = generator(GEN_BOX, list(-240, -240), list(240, 240), NORMAL_RAND) + drift = generator(GEN_VECTOR, list(-0.1, 0), list(0.1, 0)) + rotation = generator(GEN_NUM, 0, 360, NORMAL_RAND) diff --git a/code/game/objects/effects/particles/food.dm b/code/game/objects/effects/particles/food.dm new file mode 100644 index 000000000000..30f9e6ec2f43 --- /dev/null +++ b/code/game/objects/effects/particles/food.dm @@ -0,0 +1,13 @@ +// Food related particles. +/particles/stink + icon = 'icons/effects/particles/stink.dmi' + icon_state = list("stink_1" = 1, "stink_2" = 2, "stink_3" = 2) + color = "#0BDA51" + width = 100 + height = 100 + count = 25 + spawning = 0.25 + lifespan = 1 SECONDS + fade = 1 SECONDS + position = generator(GEN_CIRCLE, 0, 16, UNIFORM_RAND) + gravity = list(0, 0.25) diff --git a/code/game/objects/effects/particles/misc.dm b/code/game/objects/effects/particles/misc.dm deleted file mode 100644 index a1f188f88c90..000000000000 --- a/code/game/objects/effects/particles/misc.dm +++ /dev/null @@ -1,45 +0,0 @@ -// General or un-matched particles, make a new file if a few can be sorted together. -/particles/pollen - icon = 'icons/effects/particles/pollen.dmi' - icon_state = "pollen" - width = 100 - height = 100 - count = 1000 - spawning = 4 - lifespan = 0.7 SECONDS - fade = 1 SECONDS - grow = -0.01 - velocity = list(0, 0) - position = generator(GEN_CIRCLE, 0, 16, NORMAL_RAND) - drift = generator(GEN_VECTOR, list(0, -0.2), list(0, 0.2)) - gravity = list(0, 0.95) - scale = generator(GEN_VECTOR, list(0.3, 0.3), list(1,1), NORMAL_RAND) - rotation = 30 - spin = generator(GEN_NUM, -20, 20) - -/particles/echo - icon = 'icons/effects/particles/echo.dmi' - icon_state = list("echo1" = 1, "echo2" = 1, "echo3" = 2) - width = 480 - height = 480 - count = 1000 - spawning = 0.5 - lifespan = 2 SECONDS - fade = 1 SECONDS - gravity = list(0, -0.1) - position = generator(GEN_BOX, list(-240, -240), list(240, 240), NORMAL_RAND) - drift = generator(GEN_VECTOR, list(-0.1, 0), list(0.1, 0)) - rotation = generator(GEN_NUM, 0, 360, NORMAL_RAND) - -/particles/stink - icon = 'icons/effects/particles/stink.dmi' - icon_state = list("stink_1" = 1, "stink_2" = 2, "stink_3" = 2) - color = "#0BDA51" - width = 100 - height = 100 - count = 25 - spawning = 0.25 - lifespan = 1 SECONDS - fade = 1 SECONDS - position = generator(GEN_CIRCLE, 0, 16, UNIFORM_RAND) - gravity = list(0, 0.25) diff --git a/code/game/objects/effects/particles/plant.dm b/code/game/objects/effects/particles/plant.dm new file mode 100644 index 000000000000..eca8b6fe5d06 --- /dev/null +++ b/code/game/objects/effects/particles/plant.dm @@ -0,0 +1,18 @@ +// Plant related particles. +/particles/pollen + icon = 'icons/effects/particles/pollen.dmi' + icon_state = "pollen" + width = 100 + height = 100 + count = 1000 + spawning = 4 + lifespan = 0.7 SECONDS + fade = 1 SECONDS + grow = -0.01 + velocity = list(0, 0) + position = generator(GEN_CIRCLE, 0, 16, NORMAL_RAND) + drift = generator(GEN_VECTOR, list(0, -0.2), list(0, 0.2)) + gravity = list(0, 0.95) + scale = generator(GEN_VECTOR, list(0.3, 0.3), list(1,1), NORMAL_RAND) + rotation = 30 + spin = generator(GEN_NUM, -20, 20) diff --git a/code/game/objects/effects/spawners/random/entertainment.dm b/code/game/objects/effects/spawners/random/entertainment.dm index 5c94cb3a0cca..e51d83b46a8a 100644 --- a/code/game/objects/effects/spawners/random/entertainment.dm +++ b/code/game/objects/effects/spawners/random/entertainment.dm @@ -294,6 +294,6 @@ loot = list( /obj/item/grenade/chem_grenade/glitter/pink, /obj/item/grenade/chem_grenade/glitter/blue, - /obj/item/grenade/chem_grenade/glitter/white, + /obj/item/grenade/chem_grenade/glitter, /obj/item/grenade/chem_grenade/colorful ) diff --git a/code/game/objects/effects/temporary_visuals/projectiles/impact.dm b/code/game/objects/effects/temporary_visuals/projectiles/impact.dm index 879fd3c00937..e4c45d83deb6 100644 --- a/code/game/objects/effects/temporary_visuals/projectiles/impact.dm +++ b/code/game/objects/effects/temporary_visuals/projectiles/impact.dm @@ -37,6 +37,26 @@ /obj/effect/projectile/impact/wormhole icon_state = "wormhole_g" +/obj/effect/projectile/impact/laser/emitter/psy + name = "psychosiphoning impact" + icon_state = "impact_greyscale" + color = COLOR_PINK + +/obj/effect/projectile/impact/laser/emitter/magnetic + name = "magnetogenerative impact" + icon_state = "impact_greyscale" + color = COLOR_SILVER + +/obj/effect/projectile/impact/laser/emitter/quake + name = "seismodisintegrating impact" + icon_state = "impact_greyscale" + color = COLOR_BROWNER_BROWN + +/obj/effect/projectile/impact/laser/emitter/blast + name = "hyperconcussive impact" + icon_state = "impact_greyscale" + color = COLOR_ORANGE + /obj/effect/projectile/impact/laser/emitter name = "emitter impact" icon_state = "impact_emitter" diff --git a/code/game/objects/effects/temporary_visuals/projectiles/muzzle.dm b/code/game/objects/effects/temporary_visuals/projectiles/muzzle.dm index a68f58e1709d..ec996ad6ad88 100644 --- a/code/game/objects/effects/temporary_visuals/projectiles/muzzle.dm +++ b/code/game/objects/effects/temporary_visuals/projectiles/muzzle.dm @@ -29,6 +29,26 @@ /obj/effect/projectile/muzzle/wormhole icon_state = "wormhole_g" +/obj/effect/projectile/muzzle/laser/emitter/psy + name = "psychosiphoning flash" + icon_state = "muzzle_greyscale" + color = COLOR_PINK + +/obj/effect/projectile/muzzle/laser/emitter/magnetic + name = "magnetogenerative flash" + icon_state = "muzzle_greyscale" + color = COLOR_SILVER + +/obj/effect/projectile/muzzle/laser/emitter/quake + name = "seismodisintegrating flash" + icon_state = "muzzle_greyscale" + color = COLOR_BROWNER_BROWN + +/obj/effect/projectile/muzzle/laser/emitter/blast + name = "hyperconcussive flash" + icon_state = "muzzle_greyscale" + color = COLOR_ORANGE + /obj/effect/projectile/muzzle/laser/emitter name = "emitter flash" icon_state = "muzzle_emitter" diff --git a/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm b/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm index 4c8f46b7fd45..e32d2b833153 100644 --- a/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm +++ b/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm @@ -58,17 +58,37 @@ name = "emitter beam" icon_state = "emitter" -/obj/effect/projectile/tracer/sniper - icon_state = "sniper" +/obj/effect/projectile/tracer/laser/emitter/bluelens + name = "electrodisruptive emitter beam" + icon_state = "u_laser" -/obj/effect/projectile/tracer/lightning - icon = 'icons/effects/beam.dmi' - icon_state = "lightning2" +/obj/effect/projectile/tracer/laser/emitter/redlens + name = "hyperenergetic emitter beam" + icon_state = "beam_heavy" + +/obj/effect/projectile/tracer/laser/emitter/bioregen + name = "bioregenerative emitter beam" + icon_state = "solar" -/obj/effect/projectile/tracer/lightning/Initialize(mapload) - . = ..() - update_appearance() +/obj/effect/projectile/tracer/laser/emitter/psy + name = "psychosiphoning emitter beam" + icon_state = "tracer_greyscale" + color = COLOR_PINK -/obj/effect/projectile/tracer/lightning/update_icon_state() - . = ..() - icon_state = "lightning[rand(1, 12)]" +/obj/effect/projectile/tracer/laser/emitter/magnetic + name = "magnetogenerative emitter beam" + icon_state = "tracer_greyscale" + color = COLOR_SILVER + +/obj/effect/projectile/tracer/laser/emitter/quake + name = "seismodisintegrating emitter beam" + icon_state = "tracer_greyscale" + color = COLOR_BROWNER_BROWN + +/obj/effect/projectile/tracer/laser/emitter/blast + name = "hyperconcussive emitter beam" + icon_state = "tracer_greyscale" + color = COLOR_ORANGE + +/obj/effect/projectile/tracer/sniper + icon_state = "sniper" diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index cde46ba28460..5b0bd0ada2c6 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -155,11 +155,11 @@ /// The click cooldown on secondary attacks. Lower numbers mean faster attacks. Will use attack_speed if undefined. var/secondary_attack_speed ///In deciseconds, how long an item takes to equip; counts only for normal clothing slots, not pockets etc. - var/equip_delay_self = 0 + var/equip_delay_self = 0 SECONDS ///In deciseconds, how long an item takes to put on another person - var/equip_delay_other = 20 + var/equip_delay_other = 2 SECONDS ///In deciseconds, how long an item takes to remove from another person - var/strip_delay = 40 + var/strip_delay = 4 SECONDS ///How long it takes to resist out of the item (cuffs and such) var/breakouttime = 0 @@ -280,8 +280,6 @@ if(damtype == BRUTE) hitsound = SFX_SWING_HIT - add_weapon_description() - SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NEW_ITEM, src) setup_reskinning() @@ -475,6 +473,13 @@ /obj/item/examine_descriptor(mob/user) return "item" +/obj/item/examine(mob/user) + // lazily initialize the weapon description element if it hasn't been already + if(!(item_flags & WEAPON_DESCRIPTION_INITIALIZED)) + add_weapon_description() + item_flags |= WEAPON_DESCRIPTION_INITIALIZED + return ..() + /obj/item/examine_more(mob/user) . = ..() if(HAS_TRAIT(user, TRAIT_RESEARCH_SCANNER)) @@ -750,7 +755,7 @@ SEND_SIGNAL(src, COMSIG_ITEM_DROPPED, user) if(!silent) play_drop_sound(DROP_SOUND_VOLUME) - user?.update_equipment_speed_mods() + user?.update_equipment(src) /// called just as an item is picked up (loc is not yet changed) /obj/item/proc/pickup(mob/user) @@ -813,7 +818,7 @@ item_flags |= IN_INVENTORY RegisterSignals(src, list(SIGNAL_ADDTRAIT(TRAIT_NO_WORN_ICON), SIGNAL_REMOVETRAIT(TRAIT_NO_WORN_ICON)), PROC_REF(update_slot_icon), override = TRUE) - user.update_equipment_speed_mods() + user.update_equipment(src) if(!initial && (slot_flags & slot) && (play_equip_sound())) return diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index 882953377a1e..5d33a69af6f5 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -898,7 +898,7 @@ /obj/item/card/id/GetID() return src -/obj/item/card/id/RemoveID() +/obj/item/card/id/remove_id() return src /// Called on COMSIG_ATOM_UPDATED_ICON. Updates the visuals of the wallet this card is in. @@ -1938,7 +1938,7 @@ var/mob/living/carbon/human/owner = user if (!selected_trim_path) // Ensure that even without a trim update, we update user's sechud - owner.sec_hud_set_ID() + owner.update_ID_card() if (registered_account) return @@ -2048,13 +2048,20 @@ /obj/item/card/cardboard/equipped(mob/user, slot, initial = FALSE) . = ..() - if(slot == ITEM_SLOT_ID) - RegisterSignal(user, COMSIG_HUMAN_GET_VISIBLE_NAME, PROC_REF(return_visible_name)) - RegisterSignal(user, COMSIG_MOVABLE_MESSAGE_GET_NAME_PART, PROC_REF(return_message_name_part)) + if(slot != ITEM_SLOT_ID) + return + RegisterSignal(user, COMSIG_HUMAN_GET_VISIBLE_NAME, PROC_REF(return_visible_name)) + RegisterSignal(user, COMSIG_MOVABLE_MESSAGE_GET_NAME_PART, PROC_REF(return_message_name_part)) + if(ishuman(user)) + var/mob/living/carbon/human/as_human = user + as_human.update_visible_name() /obj/item/card/cardboard/dropped(mob/user, silent = FALSE) . = ..() UnregisterSignal(user, list(COMSIG_HUMAN_GET_VISIBLE_NAME, COMSIG_MOVABLE_MESSAGE_GET_NAME_PART)) + if(ishuman(user)) + var/mob/living/carbon/human/as_human = user + as_human.update_visible_name() /obj/item/card/cardboard/proc/return_visible_name(mob/living/carbon/human/source, list/identity) SIGNAL_HANDLER diff --git a/code/game/objects/items/cigarettes.dm b/code/game/objects/items/cigarettes.dm index 0c1474dc887b..1fe1c5bea43d 100644 --- a/code/game/objects/items/cigarettes.dm +++ b/code/game/objects/items/cigarettes.dm @@ -652,7 +652,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM /// Weighted list of random reagents to add var/static/list/possible_reagents = list( /datum/reagent/toxin/fentanyl = 2, - /datum/reagent/glitter = 2, + /datum/reagent/glitter/random = 2, /datum/reagent/drug/aranesp = 2, /datum/reagent/consumable/laughter = 2, /datum/reagent/medicine/insulin = 2, diff --git a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm index 21cd7a7fb228..013bbbc50a58 100644 --- a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm +++ b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm @@ -660,79 +660,41 @@ build_path = /obj/machinery/vending/custom req_components = list(/obj/item/vending_refill/custom = 1) - var/static/list/vending_names_paths = list( - /obj/machinery/vending/assist = "Part-Mart", - /obj/machinery/vending/autodrobe = "AutoDrobe", - /obj/machinery/vending/boozeomat = "Booze-O-Mat", - /obj/machinery/vending/cart = "PTech", - /obj/machinery/vending/cigarette = "ShadyCigs Deluxe", - /obj/machinery/vending/clothing = "ClothesMate", - /obj/machinery/vending/coffee = "Solar's Best Hot Drinks", - /obj/machinery/vending/cola = "Robust Softdrinks", - /obj/machinery/vending/custom = "Custom Vendor", - /obj/machinery/vending/cytopro = "CytoPro", - /obj/machinery/vending/dinnerware = "Plasteel Chef's Dinnerware Vendor", - /obj/machinery/vending/drugs = "NanoDrug Plus", - /obj/machinery/vending/engineering = "Robco Tool Maker", - /obj/machinery/vending/engivend = "Engi-Vend", - /obj/machinery/vending/games = "\improper Good Clean Fun", - /obj/machinery/vending/hydronutrients = "NutriMax", - /obj/machinery/vending/hydroseeds = "MegaSeed Servitor", - /obj/machinery/vending/medical = "NanoMed Plus", - /obj/machinery/vending/modularpc = "Deluxe Silicate Selections", - /obj/machinery/vending/robotics = "Robotech Deluxe", - /obj/machinery/vending/security = "SecTech", - /obj/machinery/vending/snack = "Getmore Chocolate Corp", - /obj/machinery/vending/sovietsoda = "BODA", - /obj/machinery/vending/sustenance = "Sustenance Vendor", - /obj/machinery/vending/tool = "YouTool", - /obj/machinery/vending/wallmed = "NanoMed", - /obj/machinery/vending/wardrobe/atmos_wardrobe = "AtmosDrobe", - /obj/machinery/vending/wardrobe/bar_wardrobe = "BarDrobe", - /obj/machinery/vending/wardrobe/cargo_wardrobe = "CargoDrobe", - /obj/machinery/vending/wardrobe/chap_wardrobe = "ChapDrobe", - /obj/machinery/vending/wardrobe/chef_wardrobe = "ChefDrobe", - /obj/machinery/vending/wardrobe/chem_wardrobe = "ChemDrobe", - /obj/machinery/vending/wardrobe/coroner_wardrobe = "MortiDrobe", - /obj/machinery/vending/wardrobe/curator_wardrobe = "CuraDrobe", - /obj/machinery/vending/wardrobe/det_wardrobe = "DetDrobe", - /obj/machinery/vending/wardrobe/engi_wardrobe = "EngiDrobe", - /obj/machinery/vending/wardrobe/gene_wardrobe = "GeneDrobe", - /obj/machinery/vending/wardrobe/hydro_wardrobe = "HyDrobe", - /obj/machinery/vending/wardrobe/jani_wardrobe = "JaniDrobe", - /obj/machinery/vending/wardrobe/law_wardrobe = "LawDrobe", - /obj/machinery/vending/wardrobe/medi_wardrobe = "MediDrobe", - /obj/machinery/vending/wardrobe/robo_wardrobe = "RoboDrobe", - /obj/machinery/vending/wardrobe/science_wardrobe = "SciDrobe", - /obj/machinery/vending/wardrobe/sec_wardrobe = "SecDrobe", - /obj/machinery/vending/wardrobe/viro_wardrobe = "ViroDrobe", - ) + ///Assoc list (machine name = machine typepath) of all vendors that can be chosen when the circuit is screwdrivered + var/static/list/valid_vendor_names_paths + +/obj/item/circuitboard/machine/vendor/Initialize(mapload) + . = ..() + if(!valid_vendor_names_paths) + valid_vendor_names_paths = list() + for(var/obj/machinery/vending/vendor_type as anything in subtypesof(/obj/machinery/vending)) + if(vendor_type::allow_custom) + valid_vendor_names_paths[vendor_type::name] = vendor_type /obj/item/circuitboard/machine/vendor/screwdriver_act(mob/living/user, obj/item/tool) - var/static/list/display_vending_names_paths - if(!display_vending_names_paths) - display_vending_names_paths = list() - for(var/path in vending_names_paths) - display_vending_names_paths[vending_names_paths[path]] = path - var/choice = tgui_input_list(user, "Choose a new brand", "Select an Item", sort_list(display_vending_names_paths)) + . = ITEM_INTERACT_FAILURE + var/choice = tgui_input_list(user, "Choose a new brand", "Select an Item", sort_list(valid_vendor_names_paths)) if(isnull(choice)) return - if(isnull(display_vending_names_paths[choice])) + if(!user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) return - set_type(display_vending_names_paths[choice]) - return TRUE + set_type(valid_vendor_names_paths[choice]) + return ITEM_INTERACT_SUCCESS +/** + * Sets circuitboard details based on the vending machine type to create + * + * Arguments + * * obj/machinery/vending/typepath - the vending machine type to create +*/ /obj/item/circuitboard/machine/vendor/proc/set_type(obj/machinery/vending/typepath) build_path = typepath - name = "[vending_names_paths[build_path]] Vendor" + name = "[typepath::name] Vendor" req_components = list(initial(typepath.refill_canister) = 1) flatpack_components = list(initial(typepath.refill_canister)) /obj/item/circuitboard/machine/vendor/apply_default_parts(obj/machinery/machine) - for(var/typepath in vending_names_paths) - if(istype(machine, typepath)) - set_type(typepath) - break + set_type(machine.type) return ..() /obj/item/circuitboard/machine/vending/donksofttoyvendor @@ -1929,3 +1891,35 @@ /obj/item/circuitboard/machine/engine/propulsion name = "Shuttle Engine Propulsion" build_path = /obj/machinery/power/shuttle_engine/propulsion + +/obj/item/circuitboard/machine/quantum_server + name = "Quantum Server" + greyscale_colors = CIRCUIT_COLOR_SUPPLY + build_path = /obj/machinery/quantum_server + req_components = list( + /datum/stock_part/servo = 2, + /datum/stock_part/scanning_module = 1, + /datum/stock_part/capacitor = 1, + ) + +/obj/item/circuitboard/machine/netpod + name = "Netpod" + greyscale_colors = CIRCUIT_COLOR_SUPPLY + build_path = /obj/machinery/netpod + req_components = list( + /datum/stock_part/servo = 1, + /datum/stock_part/matter_bin = 2, + ) + +/obj/item/circuitboard/computer/quantum_console + name = "Quantum Console" + greyscale_colors = CIRCUIT_COLOR_SUPPLY + build_path = /obj/machinery/computer/quantum_console + +/obj/item/circuitboard/machine/byteforge + name = "Byteforge" + greyscale_colors = CIRCUIT_COLOR_SUPPLY + build_path = /obj/machinery/byteforge + req_components = list( + /datum/stock_part/micro_laser = 1, + ) diff --git a/code/game/objects/items/climbingrope.dm b/code/game/objects/items/climbingrope.dm index f096119ee32a..394deb1e6b9c 100644 --- a/code/game/objects/items/climbingrope.dm +++ b/code/game/objects/items/climbingrope.dm @@ -65,7 +65,7 @@ if(do_after(user, final_climb_time, interacting_with)) user.forceMove(interacting_with) - user.mind?.adjust_experience(/datum/skill/athletics, 5) //get some experience for our trouble, especially since this costs us a climbing rope use + user.mind?.adjust_experience(/datum/skill/athletics, round((ATHLETICS_SKILL_MISC_EXP)/(fitness_level || 1), 1)) //get some experience for our trouble, especially since this costs us a climbing rope use QDEL_LIST(effects) return ITEM_INTERACT_SUCCESS diff --git a/code/game/objects/items/crab17.dm b/code/game/objects/items/crab17.dm index 59973a8617af..2664cff95d4a 100644 --- a/code/game/objects/items/crab17.dm +++ b/code/game/objects/items/crab17.dm @@ -6,6 +6,7 @@ w_class = WEIGHT_CLASS_SMALL attack_verb_continuous = list("dumps") attack_verb_simple = list("dump") + /// Has the phone been used already? var/dumped = FALSE /obj/item/suspiciousphone/attack_self(mob/living/user) @@ -32,11 +33,11 @@ new /obj/effect/dumpeet_target(targetturf, L) to_chat(user, span_notice("You have activated Protocol CRAB-17.")) - message_admins("[ADMIN_LOOKUPFLW(user)] has activated Protocol CRAB-17.") user.log_message("activated Protocol CRAB-17.", LOG_GAME) dumped = TRUE + /obj/structure/checkoutmachine name = "\improper Nanotrasen Space-Coin Market" desc = "This is good for spacecoin because" @@ -48,15 +49,23 @@ density = TRUE pixel_z = -8 max_integrity = 5000 + /// List of bank accounts to take money from, determines in start_dumping() var/list/accounts_to_rob + /// The original user of the suspicious phone var/mob/living/bogdanoff /// Are we able to start moving? var/canwalk = FALSE + /// Our own internal bank account, serves as a fallback to transfer money to if Bogdanoff doesn't have one + var/datum/bank_account/internal_account /obj/structure/checkoutmachine/examine(mob/living/user) . = ..() . += span_info("It has a flashing ID card reader for convenient cashing out.") +/** + * Check whether any accounts in the accounts_to_rob list are still being drained. + * Returns TRUE if no accounts are being drained, FALSE otherwise + */ /obj/structure/checkoutmachine/proc/check_if_finished() for(var/i in accounts_to_rob) var/datum/bank_account/B = i @@ -103,6 +112,7 @@ if(QDELETED(src)) return bogdanoff = user + internal_account = new /datum/bank_account/remote("CRAB-17", 0, player_account = FALSE) add_overlay("flaps") add_overlay("hatch") add_overlay("legs_retracted") @@ -110,7 +120,9 @@ QDEL_IN(src, 8 MINUTES) //Self-destruct after 8 min ADD_TRAIT(SSeconomy, TRAIT_MARKET_CRASHING, REF(src)) - +/** + * Starts the dumping process and plays a start-up animation before the checkout starts walking. + */ /obj/structure/checkoutmachine/proc/startUp() //very VERY snowflake code that adds a neat animation when the pod lands. start_dumping() //The machine doesnt move during this time, giving people close by a small window to grab their funds before it starts running around sleep(1 SECONDS) @@ -171,17 +183,23 @@ add_overlay("screen_lines") cut_overlay("text") add_overlay("text") - START_PROCESSING(SSfastprocess, src) // we only start doing economy draining stuff once our machinery is initialized, thematically + START_PROCESSING(SSfastprocess, src) canwalk = TRUE /obj/structure/checkoutmachine/Destroy() stop_dumping() STOP_PROCESSING(SSfastprocess, src) priority_announce("The credit deposit machine at [get_area(src)] has been destroyed. Station funds have stopped draining!", sender_override = "CRAB-17 Protocol") + if(internal_account.account_balance) + expel_cash() + QDEL_NULL(internal_account) explosion(src, light_impact_range = 1, flame_range = 2) REMOVE_TRAIT(SSeconomy, TRAIT_MARKET_CRASHING, REF(src)) return ..() +/** + * Grabs the accounts to be robbed and puts them in accounts_to_rob, tells the accounts they're being drained and calls dump() to start draining. + */ /obj/structure/checkoutmachine/proc/start_dumping() accounts_to_rob = flatten_list(SSeconomy.bank_accounts_by_id) accounts_to_rob -= bogdanoff?.get_bank_account() @@ -190,6 +208,11 @@ B.dumpeet() dump() +/** + * For each account being drained, pulls a random percentage of cash out the account and sends it to Bogdanoff's account. + * If Bogdanoff did not have a bank account, stores the funds in the checkout's internal_account. + * Sets a timer to call itself again after an interval. + */ /obj/structure/checkoutmachine/proc/dump() var/percentage_lost = (rand(5, 15) / 100) for(var/i in accounts_to_rob) @@ -198,10 +221,9 @@ accounts_to_rob -= B continue var/amount = round(B.account_balance * percentage_lost) // We don't want fractions of a credit stolen. That's just agony for everyone. - var/datum/bank_account/account = bogdanoff?.get_bank_account() - if (account) // get_bank_account() may return FALSE - account.transfer_money(B, amount, "?VIVA¿: !LA CRABBE¡") - B.bank_card_talk("You have lost [percentage_lost * 100]% of your funds! A spacecoin credit deposit machine is located at: [get_area(src)].") + var/datum/bank_account/account = bogdanoff?.get_bank_account() || internal_account + account.transfer_money(B, amount, "?VIVA¿: !LA CRABBE¡") + B.bank_card_talk("You have lost [percentage_lost * 100]% of your funds! A spacecoin credit deposit machine is located at: [get_area(src)].") addtimer(CALLBACK(src, PROC_REF(dump)), 15 SECONDS) //Drain every 15 seconds /obj/structure/checkoutmachine/process() @@ -209,12 +231,31 @@ if(Process_Spacemove(anydir)) Move(get_step(src, anydir), anydir) +/** + * Goes through accounts_to_rob and tells every account that the drain has stopped. + */ /obj/structure/checkoutmachine/proc/stop_dumping() for(var/i in accounts_to_rob) var/datum/bank_account/B = i if(B) B.being_dumped = FALSE +/** + * Splits the balance of the internal_account into several smaller piles of cash and scatters them around the area. + */ +/obj/structure/checkoutmachine/proc/expel_cash() + var/funds_remaining = internal_account.account_balance + var/safety = funds_remaining + 1 // In the absolute worst case scenario the loop will complete in funds_remaining steps, if this is counter reaches 0 something went terribly wrong and we need to leave + while(floor(funds_remaining)) + var/amount_to_remove = min(funds_remaining, rand(1, round(internal_account.account_balance)/8)) + var/obj/item/holochip/holochip = new (get_turf(src), amount_to_remove) + funds_remaining -= amount_to_remove + holochip.throw_at(pick(oview(7,get_turf(src))),10,1) + safety -= 1 + if(safety <= 0) + CRASH("/obj/structure/checkoutmachine/proc/expel_cash() did not complete in the theoretical maximum number of steps. Starting value: [internal_account.account_balance]. Value at crash: [funds_remaining].") + + /obj/effect/dumpeet_fall //Falling pod name = "" icon = 'icons/obj/machines/money_machine_64.dmi' @@ -224,6 +265,7 @@ plane = ABOVE_GAME_PLANE icon_state = "missile_blur" + /obj/effect/dumpeet_target name = "Landing Zone Indicator" desc = "A holographic projection designating the landing zone of something. It's probably best to stand back." @@ -242,6 +284,9 @@ sound_to_playing_players('sound/items/dump_it.ogg', 20) deadchat_broadcast("Protocol CRAB-17 has been activated. A space-coin market has been launched at the station!", turf_target = get_turf(src), message_type=DEADCHAT_ANNOUNCEMENT) +/** + * Sets up the falling animation for the checkout machine. + */ /obj/effect/dumpeet_target/proc/startLaunch() DF = new /obj/effect/dumpeet_fall(drop_location()) dump = new /obj/structure/checkoutmachine(null, bogdanoff) @@ -250,8 +295,9 @@ playsound(src, 'sound/items/weapons/mortar_whistle.ogg', 70, TRUE, 6) addtimer(CALLBACK(src, PROC_REF(endLaunch)), 5, TIMER_CLIENT_TIME) //Go onto the last step after a very short falling animation - - +/** + * Cleans up after the falling animation. + */ /obj/effect/dumpeet_target/proc/endLaunch() QDEL_NULL(DF) //Delete the falling machine effect, because at this point its animation is over. We dont use temp_visual because we want to manually delete it as soon as the pod appears playsound(src, SFX_EXPLOSION, 80, TRUE) diff --git a/code/game/objects/items/devices/mulligan_kit.dm b/code/game/objects/items/devices/mulligan_kit.dm index 9560add9fa40..ae8ad36c9e6d 100644 --- a/code/game/objects/items/devices/mulligan_kit.dm +++ b/code/game/objects/items/devices/mulligan_kit.dm @@ -59,7 +59,7 @@ else to_chat(user, span_notice("You quickly put your new ID card [placed_in].")) - user.sec_hud_set_ID() + user.update_ID_card() var/mob/living/carbon/human/dummy/consistent/dummy = new() // For manifest rendering, unfortunately dummy.physique = user.physique diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index beaab018372f..9e81f9b9d2b0 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -177,7 +177,7 @@ GLOBAL_LIST_INIT(channel_tokens, list( /obj/item/radio/headset/syndicate/alt/Initialize(mapload) . = ..() - AddComponent(/datum/component/wearertargeting/earprotection, list(ITEM_SLOT_EARS)) + AddComponent(/datum/component/wearertargeting/earprotection) /obj/item/radio/headset/syndicate/alt/leader name = "team leader headset" @@ -201,7 +201,7 @@ GLOBAL_LIST_INIT(channel_tokens, list( /obj/item/radio/headset/headset_sec/alt/Initialize(mapload) . = ..() - AddComponent(/datum/component/wearertargeting/earprotection, list(ITEM_SLOT_EARS)) + AddComponent(/datum/component/wearertargeting/earprotection) /obj/item/radio/headset/headset_eng name = "engineering radio headset" @@ -284,7 +284,7 @@ GLOBAL_LIST_INIT(channel_tokens, list( /obj/item/radio/headset/heads/captain/alt/Initialize(mapload) . = ..() - AddComponent(/datum/component/wearertargeting/earprotection, list(ITEM_SLOT_EARS)) + AddComponent(/datum/component/wearertargeting/earprotection) /obj/item/radio/headset/heads/rd name = "\proper the research director's headset" @@ -316,7 +316,7 @@ GLOBAL_LIST_INIT(channel_tokens, list( /obj/item/radio/headset/heads/hos/alt/Initialize(mapload) . = ..() - AddComponent(/datum/component/wearertargeting/earprotection, list(ITEM_SLOT_EARS)) + AddComponent(/datum/component/wearertargeting/earprotection) /obj/item/radio/headset/heads/ce name = "\proper the chief engineer's headset" @@ -408,7 +408,7 @@ GLOBAL_LIST_INIT(channel_tokens, list( /obj/item/radio/headset/headset_cent/alt/Initialize(mapload) . = ..() - AddComponent(/datum/component/wearertargeting/earprotection, list(ITEM_SLOT_EARS)) + AddComponent(/datum/component/wearertargeting/earprotection) /obj/item/radio/headset/headset_cent/alt/leader command = TRUE diff --git a/code/game/objects/items/devices/scanners/gas_analyzer.dm b/code/game/objects/items/devices/scanners/gas_analyzer.dm index 724466808294..828476d887d6 100644 --- a/code/game/objects/items/devices/scanners/gas_analyzer.dm +++ b/code/game/objects/items/devices/scanners/gas_analyzer.dm @@ -148,6 +148,10 @@ ui_interact(user) /obj/item/analyzer/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(istype(interacting_with, /obj/effect/anomaly) && can_see(user, interacting_with, ranged_scan_distance)) + var/obj/effect/anomaly/ranged_anomaly = interacting_with + ranged_anomaly.analyzer_act(user, src) + return ITEM_INTERACT_SUCCESS return interact_with_atom(interacting_with, user, modifiers) /obj/item/analyzer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) diff --git a/code/game/objects/items/food/_food.dm b/code/game/objects/items/food/_food.dm index 1003119a2c42..d174480f8cfa 100644 --- a/code/game/objects/items/food/_food.dm +++ b/code/game/objects/items/food/_food.dm @@ -152,7 +152,7 @@ /// This proc handles the microwave component. Overwrite if you want special microwave results. /// By default, all food is microwavable. However, they will be microwaved into a bad recipe (burnt mess). /obj/item/food/proc/make_microwaveable() - AddElement(/datum/element/microwavable) + AddElement(/datum/element/microwavable, /obj/item/food/badrecipe, skip_matcheck = TRUE) ///This proc handles trash components, overwrite this if you want the object to spawn trash /obj/item/food/proc/make_leave_trash() diff --git a/code/game/objects/items/food/bread.dm b/code/game/objects/items/food/bread.dm index 12a9a4b35def..d16d90b5dcfb 100644 --- a/code/game/objects/items/food/bread.dm +++ b/code/game/objects/items/food/bread.dm @@ -118,6 +118,7 @@ /datum/reagent/consumable/nutriment/vitamin = 2, /datum/reagent/consumable/nutriment/protein = 2.4, ) + custom_materials = list(/datum/material/meat = MEATSLAB_MATERIAL_AMOUNT / 5) tastes = list("bread" = 1, "meat" = 1) foodtypes = GRAIN | MEAT | DAIRY crafting_complexity = FOOD_COMPLEXITY_3 @@ -146,6 +147,7 @@ /datum/reagent/consumable/nutriment/vitamin = 2, /datum/reagent/consumable/nutriment/protein = 2.4, ) + custom_materials = list(/datum/material/meat = MEATSLAB_MATERIAL_AMOUNT / 2.5) tastes = list("bread" = 10, "meat" = 10) foodtypes = GRAIN | MEAT crafting_complexity = FOOD_COMPLEXITY_3 @@ -174,6 +176,7 @@ /datum/reagent/consumable/nutriment/vitamin = 2, /datum/reagent/consumable/nutriment/protein = 3, ) + custom_materials = list(/datum/material/meat = MEATSLAB_MATERIAL_AMOUNT / 5) tastes = list("bread" = 10, "acid" = 10) foodtypes = GRAIN | MEAT | DAIRY crafting_complexity = FOOD_COMPLEXITY_3 @@ -204,6 +207,7 @@ /datum/reagent/consumable/nutriment/protein = 4, /datum/reagent/consumable/nutriment/vitamin = 1, ) + custom_materials = list(/datum/material/meat = MEATSLAB_MATERIAL_AMOUNT / 5) tastes = list("bread" = 10, "cobwebs" = 5) foodtypes = GRAIN|MEAT|DAIRY|TOXIC crafting_complexity = FOOD_COMPLEXITY_3 diff --git a/code/game/objects/items/food/cake.dm b/code/game/objects/items/food/cake.dm index f6c123208c40..9f45ac42b686 100644 --- a/code/game/objects/items/food/cake.dm +++ b/code/game/objects/items/food/cake.dm @@ -500,6 +500,7 @@ tastes = list("acid" = 3, "metal" = 4, "glass" = 5) foodtypes = GRAIN|DAIRY|SUGAR|GROSS crafting_complexity = FOOD_COMPLEXITY_3 + custom_materials = list(/datum/material/glass = SHEET_MATERIAL_AMOUNT / 5) /obj/item/food/cake/vanilla_cake name = "vanilla cake" diff --git a/code/game/objects/items/food/donkpocket.dm b/code/game/objects/items/food/donkpocket.dm index c2047e17d965..a75f71a0647c 100644 --- a/code/game/objects/items/food/donkpocket.dm +++ b/code/game/objects/items/food/donkpocket.dm @@ -16,20 +16,20 @@ /// What type of donk pocket we're warmed into via baking or microwaving. var/warm_type = /obj/item/food/donkpocket/warm + /// Whether baking/microwaving it yields a positive result + var/positive_result = TRUE /// The lower end for how long it takes to bake var/baking_time_short = 25 SECONDS /// The upper end for how long it takes to bake var/baking_time_long = 30 SECONDS - /// The reagents added when microwaved. Needed since microwaving ignores food_reagents - var/static/list/added_reagents = list(/datum/reagent/medicine/omnizine = 6) - /// The reagents that most child types add when microwaved. Needed because you can't override static lists. - var/static/list/child_added_reagents = list(/datum/reagent/medicine/omnizine = 2) + /// The amount of omnizine added when it's cooked. + var/omnizine_to_add = 6 /obj/item/food/donkpocket/make_bakeable() - AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE, added_reagents) + AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), positive_result, TRUE, list(/datum/reagent/medicine/omnizine = omnizine_to_add)) /obj/item/food/donkpocket/make_microwaveable() - AddElement(/datum/element/microwavable, warm_type, added_reagents) + AddElement(/datum/element/microwavable, warm_type, string_assoc_list(list(/datum/reagent/medicine/omnizine = omnizine_to_add)), !positive_result) /obj/item/food/donkpocket/warm name = "warm Donk-pocket" @@ -44,8 +44,10 @@ // Warmed donk pockets will burn if you leave them in the oven or microwave. warm_type = /obj/item/food/badrecipe + positive_result = FALSE baking_time_short = 10 SECONDS baking_time_long = 15 SECONDS + omnizine_to_add = 0 /obj/item/food/donkpocket/homemade foodtypes = MEAT|GRAIN @@ -71,12 +73,7 @@ foodtypes = GRAIN|VEGETABLES crafting_complexity = FOOD_COMPLEXITY_2 warm_type = /obj/item/food/donkpocket/warm/dank - -/obj/item/food/donkpocket/dank/make_bakeable() - AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE, child_added_reagents) - -/obj/item/food/donkpocket/dank/make_microwaveable() - AddElement(/datum/element/microwavable, warm_type, child_added_reagents) + omnizine_to_add = 2 /obj/item/food/donkpocket/warm/dank name = "warm Dank-pocket" @@ -104,12 +101,7 @@ tastes = list("umami" = 2, "dough" = 2, "spice" = 1) foodtypes = VEGETABLES|GRAIN warm_type = /obj/item/food/donkpocket/warm/spicy - -/obj/item/food/donkpocket/spicy/make_bakeable() - AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE, child_added_reagents) - -/obj/item/food/donkpocket/spicy/make_microwaveable() - AddElement(/datum/element/microwavable, warm_type, child_added_reagents) + omnizine_to_add = 2 /obj/item/food/donkpocket/warm/spicy name = "warm Spicy-pocket" @@ -147,12 +139,7 @@ tastes = list("umami" = 2, "dough" = 2, "soy sauce" = 2) foodtypes = GRAIN warm_type = /obj/item/food/donkpocket/warm/teriyaki - -/obj/item/food/donkpocket/teriyaki/make_bakeable() - AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE, child_added_reagents) - -/obj/item/food/donkpocket/teriyaki/make_microwaveable() - AddElement(/datum/element/microwavable, warm_type, child_added_reagents) + omnizine_to_add = 2 /obj/item/food/donkpocket/warm/teriyaki name = "warm Teriyaki-pocket" @@ -190,12 +177,7 @@ tastes = list("tomato" = 2, "dough" = 2, "cheese"= 2) foodtypes = VEGETABLES|GRAIN|DAIRY warm_type = /obj/item/food/donkpocket/warm/pizza - -/obj/item/food/donkpocket/pizza/make_bakeable() - AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE, child_added_reagents) - -/obj/item/food/donkpocket/pizza/make_microwaveable() - AddElement(/datum/element/microwavable, warm_type, child_added_reagents) + omnizine_to_add = 2 /obj/item/food/donkpocket/warm/pizza name = "warm Pizza-pocket" @@ -229,10 +211,10 @@ custom_materials = null /obj/item/food/donkpocket/honk/make_bakeable() - AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE, honk_added_reagents) + AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), positive_result, TRUE, honk_added_reagents) /obj/item/food/donkpocket/honk/make_microwaveable() - AddElement(/datum/element/microwavable, warm_type, honk_added_reagents) + AddElement(/datum/element/microwavable, warm_type, honk_added_reagents, positive_result) /obj/item/food/donkpocket/warm/honk name = "warm Honk-pocket" @@ -261,12 +243,7 @@ foodtypes = GRAIN|FRUIT|SUGAR warm_type = /obj/item/food/donkpocket/warm/berry custom_materials = null - -/obj/item/food/donkpocket/berry/make_bakeable() - AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE, child_added_reagents) - -/obj/item/food/donkpocket/berry/make_microwaveable() - AddElement(/datum/element/microwavable, warm_type, child_added_reagents) + omnizine_to_add = 2 /obj/item/food/donkpocket/warm/berry name = "warm Berry-pocket" @@ -301,10 +278,10 @@ ) /obj/item/food/donkpocket/gondola/make_bakeable() - AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE, gondola_added_reagents) + AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), positive_result, TRUE, gondola_added_reagents) /obj/item/food/donkpocket/gondola/make_microwaveable() - AddElement(/datum/element/microwavable, warm_type, gondola_added_reagents) + AddElement(/datum/element/microwavable, warm_type, gondola_added_reagents, positive_result) /obj/item/food/donkpocket/warm/gondola name = "warm Gondola-pocket" @@ -341,10 +318,10 @@ custom_materials = list(/datum/material/meat = MEATDISH_MATERIAL_AMOUNT * 2) /obj/item/food/donkpocket/deluxe/make_bakeable() - AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE, deluxe_added_reagents) + AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), positive_result, TRUE, deluxe_added_reagents) /obj/item/food/donkpocket/deluxe/make_microwaveable() - AddElement(/datum/element/microwavable, warm_type, deluxe_added_reagents) + AddElement(/datum/element/microwavable, warm_type, deluxe_added_reagents, positive_result) /obj/item/food/donkpocket/warm/deluxe name = "warm Donk-pocket Deluxe" @@ -375,12 +352,6 @@ warm_type = /obj/item/food/donkpocket/warm/deluxe/nocarb custom_materials = list(/datum/material/meat = MEATDISH_MATERIAL_AMOUNT * 4) -/obj/item/food/donkpocket/deluxe/meat/make_bakeable() - AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE, deluxe_added_reagents) - -/obj/item/food/donkpocket/deluxe/meat/make_microwaveable() - AddElement(/datum/element/microwavable, warm_type, deluxe_added_reagents) - /obj/item/food/donkpocket/warm/deluxe/nocarb name = "warm Meat-pocket" desc = "The warm food of choice for the carnivorous traitor." @@ -409,12 +380,6 @@ warm_type = /obj/item/food/donkpocket/warm/deluxe/vegan custom_materials = null -/obj/item/food/donkpocket/deluxe/vegan/make_bakeable() - AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE, deluxe_added_reagents) - -/obj/item/food/donkpocket/deluxe/vegan/make_microwaveable() - AddElement(/datum/element/microwavable, warm_type, deluxe_added_reagents) - /obj/item/food/donkpocket/warm/deluxe/vegan name = "warm Donk-roll" desc = "The classic station snack, now with rice! It's been fried to perfection." diff --git a/code/game/objects/items/food/egg.dm b/code/game/objects/items/food/egg.dm index 8ef8ff8f29ff..8faea08ad94f 100644 --- a/code/game/objects/items/food/egg.dm +++ b/code/game/objects/items/food/egg.dm @@ -134,7 +134,7 @@ GLOBAL_VAR_INIT(chicks_from_eggs, 0) if(LAZYACCESS(modifiers, ICON_Y)) broken_egg.pixel_y = clamp(text2num(LAZYACCESS(modifiers, ICON_Y)) - 16, -(ICON_SIZE_Y/2), ICON_SIZE_Y/2) playsound(user, 'sound/items/sheath.ogg', 40, TRUE) - reagents.copy_to(broken_egg, reagents.total_volume) + reagents.trans_to(broken_egg, reagents.total_volume, copy_only = TRUE) hit_griddle.AddToGrill(broken_egg, user) interacting_with.balloon_alert(user, "cracks [src] open") @@ -383,7 +383,7 @@ GLOBAL_VAR_INIT(chicks_from_eggs, 0) if(LAZYACCESS(modifiers, ICON_Y)) broken_egg.pixel_y = clamp(text2num(LAZYACCESS(modifiers, ICON_Y)) - 16, -(ICON_SIZE_Y/2), ICON_SIZE_Y/2) playsound(user, 'sound/items/sheath.ogg', 40, TRUE) - reagents.copy_to(broken_egg, reagents.total_volume) + reagents.trans_to(broken_egg, reagents.total_volume, copy_only = TRUE) hit_griddle.AddToGrill(broken_egg, user) interacting_with.balloon_alert(user, "cracks [src] open") diff --git a/code/game/objects/items/food/lizard.dm b/code/game/objects/items/food/lizard.dm index 5c66986a74ff..ea614d0c7430 100644 --- a/code/game/objects/items/food/lizard.dm +++ b/code/game/objects/items/food/lizard.dm @@ -88,6 +88,7 @@ foodtypes = MEAT | GORE w_class = WEIGHT_CLASS_TINY crafting_complexity = FOOD_COMPLEXITY_2 + custom_materials = list(/datum/material/meat = MEATSLAB_MATERIAL_AMOUNT / 5) /obj/item/food/shredded_lungs name = "crispy shredded lung stirfry" @@ -266,6 +267,7 @@ foodtypes = MEAT | VEGETABLES | NUTS | GORE w_class = WEIGHT_CLASS_SMALL crafting_complexity = FOOD_COMPLEXITY_3 + custom_materials = list(/datum/material/meat = MEATSLAB_MATERIAL_AMOUNT / 5) /obj/item/food/kebab/picoss_skewers name = "picoss skewer" @@ -711,7 +713,7 @@ food_flags = FOOD_FINGER_FOOD w_class = WEIGHT_CLASS_SMALL crafting_complexity = FOOD_COMPLEXITY_4 - custom_materials = list(/datum/material/meat = MEATDISH_MATERIAL_AMOUNT) + custom_materials = list(/datum/material/meat = MEATDISH_MATERIAL_AMOUNT * 2.25) /obj/item/food/honey_roll name = "honey sweetroll" diff --git a/code/game/objects/items/food/martian.dm b/code/game/objects/items/food/martian.dm index be233b18a8ad..b83e28ec0767 100644 --- a/code/game/objects/items/food/martian.dm +++ b/code/game/objects/items/food/martian.dm @@ -1328,6 +1328,7 @@ foodtypes = MEAT w_class = WEIGHT_CLASS_SMALL crafting_complexity = FOOD_COMPLEXITY_3 + custom_materials = list(/datum/material/meat = MEATDISH_MATERIAL_AMOUNT) // Ethereal-suitable cross-culture food /* Ethereals are, as part of the uplifting process, considered as citizens of the Terran Federation. diff --git a/code/game/objects/items/food/meatdish.dm b/code/game/objects/items/food/meatdish.dm index 34685f5373f1..42d7b4dfb62c 100644 --- a/code/game/objects/items/food/meatdish.dm +++ b/code/game/objects/items/food/meatdish.dm @@ -651,6 +651,7 @@ food_flags = FOOD_FINGER_FOOD w_class = WEIGHT_CLASS_SMALL crafting_complexity = FOOD_COMPLEXITY_2 + custom_materials = list(/datum/material/meat = MEATSLAB_MATERIAL_AMOUNT / 6) /obj/item/food/rawkhinkali name = "raw khinkali" @@ -688,6 +689,7 @@ foodtypes = MEAT|GRAIN|VEGETABLES w_class = WEIGHT_CLASS_SMALL crafting_complexity = FOOD_COMPLEXITY_3 + custom_materials = list(/datum/material/meat = MEATDISH_MATERIAL_AMOUNT) /obj/item/food/meatbun name = "meat bun" @@ -1036,9 +1038,10 @@ w_class = WEIGHT_CLASS_SMALL venue_value = FOOD_PRICE_NORMAL crafting_complexity = FOOD_COMPLEXITY_5 + custom_materials = list(/datum/material/meat = MEATDISH_MATERIAL_AMOUNT * (4/3)) /obj/item/food/korta_wellington - name = "Kotra wellington" + name = "Korta wellington" desc = "A luxurious log of beef, covered in a fine mushroom duxelle and pancetta ham, then bound in korta pastry." icon = 'icons/obj/food/meat.dmi' icon_state = "korta_wellington" @@ -1070,6 +1073,7 @@ w_class = WEIGHT_CLASS_SMALL venue_value = FOOD_PRICE_NORMAL crafting_complexity = FOOD_COMPLEXITY_5 + custom_materials = list(/datum/material/meat = MEATDISH_MATERIAL_AMOUNT * (4/3)) /obj/item/food/roast_dinner name = "roast dinner" @@ -1104,6 +1108,7 @@ w_class = WEIGHT_CLASS_SMALL venue_value = FOOD_PRICE_NORMAL crafting_complexity = FOOD_COMPLEXITY_5 + custom_materials = list(/datum/material/meat = MEATDISH_MATERIAL_AMOUNT * 2) /obj/item/food/roast_dinner_lizzy name = "grain-free roast dinner" @@ -1138,6 +1143,7 @@ w_class = WEIGHT_CLASS_SMALL venue_value = FOOD_PRICE_NORMAL crafting_complexity = FOOD_COMPLEXITY_5 + custom_materials = list(/datum/material/meat = MEATDISH_MATERIAL_AMOUNT * 2) /obj/item/food/roast_dinner_tofu name = "tofu roast dinner" @@ -1240,6 +1246,7 @@ foodtypes = MEAT | VEGETABLES w_class = WEIGHT_CLASS_SMALL crafting_complexity = FOOD_COMPLEXITY_4 + custom_materials = list(/datum/material/meat = MEATSLAB_MATERIAL_AMOUNT / 2) /obj/item/food/sweet_and_sour_meatballs name = "sweet and sour meatballs" diff --git a/code/game/objects/items/food/misc.dm b/code/game/objects/items/food/misc.dm index 4e5bee86fe38..6d957f4c5f2a 100644 --- a/code/game/objects/items/food/misc.dm +++ b/code/game/objects/items/food/misc.dm @@ -194,9 +194,28 @@ /obj/item/food/badrecipe/Initialize(mapload) . = ..() RegisterSignal(src, COMSIG_ITEM_GRILL_PROCESS, PROC_REF(OnGrill)) + RegisterSignals(src, list(COMSIG_ITEM_GRILLED_RESULT, COMSIG_ITEM_BAKED_RESULT, COMSIG_ITEM_MICROWAVE_COOKED_FROM), PROC_REF(convert_to_bad_food)) if(stink_particles) add_shared_particles(stink_particles) +///Prevents grilling burnt shit from well, burning. +/obj/item/food/badrecipe/proc/OnGrill() + SIGNAL_HANDLER + return COMPONENT_HANDLED_GRILLING + +/** + * The bad food reagent is cleared when cooked rather than just spawned and the reagents of the item this is from are transferred to this instead, + * So we want to convert most of the consumable reagents into bad food, which is what makes the burned mess a bad thing to eat, taste aside. + */ +/obj/item/food/badrecipe/proc/convert_to_bad_food(atom/source) + SIGNAL_HANDLER + var/bad_food_amount = 0 + for(var/datum/reagent/consumable/food_reagent in reagents.reagent_list) + var/amount_to_remove = food_reagent.volume * rand(6, 8) * 0.1 //around 60% to 80% of the volume is to be converted. + reagents.remove_reagent(food_reagent.type, amount_to_remove, safety = FALSE) + bad_food_amount += amount_to_remove + reagents.add_reagent(/datum/reagent/toxin/bad_food, bad_food_amount, reagtemp = reagents.chem_temp) + /obj/item/food/badrecipe/Destroy(force) if (stink_particles) remove_shared_particles(stink_particles) @@ -227,11 +246,6 @@ . = ..() AddElement(/datum/element/swabable, CELL_LINE_TABLE_MOLD, CELL_VIRUS_TABLE_GENERIC, rand(2, 4), 25) -///Prevents grilling burnt shit from well, burning. -/obj/item/food/badrecipe/proc/OnGrill() - SIGNAL_HANDLER - return COMPONENT_HANDLED_GRILLING - /obj/item/food/spidereggs name = "spider eggs" desc = "A cluster of juicy spider eggs. A great side dish for when you care not for your health." @@ -705,6 +719,7 @@ tastes = list("cooked eggplant" = 5, "potato" = 1, "baked veggies" = 2, "meat" = 4, "bechamel sauce" = 3) foodtypes = MEAT|VEGETABLES|GRAIN|DAIRY crafting_complexity = FOOD_COMPLEXITY_4 + custom_materials = list(/datum/material/meat = MEATDISH_MATERIAL_AMOUNT / 4) /obj/item/food/candied_pineapple name = "candied pineapple" diff --git a/code/game/objects/items/food/pie.dm b/code/game/objects/items/food/pie.dm index f0131dc9a277..e7535c7ee05c 100644 --- a/code/game/objects/items/food/pie.dm +++ b/code/game/objects/items/food/pie.dm @@ -137,6 +137,7 @@ tastes = list("pie" = 1, "meat" = 1) foodtypes = GRAIN|DAIRY|MEAT crafting_complexity = FOOD_COMPLEXITY_3 + custom_materials = list(/datum/material/meat = MEATSLAB_MATERIAL_AMOUNT / 5) /obj/item/food/pie/tofupie name = "tofu-pie" @@ -221,6 +222,7 @@ tastes = list("pie" = 1, "acid" = 1, "meat" = 1) foodtypes = GRAIN|DAIRY|MEAT crafting_complexity = FOOD_COMPLEXITY_3 + custom_materials = list(/datum/material/meat = MEATDISH_MATERIAL_AMOUNT / 5) /obj/item/food/pie/applepie name = "apple pie" @@ -481,6 +483,7 @@ tastes = list("juicy meat" = 1, "mashed potatoes" = 1, "baked veggies" = 1) foodtypes = MEAT | DAIRY | VEGETABLES crafting_complexity = FOOD_COMPLEXITY_5 + custom_materials = list(/datum/material/meat = SHEET_MATERIAL_AMOUNT) /obj/item/food/pie/asdfpie name = "pie-flavored pie" diff --git a/code/game/objects/items/food/spaghetti.dm b/code/game/objects/items/food/spaghetti.dm index 30e2a05a858b..8a1e6e363c3a 100644 --- a/code/game/objects/items/food/spaghetti.dm +++ b/code/game/objects/items/food/spaghetti.dm @@ -25,7 +25,7 @@ tastes = list("pasta" = 1) crafting_complexity = FOOD_COMPLEXITY_1 -/obj/item/food/spaghetti/make_bakeable() +/obj/item/food/spaghetti/raw/make_bakeable() AddComponent(/datum/component/bakeable, /obj/item/food/spaghetti/boiledspaghetti, rand(15 SECONDS, 20 SECONDS), TRUE, TRUE) /obj/item/food/spaghetti/raw/make_microwaveable() diff --git a/code/game/objects/items/grenades/chem_grenade.dm b/code/game/objects/items/grenades/chem_grenade.dm index 586df9369aaf..98b7edf19ae2 100644 --- a/code/game/objects/items/grenades/chem_grenade.dm +++ b/code/game/objects/items/grenades/chem_grenade.dm @@ -586,17 +586,17 @@ beakers += beaker_two /obj/item/grenade/chem_grenade/glitter - name = "generic glitter grenade" - desc = "You shouldn't see this description." + name = "white glitter grenade" + desc = "For that somnolent glittery look." stage = GRENADE_READY - var/glitter_type = /datum/reagent/glitter + var/glitter_colors = list(COLOR_WHITE = 100) /obj/item/grenade/chem_grenade/glitter/Initialize(mapload) . = ..() var/obj/item/reagent_containers/cup/beaker/beaker_one = new(src) var/obj/item/reagent_containers/cup/beaker/beaker_two = new(src) - beaker_one.reagents.add_reagent(glitter_type, 25) + beaker_one.reagents.add_reagent(/datum/reagent/glitter, 25, data = list("colors" = glitter_colors)) beaker_one.reagents.add_reagent(/datum/reagent/potassium, 25) beaker_two.reagents.add_reagent(/datum/reagent/phosphorus, 25) beaker_two.reagents.add_reagent(/datum/reagent/consumable/sugar, 25) @@ -607,17 +607,12 @@ /obj/item/grenade/chem_grenade/glitter/pink name = "pink glitter bomb" desc = "For that HOT glittery look." - glitter_type = /datum/reagent/glitter/pink + glitter_colors = list("#ff8080" = 100) /obj/item/grenade/chem_grenade/glitter/blue name = "blue glitter bomb" desc = "For that COOL glittery look." - glitter_type = /datum/reagent/glitter/blue - -/obj/item/grenade/chem_grenade/glitter/white - name = "white glitter bomb" - desc = "For that somnolent glittery look." - glitter_type = /datum/reagent/glitter/white + glitter_colors = list("#4040ff" = 100) /obj/item/grenade/chem_grenade/clf3 name = "clf3 grenade" diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index d09266f394dd..67cb04a614d5 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -4,7 +4,7 @@ /obj/item/melee/chainofcommand name = "chain of command" - desc = "A tool used by great men to placate the frothing masses." + desc = "A tool used by great men to placate the frothing masses. Can be used to hasten allies with right-click." icon = 'icons/obj/weapons/whip.dmi' icon_state = "chain" inhand_icon_state = "chain" @@ -24,11 +24,42 @@ attack_verb_simple = list("flog", "whip", "lash", "discipline") hitsound = 'sound/items/weapons/chainhit.ogg' custom_materials = list(/datum/material/iron = HALF_SHEET_MATERIAL_AMOUNT) + ///Does this chain allow you to speed people up with right click? + var/can_hasten = TRUE /obj/item/melee/chainofcommand/suicide_act(mob/living/user) user.visible_message(span_suicide("[user] is strangling [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!")) return OXYLOSS +/obj/item/melee/chainofcommand/attack_secondary(mob/living/victim, mob/living/user, list/modifiers, list/attack_modifiers) + . = ..() + + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + if(victim == user) + to_chat(user, span_warning("You consider lashing yourself, but hesitate at the thought of how much it would hurt.")) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + playsound(victim, 'sound/items/weapons/whip.ogg', 50, TRUE, -1) + victim.apply_status_effect(/datum/status_effect/speed_boost/commanded) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + +/datum/status_effect/speed_boost/commanded + id = "commanded" + status_type = STATUS_EFFECT_REFRESH + alert_type = /atom/movable/screen/alert/status_effect/commanded + move_datum = /datum/movespeed_modifier/status_speed_boost/minor + duration = 7 SECONDS + +/datum/movespeed_modifier/status_speed_boost/minor + multiplicative_slowdown = -0.20 + +/atom/movable/screen/alert/status_effect/commanded + name = "Commanded" + desc = "You are inspired to move faster!" + icon_state = "commanded" + /obj/item/melee/synthetic_arm_blade name = "synthetic arm blade" desc = "A grotesque blade that on closer inspection seems to be made out of synthetic flesh, it still feels like it would hurt very badly as a weapon." diff --git a/code/game/objects/items/religion.dm b/code/game/objects/items/religion.dm index 7d91b02eb4a9..25790cada0ab 100644 --- a/code/game/objects/items/religion.dm +++ b/code/game/objects/items/religion.dm @@ -97,7 +97,7 @@ /datum/crafting_recipe/security_banner name = "Securistan Banner" result = /obj/item/banner/security/mundane - time = 40 + time = 4 SECONDS reqs = list(/obj/item/stack/rods = 2, /obj/item/clothing/under/rank/security/officer = 1) category = CAT_MISC @@ -122,7 +122,7 @@ /datum/crafting_recipe/medical_banner name = "Meditopia Banner" result = /obj/item/banner/medical/mundane - time = 40 + time = 4 SECONDS reqs = list(/obj/item/stack/rods = 2, /obj/item/clothing/under/rank/medical/doctor = 1) category = CAT_MISC @@ -155,7 +155,7 @@ /datum/crafting_recipe/science_banner name = "Sciencia Banner" result = /obj/item/banner/science/mundane - time = 40 + time = 4 SECONDS reqs = list(/obj/item/stack/rods = 2, /obj/item/clothing/under/rank/rnd/scientist = 1) category = CAT_MISC @@ -177,7 +177,7 @@ /datum/crafting_recipe/cargo_banner name = "Cargonia Banner" result = /obj/item/banner/cargo/mundane - time = 40 + time = 4 SECONDS reqs = list(/obj/item/stack/rods = 2, /obj/item/clothing/under/rank/cargo/tech = 1) category = CAT_MISC @@ -202,7 +202,7 @@ /datum/crafting_recipe/engineering_banner name = "Engitopia Banner" result = /obj/item/banner/engineering/mundane - time = 40 + time = 4 SECONDS reqs = list(/obj/item/stack/rods = 2, /obj/item/clothing/under/rank/engineering/engineer = 1) category = CAT_MISC @@ -226,7 +226,7 @@ /datum/crafting_recipe/command_banner name = "Command Banner" result = /obj/item/banner/command/mundane - time = 40 + time = 4 SECONDS reqs = list(/obj/item/stack/rods = 2, /obj/item/clothing/under/rank/captain/parade = 1) category = CAT_MISC diff --git a/code/game/objects/items/signs.dm b/code/game/objects/items/signs.dm index a725791e2389..671cad6780f2 100644 --- a/code/game/objects/items/signs.dm +++ b/code/game/objects/items/signs.dm @@ -74,5 +74,5 @@ result = /obj/item/picket_sign reqs = list(/obj/item/stack/rods = 1, /obj/item/stack/sheet/cardboard = 2) - time = 80 + time = 8 SECONDS category = CAT_ENTERTAINMENT diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index fbe077ccfdd6..097723b59cf9 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -189,7 +189,9 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \ /obj/item/stack/sheet/iron/examine(mob/user) . = ..() - . += span_notice("You can build a wall girder (unanchored) by right clicking on an empty floor.") + . += span_notice("Right click on floor to build:") + . += span_notice("- Unanchored wall girder") + . += span_notice("- Computer or Machine frame (with circuitboard)") /obj/item/stack/sheet/iron/narsie_act() new /obj/item/stack/sheet/runed_metal(loc, amount) @@ -253,18 +255,39 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \ if(build_on.is_blocked_turf()) user.balloon_alert(user, "something is blocking the tile!") return ITEM_INTERACT_BLOCKING - if(get_amount() < 2) - user.balloon_alert(user, "not enough material!") + + var/frame_path = null + var/cost = 2 // Default girder cost + var/time = 4 SECONDS //Default girder build time + var/obj/item/circuitboard/held_board = locate() in user.held_items + if(!isnull(held_board)) + if(istype(held_board, /obj/item/circuitboard/machine)) + frame_path = /obj/structure/frame/machine + else + frame_path = /obj/structure/frame/computer + for(var/datum/stack_recipe/recipe in GLOB.metal_recipes) + if(recipe.result_type == frame_path) + time = recipe.time + cost = recipe.req_amount + break + if(get_amount() < cost) + user.balloon_alert(user, "need [cost] metal sheets!") return ITEM_INTERACT_BLOCKING - if(!do_after(user, 4 SECONDS, build_on)) + if(!do_after(user, time, build_on)) return ITEM_INTERACT_BLOCKING if(build_on.is_blocked_turf()) user.balloon_alert(user, "something is blocking the tile!") return ITEM_INTERACT_BLOCKING - if(!use(2)) + if(!use(cost)) user.balloon_alert(user, "not enough material!") return ITEM_INTERACT_BLOCKING - new/obj/structure/girder/displaced(build_on) + if(frame_path) + var/obj/structure/frame/constructed_frame = new frame_path(build_on) + constructed_frame.setDir(REVERSE_DIR(user.dir)) //to align computer frame with player direction + user.balloon_alert(user, "frame created") + else + new/obj/structure/girder/displaced(build_on) + user.balloon_alert(user, "girder created") return ITEM_INTERACT_SUCCESS /* diff --git a/code/game/objects/items/stacks/stack_recipe.dm b/code/game/objects/items/stacks/stack_recipe.dm index 11d5315e5f63..f507e2fc784a 100644 --- a/code/game/objects/items/stacks/stack_recipe.dm +++ b/code/game/objects/items/stacks/stack_recipe.dm @@ -35,7 +35,7 @@ req_amount = 1, res_amount = 1, max_res_amount = 1, - time = 0, + time = 0 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY, placement_checks = NONE, trait_booster, @@ -74,7 +74,7 @@ req_amount = 1, res_amount = 1, max_res_amount = 1, - time = 0, + time = 0 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY, placement_checks = NONE, trait_booster, diff --git a/code/game/objects/items/stacks/tape.dm b/code/game/objects/items/stacks/tape.dm index d06b2250ed2e..62ac35ec7281 100644 --- a/code/game/objects/items/stacks/tape.dm +++ b/code/game/objects/items/stacks/tape.dm @@ -186,6 +186,10 @@ if(!isobj(interacting_with) || iseffect(interacting_with)) return NONE + if(HAS_TRAIT(interacting_with, TRAIT_DUCT_TAPE_UNREPAIRABLE)) + user.balloon_alert(user, "cannot be repaired with duct tape!") + return ITEM_INTERACT_BLOCKING + var/obj/item/object_to_repair = interacting_with var/object_is_damaged = object_to_repair.get_integrity() < object_to_repair.max_integrity diff --git a/code/game/objects/items/storage/boxes/clothes_boxes.dm b/code/game/objects/items/storage/boxes/clothes_boxes.dm index 6d789293e79e..2ac97ff0313d 100644 --- a/code/game/objects/items/storage/boxes/clothes_boxes.dm +++ b/code/game/objects/items/storage/boxes/clothes_boxes.dm @@ -209,6 +209,7 @@ /obj/item/storage/box/holy/adept/PopulateContents() new /obj/item/clothing/suit/chaplainsuit/armor/adept(src) new /obj/item/clothing/head/helmet/chaplain/adept(src) + new /obj/item/clothing/gloves/bracer(src) /obj/item/storage/box/holy/follower name = "Followers of the Chaplain Kit" diff --git a/code/game/objects/items/storage/boxes/medical_boxes.dm b/code/game/objects/items/storage/boxes/medical_boxes.dm index 1a85927b5ef1..7d468ff81b1a 100644 --- a/code/game/objects/items/storage/boxes/medical_boxes.dm +++ b/code/game/objects/items/storage/boxes/medical_boxes.dm @@ -51,7 +51,7 @@ /obj/item/storage/box/beakers/big/PopulateContents() for(var/i in 1 to 7) - new /obj/item/reagent_containers/cup/beaker/large + new /obj/item/reagent_containers/cup/beaker/large(src) /obj/item/storage/box/beakers/bluespace name = "box of bluespace beakers" diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm index 9ff03b3a9026..709f3e190b3c 100644 --- a/code/game/objects/items/storage/uplink_kits.dm +++ b/code/game/objects/items/storage/uplink_kits.dm @@ -300,7 +300,7 @@ new /obj/item/clothing/suit/armor/vest/marine/pmc(src) //The armor kit is comparable to the infiltrator, 6 TC new /obj/item/clothing/head/helmet/marine/pmc(src) new /obj/item/clothing/mask/gas/sechailer(src) - new /obj/item/clothing/glasses/night/colorless(src) // 3~ TC + new /obj/item/clothing/glasses/night(src) // 3~ TC new /obj/item/clothing/gloves/krav_maga/combatglovesplus(src) //5TC new /obj/item/clothing/shoes/jackboots(src) new /obj/item/storage/belt/military/assault/fisher(src) //items in this belt easily costs 18 TC diff --git a/code/game/objects/items/storage/wallets.dm b/code/game/objects/items/storage/wallets.dm index 27aea36ee15b..8ab4b176ee1a 100644 --- a/code/game/objects/items/storage/wallets.dm +++ b/code/game/objects/items/storage/wallets.dm @@ -51,7 +51,7 @@ if(ishuman(loc)) var/mob/living/carbon/human/wearing_human = loc if(wearing_human.wear_id == src) - wearing_human.sec_hud_set_ID() + wearing_human.update_ID_card() update_label() update_appearance(UPDATE_ICON) @@ -98,14 +98,14 @@ /obj/item/storage/wallet/GetID() return front_id -/obj/item/storage/wallet/RemoveID() +/obj/item/storage/wallet/remove_id() if(!front_id) return . = front_id front_id.forceMove(get_turf(src)) -/obj/item/storage/wallet/InsertID(obj/item/inserting_item) - var/obj/item/card/inserting_id = inserting_item.RemoveID() +/obj/item/storage/wallet/insert_id(obj/item/inserting_item) + var/obj/item/card/inserting_id = inserting_item.remove_id() if(!inserting_id) return FALSE attackby(inserting_id) diff --git a/code/game/objects/items/vending_items.dm b/code/game/objects/items/vending_items.dm index 7084b313dff5..6d11220251a3 100644 --- a/code/game/objects/items/vending_items.dm +++ b/code/game/objects/items/vending_items.dm @@ -3,8 +3,6 @@ */ /obj/item/vending_refill name = "resupply canister" - var/machine_name = "Generic" - icon = 'icons/obj/vending_restock.dmi' icon_state = "refill_snack" inhand_icon_state = "restock_unit" @@ -19,13 +17,14 @@ w_class = WEIGHT_CLASS_BULKY armor_type = /datum/armor/item_vending_refill - /** - * Built automatically from the corresponding vending machine. - * If null, considered to be full. Otherwise, is list(/typepath = amount). - */ + ///Name of the vending machine this canister is associated with + var/machine_name = "Generic" + + ///corresponds to /obj/machinery/vending::list/products var/list/products - var/list/product_categories + ///corresponds to /obj/machinery/vending::list/contraband var/list/contraband + ///corresponds to /obj/machinery/vending::list/premium var/list/premium /datum/armor/item_vending_refill @@ -38,18 +37,21 @@ /obj/item/vending_refill/examine(mob/user) . = ..() + var/num = get_part_rating() - if (num == INFINITY) - . += "It's sealed tight, completely full of supplies." - else if (num == 0) - . += "It's empty!" + if (!num) + . += span_notice("It's empty!") + else if(num == INFINITY) + . += span_notice("It's full of supplies!") else - . += "It can restock [num] item\s." + . += span_notice("It can restock [num] item\s.") /obj/item/vending_refill/get_part_rating() - if (!products || !product_categories || !contraband || !premium) - return INFINITY . = 0 + //first time needs to be filled by the vending machine + if(!products) + return INFINITY + for(var/key in products) . += products[key] for(var/key in contraband) @@ -57,9 +59,3 @@ for(var/key in premium) . += premium[key] - for (var/list/category as anything in product_categories) - var/list/products = category["products"] - for (var/product_key in products) - . += products[product_key] - - return . diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 0c9b1d2cb3bc..802ea57f9140 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -840,6 +840,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 icon_state = "tailwhip" inhand_icon_state = "tailwhip" item_flags = NONE + can_hasten = FALSE /obj/item/melee/chainofcommand/tailwhip/kitty name = "cat o' nine tails" diff --git a/code/game/objects/structures/crates_lockers/closet_see_inside.dm b/code/game/objects/structures/crates_lockers/closet_see_inside.dm index 7895d31d5195..efd7b338e401 100644 --- a/code/game/objects/structures/crates_lockers/closet_see_inside.dm +++ b/code/game/objects/structures/crates_lockers/closet_see_inside.dm @@ -1,41 +1,34 @@ /// Responsible for showing the insides of a closet to those inside it. /datum/closet_see_inside - var/obj/structure/closet/closet - + ///Closet grayed out image so players can click on it to get out of closet var/image/background_image + ///Stuff inside closet image var/image/contents_image - var/list/client/clients_looking_at_image = list() - - var/door_alpha = 85 - /datum/closet_see_inside/New(obj/structure/closet/closet) - src.closet = closet - - RegisterSignal(closet, COMSIG_ATOM_ENTERED, PROC_REF(on_atom_entered)) - RegisterSignal(closet, COMSIG_ATOM_EXITED, PROC_REF(on_atom_exited)) + RegisterSignal(closet, COMSIG_CLOSET_PRE_OPEN, PROC_REF(on_closet_pre_open)) + RegisterSignal(closet, COMSIG_CLOSET_POST_CLOSE, PROC_REF(on_closet_closed)) /datum/closet_see_inside/Destroy(force) - if (contents_image) - for (var/client/looking_at_image as anything in clients_looking_at_image) - looking_at_image.images -= background_image - looking_at_image.images -= contents_image - - contents_image.vis_contents.Cut() - - clients_looking_at_image.Cut() - - + on_closet_pre_open(src) return ..() -/datum/closet_see_inside/proc/create_image() - contents_image = new - contents_image.loc = closet - contents_image.appearance_flags |= KEEP_TOGETHER +/** + * Creates the closet background & contents image to display for the client + * + * Arguments + * * obj/structure/closet/closet - the closet whose insides we are taking a snapshot of +*/ +/datum/closet_see_inside/proc/create_image(obj/structure/closet/closet) + PRIVATE_PROC(TRUE) + if(contents_image) + return + + ///closet grayed out image background_image = image( icon = closet.icon, - icon_state = closet.base_icon_state == null ? initial(closet.icon_state) : closet.base_icon_state, + icon_state = isnull(closet.base_icon_state) ? initial(closet.icon_state) : closet.base_icon_state, loc = closet, layer = BELOW_OBJ_LAYER, ) @@ -43,6 +36,10 @@ background_image.opacity = MOUSE_OPACITY_TRANSPARENT background_image.override = TRUE + //all stuff inside the closet image + contents_image = new + contents_image.loc = closet + contents_image.appearance_flags |= KEEP_TOGETHER contents_image.add_filter( "mask", 1, @@ -52,7 +49,6 @@ y = -3, ) ) - contents_image.add_filter( "color", 2, @@ -62,45 +58,39 @@ ) ) + //door & contents to add to image if (closet.enable_door_overlay) var/obj/effect/overlay/door = new door.icon = closet.icon door.icon_state = "[closet.icon_door || background_image.icon_state]_door" - door.alpha = door_alpha + door.alpha = 85 door.layer = ABOVE_ALL_MOB_LAYER door.mouse_opacity = MOUSE_OPACITY_TRANSPARENT contents_image.vis_contents += door - for (var/atom/movable/movable in closet) contents_image.vis_contents += movable -/datum/closet_see_inside/proc/on_atom_entered(obj/structure/closet/source, atom/movable/arrived) +/datum/closet_see_inside/proc/on_closet_pre_open(obj/structure/closet/source, mob/user) SIGNAL_HANDLER - if (contents_image) - contents_image.vis_contents += arrived - - if (ismob(arrived)) - var/mob/arrived_mob = arrived - var/client/client = GET_CLIENT(arrived_mob) - if (client) - create_image() - clients_looking_at_image += client - client.images += background_image - client.images += contents_image + if(contents_image) + for(var/atom/movable/movable in source) + if(ismob(movable)) + var/client/client = GET_CLIENT(astype(movable, /mob)) + if (client) + client.images -= background_image + client.images -= contents_image + contents_image.vis_contents.Cut() -/datum/closet_see_inside/proc/on_atom_exited(obj/structure/closet/source, atom/movable/exited) +/datum/closet_see_inside/proc/on_closet_closed(obj/structure/closet/source, mob/user) SIGNAL_HANDLER - if (!contents_image) - return - - contents_image.vis_contents -= exited - - if (ismob(exited)) - var/mob/exited_mob = exited - var/client/client = GET_CLIENT(exited_mob) - if (client) - clients_looking_at_image -= client - client.images -= background_image - client.images -= contents_image + for(var/atom/movable/movable in source) + if(ismob(movable)) + var/client/client = GET_CLIENT(astype(movable, /mob)) + if (client) + create_image(source) + client.images += background_image + client.images += contents_image + if(contents_image) + contents_image.vis_contents += movable diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index c511562d769c..8a35511c6f46 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -100,9 +100,8 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets) var/x_shake_pixel_shift = 2 /// how many pixels the closet can shift on the y axes when shaking var/y_shake_pixel_shift = 1 - - VAR_PRIVATE - datum/closet_see_inside/closet_see_inside + ///Creates see through image for clients to see while inside closet + VAR_PRIVATE/datum/closet_see_inside/closet_see_inside /datum/armor/structure_closet melee = 20 diff --git a/code/game/objects/structures/crates_lockers/closets/bodybag.dm b/code/game/objects/structures/crates_lockers/closets/bodybag.dm index 2e9c6687826a..2c596b67aebb 100644 --- a/code/game/objects/structures/crates_lockers/closets/bodybag.dm +++ b/code/game/objects/structures/crates_lockers/closets/bodybag.dm @@ -270,6 +270,7 @@ /obj/structure/closet/body_bag/environmental/prisoner/attempt_fold(mob/living/carbon/human/the_folder) if(sinched) to_chat(the_folder, span_warning("You wrestle with [src], but it won't fold while its straps are fastened.")) + return FALSE return ..() /obj/structure/closet/body_bag/environmental/prisoner/before_open(mob/living/user, force) diff --git a/code/game/objects/structures/crates_lockers/closets/syndicate.dm b/code/game/objects/structures/crates_lockers/closets/syndicate.dm index 06b006fe4cc3..fc2c2fe56d10 100644 --- a/code/game/objects/structures/crates_lockers/closets/syndicate.dm +++ b/code/game/objects/structures/crates_lockers/closets/syndicate.dm @@ -20,7 +20,7 @@ /obj/structure/closet/syndicate/personal/PopulateContents() ..() new /obj/item/trench_tool(src) - new /obj/item/clothing/glasses/night/colorless(src) + new /obj/item/clothing/glasses/night(src) new /obj/item/ammo_box/magazine/m10mm(src) new /obj/item/storage/belt/military(src) new /obj/item/storage/belt/holster/nukie(src) diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index 1c3ff385b4d7..c54605eb78c2 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -476,14 +476,26 @@ /obj/structure/closet/crate/add_to_roundstart_list() return -/obj/structure/closet/crate/pink +/obj/structure/closet/crate/glitter name = "pink crate" desc = "A glittery pink crate." icon_state = "pink" base_icon_state = "pink" + var/glitter_prob = 25 + var/glitter_color = "#ff8080" -/obj/structure/closet/crate/lavender +/obj/structure/closet/crate/glitter/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change) + . = ..() + + var/turf/old_turf = get_turf(old_loc) + if(!old_turf) + return + if(prob(glitter_prob)) + old_turf.spawn_glitter(list("[glitter_color]" = 100)) + +/obj/structure/closet/crate/glitter/lavender name = "lavender crate" desc = "A glittery purple... no, lavender crate." icon_state = "lavender" base_icon_state = "lavender" + glitter_color = "#db80ff" diff --git a/code/game/objects/structures/gym/weight_machine_action.dm b/code/game/objects/structures/gym/weight_machine_action.dm index 6023a1b19470..2f370e20b0d0 100644 --- a/code/game/objects/structures/gym/weight_machine_action.dm +++ b/code/game/objects/structures/gym/weight_machine_action.dm @@ -15,7 +15,7 @@ return FALSE return TRUE -/datum/action/push_weights/Trigger(trigger_flags) +/datum/action/push_weights/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return FALSE diff --git a/code/game/objects/structures/ladders.dm b/code/game/objects/structures/ladders.dm index 95534b286105..6a60c80f92df 100644 --- a/code/game/objects/structures/ladders.dm +++ b/code/game/objects/structures/ladders.dm @@ -277,7 +277,8 @@ user.zMove(target = target, z_move_flags = ZMOVE_CHECK_PULLEDBY|ZMOVE_ALLOW_BUCKLED|ZMOVE_INCLUDE_PULLED) if(grant_exp) - user.mind?.adjust_experience(/datum/skill/athletics, 10) //get a little experience for our trouble + var/fitness_level = user.mind?.get_skill_level(/datum/skill/athletics) + user.mind?.adjust_experience(/datum/skill/athletics, round(ATHLETICS_SKILL_MISC_EXP/(fitness_level || 1), 1)) //get a little experience for our trouble if(!is_ghost) show_final_fluff_message(user, ladder, going_up) diff --git a/code/game/objects/structures/platform.dm b/code/game/objects/structures/platform.dm index 48e1e2b78c7d..6adfcf310aa5 100644 --- a/code/game/objects/structures/platform.dm +++ b/code/game/objects/structures/platform.dm @@ -1,4 +1,4 @@ -#define PLATFORM_BASE_MATERIAL_AMOUNT 2000 +#define PLATFORM_BASE_MATERIAL_AMOUNT (2 * SHEET_MATERIAL_AMOUNT) /// A raised platform you can stand on top of /obj/structure/platform @@ -21,7 +21,7 @@ /// Icon used for the frame var/frame_icon = 'icons/obj/smooth_structures/platform/frame_faces/window_frame_normal.dmi' /// Material used in our construction - var/sheet_type = /obj/item/stack/sheet/iron + var/sheet_type = null /// Count of sheets used in our construction var/sheet_amount = 2 /// What footstep do we use? diff --git a/code/game/say.dm b/code/game/say.dm index 8baabda3be9e..85848ee0f489 100644 --- a/code/game/say.dm +++ b/code/game/say.dm @@ -62,7 +62,8 @@ GLOBAL_LIST_INIT(freqtospan, list( return spans |= speech_span language ||= get_selected_language() - message_mods[SAY_MOD_VERB] = say_mod(message, message_mods) + if(!message_mods[SAY_MOD_VERB]) + message_mods[SAY_MOD_VERB] = say_mod(message, message_mods) send_speech(message, message_range, src, bubble_type, spans, language, message_mods, forced = forced) /// Called when this movable hears a message from a source. @@ -167,18 +168,15 @@ GLOBAL_LIST_INIT(freqtospan, list( //End name span. var/endspanpart = "" - //Message - var/messagepart + // Language icon. var/languageicon = "" - if(message_mods[MODE_CUSTOM_SAY_ERASE_INPUT]) - messagepart = message_mods[MODE_CUSTOM_SAY_EMOTE] - else - messagepart = speaker.say_quote(raw_message, spans, message_mods) - + if(!message_mods[MODE_CUSTOM_SAY_ERASE_INPUT]) var/datum/language/dialect = GLOB.language_datum_instances[message_language] if(istype(dialect) && dialect.display_icon(src)) languageicon = "[dialect.get_icon()] " + // The actual message part. + var/messagepart = speaker.generate_messagepart(raw_message, spans, message_mods) messagepart = " [messagepart]" return "[spanpart1][spanpart2][freqpart][languageicon][compose_track_href(speaker, namepart)][namepart][compose_job(speaker, message_language, raw_message, radio_freq)][endspanpart][messagepart]" @@ -219,14 +217,20 @@ GLOBAL_LIST_INIT(freqtospan, list( return verb_say /** - * This prock is used to generate a message for chat - * Generates the `says, "meme"` part of the `Grey Tider says, "meme"`. + * This proc is used to generate the 'message' part of a chat message. + * Generates the `says, "meme"` part of the `Grey Tider says, "meme"`, + * or the `taps their microphone.` part of `Grey Tider taps their microphone.`. * * input - The message to be said * spans - A list of spans to attach to the message. Includes the atom's speech span by default * message_mods - A list of message modifiers, i.e. whispering/singing */ -/atom/movable/proc/say_quote(input, list/spans = list(speech_span), list/message_mods = list()) +/atom/movable/proc/generate_messagepart(input, list/spans = list(speech_span), list/message_mods = list()) + // If we only care about the emote part, early return. + if(message_mods[MODE_CUSTOM_SAY_ERASE_INPUT]) + return apply_message_emphasis(message_mods[MODE_CUSTOM_SAY_EMOTE]) + + // Otherwise, we format our full quoted message. if(!input) input = "..." diff --git a/code/game/turfs/closed/indestructible.dm b/code/game/turfs/closed/indestructible.dm index a32e0a1b1458..82a0cca5305d 100644 --- a/code/game/turfs/closed/indestructible.dm +++ b/code/game/turfs/closed/indestructible.dm @@ -137,12 +137,6 @@ INITIALIZE_IMMEDIATE(/turf/closed/indestructible/splashscreen) smoothing_groups = SMOOTH_GROUP_WALLS + SMOOTH_GROUP_CLOSED_TURFS + SMOOTH_GROUP_SYNDICATE_WALLS canSmoothWith = SMOOTH_GROUP_SHUTTLE_PARTS + SMOOTH_GROUP_AIRLOCK + SMOOTH_GROUP_PLASTITANIUM_WALLS + SMOOTH_GROUP_SYNDICATE_WALLS -/turf/closed/indestructible/syndicate/nodiagonal - icon = 'icons/turf/walls/plastitanium_wall.dmi' - icon_state = "map-shuttle_nd" - base_icon_state = "plastitanium_wall" - smoothing_flags = SMOOTH_BITMASK - /turf/closed/indestructible/riveted/uranium icon = 'icons/turf/walls/uranium_wall.dmi' icon_state = "uranium_wall-0" @@ -160,7 +154,8 @@ INITIALIZE_IMMEDIATE(/turf/closed/indestructible/splashscreen) canSmoothWith = SMOOTH_GROUP_PLASTINUM_WALLS /turf/closed/indestructible/riveted/plastinum/nodiagonal - icon_state = "map-shuttle_nd" + icon = MAP_SWITCH('icons/turf/walls/plastinum_wall.dmi', 'icons/turf/walls/misc_wall.dmi') + icon_state = MAP_SWITCH("plastinum_wall-0", "plastinum_nd") smoothing_flags = SMOOTH_BITMASK /turf/closed/indestructible/wood diff --git a/code/game/turfs/closed/wall/mineral_walls.dm b/code/game/turfs/closed/wall/mineral_walls.dm index 49c4e09c8b37..460da266758a 100644 --- a/code/game/turfs/closed/wall/mineral_walls.dm +++ b/code/game/turfs/closed/wall/mineral_walls.dm @@ -281,14 +281,13 @@ return ..() /turf/closed/wall/mineral/titanium/nodiagonal - icon = 'icons/turf/walls/shuttle_wall.dmi' - icon_state = "map-shuttle_nd" - base_icon_state = "shuttle_wall" + icon = MAP_SWITCH('icons/turf/walls/shuttle_wall.dmi', 'icons/turf/walls/misc_wall.dmi') + icon_state = MAP_SWITCH("shuttle_wall-0", "shuttle_nd") smoothing_flags = SMOOTH_BITMASK /turf/closed/wall/mineral/titanium/overspace - icon_state = "map-overspace" - smoothing_flags = SMOOTH_BITMASK | SMOOTH_DIAGONAL_CORNERS + icon = MAP_SWITCH('icons/turf/walls/shuttle_wall.dmi', 'icons/turf/walls/misc_wall.dmi') + icon_state = MAP_SWITCH("shuttle_wall-0", "shuttle_overspace") fixed_underlay = list("space" = TRUE) /turf/closed/wall/mineral/titanium/interior/copyTurf(turf/copy_to_turf, copy_air = FALSE, flags = null) @@ -352,17 +351,14 @@ /turf/closed/wall/mineral/plastitanium/nodiagonal - icon = 'icons/turf/walls/plastitanium_wall.dmi' - icon_state = "map-shuttle_nd" - base_icon_state = "plastitanium_wall" + icon = MAP_SWITCH('icons/turf/walls/plastitanium_wall.dmi', 'icons/turf/walls/misc_wall.dmi') + icon_state = MAP_SWITCH("plastitanium_wall-0", "plastitanium_nd") smoothing_flags = SMOOTH_BITMASK - rust_resistance = RUST_RESISTANCE_TITANIUM /turf/closed/wall/mineral/plastitanium/overspace - icon_state = "map-overspace" - smoothing_flags = SMOOTH_BITMASK | SMOOTH_DIAGONAL_CORNERS + icon = MAP_SWITCH('icons/turf/walls/plastitanium_wall.dmi', 'icons/turf/walls/misc_wall.dmi') + icon_state = MAP_SWITCH("plastitanium_wall-0", "plastitanium_overspace") fixed_underlay = list("space" = TRUE) - rust_resistance = RUST_RESISTANCE_TITANIUM /turf/closed/wall/mineral/plastitanium/rust_turf() if(HAS_TRAIT(src, TRAIT_RUSTY)) diff --git a/code/game/turfs/closed/wall/reinf_walls.dm b/code/game/turfs/closed/wall/reinf_walls.dm index c612e550ce58..a416091aed5c 100644 --- a/code/game/turfs/closed/wall/reinf_walls.dm +++ b/code/game/turfs/closed/wall/reinf_walls.dm @@ -248,14 +248,13 @@ rust_resistance = RUST_RESISTANCE_TITANIUM /turf/closed/wall/r_wall/plastitanium/nodiagonal - icon = 'icons/turf/walls/plastitanium_wall.dmi' - icon_state = "map-shuttle_nd" - base_icon_state = "plastitanium_wall" + icon = MAP_SWITCH('icons/turf/walls/plastitanium_wall.dmi', 'icons/turf/walls/misc_wall.dmi') + icon_state = MAP_SWITCH("plastitanium_wall-0", "plastitanium_nd") smoothing_flags = SMOOTH_BITMASK /turf/closed/wall/r_wall/plastitanium/overspace - icon_state = "map-overspace" - smoothing_flags = SMOOTH_BITMASK | SMOOTH_DIAGONAL_CORNERS + icon = MAP_SWITCH('icons/turf/walls/plastitanium_wall.dmi', 'icons/turf/walls/misc_wall.dmi') + icon_state = MAP_SWITCH("plastitanium_wall-0", "plastitanium_overspace") fixed_underlay = list("space" = TRUE) /turf/closed/wall/r_wall/plastitanium/syndicate @@ -267,12 +266,11 @@ return FALSE /turf/closed/wall/r_wall/plastitanium/syndicate/nodiagonal - icon = 'icons/turf/walls/plastitanium_wall.dmi' - icon_state = "map-shuttle_nd" - base_icon_state = "plastitanium_wall" + icon = MAP_SWITCH('icons/turf/walls/plastitanium_wall.dmi', 'icons/turf/walls/misc_wall.dmi') + icon_state = MAP_SWITCH("plastitanium_wall-0", "plastitanium_nd") smoothing_flags = SMOOTH_BITMASK /turf/closed/wall/r_wall/plastitanium/syndicate/overspace - icon_state = "map-overspace" - smoothing_flags = SMOOTH_BITMASK | SMOOTH_DIAGONAL_CORNERS + icon = MAP_SWITCH('icons/turf/walls/plastitanium_wall.dmi', 'icons/turf/walls/misc_wall.dmi') + icon_state = MAP_SWITCH("plastitanium_wall-0", "plastitanium_overspace") fixed_underlay = list("space" = TRUE) diff --git a/code/game/turfs/open/space/space.dm b/code/game/turfs/open/space/space.dm index 754793963294..dadd4de9ab84 100644 --- a/code/game/turfs/open/space/space.dm +++ b/code/game/turfs/open/space/space.dm @@ -44,7 +44,7 @@ GLOBAL_LIST_EMPTY(starlight) /turf/open/space icon = 'icons/turf/space.dmi' - icon_state = "space" + MAP_SWITCH(icon_state = "space", icon_state = "space_map") name = "\proper space" overfloor_placed = FALSE underfloor_accessibility = UNDERFLOOR_INTERACTABLE @@ -75,6 +75,9 @@ GLOBAL_LIST_EMPTY(starlight) force_no_gravity = TRUE +/turf/open/space/basic + MAP_SWITCH(icon_state = "space", icon_state = "space_basic_map") + /turf/open/space/basic/New() //Do not convert to Initialize SHOULD_CALL_PARENT(FALSE) //This is used to optimize the map loader diff --git a/code/game/turfs/open/water.dm b/code/game/turfs/open/water.dm index 748cdeef85ee..cabdd3fd434d 100644 --- a/code/game/turfs/open/water.dm +++ b/code/game/turfs/open/water.dm @@ -202,6 +202,8 @@ ///Registers the signals from the immerse element and calls dip_in if the movable has the required trait. /turf/open/water/hot_spring/proc/enter_hot_spring(atom/movable/movable) + if(is_type_in_typecache(movable, GLOB.immerse_ignored_movable)) // So we don't immerse weird things like turf decals/effects, projectiles, etc + return FALSE RegisterSignal(movable, SIGNAL_ADDTRAIT(TRAIT_IMMERSED), PROC_REF(dip_in)) if(isliving(movable)) //so far, exiting a hot spring only has effects on living mobs. RegisterSignal(movable, SIGNAL_REMOVETRAIT(TRAIT_IMMERSED), PROC_REF(dip_out)) diff --git a/code/modules/admin/verbs/admin_newscaster.dm b/code/modules/admin/verbs/admin_newscaster.dm index d199d31e9b9a..e300150659b1 100644 --- a/code/modules/admin/verbs/admin_newscaster.dm +++ b/code/modules/admin/verbs/admin_newscaster.dm @@ -86,15 +86,15 @@ ADMIN_VERB(access_news_network, R_ADMIN, "Access Newscaster Network", "Allows yo "author" = channel.author, "censored" = channel.censored, "locked" = channel.locked, - "ID" = channel.channel_ID, + "ID" = channel.channel_id, )) if(current_channel) for(var/datum/feed_message/feed_message as anything in current_channel.messages) - var/photo_ID = null + var/photo_id = null var/list/comment_list if(feed_message.img) - user << browse_rsc(feed_message.img, "tmp_photo[feed_message.message_ID].png") - photo_ID = "tmp_photo[feed_message.message_ID].png" + user << browse_rsc(feed_message.img, "tmp_photo[feed_message.message_id].png") + photo_id = "tmp_photo[feed_message.message_id].png" for(var/datum/feed_comment/comment_message as anything in feed_message.comments) comment_list += list(list( "auth" = comment_message.author, @@ -105,16 +105,16 @@ ADMIN_VERB(access_news_network, R_ADMIN, "Access Newscaster Network", "Allows yo "auth" = feed_message.author, "body" = feed_message.body, "time" = feed_message.time_stamp, - "channel_num" = feed_message.parent_ID, + "channel_num" = feed_message.parent_id, "censored_message" = feed_message.body_censor, "censored_author" = feed_message.author_censor, - "ID" = feed_message.message_ID, - "photo" = photo_ID, + "ID" = feed_message.message_id, + "photo" = photo_id, "comments" = comment_list )) - data["viewing_channel"] = current_channel?.channel_ID + data["viewing_channel"] = current_channel?.channel_id //Here we display all the information about the current channel. data["channelName"] = current_channel?.channel_name data["channelAuthor"] = current_channel?.author @@ -141,19 +141,20 @@ ADMIN_VERB(access_news_network, R_ADMIN, "Access Newscaster Network", "Allows yo switch(action) if("setChannel") - var/prototype_channel = params["channel"] - if(isnull(prototype_channel)) + var/selected_channel_id = params["channel"] + if(isnull(selected_channel_id)) return TRUE - for(var/datum/feed_channel/potential_channel as anything in GLOB.news_network.network_channels) - if(prototype_channel == potential_channel.channel_ID) - current_channel = potential_channel + var/datum/feed_channel/potential_channel = GLOB.news_network.network_channels_by_id["[selected_channel_id]"] + if(isnull(potential_channel)) + return TRUE + current_channel = potential_channel if("createStory") if(!current_channel) to_chat(usr, "select a channel first!") return TRUE - var/prototype_channel = params["current"] - create_story(channel_name = prototype_channel) + var/current_channel_id = params["current"] + create_story(channel_id = current_channel_id) if("togglePhoto") toggle_photo() @@ -189,23 +190,25 @@ ADMIN_VERB(access_news_network, R_ADMIN, "Access Newscaster Network", "Allows yo if("storyCensor") var/questionable_message = params["messageID"] for(var/datum/feed_message/iterated_feed_message as anything in current_channel.messages) - if(iterated_feed_message.message_ID == questionable_message) + if(iterated_feed_message.message_id == questionable_message) iterated_feed_message.toggle_censor_body() break if("author_censor") var/questionable_message = params["messageID"] for(var/datum/feed_message/iterated_feed_message in current_channel.messages) - if(iterated_feed_message.message_ID == questionable_message) + if(iterated_feed_message.message_id == questionable_message) iterated_feed_message.toggle_censor_author() break if("channelDNotice") - var/prototype_channel = (params["channel"]) - for(var/datum/feed_channel/potential_channel in GLOB.news_network.network_channels) - if(prototype_channel == potential_channel.channel_ID) - current_channel = potential_channel - break + var/selected_channel_id = (params["channel"]) + if(isnull(selected_channel_id)) + return TRUE + var/datum/feed_channel/potential_channel = GLOB.news_network.network_channels_by_id["[selected_channel_id]"] + if(isnull(potential_channel)) + return TRUE + current_channel = potential_channel current_channel.toggle_censor_D_class() if("startComment") @@ -214,7 +217,7 @@ ADMIN_VERB(access_news_network, R_ADMIN, "Access Newscaster Network", "Allows yo if(!commentable_message) return TRUE for(var/datum/feed_message/iterated_feed_message as anything in current_channel.messages) - if(iterated_feed_message.message_ID == commentable_message) + if(iterated_feed_message.message_id == commentable_message) current_message = iterated_feed_message return TRUE @@ -284,10 +287,10 @@ ADMIN_VERB(access_news_network, R_ADMIN, "Access Newscaster Network", "Allows yo /datum/newspanel/proc/create_channel(channel_locked) if(!channel_name) return - for(var/datum/feed_channel/iterated_feed_channel as anything in GLOB.news_network.network_channels) - if(iterated_feed_channel.channel_name == channel_name) - tgui_alert(usr, "ERROR: Feed channel with that name already exists on the Network.", list("Okay")) - return TRUE + var/datum/feed_channel/potential_channel = GLOB.news_network.network_channels_by_name[channel_name] + if(potential_channel) + tgui_alert(usr, "ERROR: Feed channel with that name already exists on the Network.", list("Okay")) + return TRUE if(!channel_desc) return TRUE if(isnull(channel_locked)) @@ -334,11 +337,12 @@ ADMIN_VERB(access_news_network, R_ADMIN, "Access Newscaster Network", "Allows yo * Verifies that the message is being written to a real feed_channel, then provides a text input for the feed story to be written into. * Finally, it submits the message to the network, is logged globally, and clears all message-specific variables from the machine. */ -/datum/newspanel/proc/create_story(channel_name) - for(var/datum/feed_channel/potential_channel as anything in GLOB.news_network.network_channels) - if(channel_name == potential_channel.channel_ID) - current_channel = potential_channel - break +/datum/newspanel/proc/create_story(channel_id) + var/datum/feed_channel/potential_channel = GLOB.news_network.network_channels_by_id["[channel_id]"] + if(isnull(potential_channel)) + return + current_channel = potential_channel + var/temp_message = tgui_input_text(usr, "Write your Feed story", "Network Channel Handler", feed_channel_message, max_length = MAX_BROADCAST_LEN, multiline = TRUE) if(length(temp_message) <= 1) return TRUE diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index c0abfcd88cca..3a6667af6d1f 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -139,7 +139,7 @@ ADMIN_VERB(cmd_admin_grantfullaccess, R_DEBUG, "Grant Full Access", "Grant full if(worn) if(istype(worn, /obj/item/modular_computer)) var/obj/item/modular_computer/worn_computer = worn - worn_computer.InsertID(id, H) + worn_computer.insert_id(id, H) else if(istype(worn, /obj/item/storage/wallet)) var/obj/item/storage/wallet/W = worn diff --git a/code/modules/admin/verbs/light_debug.dm b/code/modules/admin/verbs/light_debug.dm index f9758de0bd04..04026573b26e 100644 --- a/code/modules/admin/verbs/light_debug.dm +++ b/code/modules/admin/verbs/light_debug.dm @@ -357,7 +357,7 @@ GLOBAL_LIST_EMPTY(light_debugged_atoms) SIGNAL_HANDLER Grant(new_mob) -/datum/action/spawn_light/Trigger(trigger_flags) +/datum/action/spawn_light/Trigger(mob/clicker, trigger_flags) . = ..() ui_interact(usr) diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm index 9c24b174b225..1f9d16332f6d 100644 --- a/code/modules/antagonists/_common/antag_datum.dm +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -123,8 +123,8 @@ GLOBAL_LIST_EMPTY(antagonists) /datum/antagonist/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) . = ..() - if(. || isobserver(ui.user)) - return + if(. || ui.user != owner.current) + return TRUE switch(action) if("change_objectives") submit_player_objective() @@ -155,12 +155,12 @@ GLOBAL_LIST_EMPTY(antagonists) . = ..() name = "Open [target] Information:" -/datum/action/antag_info/Trigger(trigger_flags) +/datum/action/antag_info/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return - target.ui_interact(usr || owner) + target.ui_interact(clicker || owner) /datum/action/antag_info/IsAvailable(feedback = FALSE) if(!target) diff --git a/code/modules/antagonists/abductor/equipment/abduction_surgery.dm b/code/modules/antagonists/abductor/equipment/abduction_surgery.dm index 790dd0f8e535..07be8836f970 100644 --- a/code/modules/antagonists/abductor/equipment/abduction_surgery.dm +++ b/code/modules/antagonists/abductor/equipment/abduction_surgery.dm @@ -27,7 +27,7 @@ /datum/surgery_step/extract_organ name = "remove heart" accept_hand = 1 - time = 32 + time = 3.2 SECONDS var/obj/item/organ/IC = null var/list/organ_types = list(/obj/item/organ/heart) @@ -51,7 +51,7 @@ /datum/surgery_step/gland_insert name = "insert gland" implements = list(/obj/item/organ/heart/gland = 100) - time = 32 + time = 3.2 SECONDS /datum/surgery_step/gland_insert/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) user.visible_message(span_notice("[user] starts to insert [tool] into [target]."), span_notice("You start to insert [tool] into [target]...")) diff --git a/code/modules/antagonists/abductor/equipment/gear/abductor_clothing.dm b/code/modules/antagonists/abductor/equipment/gear/abductor_clothing.dm index 365ab92a160d..269c5d0f9e6d 100644 --- a/code/modules/antagonists/abductor/equipment/gear/abductor_clothing.dm +++ b/code/modules/antagonists/abductor/equipment/gear/abductor_clothing.dm @@ -87,15 +87,17 @@ if(disguise == null) return stealth_active = TRUE - if(ishuman(loc)) - var/mob/living/carbon/human/wearer = loc - new /obj/effect/temp_visual/dir_setting/ninja/cloak(get_turf(wearer), wearer.dir) - RegisterSignal(wearer, COMSIG_HUMAN_GET_VISIBLE_NAME, PROC_REF(return_disguise_name)) - wearer.icon = disguise.icon - wearer.icon_state = disguise.icon_state - wearer.cut_overlays() - wearer.add_overlay(disguise.overlays) - wearer.update_held_items() + if(!ishuman(loc)) + return + var/mob/living/carbon/human/wearer = loc + new /obj/effect/temp_visual/dir_setting/ninja/cloak(get_turf(wearer), wearer.dir) + RegisterSignal(wearer, COMSIG_HUMAN_GET_VISIBLE_NAME, PROC_REF(return_disguise_name)) + wearer.icon = disguise.icon + wearer.icon_state = disguise.icon_state + wearer.cut_overlays() + wearer.add_overlay(disguise.overlays) + wearer.update_held_items() + wearer.update_visible_name() /obj/item/clothing/suit/armor/abductor/vest/proc/return_disguise_name(mob/living/carbon/human/source, list/identity) SIGNAL_HANDLER @@ -108,12 +110,14 @@ if(!stealth_active) return stealth_active = FALSE - if(ishuman(loc)) - var/mob/living/carbon/human/wearer = loc - new /obj/effect/temp_visual/dir_setting/ninja(get_turf(wearer), wearer.dir) - UnregisterSignal(wearer, COMSIG_HUMAN_GET_VISIBLE_NAME) - wearer.cut_overlays() - wearer.regenerate_icons() + if(!ishuman(loc)) + return + var/mob/living/carbon/human/wearer = loc + new /obj/effect/temp_visual/dir_setting/ninja(get_turf(wearer), wearer.dir) + UnregisterSignal(wearer, COMSIG_HUMAN_GET_VISIBLE_NAME) + wearer.cut_overlays() + wearer.regenerate_icons() + wearer.update_visible_name() /obj/item/clothing/suit/armor/abductor/vest/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) DeactivateStealth() diff --git a/code/modules/antagonists/abductor/equipment/gear/abductor_items.dm b/code/modules/antagonists/abductor/equipment/gear/abductor_items.dm index 57d3e2a36d73..90d2d5a90538 100644 --- a/code/modules/antagonists/abductor/equipment/gear/abductor_items.dm +++ b/code/modules/antagonists/abductor/equipment/gear/abductor_items.dm @@ -520,7 +520,7 @@ Return to step 11 of normal process."} /obj/item/radio/headset/abductor/Initialize(mapload) . = ..() - AddComponent(/datum/component/wearertargeting/earprotection, list(ITEM_SLOT_EARS)) + AddComponent(/datum/component/wearertargeting/earprotection) make_syndie() // Stops humans from disassembling abductor headsets. diff --git a/code/modules/antagonists/blob/overmind.dm b/code/modules/antagonists/blob/overmind.dm index ad0a89ee8023..582feac39922 100644 --- a/code/modules/antagonists/blob/overmind.dm +++ b/code/modules/antagonists/blob/overmind.dm @@ -321,10 +321,11 @@ GLOBAL_LIST_EMPTY(blob_nodes) if (!message) return - src.log_talk(message, LOG_SAY) - - var/message_a = say_quote(message) - var/rendered = span_big(span_blob("\[Blob Telepathy\] [name]([blobstrain.name]) [message_a]")) + var/list/message_mods = list() + var/adjusted_message = check_for_custom_say_emote(message, message_mods) + log_sayverb_talk(message, message_mods, tag = "blob hivemind telepathy") + var/messagepart = generate_messagepart(adjusted_message, message_mods = message_mods) + var/rendered = span_big(span_blob("\[Blob Telepathy\] [name]([blobstrain.name]) [messagepart]")) relay_to_list_and_observers(rendered, GLOB.blob_telepathy_mobs, src, MESSAGE_TYPE_RADIO) /mob/eye/blob/blob_act(obj/structure/blob/B) diff --git a/code/modules/antagonists/changeling/cellular_emporium.dm b/code/modules/antagonists/changeling/cellular_emporium.dm index 754d2343d5cd..4641f859bee6 100644 --- a/code/modules/antagonists/changeling/cellular_emporium.dm +++ b/code/modules/antagonists/changeling/cellular_emporium.dm @@ -99,7 +99,7 @@ stack_trace("cellular_emporium action created with non-emporium.") qdel(src) -/datum/action/cellular_emporium/Trigger(trigger_flags) +/datum/action/cellular_emporium/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return diff --git a/code/modules/antagonists/changeling/changeling_power.dm b/code/modules/antagonists/changeling/changeling_power.dm index d06d8fe91735..85fa4b537806 100644 --- a/code/modules/antagonists/changeling/changeling_power.dm +++ b/code/modules/antagonists/changeling/changeling_power.dm @@ -44,7 +44,7 @@ the same goes for Remove(). if you override Remove(), call parent or else your p /datum/action/changeling/proc/on_purchase(mob/user, is_respec) Grant(user)//how powers are added rather than the checks in mob.dm -/datum/action/changeling/Trigger(trigger_flags) +/datum/action/changeling/Trigger(mob/clicker, trigger_flags) var/mob/user = owner if(!user || !IS_CHANGELING(user)) return diff --git a/code/modules/antagonists/changeling/powers/mimic_voice.dm b/code/modules/antagonists/changeling/powers/mimic_voice.dm index 9caf0abb450f..99f543045804 100644 --- a/code/modules/antagonists/changeling/powers/mimic_voice.dm +++ b/code/modules/antagonists/changeling/powers/mimic_voice.dm @@ -2,7 +2,7 @@ name = "Mimic Voice" desc = "We shape our vocal glands to sound like a desired voice. Maintaining this power slows chemical production." button_icon_state = "mimic_voice" - helptext = "Will turn your voice into the name that you enter. We must constantly expend chemicals to maintain our form like this." + helptext = "Will turn our voice into the name that we enter. We must constantly expend chemicals to maintain our form like this." chemical_cost = 0//constant chemical drain hardcoded dna_cost = 1 req_human = TRUE diff --git a/code/modules/antagonists/changeling/powers/mmi_talk.dm b/code/modules/antagonists/changeling/powers/mmi_talk.dm index 59048463e1e4..47c748f6f18b 100644 --- a/code/modules/antagonists/changeling/powers/mmi_talk.dm +++ b/code/modules/antagonists/changeling/powers/mmi_talk.dm @@ -2,7 +2,7 @@ name = "MMI Talk" desc = "Our decoy brain has been implanted into a Man-Machine Interface. \ In order to maintain our secrecy, we can speak through the decoy as if a normal brain. \ - The decoy brain will relay speech it hears to you in purple." + The decoy brain will relay speech it hears to us in purple." button_icon = 'icons/obj/devices/assemblies.dmi' button_icon_state = "mmi_off" dna_cost = CHANGELING_POWER_UNOBTAINABLE diff --git a/code/modules/antagonists/changeling/powers/tiny_prick.dm b/code/modules/antagonists/changeling/powers/tiny_prick.dm index 739eb3ec2eba..f6bc841e11c0 100644 --- a/code/modules/antagonists/changeling/powers/tiny_prick.dm +++ b/code/modules/antagonists/changeling/powers/tiny_prick.dm @@ -2,7 +2,7 @@ name = "Tiny Prick" desc = "Stabby stabby" -/datum/action/changeling/sting/Trigger(trigger_flags) +/datum/action/changeling/sting/Trigger(mob/clicker, trigger_flags) var/mob/user = owner if(!user || !user.mind) return @@ -166,7 +166,7 @@ var/obj/item/held = target.get_active_held_item() if(held && !target.dropItemToGround(held)) - to_chat(user, span_warning("[held] is stuck to [target.p_their()] hand, you cannot grow a false armblade over it!")) + to_chat(user, span_warning("[held] is stuck to [target.p_their()] hand, we cannot grow a false armblade over it!")) return ..() @@ -193,7 +193,7 @@ /datum/action/changeling/sting/extract_dna name = "Extract DNA Sting" desc = "We stealthily sting a target and extract their DNA. Costs 25 chemicals." - helptext = "Will give you the DNA of your target, allowing you to transform into them." + helptext = "Will give us the DNA of our target, allowing us to transform into them. This will render us unable to absorb their body fully later." button_icon_state = "sting_extract" chemical_cost = 25 dna_cost = 0 diff --git a/code/modules/antagonists/changeling/powers/void_adaption.dm b/code/modules/antagonists/changeling/powers/void_adaption.dm index eb21fef598cc..f066b24b5da3 100644 --- a/code/modules/antagonists/changeling/powers/void_adaption.dm +++ b/code/modules/antagonists/changeling/powers/void_adaption.dm @@ -1,9 +1,9 @@ /datum/action/changeling/void_adaption name = "Void Adaption" desc = "We prepare our cells to resist the hostile environment outside of the station. We may freely travel wherever we wish." - helptext = "This ability is passive, and will automatically protect you in situations of extreme cold or vacuum, \ - as well as removing your need to breathe oxygen, although you will still be affected by hazardous gases. \ - While it is actively protecting you from temperature or pressure it reduces your chemical regeneration rate." + helptext = "This ability is passive, and will automatically protect us in situations of extreme cold or vacuum, \ + as well as removing our need to breathe oxygen, although we will still be affected by hazardous gases. \ + While it is actively protecting us from temperature or pressure it reduces our chemical regeneration rate." owner_has_control = FALSE dna_cost = 2 diff --git a/code/modules/antagonists/clown_ops/clown_weapons.dm b/code/modules/antagonists/clown_ops/clown_weapons.dm index c66df8215ca2..cba33a918026 100644 --- a/code/modules/antagonists/clown_ops/clown_weapons.dm +++ b/code/modules/antagonists/clown_ops/clown_weapons.dm @@ -19,7 +19,7 @@ slowdown = SHOES_SLOWDOWN body_parts_covered = FEET|LEGS armor_type = /datum/armor/clown_shoes_combat - strip_delay = 70 + strip_delay = 7 SECONDS resistance_flags = NONE /datum/armor/clown_shoes_combat @@ -47,7 +47,7 @@ desc = "The culmination of years of clown combat research, these shoes leave a trail of chaos in their wake. They will slowly recharge themselves over time, or can be manually charged with bananium." slowdown = SHOES_SLOWDOWN armor_type = /datum/armor/banana_shoes_combat - strip_delay = 70 + strip_delay = 7 SECONDS resistance_flags = NONE always_noslip = TRUE body_parts_covered = FEET|LEGS diff --git a/code/modules/antagonists/cult/cult_armor.dm b/code/modules/antagonists/cult/cult_armor.dm index 939e5bd2c809..4f6aae945be4 100644 --- a/code/modules/antagonists/cult/cult_armor.dm +++ b/code/modules/antagonists/cult/cult_armor.dm @@ -246,7 +246,6 @@ actions_types = null color_cutoffs = list(40, 0, 0) //red glass_colour_type = null - forced_glass_color = FALSE /obj/item/clothing/glasses/hud/health/night/cultblind/equipped(mob/living/user, slot) . = ..() diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index 0b638295be7d..799e54f2c488 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -406,29 +406,36 @@ structure_check() searches for nearby cultist structures required for the invoca /// Tries to convert a null rod over the rune to a cult sword /obj/effect/rune/convert/proc/try_spawn_sword() - for(var/obj/item/nullrod/rod in loc) - if(rod.anchored || (rod.resistance_flags & INDESTRUCTIBLE)) + for(var/obj/item/potential_rod in loc) + if(!HAS_TRAIT(potential_rod, TRAIT_NULLROD_ITEM)) continue - var/num_slain = LAZYLEN(rod.cultists_slain) - var/displayed_message = "[rod] glows an unholy red and begins to transform..." - if(GET_ATOM_BLOOD_DNA_LENGTH(rod)) - displayed_message += " The blood of [num_slain] fallen cultist[num_slain == 1 ? "":"s"] is absorbed into [rod]!" + if(potential_rod.anchored || (potential_rod.resistance_flags & INDESTRUCTIBLE)) + continue + + var/num_slain = 0 + if (istype(potential_rod, /obj/item/nullrod)) + var/obj/item/nullrod/actual_rod = potential_rod + num_slain = LAZYLEN(actual_rod.cultists_slain) + + var/displayed_message = "[potential_rod] glows an unholy red and begins to transform..." + if(num_slain && GET_ATOM_BLOOD_DNA_LENGTH(potential_rod)) + displayed_message += " The blood of [num_slain] fallen cultist[num_slain == 1 ? "":"s"] is absorbed into [potential_rod]!" - rod.visible_message(span_cult_italic(displayed_message)) + potential_rod.visible_message(span_cult_italic(displayed_message)) switch(num_slain) if(0) - animate_spawn_sword(rod, /obj/item/melee/cultblade/dagger) + animate_spawn_sword(potential_rod, /obj/item/melee/cultblade/dagger) if(1) - animate_spawn_sword(rod, /obj/item/melee/cultblade) + animate_spawn_sword(potential_rod, /obj/item/melee/cultblade) else - animate_spawn_sword(rod, /obj/item/melee/cultblade/halberd) + animate_spawn_sword(potential_rod, /obj/item/melee/cultblade/halberd) return TRUE return FALSE /// Does an animation of a null rod transforming into a cult sword -/obj/effect/rune/convert/proc/animate_spawn_sword(obj/item/nullrod/former_rod, new_blade_typepath) +/obj/effect/rune/convert/proc/animate_spawn_sword(obj/item/former_rod, new_blade_typepath) playsound(src, 'sound/effects/magic.ogg', 33, vary = TRUE, extrarange = SILENCED_SOUND_EXTRARANGE, frequency = 0.66) former_rod.anchored = TRUE former_rod.Shake() diff --git a/code/modules/antagonists/fugitive/hunters/hunter_gear.dm b/code/modules/antagonists/fugitive/hunters/hunter_gear.dm index 4efe29b1048c..34d10b057890 100644 --- a/code/modules/antagonists/fugitive/hunters/hunter_gear.dm +++ b/code/modules/antagonists/fugitive/hunters/hunter_gear.dm @@ -218,7 +218,7 @@ /obj/item/radio/headset/psyker/Initialize(mapload) . = ..() - AddComponent(/datum/component/wearertargeting/earprotection, list(ITEM_SLOT_EARS)) + AddComponent(/datum/component/wearertargeting/earprotection) /obj/item/radio/headset/psyker/equipped(mob/living/user, slot) . = ..() diff --git a/code/modules/antagonists/heretic/heretic_living_heart.dm b/code/modules/antagonists/heretic/heretic_living_heart.dm index 443ea0603fd1..f8f18a8188e2 100644 --- a/code/modules/antagonists/heretic/heretic_living_heart.dm +++ b/code/modules/antagonists/heretic/heretic_living_heart.dm @@ -101,7 +101,7 @@ return TRUE -/datum/action/cooldown/track_target/Trigger(trigger_flags, atom/target) +/datum/action/cooldown/track_target/Trigger(mob/clicker, trigger_flags, atom/target) right_clicked = !!(trigger_flags & TRIGGER_SECONDARY_ACTION) return ..() diff --git a/code/modules/antagonists/heretic/items/corrupted_organs.dm b/code/modules/antagonists/heretic/items/corrupted_organs.dm index 1035a006a9c6..5ffe055de80a 100644 --- a/code/modules/antagonists/heretic/items/corrupted_organs.dm +++ b/code/modules/antagonists/heretic/items/corrupted_organs.dm @@ -191,13 +191,14 @@ return ..() - /// Occasionally bombards you with spooky hands and lets everyone hear your pulse. /obj/item/organ/heart/corrupt name = "corrupt heart" desc = "What corruption is this spreading along with the blood?" beat_noise = "THE THUMPTHUMPTHUMPING OF THE CHISEL ON THE GLASS. OPEN THE FUTURE SHATTER THE-" organ_flags = parent_type::organ_flags | ORGAN_HAZARDOUS + cell_line = CELL_LINE_ORGAN_HEART_CURSED + cells_minimum = 2 //guarantees we always get sacred heart and corrupted heart cells /// How long until the next heart? COOLDOWN_DECLARE(hand_cooldown) diff --git a/code/modules/antagonists/heretic/items/hunter_rifle.dm b/code/modules/antagonists/heretic/items/hunter_rifle.dm index e7f8ba9ec6d7..43f55b8b77f6 100644 --- a/code/modules/antagonists/heretic/items/hunter_rifle.dm +++ b/code/modules/antagonists/heretic/items/hunter_rifle.dm @@ -24,9 +24,7 @@ name = "lionhunter rifle internal magazine" ammo_type = /obj/item/ammo_casing/strilka310/lionhunter caliber = CALIBER_STRILKA310 - armour_penetration = 100 max_ammo = 3 - multiload = TRUE /obj/item/ammo_casing/strilka310/lionhunter projectile_type = /obj/projectile/bullet/strilka310/lionhunter diff --git a/code/modules/antagonists/heretic/items/keyring.dm b/code/modules/antagonists/heretic/items/keyring.dm index 19ae1810507b..61dbef21dc19 100644 --- a/code/modules/antagonists/heretic/items/keyring.dm +++ b/code/modules/antagonists/heretic/items/keyring.dm @@ -139,7 +139,7 @@ trim = card.trim if(ishuman(loc)) var/mob/living/carbon/human/wearing = loc - wearing.sec_hud_set_ID() + wearing.update_ID_card() assignment = card.assignment registered_age = card.registered_age registered_name = card.registered_name diff --git a/code/modules/antagonists/heretic/magic/ash_ascension.dm b/code/modules/antagonists/heretic/magic/ash_ascension.dm index dcedaf03cecb..7dc39389a563 100644 --- a/code/modules/antagonists/heretic/magic/ash_ascension.dm +++ b/code/modules/antagonists/heretic/magic/ash_ascension.dm @@ -110,7 +110,7 @@ ranged_mousepointer = 'icons/effects/mouse_pointers/throw_target.dmi' school = SCHOOL_FORBIDDEN - cooldown_time = 300 + cooldown_time = 30 SECONDS invocation = "F'R." invocation_type = INVOCATION_WHISPER diff --git a/code/modules/antagonists/heretic/status_effects/buffs.dm b/code/modules/antagonists/heretic/status_effects/buffs.dm index 8f37d5ff298a..ab327817735a 100644 --- a/code/modules/antagonists/heretic/status_effects/buffs.dm +++ b/code/modules/antagonists/heretic/status_effects/buffs.dm @@ -35,7 +35,7 @@ button_icon = 'icons/obj/antags/eldritch.dmi' button_icon_state = "crucible_soul" -/datum/action/cancel_crucible_soul/Trigger(trigger_flags) +/datum/action/cancel_crucible_soul/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return diff --git a/code/modules/antagonists/heretic/structures/carving_knife.dm b/code/modules/antagonists/heretic/structures/carving_knife.dm index 5b2f8743691b..289b1784c4d7 100644 --- a/code/modules/antagonists/heretic/structures/carving_knife.dm +++ b/code/modules/antagonists/heretic/structures/carving_knife.dm @@ -190,7 +190,7 @@ return ..() /obj/structure/trap/eldritch/item_interaction(mob/living/user, obj/item/tool, list/modifiers) - if(istype(tool, /obj/item/melee/rune_carver) || istype(tool, /obj/item/nullrod)) + if(istype(tool, /obj/item/melee/rune_carver) || HAS_TRAIT(tool, TRAIT_NULLROD_ITEM)) loc.balloon_alert(user, "carving dispelled") playsound(src, 'sound/items/sheath.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, ignore_walls = FALSE) qdel(src) diff --git a/code/modules/antagonists/malf_ai/malf_ai_modules.dm b/code/modules/antagonists/malf_ai/malf_ai_modules.dm index ba155b663a8d..029477f9fb14 100644 --- a/code/modules/antagonists/malf_ai/malf_ai_modules.dm +++ b/code/modules/antagonists/malf_ai/malf_ai_modules.dm @@ -83,7 +83,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module/malf)) return FALSE . = ..() -/datum/action/innate/ai/Trigger(trigger_flags) +/datum/action/innate/ai/Trigger(mob/clicker, trigger_flags) . = ..() if(auto_use_uses) adjust_uses(-1) diff --git a/code/modules/antagonists/ninja/outfit.dm b/code/modules/antagonists/ninja/outfit.dm index 924943dce777..f91f660a3e8b 100644 --- a/code/modules/antagonists/ninja/outfit.dm +++ b/code/modules/antagonists/ninja/outfit.dm @@ -1,7 +1,7 @@ /datum/outfit/ninja name = "Space Ninja" uniform = /obj/item/clothing/under/syndicate/ninja - glasses = /obj/item/clothing/glasses/night/colorless + glasses = /obj/item/clothing/glasses/night mask = /obj/item/clothing/mask/gas/ninja ears = /obj/item/radio/headset shoes = /obj/item/clothing/shoes/jackboots diff --git a/code/modules/antagonists/nukeop/outfits.dm b/code/modules/antagonists/nukeop/outfits.dm index 5be8f13f2fce..07f00f626db0 100644 --- a/code/modules/antagonists/nukeop/outfits.dm +++ b/code/modules/antagonists/nukeop/outfits.dm @@ -66,7 +66,7 @@ /datum/outfit/syndicate/full name = "Syndicate Operative - Full Kit" - glasses = /obj/item/clothing/glasses/night/colorless + glasses = /obj/item/clothing/glasses/night mask = /obj/item/clothing/mask/gas/syndicate back = /obj/item/mod/control/pre_equipped/nuclear r_pocket = /obj/item/tank/internals/emergency_oxygen/engi diff --git a/code/modules/antagonists/revenant/haunted_item.dm b/code/modules/antagonists/revenant/haunted_item.dm index 642002976cb6..bd1cac77fb72 100644 --- a/code/modules/antagonists/revenant/haunted_item.dm +++ b/code/modules/antagonists/revenant/haunted_item.dm @@ -7,6 +7,8 @@ var/despawn_message /// List of types that, if they hit our item, we will instantly stop the haunting var/list/types_which_dispell_us + /// List of traits which allow items outside of types_which_dispell_us to also work on us + var/list/traits_which_dispell_us /datum/component/haunted_item/Initialize( // What color should the haunted item be glowing? By default the color's white (passed into the haunted element). @@ -25,6 +27,9 @@ throw_force_max = 15, // See the types_which_dispell_us list. By default / if null, this will become the default static list. list/types_which_dispell_us, + // List of traits which allow items outside of types_which_dispell_us to also work on us + // By default / if null will default to TRAIT_NULLROD_ITEM + list/traits_which_dispell_us, ) if(!isitem(parent)) @@ -62,7 +67,9 @@ haunted_item.throwforce = min(haunted_item.throwforce + throw_force_bonus, throw_force_max) var/static/list/default_dispell_types = list(/obj/item/nullrod, /obj/item/book/bible) + var/static/list/default_dispell_traits = list(TRAIT_NULLROD_ITEM) src.types_which_dispell_us = types_which_dispell_us || default_dispell_types + src.traits_which_dispell_us = traits_which_dispell_us || default_dispell_traits src.despawn_message = despawn_message /datum/component/haunted_item/Destroy(force) @@ -94,7 +101,14 @@ SIGNAL_HANDLER if(!is_type_in_list(attacking_item, types_which_dispell_us)) - return + var/has_trait = FALSE + for(var/dispell_trait in traits_which_dispell_us) + if(HAS_TRAIT(attacking_item, dispell_trait)) + has_trait = TRUE + break + + if(!has_trait) + return attacker.visible_message(span_warning("[attacker] dispells the ghostly energy from [source]!"), span_warning("You dispel the ghostly energy from [source]!")) clear_haunting() diff --git a/code/modules/antagonists/space_dragon/carp_rift.dm b/code/modules/antagonists/space_dragon/carp_rift.dm index 05d712254e8e..432fba6e7ea6 100644 --- a/code/modules/antagonists/space_dragon/carp_rift.dm +++ b/code/modules/antagonists/space_dragon/carp_rift.dm @@ -278,6 +278,21 @@ update_light() return TRUE +/obj/structure/carp_rift/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers) + if(HAS_TRAIT(attacking_item, TRAIT_TELEKINESIS_CONTROLLED)) + if(user) + to_chat(user, span_warning("The gravitational field of [src] interferes with the telekenetic control of [user], nullifying the hit!")) + return FALSE + . = ..() + +/obj/structure/carp_rift/hitby(atom/movable/hit_by, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) + if(HAS_TRAIT(hit_by, TRAIT_TELEKINESIS_CONTROLLED)) + var/mob/thrower = throwingdatum.thrower.resolve() + if(thrower && ismob(thrower)) + to_chat(thrower, span_warning("The gravitational field of [src] interferes with the telekenetic control of [hit_by], nullifying the hit!")) + return + . = ..() + #undef CHARGE_ONGOING #undef CHARGE_FINALWARNING #undef CHARGE_COMPLETED diff --git a/code/modules/antagonists/spy/spy.dm b/code/modules/antagonists/spy/spy.dm index e39740bc1aab..d0297b9842c9 100644 --- a/code/modules/antagonists/spy/spy.dm +++ b/code/modules/antagonists/spy/spy.dm @@ -224,7 +224,7 @@ stack_trace("[type] created on invalid target [Target || "null"]") qdel(src) -/datum/action/backup_uplink/Trigger(trigger_flags) +/datum/action/backup_uplink/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm index bee49757a18f..4d90d4aa53bf 100644 --- a/code/modules/antagonists/wizard/equipment/artefact.dm +++ b/code/modules/antagonists/wizard/equipment/artefact.dm @@ -63,13 +63,13 @@ qdel(src) return PROCESS_KILL -/obj/effect/rend/attackby(obj/item/I, mob/user, list/modifiers, list/attack_modifiers) - if(istype(I, /obj/item/nullrod)) - user.visible_message(span_danger("[user] seals \the [src] with \the [I].")) - qdel(src) - return - else - return ..() +/obj/effect/rend/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!HAS_TRAIT(tool, TRAIT_NULLROD_ITEM)) + return NONE + + user.visible_message(span_danger("[user] seals \the [src] with \the [tool].")) + qdel(src) + return ITEM_INTERACT_SUCCESS /obj/effect/rend/singularity_act() return diff --git a/code/modules/antagonists/wizard/equipment/soulstone.dm b/code/modules/antagonists/wizard/equipment/soulstone.dm index 4db1dc6f3357..79798ec1f5e4 100644 --- a/code/modules/antagonists/wizard/equipment/soulstone.dm +++ b/code/modules/antagonists/wizard/equipment/soulstone.dm @@ -546,7 +546,7 @@ else make_new_construct(/mob/living/basic/construct/harvester, target, creator, cultoverride, loc_override) -/proc/make_new_construct(mob/living/basic/construct/ctype, mob/target, mob/stoner = null, cultoverride = FALSE, loc_override = null) +/proc/make_new_construct(mob/living/basic/construct/ctype, mob/target, mob/stoner = null, cultoverride = FALSE, loc_override = null, ghost_activated = FALSE) if(QDELETED(target)) return var/mob/living/basic/construct/newstruct = new ctype(loc_override || get_turf(target)) @@ -560,7 +560,13 @@ var/datum/action/innate/seek_master/seek_master = new seek_master.Grant(newstruct) - if (!target.ckey || isnull(target.mind) || is_banned_from(target.ckey, ROLE_CULTIST)) + if(ghost_activated) + if(isnull(target.mind)) + newstruct.PossessByPlayer(target.ckey) + else + target.mind.transfer_to(newstruct, force_key_move = TRUE) + + else if (!target.ckey || isnull(target.mind) || is_banned_from(target.ckey, ROLE_CULTIST)) to_chat(stoner, span_userdanger("Shell imbuement failed!")) to_chat(stoner, span_warning("The soul has already fled its mortal frame. You attempt to bring it back...")) target = SSpolling.poll_ghosts_for_target( @@ -593,7 +599,7 @@ var/atom/movable/screen/alert/bloodsense/sense_alert if(newstruct.mind && !IS_CULTIST(newstruct) && ((stoner && IS_CULTIST(stoner)) || cultoverride) && SSticker.HasRoundStarted()) newstruct.mind.add_antag_datum(/datum/antagonist/cult/construct) - if(IS_CULTIST(stoner) || cultoverride) + if(cultoverride || (stoner && IS_CULTIST(stoner))) to_chat(newstruct, span_cult_bold("You are still bound to serve the cult[stoner ? " and [stoner]" : ""], follow [stoner?.p_their() || "their"] orders and help [stoner?.p_them() || "them"] complete [stoner?.p_their() || "their"] goals at all costs.")) else if(stoner) to_chat(newstruct, span_boldwarning("You are still bound to serve your creator, [stoner], follow [stoner.p_their()] orders and help [stoner.p_them()] complete [stoner.p_their()] goals at all costs.")) diff --git a/code/modules/asset_cache/spritesheet/batched/batched_spritesheet.dm b/code/modules/asset_cache/spritesheet/batched/batched_spritesheet.dm index 9256231c0e8d..d537b20c7b16 100644 --- a/code/modules/asset_cache/spritesheet/batched/batched_spritesheet.dm +++ b/code/modules/asset_cache/spritesheet/batched/batched_spritesheet.dm @@ -189,10 +189,10 @@ var/data_out if(yield || !isnull(job_id)) if(isnull(job_id)) - job_id = rustg_iconforge_generate_async("data/spritesheets/", name, entries_json, do_cache) + job_id = rustg_iconforge_generate_async("data/spritesheets/", name, entries_json, do_cache, FALSE, TRUE) UNTIL((data_out = rustg_iconforge_check(job_id)) != RUSTG_JOB_NO_RESULTS_YET) else - data_out = rustg_iconforge_generate("data/spritesheets/", name, entries_json, do_cache) + data_out = rustg_iconforge_generate("data/spritesheets/", name, entries_json, do_cache, FALSE, TRUE) if (data_out == RUSTG_JOB_ERROR) CRASH("Spritesheet [name] JOB PANIC") else if(!findtext(data_out, "{", 1, 2)) @@ -232,7 +232,7 @@ CRASH("Error during spritesheet generation for [name]: [data["error"]]") /datum/asset/spritesheet_batched/queued_generation() - realize_spritesheets(yield = TRUE) + INVOKE_ASYNC(src, PROC_REF(realize_spritesheets), TRUE) // The proc is called inside a subsystem and waits with an UNTIL /datum/asset/spritesheet_batched/ensure_ready() if(!fully_generated) diff --git a/code/modules/asset_cache/spritesheet/batched/universal_icon.dm b/code/modules/asset_cache/spritesheet/batched/universal_icon.dm index 3f06001900b1..0ecdd1ea349f 100644 --- a/code/modules/asset_cache/spritesheet/batched/universal_icon.dm +++ b/code/modules/asset_cache/spritesheet/batched/universal_icon.dm @@ -10,7 +10,7 @@ var/datum/icon_transformer/transform /// Don't instantiate these yourself, use uni_icon. -/datum/universal_icon/New(icon/icon_file, icon_state="", dir=SOUTH, frame=1, datum/icon_transformer/transform=null, color=null) +/datum/universal_icon/New(icon/icon_file, icon_state="", dir=null, frame=null, datum/icon_transformer/transform=null, color=null) #ifdef UNIT_TESTS // This check is kinda slow and shouldn't fail unless a developer makes a mistake. So it'll get caught in unit tests. if(!isicon(icon_file) || !isfile(icon_file) || "[icon_file]" == "/icon" || !length("[icon_file]")) @@ -44,10 +44,10 @@ transform.blend_color(color, blend_mode) return src -/datum/universal_icon/proc/blend_icon(datum/universal_icon/icon_object, blend_mode) +/datum/universal_icon/proc/blend_icon(datum/universal_icon/icon_object, blend_mode, x=1, y=1) if(!transform) transform = new - transform.blend_icon(icon_object, blend_mode) + transform.blend_icon(icon_object, blend_mode, x, y) return src /datum/universal_icon/proc/scale(width, height) @@ -62,14 +62,116 @@ transform.crop(x1, y1, x2, y2) return src -/// Internally performs a crop. -/datum/universal_icon/proc/shift(dir, amount, icon_width, icon_height) +/datum/universal_icon/proc/flip(dir) if(!transform) transform = new - var/list/offsets = dir2offset(dir) - var/shift_x = -offsets[1] * amount - var/shift_y = -offsets[2] * amount - transform.crop(1 + shift_x, 1 + shift_y, icon_width + shift_x, icon_height + shift_y) + transform.flip(dir) + return src + +/datum/universal_icon/proc/rotate(angle) + if(!transform) + transform = new + transform.rotate(angle) + return src + +/datum/universal_icon/proc/shift(dir, offset, wrap=0) + if(!transform) + transform = new + transform.shift(dir, offset, wrap) + return src + +/datum/universal_icon/proc/swap_color(src_color, dst_color) + if(!transform) + transform = new + transform.swap_color(src_color, dst_color) + return src + +/datum/universal_icon/proc/draw_box(color, x1, y1, x2=x1, y2=y1) + if(!transform) + transform = new + transform.draw_box(color, x1, y1, x2, y2) + return src + +/datum/universal_icon/proc/map_colors_inferred(list/color_args) + var/num_args = length(color_args) + if(num_args <= 20 || num_args >= 16) + src.map_colors_rgba(arglist(color_args)) + else if(num_args <= 12 || num_args >= 9) + src.map_colors_rgb(arglist(color_args)) + else if(num_args == 5) + src.map_colors_rgba_hex(arglist(color_args)) + else if(num_args == 4) + // is there alpha in the hex? + if(length(color_args[3]) == 7 || length(color_args[3]) == 4) + src.map_colors_rgb_hex(arglist(color_args)) + else + src.map_colors_rgba_hex(arglist(color_args)) + else if(num_args == 3) + src.map_colors_rgb_hex(arglist(color_args)) + +/datum/universal_icon/proc/map_colors_rgba(rr, rg, rb, ra, gr, gg, gb, ga, br, bg, bb, ba, ar, ag, ab, aa, r0=0, g0=0, b0=0, a0=0) + if(!transform) + transform = new + transform.map_colors(rr, rg, rb, ra, gr, gg, gb, ga, br, bg, bb, ba, ar, ag, ab, aa, r0, g0, b0, a0) + return src + +/datum/universal_icon/proc/map_colors_rgb(rr, rg, rb, gr, gg, gb, br, bg, bb, r0=0, g0=0, b0=0) + if(!transform) + transform = new + transform.map_colors(rr, rg, rb, 0, gr, gg, gb, 0, br, bg, bb, 0, 0, 0, 0, 1, r0, g0, b0, 0) + return src + +/datum/universal_icon/proc/map_colors_rgb_hex(r_rgb, g_rgb, b_rgb, rgb0=rgb(0,0,0)) + if(!transform) + transform = new + var/rr = hex2num(copytext(r_rgb, 2, 4)) / 255 + var/rg = hex2num(copytext(r_rgb, 4, 6)) / 255 + var/rb = hex2num(copytext(r_rgb, 6, 8)) / 255 + + var/gr = hex2num(copytext(g_rgb, 2, 4)) / 255 + var/gg = hex2num(copytext(g_rgb, 4, 6)) / 255 + var/gb = hex2num(copytext(g_rgb, 6, 8)) / 255 + + var/br = hex2num(copytext(b_rgb, 2, 4)) / 255 + var/bg = hex2num(copytext(b_rgb, 4, 6)) / 255 + var/bb = hex2num(copytext(b_rgb, 6, 8)) / 255 + + var/r0 = hex2num(copytext(rgb0, 2, 4)) / 255 + var/b0 = hex2num(copytext(rgb0, 4, 6)) / 255 + var/g0 = hex2num(copytext(rgb0, 6, 8)) / 255 + + transform.map_colors(rr, rg, rb, 0, gr, gg, gb, 0, br, bg, bb, 0, 0, 0, 0, 1, r0, b0, g0, 0) + return src + +/datum/universal_icon/proc/map_colors_rgba_hex(r_rgba, g_rgba, b_rgba, a_rgba, rgba0="#00000000") + if(!transform) + transform = new + var/rr = hex2num(copytext(r_rgba, 2, 4)) / 255 + var/rg = hex2num(copytext(r_rgba, 4, 6)) / 255 + var/rb = hex2num(copytext(r_rgba, 6, 8)) / 255 + var/ra = hex2num(copytext(r_rgba, 8, 10)) / 255 + + var/gr = hex2num(copytext(g_rgba, 2, 4)) / 255 + var/gg = hex2num(copytext(g_rgba, 4, 6)) / 255 + var/gb = hex2num(copytext(g_rgba, 6, 8)) / 255 + var/ga = hex2num(copytext(g_rgba, 8, 10)) / 255 + + var/br = hex2num(copytext(b_rgba, 2, 4)) / 255 + var/bg = hex2num(copytext(b_rgba, 4, 6)) / 255 + var/bb = hex2num(copytext(b_rgba, 6, 8)) / 255 + var/ba = hex2num(copytext(b_rgba, 8, 10)) / 255 + + var/ar = hex2num(copytext(a_rgba, 2, 4)) / 255 + var/ag = hex2num(copytext(a_rgba, 4, 6)) / 255 + var/ab = hex2num(copytext(a_rgba, 6, 8)) / 255 + var/aa = hex2num(copytext(a_rgba, 8, 10)) / 255 + + var/r0 = hex2num(copytext(rgba0, 2, 4)) / 255 + var/b0 = hex2num(copytext(rgba0, 4, 6)) / 255 + var/g0 = hex2num(copytext(rgba0, 6, 8)) / 255 + var/a0 = hex2num(copytext(rgba0, 8, 10)) / 255 + + transform.map_colors(rr, rg, rb, ra, gr, gg, gb, ga, br, bg, bb, ba, ar, ag, ab, aa, r0, b0, g0, a0) return src /// Internally performs a color blend. @@ -118,11 +220,29 @@ if(!istype(icon_object)) stack_trace("Invalid icon found in icon transformer during apply()! [icon_object]") continue - target.Blend(icon_object.to_icon(), transform["blend_mode"]) + target.Blend(icon_object.to_icon(), transform["blend_mode"], transform["x"], transform["y"]) if(RUSTG_ICONFORGE_SCALE) target.Scale(transform["width"], transform["height"]) if(RUSTG_ICONFORGE_CROP) target.Crop(transform["x1"], transform["y1"], transform["x2"], transform["y2"]) + if(RUSTG_ICONFORGE_MAP_COLORS) + target.MapColors( + transform["rr"], transform["rg"], transform["rb"], transform["ra"], + transform["gr"], transform["gg"], transform["gb"], transform["ga"], + transform["br"], transform["bg"], transform["bb"], transform["ba"], + transform["ar"], transform["ag"], transform["ab"], transform["aa"], + transform["r0"], transform["g0"], transform["b0"], transform["a0"], + ) + if(RUSTG_ICONFORGE_FLIP) + target.Flip(transform["dir"]) + if(RUSTG_ICONFORGE_TURN) + target.Turn(transform["angle"]) + if(RUSTG_ICONFORGE_SHIFT) + target.Shift(transform["dir"], transform["offset"], transform["wrap"]) + if(RUSTG_ICONFORGE_SWAP_COLOR) + target.SwapColor(transform["src_color"], transform["dst_color"]) + if(RUSTG_ICONFORGE_DRAW_BOX) + target.DrawBox(transform["color"], transform["x1"], transform["y1"], transform["x2"], transform["y2"]) return target /datum/icon_transformer/proc/copy() @@ -142,13 +262,17 @@ #endif transforms += list(list("type" = RUSTG_ICONFORGE_BLEND_COLOR, "color" = color, "blend_mode" = blend_mode)) -/datum/icon_transformer/proc/blend_icon(datum/universal_icon/icon_object, blend_mode) +/datum/icon_transformer/proc/blend_icon(datum/universal_icon/icon_object, blend_mode, x=1, y=1) #ifdef UNIT_TESTS // icon_object's type is checked later in to_list if(!isnum(blend_mode)) CRASH("Invalid blend_mode provided to blend_icon: [blend_mode]") + if(!isnum(x)) + CRASH("Invalid x offset provided to blend_icon: [x]") + if(!isnum(y)) + CRASH("Invalid y offset provided to blend_icon: [y]") #endif - transforms += list(list("type" = RUSTG_ICONFORGE_BLEND_ICON, "icon" = icon_object, "blend_mode" = blend_mode)) + transforms += list(list("type" = RUSTG_ICONFORGE_BLEND_ICON, "icon" = icon_object, "blend_mode" = blend_mode, "x" = x, "y" = y)) /datum/icon_transformer/proc/scale(width, height) #ifdef UNIT_TESTS @@ -164,6 +288,51 @@ #endif transforms += list(list("type" = RUSTG_ICONFORGE_CROP, "x1" = x1, "y1" = y1, "x2" = x2, "y2" = y2)) +/datum/icon_transformer/proc/flip(dir) + #ifdef UNIT_TESTS + if(!isnum(dir)) + CRASH("Invalid arguments provided to flip: [dir]") + #endif + transforms += list(list("type" = RUSTG_ICONFORGE_FLIP, "dir" = dir)) + +/datum/icon_transformer/proc/rotate(angle) + #ifdef UNIT_TESTS + if(!isnum(angle)) + CRASH("Invalid arguments provided to rotate: [angle]") + #endif + transforms += list(list("type" = RUSTG_ICONFORGE_TURN, "angle" = angle)) + +/datum/icon_transformer/proc/shift(dir, offset, wrap=FALSE) + #ifdef UNIT_TESTS + if(!isnum(dir) || !isnum(offset) || (wrap != FALSE && wrap != TRUE)) + CRASH("Invalid arguments provided to shift: [dir],[offset],[wrap]") + #endif + transforms += list(list("type" = RUSTG_ICONFORGE_SHIFT, "dir" = dir, "offset" = offset, "wrap" = wrap)) + +/datum/icon_transformer/proc/swap_color(src_color, dst_color) + #ifdef UNIT_TESTS + if(!istext(src_color) || !istext(dst_color)) + CRASH("Invalid arguments provided to swap_color: [src_color],[dst_color]") + #endif + transforms += list(list("type" = RUSTG_ICONFORGE_SWAP_COLOR, "src_color" = src_color, "dst_color" = dst_color)) + +/datum/icon_transformer/proc/draw_box(color, x1, y1, x2=x1, y2=y1) + #ifdef UNIT_TESTS + if(!istext(color) || !isnum(x1) || !isnum(y1) || !isnum(x2) || !isnum(y2)) + CRASH("Invalid arguments provided to draw_box: [color],[x1],[y1],[x2],[y2]") + #endif + transforms += list(list("type" = RUSTG_ICONFORGE_DRAW_BOX, "color" = color, "x1" = x1, "y1" = y1, "x2" = x2, "y2" = y2)) + +/datum/icon_transformer/proc/map_colors(rr, rg, rb, ra, gr, gg, gb, ga, br, bg, bb, ba, ar, ag, ab, aa, r0=0, g0=0, b0=0, a0=0) + transforms += list(list( + "type" = RUSTG_ICONFORGE_MAP_COLORS, + "rr" = rr, "rg" = rg, "rb" = rb, "ra" = ra, + "gr" = gr, "gg" = gg, "gb" = gb, "ga" = ga, + "br" = br, "bg" = bg, "bb" = bb, "ba" = ba, + "ar" = ar, "ag" = ag, "ab" = ab, "aa" = aa, + "r0" = r0, "g0" = g0, "b0" = b0, "a0" = a0, + )) + /// Recursively converts all contained [/datum/universal_icon]s and their associated [/datum/icon_transformer]s into list form so the transforms can be JSON encoded. /datum/icon_transformer/proc/to_list() RETURN_TYPE(/list) @@ -218,21 +387,19 @@ /proc/get_display_icon_for(atom/atom_path) if (!ispath(atom_path, /atom)) return FALSE - var/icon_file = initial(atom_path.icon) - var/icon_state = initial(atom_path.icon_state) - if(initial(atom_path.greyscale_config) && initial(atom_path.greyscale_colors)) + var/icon_file = atom_path::icon + var/icon_state = atom_path::icon_state + if(atom_path::greyscale_config && atom_path::greyscale_colors) return gags_to_universal_icon(atom_path) if(ispath(atom_path, /obj)) var/obj/obj_path = atom_path - if(initial(obj_path.icon_state_preview)) - icon_state = initial(obj_path.icon_state_preview) - return uni_icon(icon_file, icon_state, color=initial(atom_path.color)) + if(obj_path::icon_state_preview) + icon_state = obj_path::icon_state_preview + return uni_icon(icon_file, icon_state, color=atom_path::color) /// getFlatIcon for [/datum/universal_icon]s -/// Only supports 32x32 icons facing south -/// Tough luck if you want anything else /// Still fairly slow for complex appearances due to filesystem operations. Try to avoid using it -/proc/get_flat_uni_icon(image/appearance, deficon, defstate, defblend, start = TRUE, parentcolor) +/proc/get_flat_uni_icon(image/appearance, defdir, deficon, defstate, defblend, start = TRUE, parentcolor) // Loop through the underlays, then overlays, sorting them into the layers list #define PROCESS_OVERLAYS_OR_UNDERLAYS(flat, process, base_layer) \ for (var/i in 1 to process.len) { \ @@ -283,7 +450,7 @@ var/curstate = appearance.icon_state || defstate // Filter out 'runtime' icons (server-generated RSC cache icons) // Write the icon to the filesystem so it can be used by iconforge - if(!isfile(curicon) || string_curicon == "/icon" || string_curicon == "/image" || !length(string_curicon)) + if(!isfile(curicon) || !length(string_curicon)) var/file_path_tmp = "tmp/uni_icon-tmp-[rand(1, 999)].dmi" // this filename is temporary. fcopy(curicon, file_path_tmp) var/file_hash = rustg_hash_file(RUSTG_HASH_MD5, file_path_tmp) @@ -293,21 +460,51 @@ fdel(file_path_tmp) // delete the old one curicon = file(file_path) - var/curblend = appearance.blend_mode || defblend - var/list/curstates = icon_states(curicon) - if(!(curstate in curstates)) - if("" in curstates) // BYOND defaulting functionality + if(!icon_exists(curicon, curstate)) + if("" in icon_states_fast(curicon)) // BYOND defaulting functionality curstate = "" else should_display = FALSE + var/curdir = (!appearance.dir || appearance.dir == SOUTH) ? defdir : appearance.dir + var/base_icon_dir //We'll use this to get the icon state to display if not null BUT NOT pass it to overlays as the dir we have + + if(should_display) + //Determines if there're directionals. + if (curdir != SOUTH) + // icon states either have 1, 4 or 8 dirs. We only have to check + // one of NORTH, EAST or WEST to know that this isn't a 1-dir icon_state since they just have SOUTH. + var/list/metadata = icon_metadata(curicon) + if(islist(metadata)) + for(var/list/state_data as anything in metadata["states"]) + var/name = state_data["name"] + if(name != curstate) + continue + var/dir_count = state_data["dirs"] + if(dir_count == 1) + base_icon_dir = SOUTH + else if(!length(icon_states(icon(curicon, curstate, NORTH)))) + base_icon_dir = SOUTH + + var/list/icon_dimensions = get_icon_dimensions(curicon) + var/icon_width = icon_dimensions["width"] + var/icon_height = icon_dimensions["height"] + if(icon_width != 32 || icon_height != 32) + flat.scale(icon_width, icon_height) + + if(!base_icon_dir) + base_icon_dir = curdir + + var/curblend = appearance.blend_mode || defblend + + if(appearance.overlays.len || appearance.underlays.len) // Layers will be a sorted list of icons/overlays, based on the order in which they are displayed var/list/layers = list() var/image/copy if(should_display) // Add the atom's icon itself, without pixel_x/y offsets. - copy = image(icon=curicon, icon_state=curstate, layer=appearance.layer, dir=SOUTH) + copy = image(icon=curicon, icon_state=curstate, layer=appearance.layer, dir=base_icon_dir) copy.color = appearance.color copy.alpha = appearance.alpha copy.blend_mode = curblend @@ -318,15 +515,26 @@ var/datum/universal_icon/add // Icon of overlay being added + var/list/flat_dimensions = get_icon_dimensions(flat) + var/flatX1 = 1 + var/flatX2 = flat_dimensions["width"] + var/flatY1 = 1 + var/flatY2 = flat_dimensions["height"] + + var/addX1 = 0 + var/addX2 = 0 + var/addY1 = 0 + var/addY2 = 0 + if(appearance.color) if(islist(appearance.color)) - stack_trace("Unsupported color map appearance provided to get_flat_uni_icon, ignoring it.") + flat.map_colors_inferred(appearance.color) else flat.blend_color(appearance.color, ICON_MULTIPLY) if(parentcolor && !(appearance.appearance_flags & RESET_COLOR)) if(islist(parentcolor)) - stack_trace("Unsupported color map appearance provided to get_flat_uni_icon, ignoring it.") + flat.map_colors_inferred(parentcolor) else flat.blend_color(parentcolor, ICON_MULTIPLY) @@ -338,19 +546,45 @@ if(layer_image == copy && length("[layer_image.icon]")) // 'layer_image' is an /image based on the object being flattened, and isn't a 'runtime' icon. curblend = BLEND_OVERLAY - add = uni_icon(layer_image.icon, layer_image.icon_state, SOUTH) + add = uni_icon(layer_image.icon, layer_image.icon_state, base_icon_dir) if(appearance.color) if(islist(appearance.color)) - stack_trace("Unsupported color map appearance provided to get_flat_uni_icon, ignoring it.") + add.map_colors_inferred(appearance.color) else add.blend_color(appearance.color, ICON_MULTIPLY) else // 'layer_image' is an appearance object. - add = get_flat_uni_icon(layer_image, curicon, curstate, curblend, FALSE, next_parentcolor) + add = get_flat_uni_icon(layer_image, curdir, curicon, curstate, curblend, FALSE, next_parentcolor) if(!add || !length(add.icon_file)) continue + // Find the new dimensions of the flat icon to fit the added overlay + var/list/add_dimensions = get_icon_dimensions(add) + addX1 = min(flatX1, layer_image.pixel_x + layer_image.pixel_w + 1) + addX2 = max(flatX2, layer_image.pixel_x + layer_image.pixel_w + add_dimensions["width"]) // assuming 32x32 + addY1 = min(flatY1, layer_image.pixel_y + layer_image.pixel_z + 1) + addY2 = max(flatY2, layer_image.pixel_y + layer_image.pixel_z + add_dimensions["height"]) + + if ( + addX1 != flatX1 \ + && addX2 != flatX2 \ + && addY1 != flatY1 \ + && addY2 != flatY2 \ + ) + // Resize the flattened icon so the new icon fits + flat.crop( + addX1 - flatX1 + 1, + addY1 - flatY1 + 1, + addX2 - flatX1 + 1, + addY2 - flatY1 + 1 + ) + + flatX1 = addX1 + flatX2 = addY1 + flatY1 = addX2 + flatY2 = addY2 + // Blend the overlay into the flattened icon - flat.blend_icon(add, blendMode2iconMode(curblend)) + flat.blend_icon(add, blendMode2iconMode(curblend), layer_image.pixel_x + layer_image.pixel_w + 2 - flatX1, layer_image.pixel_y + layer_image.pixel_z + 2 - flatY1) if(appearance.alpha < 255) flat.blend_color(rgb(255, 255, 255, appearance.alpha), ICON_MULTIPLY) @@ -358,14 +592,14 @@ return flat else if(should_display) // There's no overlays. - var/datum/universal_icon/final_icon = uni_icon(curicon, curstate, SOUTH) + var/datum/universal_icon/final_icon = uni_icon(curicon, curstate, base_icon_dir) if (appearance.alpha < 255) final_icon.blend_color(rgb(255,255,255, appearance.alpha), ICON_MULTIPLY) if (appearance.color) if (islist(appearance.color)) - stack_trace("Unsupported color map appearance provided to get_flat_uni_icon, ignoring it.") + final_icon.map_colors_inferred(appearance.color) else final_icon.blend_color(appearance.color, ICON_MULTIPLY) diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm index 45371190a15c..7a76dc6ec4ea 100644 --- a/code/modules/atmospherics/gasmixtures/reactions.dm +++ b/code/modules/atmospherics/gasmixtures/reactions.dm @@ -555,8 +555,8 @@ ASSERT_GAS(/datum/gas/nitrogen, air) ASSERT_GAS(/datum/gas/oxygen, air) var/amount_decomposed = 0.4 * bz_formed * nitrous_oxide_decomposed_factor - cached_gases[/datum/gas/nitrogen] += amount_decomposed - cached_gases[/datum/gas/oxygen] += 0.5 * amount_decomposed + cached_gases[/datum/gas/nitrogen][MOLES] += amount_decomposed + cached_gases[/datum/gas/oxygen][MOLES] += 0.5 * amount_decomposed ASSERT_GAS(/datum/gas/bz, air) cached_gases[/datum/gas/bz][MOLES] += bz_formed * (1-nitrous_oxide_decomposed_factor) diff --git a/code/modules/atmospherics/machinery/components/components_base.dm b/code/modules/atmospherics/machinery/components/components_base.dm index 74bbfca0bdff..23babb68c963 100644 --- a/code/modules/atmospherics/machinery/components/components_base.dm +++ b/code/modules/atmospherics/machinery/components/components_base.dm @@ -71,7 +71,7 @@ underlays.Cut() color = null - var/uncovered_turf = HAS_TRAIT(loc, TRAIT_UNCOVERED_TURF) + var/uncovered_turf = loc && HAS_TRAIT(loc, TRAIT_UNCOVERED_TURF) SET_PLANE_IMPLICIT(src, (underfloor_state == UNDERFLOOR_INTERACTABLE && !uncovered_turf) ? GAME_PLANE : FLOOR_PLANE) // Layer is handled in update_layer() @@ -112,7 +112,7 @@ /obj/machinery/atmospherics/components/get_pipe_image(iconfile, iconstate, direction, color, piping_layer, trinary) var/mutable_appearance/pipe_appearance = ..() - if (underfloor_state == UNDERFLOOR_VISIBLE || HAS_TRAIT(loc, TRAIT_UNCOVERED_TURF)) + if (underfloor_state == UNDERFLOOR_VISIBLE || (loc && HAS_TRAIT(loc, TRAIT_UNCOVERED_TURF))) pipe_appearance.layer = BELOW_CATWALK_LAYER + get_pipe_layer_offset() SET_PLANE_EXPLICIT(pipe_appearance, FLOOR_PLANE, src) return pipe_appearance diff --git a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm index 72c322621ac3..8e5fccbde95f 100644 --- a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm +++ b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm @@ -75,8 +75,10 @@ return ..() /obj/machinery/portable_atmospherics/Destroy() - disconnect() + disconnect(destroyed = TRUE) air_contents = null + if(holding) + unregister_holding() SSair.stop_processing_machine(src) return ..() @@ -194,12 +196,15 @@ /** * Allow the portable machine to be disconnected from the connector */ -/obj/machinery/portable_atmospherics/proc/disconnect() +/obj/machinery/portable_atmospherics/proc/disconnect(destroyed = FALSE) if(!connected_port) return FALSE - set_anchored(FALSE) connected_port.connected_device = null connected_port = null + if (destroyed) + return TRUE + + set_anchored(FALSE) pixel_x = 0 pixel_y = 0 diff --git a/code/modules/bitrunning/abilities.dm b/code/modules/bitrunning/abilities.dm index ea6a1aa0a7cf..531f10d5ed16 100644 --- a/code/modules/bitrunning/abilities.dm +++ b/code/modules/bitrunning/abilities.dm @@ -31,7 +31,7 @@ . = ..() name = "Open Domain Information" -/datum/action/avatar_domain_info/Trigger(trigger_flags) +/datum/action/avatar_domain_info/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return diff --git a/code/modules/bitrunning/designs.dm b/code/modules/bitrunning/designs.dm deleted file mode 100644 index 96ae65d41e99..000000000000 --- a/code/modules/bitrunning/designs.dm +++ /dev/null @@ -1,74 +0,0 @@ -// Quantum server - -/obj/item/circuitboard/machine/quantum_server - name = "Quantum Server" - greyscale_colors = CIRCUIT_COLOR_SUPPLY - build_path = /obj/machinery/quantum_server - req_components = list( - /datum/stock_part/servo = 2, - /datum/stock_part/scanning_module = 1, - /datum/stock_part/capacitor = 1, - ) - -/** - * quantum server design - * are you absolutely sure?? - */ - -// Netpod - -/obj/item/circuitboard/machine/netpod - name = "Netpod" - greyscale_colors = CIRCUIT_COLOR_SUPPLY - build_path = /obj/machinery/netpod - req_components = list( - /datum/stock_part/servo = 1, - /datum/stock_part/matter_bin = 2, - ) - -/datum/design/board/netpod - name = "Netpod Board" - desc = "The circuit board for a netpod." - id = "netpod" - build_path = /obj/item/circuitboard/machine/netpod - category = list( - RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_CARGO - ) - departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING - -// Quantum console - -/obj/item/circuitboard/computer/quantum_console - name = "Quantum Console" - greyscale_colors = CIRCUIT_COLOR_SUPPLY - build_path = /obj/machinery/computer/quantum_console - -/datum/design/board/quantum_console - name = "Quantum Console Board" - desc = "Allows for the construction of circuit boards used to build a Quantum Console." - id = "quantum_console" - build_path = /obj/item/circuitboard/computer/quantum_console - category = list( - RND_CATEGORY_COMPUTER + RND_SUBCATEGORY_COMPUTER_CARGO - ) - departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING - -// Byteforge - -/obj/item/circuitboard/machine/byteforge - name = "Byteforge" - greyscale_colors = CIRCUIT_COLOR_SUPPLY - build_path = /obj/machinery/byteforge - req_components = list( - /datum/stock_part/micro_laser = 1, - ) - -/datum/design/board/byteforge - name = "Byteforge Board" - desc = "Allows for the construction of circuit boards used to build a Byteforge." - id = "byteforge" - build_path = /obj/item/circuitboard/machine/byteforge - category = list( - RND_CATEGORY_COMPUTER + RND_SUBCATEGORY_COMPUTER_CARGO - ) - departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING diff --git a/code/modules/bitrunning/netpod/_netpod.dm b/code/modules/bitrunning/netpod/_netpod.dm index 2208c56a7414..e372f004255f 100644 --- a/code/modules/bitrunning/netpod/_netpod.dm +++ b/code/modules/bitrunning/netpod/_netpod.dm @@ -48,9 +48,37 @@ QDEL_LIST(cached_outfits) +/obj/machinery/netpod/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = ..() + + if(isnull(held_item)) + context[SCREENTIP_CONTEXT_LMB] = "Select Outfit" + return CONTEXTUAL_SCREENTIP_SET + + if(held_item.tool_behaviour == TOOL_SCREWDRIVER && !occupant && !state_open) + context[SCREENTIP_CONTEXT_LMB] = "[panel_open ? "Close" : "Open"] Panel" + return CONTEXTUAL_SCREENTIP_SET + + if(held_item.tool_behaviour == TOOL_CROWBAR) + if(isnull(occupant)) + if(panel_open) + context[SCREENTIP_CONTEXT_LMB] = "Deconstruct" + else + context[SCREENTIP_CONTEXT_LMB] = "[state_open ? "Close" : "Open"] Cover" + else + context[SCREENTIP_CONTEXT_LMB] = "Break out" + return CONTEXTUAL_SCREENTIP_SET + /obj/machinery/netpod/examine(mob/user) . = ..() + . += span_notice("Its maintainance panel can be [EXAMINE_HINT("screwed")] [panel_open ? "close" : "open"].") + if(isnull(occupant)) + if(panel_open) + . += span_notice("It can be [EXAMINE_HINT("pried")] apart.") + else + . += span_notice("Its hatch can be [EXAMINE_HINT("pried")] [state_open ? "closed" : "open"]") + if(isnull(server_ref?.resolve())) . += span_infoplain("It's not connected to anything.") . += span_infoplain("Netpods must be built within 4 tiles of a server.") @@ -74,18 +102,6 @@ . += span_notice("It can be pried open with a crowbar, but its safety mechanisms will alert the occupant.") -/obj/machinery/netpod/add_context(atom/source, list/context, obj/item/held_item, mob/user) - . = ..() - - if(isnull(held_item)) - context[SCREENTIP_CONTEXT_LMB] = "Select Outfit" - return CONTEXTUAL_SCREENTIP_SET - - if(istype(held_item, /obj/item/crowbar) && occupant) - context[SCREENTIP_CONTEXT_LMB] = "Pry Open" - return CONTEXTUAL_SCREENTIP_SET - - /obj/machinery/netpod/update_icon_state() if(!is_operational) icon_state = base_icon_state diff --git a/code/modules/bitrunning/objects/byteforge.dm b/code/modules/bitrunning/objects/byteforge.dm index cc18d2011a29..29ca48d0af18 100644 --- a/code/modules/bitrunning/objects/byteforge.dm +++ b/code/modules/bitrunning/objects/byteforge.dm @@ -5,6 +5,7 @@ desc = "A machine used by the quantum server. Quantum code converges here, materializing decrypted assets from the virtual abyss." icon = 'icons/obj/machines/bitrunning.dmi' icon_state = "byteforge" + base_icon_state = "byteforge" obj_flags = BLOCKS_CONSTRUCTION | CAN_BE_HIT /// Idle particles var/mutable_appearance/byteforge_particles @@ -12,18 +13,49 @@ /obj/machinery/byteforge/Initialize(mapload) . = ..() - return INITIALIZE_HINT_LATELOAD + register_context() /obj/machinery/byteforge/post_machine_initialize() . = ..() setup_particles() +/obj/machinery/byteforge/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = NONE + if(isnull(held_item)) + return + + if(held_item.tool_behaviour == TOOL_SCREWDRIVER) + context[SCREENTIP_CONTEXT_LMB] = "[panel_open ? "Close" : "Open"] Panel" + return CONTEXTUAL_SCREENTIP_SET + else if(held_item.tool_behaviour == TOOL_CROWBAR && panel_open) + context[SCREENTIP_CONTEXT_LMB] = "Deconstruct" + return CONTEXTUAL_SCREENTIP_SET + +/obj/machinery/byteforge/examine(mob/user) + . = ..() + + . += span_notice("Make sure this is 4 tiles from the quantum server") + + . += span_notice("Its maintainance panel can be [EXAMINE_HINT("screwed")] [panel_open ? "close" : "open"].") + if(panel_open) + . += span_notice("It can be [EXAMINE_HINT("pried")] apart.") + /obj/machinery/byteforge/update_appearance(updates) . = ..() setup_particles() +/obj/machinery/byteforge/screwdriver_act(mob/living/user, obj/item/screwdriver) + . = ITEM_INTERACT_FAILURE + if(default_deconstruction_screwdriver(user, "[base_icon_state]_panel", base_icon_state, screwdriver)) + return ITEM_INTERACT_SUCCESS + +/obj/machinery/byteforge/crowbar_act(mob/living/user, obj/item/crowbar) + . = ITEM_INTERACT_FAILURE + if(default_deconstruction_crowbar(crowbar)) + return ITEM_INTERACT_SUCCESS + /// Does some sparks after it's done /obj/machinery/byteforge/proc/flash(atom/movable/thing) playsound(src, 'sound/effects/magic/blink.ogg', 50, TRUE) diff --git a/code/modules/bitrunning/objects/quantum_console.dm b/code/modules/bitrunning/objects/quantum_console.dm index 71b952c46e19..d79ae60c3a70 100644 --- a/code/modules/bitrunning/objects/quantum_console.dm +++ b/code/modules/bitrunning/objects/quantum_console.dm @@ -16,6 +16,11 @@ . = ..() find_server() +/obj/machinery/computer/quantum_console/examine(mob/user) + . = ..() + if(!server_ref) + . += span_warning("Please install an quantum server in any tile next to this console.") + /obj/machinery/computer/quantum_console/ui_interact(mob/user, datum/tgui/ui) . = ..() diff --git a/code/modules/bitrunning/server/_parent.dm b/code/modules/bitrunning/server/_parent.dm index 09ea24ae2dae..71e02f45a1c4 100644 --- a/code/modules/bitrunning/server/_parent.dm +++ b/code/modules/bitrunning/server/_parent.dm @@ -51,6 +51,9 @@ /// Cooldown for how often you're allowed to harass deadchat for PVP domains COOLDOWN_DECLARE(polling_cooldown) +/obj/machinery/quantum_server/Initialize(mapload) + . = ..() + register_context() /obj/machinery/quantum_server/post_machine_initialize() . = ..() @@ -58,7 +61,6 @@ RegisterSignals(src, list(COMSIG_MACHINERY_BROKEN, COMSIG_MACHINERY_POWER_LOST), PROC_REF(on_broken)) RegisterSignal(src, COMSIG_QDELETING, PROC_REF(on_delete)) - /obj/machinery/quantum_server/Destroy(force) mutation_candidate_refs.Cut() avatar_connection_refs.Cut() @@ -67,11 +69,27 @@ QDEL_NULL(generated_domain) return ..() +/obj/machinery/quantum_server/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = NONE + if(isnull(held_item)) + return + + if(held_item.tool_behaviour == TOOL_SCREWDRIVER) + context[SCREENTIP_CONTEXT_LMB] = "[panel_open ? "Close" : "Open"] Panel" + return CONTEXTUAL_SCREENTIP_SET + else if(held_item.tool_behaviour == TOOL_CROWBAR && panel_open) + context[SCREENTIP_CONTEXT_LMB] = "Deconstruct" + return CONTEXTUAL_SCREENTIP_SET + /obj/machinery/quantum_server/examine(mob/user) . = ..() . += span_infoplain("Can be resource intensive to run. Ensure adequate power supply.") + . += span_notice("Its maintainance panel can be [EXAMINE_HINT("screwed")] [panel_open ? "close" : "open"].") + if(panel_open) + . += span_notice("It can be [EXAMINE_HINT("pried")] apart.") + var/upgraded = FALSE if(capacitor_coefficient < 1) . += span_infoplain("- Its coolant capacity reduces cooldown time by [(1 - capacitor_coefficient) * 100]%.") @@ -138,29 +156,23 @@ /obj/machinery/quantum_server/crowbar_act(mob/living/user, obj/item/crowbar) - . = ..() - + . = NONE if(!is_ready) balloon_alert(user, "it's scalding hot!") - return TRUE + return ITEM_INTERACT_FAILURE if(length(avatar_connection_refs)) balloon_alert(user, "all clients must disconnect!") - return TRUE + return ITEM_INTERACT_FAILURE if(default_deconstruction_crowbar(crowbar)) - return TRUE - return FALSE - + return ITEM_INTERACT_SUCCESS /obj/machinery/quantum_server/screwdriver_act(mob/living/user, obj/item/screwdriver) - . = ..() - + . = NONE if(!is_ready) balloon_alert(user, "it's scalding hot!") - return TRUE - if(default_deconstruction_screwdriver(user, "[base_icon_state]_panel", icon_state, screwdriver)) - return TRUE - return FALSE - + return ITEM_INTERACT_FAILURE + if(default_deconstruction_screwdriver(user, "[base_icon_state]_panel", base_icon_state, screwdriver)) + return ITEM_INTERACT_SUCCESS /obj/machinery/quantum_server/RefreshParts() var/capacitor_rating = 1.15 diff --git a/code/modules/cargo/markets/market_items/misc.dm b/code/modules/cargo/markets/market_items/misc.dm index 057d94264ae4..69bfef56fe01 100644 --- a/code/modules/cargo/markets/market_items/misc.dm +++ b/code/modules/cargo/markets/market_items/misc.dm @@ -185,7 +185,7 @@ /datum/market_item/misc/girlypop/spawn_item(loc, datum/market_purchase/purchase) . = ..() - var/obj/structure/closet/crate/pink/C = new(loc) + var/obj/structure/closet/crate/glitter/C = new(loc) for (var/type in list( /obj/item/poster/contraband/dream, /obj/item/poster/contraband/beekind, diff --git a/code/modules/cargo/markets/market_uplink.dm b/code/modules/cargo/markets/market_uplink.dm index 3c60bc29a7b6..9a5509b5e8b6 100644 --- a/code/modules/cargo/markets/market_uplink.dm +++ b/code/modules/cargo/markets/market_uplink.dm @@ -165,7 +165,7 @@ /datum/crafting_recipe/blackmarket_uplink name = "Black Market Uplink" result = /obj/item/market_uplink/blackmarket - time = 30 + time = 3 SECONDS tool_behaviors = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER, TOOL_MULTITOOL) reqs = list( /obj/item/stock_parts/micro_laser = 1, diff --git a/code/modules/cargo/packs/medical.dm b/code/modules/cargo/packs/medical.dm index 53b463850654..2cae5797fa2d 100644 --- a/code/modules/cargo/packs/medical.dm +++ b/code/modules/cargo/packs/medical.dm @@ -212,3 +212,17 @@ crate_name = "body freezer" crate_type = /obj/structure/closet/crate/secure/freezer +/datum/supply_pack/medical/organ_growing + name = "Organ Growing Kit" + desc = "All the tools you need to grow organs at home! Besides letting you grow standard organs from tissue samples, \ + you might find mutant cells which can be further proliferated to grow strange properties." + cost = CARGO_CRATE_VALUE * 5 + contains = list( + /obj/machinery/vatgrower/small/unanchored, + /obj/item/biopsy_tool/organ, + /obj/item/storage/box/petridish, + /obj/structure/microscope/unanchored, + /obj/item/reagent_containers/cup/mortar, + /obj/item/pestle, + ) + crate_name = "organ growing kit" diff --git a/code/modules/cargo/packs/science.dm b/code/modules/cargo/packs/science.dm index fe85c3c07a81..51a01c4b8a16 100644 --- a/code/modules/cargo/packs/science.dm +++ b/code/modules/cargo/packs/science.dm @@ -169,7 +169,7 @@ name = "Cytology supplies crate" desc = "Did out-of-control specimens pulverize xenobiology? Here's some more \ supplies for further testing. Contains a microscope, biopsy tool, two petri dishes, \ - a box of swabs, and a plumbing tool." + and a box of swabs." cost = CARGO_CRATE_VALUE * 3 access_view = ACCESS_XENOBIOLOGY contains = list(/obj/structure/microscope, diff --git a/code/modules/client/preferences/species_features/basic.dm b/code/modules/client/preferences/species_features/basic.dm index 876d3a3c45d2..b33f2818bdaf 100644 --- a/code/modules/client/preferences/species_features/basic.dm +++ b/code/modules/client/preferences/species_features/basic.dm @@ -10,7 +10,7 @@ var/datum/universal_icon/head_accessory_icon = uni_icon(sprite_accessory.icon, sprite_accessory.icon_state) if(y_offset) - head_accessory_icon.shift(NORTH, y_offset, ICON_SIZE_X, ICON_SIZE_Y) + head_accessory_icon.shift(NORTH, y_offset) head_accessory_icon.blend_color(COLOR_DARK_BROWN, ICON_MULTIPLY) final_icon.blend_icon(head_accessory_icon, ICON_OVERLAY) diff --git a/code/modules/clothing/chameleon/_chameleon_outfit.dm b/code/modules/clothing/chameleon/_chameleon_outfit.dm index df5f3056ac5c..3d53bcd79f48 100644 --- a/code/modules/clothing/chameleon/_chameleon_outfit.dm +++ b/code/modules/clothing/chameleon/_chameleon_outfit.dm @@ -31,7 +31,7 @@ return standard_outfit_options -/datum/action/chameleon_outfit/Trigger(trigger_flags) +/datum/action/chameleon_outfit/Trigger(mob/clicker, trigger_flags) . = ..() if(!. || applying) return diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index f0ba988143a0..b1095c267aba 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -644,7 +644,7 @@ BLIND // can't see anything var/emissive_alpha = get_blood_emissive_alpha(is_worn = TRUE) if (emissive_alpha) - var/mutable_appearance/emissive_overlay = emissive_appearance(blood_overlay.icon, blood_overlay.icon_state, src, alpha = emissive_alpha) + var/mutable_appearance/emissive_overlay = emissive_appearance(blood_overlay.icon, blood_overlay.icon_state, src, alpha = emissive_alpha, effect_type = EMISSIVE_NO_BLOOM) blood_overlay.overlays += emissive_overlay return blood_overlay diff --git a/code/modules/clothing/ears/_ears.dm b/code/modules/clothing/ears/_ears.dm index c1898c0ab9db..e14fb8a13ddc 100644 --- a/code/modules/clothing/ears/_ears.dm +++ b/code/modules/clothing/ears/_ears.dm @@ -16,8 +16,8 @@ icon_state = "earmuffs" inhand_icon_state = "earmuffs" clothing_traits = list(TRAIT_DEAF) - strip_delay = 15 - equip_delay_other = 25 + strip_delay = 1.5 SECONDS + equip_delay_other = 2.5 SECONDS resistance_flags = FLAMMABLE custom_price = PAYCHECK_COMMAND * 1.5 flags_cover = EARS_COVERED @@ -25,7 +25,7 @@ /obj/item/clothing/ears/earmuffs/Initialize(mapload) . = ..() AddElement(/datum/element/earhealing) - AddComponent(/datum/component/wearertargeting/earprotection, list(ITEM_SLOT_EARS)) + AddComponent(/datum/component/wearertargeting/earprotection) AddComponent(/datum/component/adjust_fishing_difficulty, -2) /obj/item/clothing/ears/earmuffs/debug diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm index c99c7e657722..9147a0e1e15b 100644 --- a/code/modules/clothing/glasses/_glasses.dm +++ b/code/modules/clothing/glasses/_glasses.dm @@ -6,8 +6,8 @@ righthand_file = 'icons/mob/inhands/clothing/glasses_righthand.dmi' w_class = WEIGHT_CLASS_SMALL slot_flags = ITEM_SLOT_EYES - strip_delay = 20 - equip_delay_other = 25 + strip_delay = 2 SECONDS + equip_delay_other = 2.5 SECONDS resistance_flags = NONE custom_materials = list(/datum/material/glass = SMALL_MATERIAL_AMOUNT*2.5) gender = PLURAL @@ -95,7 +95,6 @@ color_cutoffs = list(10, 35, 10) glass_colour_type = /datum/client_colour/glass_colour/lightgreen actions_types = list(/datum/action/item_action/toggle_nv) - forced_glass_color = TRUE /obj/item/clothing/glasses/meson/night/update_icon_state() . = ..() @@ -143,7 +142,6 @@ color_cutoffs = list(30, 5, 15) glass_colour_type = /datum/client_colour/glass_colour/lightpurple actions_types = list(/datum/action/item_action/toggle_nv) - forced_glass_color = TRUE /obj/item/clothing/glasses/science/night/update_icon_state() . = ..() @@ -160,16 +158,11 @@ color_cutoffs = list(10, 25, 10) glass_colour_type = /datum/client_colour/glass_colour/lightgreen actions_types = list(/datum/action/item_action/toggle_nv) - forced_glass_color = TRUE /obj/item/clothing/glasses/night/update_icon_state() . = ..() icon_state = length(color_cutoffs) ? initial(icon_state) : "night_off" -/obj/item/clothing/glasses/night/colorless - desc = parent_type::desc + " Now with 50% less green!" - forced_glass_color = FALSE - /obj/item/clothing/glasses/eyepatch name = "eyepatch" desc = "Yarr." diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm index b0dcb72e6fcf..79b5c263f52d 100644 --- a/code/modules/clothing/glasses/hud.dm +++ b/code/modules/clothing/glasses/hud.dm @@ -76,7 +76,6 @@ color_cutoffs = list(20, 20, 45) glass_colour_type = /datum/client_colour/glass_colour/lightgreen actions_types = list(/datum/action/item_action/toggle_nv) - forced_glass_color = TRUE /obj/item/clothing/glasses/hud/health/night/update_icon_state() . = ..() @@ -92,7 +91,6 @@ desc = "A clandestine medical science heads-up display that allows operatives to find \ both dying captains and the perfect poison to finish them off, all in complete darkness." clothing_traits = list(TRAIT_REAGENT_SCANNER, TRAIT_MEDICAL_HUD) - forced_glass_color = FALSE /obj/item/clothing/glasses/hud/health/sunglasses name = "medical HUDSunglasses" @@ -130,7 +128,6 @@ color_cutoffs = list(25, 15, 5) glass_colour_type = /datum/client_colour/glass_colour/lightyellow actions_types = list(/datum/action/item_action/toggle_nv) - forced_glass_color = TRUE /obj/item/clothing/glasses/hud/diagnostic/night/update_icon_state() . = ..() @@ -207,7 +204,6 @@ color_cutoffs = list(40, 15, 10) glass_colour_type = /datum/client_colour/glass_colour/lightred actions_types = list(/datum/action/item_action/toggle_nv) - forced_glass_color = TRUE /obj/item/clothing/glasses/hud/security/night/update_icon_state() . = ..() diff --git a/code/modules/clothing/gloves/_gloves.dm b/code/modules/clothing/gloves/_gloves.dm index a0d62978529c..f1c7785e323e 100644 --- a/code/modules/clothing/gloves/_gloves.dm +++ b/code/modules/clothing/gloves/_gloves.dm @@ -16,8 +16,8 @@ pickup_sound = 'sound/items/handling/glove_pick_up.ogg' attack_verb_continuous = list("challenges") attack_verb_simple = list("challenge") - strip_delay = 20 - equip_delay_other = 40 + strip_delay = 2 SECONDS + equip_delay_other = 4 SECONDS article = "a pair of" // Path variable. If defined, will produced the type through interaction with wirecutters. diff --git a/code/modules/clothing/gloves/bone.dm b/code/modules/clothing/gloves/bone.dm index 24dfb5de5a9a..a29d4cfd223b 100644 --- a/code/modules/clothing/gloves/bone.dm +++ b/code/modules/clothing/gloves/bone.dm @@ -3,8 +3,8 @@ desc = "For when you're expecting to get slapped on the wrist. Offers modest protection to your arms." icon_state = "bracers" inhand_icon_state = null - strip_delay = 40 - equip_delay_other = 20 + strip_delay = 4 SECONDS + equip_delay_other = 2 SECONDS body_parts_covered = ARMS cold_protection = ARMS min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT diff --git a/code/modules/clothing/gloves/boxing.dm b/code/modules/clothing/gloves/boxing.dm index 6ea7ed438f27..cfad83432e74 100644 --- a/code/modules/clothing/gloves/boxing.dm +++ b/code/modules/clothing/gloves/boxing.dm @@ -3,7 +3,7 @@ desc = "Because you really needed another excuse to punch your crewmates." icon_state = "boxing" greyscale_colors = "#f32110" - equip_delay_other = 60 + equip_delay_other = 6 SECONDS species_exception = list(/datum/species/golem) // now you too can be a golem boxing champion clothing_traits = list(TRAIT_CHUNKYFINGERS) equip_sound = 'sound/items/equip/glove_equip.ogg' @@ -46,7 +46,7 @@ icon_state = "boxinggold" custom_materials = list(/datum/material/gold = SHEET_MATERIAL_AMOUNT*1) //LITERALLY GOLD material_flags = MATERIAL_EFFECTS | MATERIAL_AFFECT_STATISTICS - equip_delay_other = 120 + equip_delay_other = 12 SECONDS resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE /obj/item/clothing/gloves/boxing/golden/Initialize(mapload) diff --git a/code/modules/clothing/gloves/color.dm b/code/modules/clothing/gloves/color.dm index 9868392ecb08..b9f82135c477 100644 --- a/code/modules/clothing/gloves/color.dm +++ b/code/modules/clothing/gloves/color.dm @@ -33,8 +33,8 @@ desc = "Plain black gloves without fingertips for the hard-working." icon_state = "fingerless" greyscale_colors = "#2f2e31" - strip_delay = 40 - equip_delay_other = 20 + strip_delay = 4 SECONDS + equip_delay_other = 2 SECONDS cold_protection = HANDS min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT custom_price = PAYCHECK_CREW * 1.5 diff --git a/code/modules/clothing/gloves/combat.dm b/code/modules/clothing/gloves/combat.dm index e7e12c8ee4b1..5ae715e1320f 100644 --- a/code/modules/clothing/gloves/combat.dm +++ b/code/modules/clothing/gloves/combat.dm @@ -4,7 +4,7 @@ icon_state = "black" greyscale_colors = "#2f2e31" siemens_coefficient = 0 - strip_delay = 80 + strip_delay = 8 SECONDS cold_protection = HANDS min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT heat_protection = HANDS diff --git a/code/modules/clothing/gloves/special.dm b/code/modules/clothing/gloves/special.dm index 8aa8c6ee5c25..6d0fe95bcf5a 100644 --- a/code/modules/clothing/gloves/special.dm +++ b/code/modules/clothing/gloves/special.dm @@ -91,7 +91,7 @@ min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT heat_protection = HANDS max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT - strip_delay = 60 + strip_delay = 6 SECONDS armor_type = /datum/armor/captain_gloves resistance_flags = NONE clothing_traits = list(TRAIT_FAST_CUFFING) diff --git a/code/modules/clothing/head/cone.dm b/code/modules/clothing/head/cone.dm index 05d967184a1d..a77d40b541f1 100644 --- a/code/modules/clothing/head/cone.dm +++ b/code/modules/clothing/head/cone.dm @@ -24,6 +24,6 @@ /obj/item/clothing/head/cone/worn_overlays(mutable_appearance/standing, isinhands, icon_file) . = ..() if(!isinhands) - . += emissive_appearance(icon_file, "[icon_state]-emissive", src, alpha = src.alpha) + . += emissive_appearance(icon_file, "[icon_state]-emissive", src, alpha = src.alpha, effect_type = EMISSIVE_SPECULAR) diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm index dd9380d415fe..353bca53a6f9 100644 --- a/code/modules/clothing/head/hardhat.dm +++ b/code/modules/clothing/head/hardhat.dm @@ -220,7 +220,7 @@ /obj/item/clothing/head/utility/hardhat/welding/atmos/worn_overlays(mutable_appearance/standing, isinhands, icon_file) . = ..() if(!isinhands) - . += emissive_appearance(icon_file, "[icon_state]-emissive", src, alpha = src.alpha) + . += emissive_appearance(icon_file, "[icon_state]-emissive", src, alpha = src.alpha, effect_type = EMISSIVE_SPECULAR) /obj/item/clothing/head/utility/hardhat/pumpkinhead name = "carved pumpkin" diff --git a/code/modules/clothing/head/hat.dm b/code/modules/clothing/head/hat.dm index 6a6153897f3a..5ed1725101b5 100644 --- a/code/modules/clothing/head/hat.dm +++ b/code/modules/clothing/head/hat.dm @@ -9,7 +9,7 @@ inhand_icon_state = "that" flags_inv = 0 armor_type = /datum/armor/hats_centhat - strip_delay = 80 + strip_delay = 8 SECONDS /datum/armor/hats_centhat melee = 30 @@ -304,7 +304,7 @@ inhand_icon_state = "that" flags_inv = 0 armor_type = /datum/armor/hats_centcom_cap - strip_delay = (8 SECONDS) + strip_delay = 8 SECONDS /datum/armor/hats_centcom_cap melee = 30 diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 18510f48a4bb..c33960f8115f 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -11,7 +11,7 @@ min_cold_protection_temperature = HELMET_MIN_TEMP_PROTECT heat_protection = HEAD max_heat_protection_temperature = HELMET_MAX_TEMP_PROTECT - strip_delay = 60 + strip_delay = 6 SECONDS clothing_flags = SNUG_FIT | STACKABLE_HELMET_EXEMPT flags_cover = HEADCOVERSEYES|EARS_COVERED flags_inv = HIDEHAIR @@ -107,7 +107,7 @@ /obj/item/clothing/head/helmet/press/worn_overlays(mutable_appearance/standing, isinhands, icon_file) . = ..() if(!isinhands) - . += emissive_appearance(icon_file, "[icon_state]-emissive", src, alpha = src.alpha) + . += emissive_appearance(icon_file, "[icon_state]-emissive", src, alpha = src.alpha, effect_type = EMISSIVE_SPECULAR) /obj/item/clothing/head/helmet/alt name = "bulletproof helmet" @@ -234,7 +234,7 @@ alt_toggle_message = "You push the visor up on" armor_type = /datum/armor/toggleable_riot flags_inv = HIDEHAIR|HIDEEARS|HIDEFACE|HIDESNOUT - strip_delay = 80 + strip_delay = 8 SECONDS actions_types = list(/datum/action/item_action/toggle) visor_flags_inv = HIDEFACE|HIDESNOUT flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH | PEPPERPROOF @@ -331,7 +331,7 @@ heat_protection = HEAD max_heat_protection_temperature = SPACE_HELM_MAX_TEMP_PROTECT clothing_flags = STOPSPRESSUREDAMAGE | STACKABLE_HELMET_EXEMPT - strip_delay = 80 + strip_delay = 8 SECONDS resistance_flags = FIRE_PROOF | ACID_PROOF dog_fashion = null clothing_traits = list(TRAIT_HEAD_INJURY_BLOCKED) @@ -379,7 +379,7 @@ min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT heat_protection = HEAD max_heat_protection_temperature = SPACE_HELM_MAX_TEMP_PROTECT - strip_delay = 80 + strip_delay = 8 SECONDS dog_fashion = null /datum/armor/helmet_thunderdome @@ -410,7 +410,7 @@ resistance_flags = FIRE_PROOF icon_state = "roman" inhand_icon_state = "roman_helmet" - strip_delay = 100 + strip_delay = 10 SECONDS dog_fashion = null /datum/armor/helmet_roman @@ -483,7 +483,7 @@ flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH resistance_flags = NONE - strip_delay = 80 + strip_delay = 8 SECONDS dog_fashion = null clothing_traits = list(TRAIT_HEAD_INJURY_BLOCKED) @@ -523,7 +523,7 @@ inhand_icon_state = "durathread_helmet" resistance_flags = FLAMMABLE armor_type = /datum/armor/helmet_durathread - strip_delay = 60 + strip_delay = 6 SECONDS /datum/armor/helmet_durathread melee = 20 @@ -610,7 +610,7 @@ flags_inv = HIDEEARS|HIDEEYES|HIDEFACE|HIDESNOUT flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH | PEPPERPROOF flash_protect = FLASH_PROTECTION_FLASH - strip_delay = 80 + strip_delay = 8 SECONDS dog_fashion = null armor_type = /datum/armor/helmet_military sound_vary = TRUE @@ -710,7 +710,7 @@ antimagic_flags = MAGIC_RESISTANCE|MAGIC_RESISTANCE_HOLY, \ inventory_flags = ITEM_SLOT_OCLOTHING, \ charges = 1, \ - drain_antimagic = CALLBACK(src, PROC_REF(drain_antimagic)), \ + block_magic = CALLBACK(src, PROC_REF(drain_antimagic)), \ expiration = CALLBACK(src, PROC_REF(decay)) \ ) diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm index 37a0ac84f8fb..d593119dafe9 100644 --- a/code/modules/clothing/head/jobs.dm +++ b/code/modules/clothing/head/jobs.dm @@ -10,8 +10,8 @@ inhand_icon_state = "chefhat" icon_state = "chef" desc = "The commander in chef's head wear." - strip_delay = 10 - equip_delay_other = 10 + strip_delay = 1 SECONDS + equip_delay_other = 1 SECONDS dog_fashion = /datum/dog_fashion/head/chef /// The chance that the movements of a mouse inside of this hat get relayed to the human wearing the hat var/mouse_control_probability = 20 @@ -101,7 +101,7 @@ inhand_icon_state = "that" flags_inv = 0 armor_type = /datum/armor/hats_caphat - strip_delay = 60 + strip_delay = 6 SECONDS dog_fashion = /datum/dog_fashion/head/captain //Captain: This is no longer space-worthy @@ -467,7 +467,7 @@ desc = "It's a special armored hat issued to the Warden of a security force. Protects the head from impacts." icon_state = "policehelm" armor_type = /datum/armor/hats_warden - strip_delay = 60 + strip_delay = 6 SECONDS dog_fashion = /datum/dog_fashion/head/warden /datum/armor/hats_warden @@ -568,7 +568,7 @@ greyscale_config_worn = /datum/greyscale_config/beret_badge/worn greyscale_colors = "#a52f29#F2F2F2" armor_type = /datum/armor/cosmetic_sec - strip_delay = 60 + strip_delay = 6 SECONDS dog_fashion = null flags_1 = NONE @@ -587,7 +587,7 @@ desc = "A special beret with the Warden's insignia emblazoned on it. For wardens with class." icon_state = "/obj/item/clothing/head/beret/sec/navywarden" greyscale_colors = "#638799#ebebeb" - strip_delay = 60 + strip_delay = 6 SECONDS /obj/item/clothing/head/beret/sec/navyofficer desc = "A special beret with the security insignia emblazoned on it. For officers with class." diff --git a/code/modules/clothing/head/mind_monkey_helmet.dm b/code/modules/clothing/head/mind_monkey_helmet.dm index 4aafaa4dfc1d..0020c43f2c96 100644 --- a/code/modules/clothing/head/mind_monkey_helmet.dm +++ b/code/modules/clothing/head/mind_monkey_helmet.dm @@ -6,7 +6,7 @@ desc = "A fragile, circuitry embedded helmet for boosting the intelligence of a monkey to a higher level. You see several warning labels..." icon_state = "monkeymind" inhand_icon_state = null - strip_delay = 100 + strip_delay = 10 SECONDS var/mob/living/carbon/human/magnification = null ///if the helmet is on a valid target (just works like a normal helmet if not (cargo please stop)) var/polling = FALSE///if the helmet is currently polling for targets (special code for removal) var/light_colors = 1 ///which icon state color this is (red, blue, yellow) diff --git a/code/modules/clothing/head/perceptomatrix.dm b/code/modules/clothing/head/perceptomatrix.dm index 9e31361e0c93..45f55a46ff09 100644 --- a/code/modules/clothing/head/perceptomatrix.dm +++ b/code/modules/clothing/head/perceptomatrix.dm @@ -102,7 +102,7 @@ // When someone makes TRAIT_DEAF an element, or status effect, or whatever, give this item a way to bypass said deafness. // just blocking future instances of deafness isn't what the item is meant to do but there's no proper way to do it otherwise at the moment. - active_components += AddComponent(/datum/component/wearertargeting/earprotection, list(ITEM_SLOT_HEAD), reduce_amount = 2) // should be same as highest value + active_components += AddComponent(/datum/component/wearertargeting/earprotection, reduce_amount = 2) // should be same as highest value active_components += AddComponent( /datum/component/anti_magic, \ antimagic_flags = MAGIC_RESISTANCE_MIND, \ diff --git a/code/modules/clothing/head/pirate.dm b/code/modules/clothing/head/pirate.dm index 0f1ede82e5ad..94f14841d3a3 100644 --- a/code/modules/clothing/head/pirate.dm +++ b/code/modules/clothing/head/pirate.dm @@ -25,8 +25,8 @@ /obj/item/clothing/head/costume/pirate/armored armor_type = /datum/armor/pirate_armored - strip_delay = 40 - equip_delay_other = 20 + strip_delay = 4 SECONDS + equip_delay_other = 2 SECONDS /datum/armor/pirate_armored melee = 30 @@ -51,8 +51,8 @@ /obj/item/clothing/head/costume/pirate/bandana/armored armor_type = /datum/armor/bandana_armored - strip_delay = 40 - equip_delay_other = 20 + strip_delay = 4 SECONDS + equip_delay_other = 2 SECONDS /datum/armor/bandana_armored melee = 30 diff --git a/code/modules/clothing/head/soft_caps.dm b/code/modules/clothing/head/soft_caps.dm index 2b7913b42c23..a074358e3790 100644 --- a/code/modules/clothing/head/soft_caps.dm +++ b/code/modules/clothing/head/soft_caps.dm @@ -125,7 +125,7 @@ icon_state = "secsoft" soft_type = "sec" armor_type = /datum/armor/cosmetic_sec - strip_delay = 60 + strip_delay = 6 SECONDS dog_fashion = null /obj/item/clothing/head/soft/veteran @@ -134,7 +134,7 @@ icon_state = "veteransoft" soft_type = "veteran" armor_type = /datum/armor/cosmetic_sec - strip_delay = 60 + strip_delay = 6 SECONDS dog_fashion = null /obj/item/clothing/head/soft/paramedic diff --git a/code/modules/clothing/head/tinfoilhat.dm b/code/modules/clothing/head/tinfoilhat.dm index febc379ac0ad..18cd6fd931a1 100644 --- a/code/modules/clothing/head/tinfoilhat.dm +++ b/code/modules/clothing/head/tinfoilhat.dm @@ -4,7 +4,7 @@ icon_state = "foilhat" inhand_icon_state = null armor_type = /datum/armor/costume_foilhat - equip_delay_other = 140 + equip_delay_other = 14 SECONDS clothing_flags = ANTI_TINFOIL_MANEUVER var/datum/brain_trauma/mild/phobia/conspiracies/paranoia var/warped = FALSE @@ -25,7 +25,7 @@ antimagic_flags = MAGIC_RESISTANCE_MIND, \ inventory_flags = ITEM_SLOT_HEAD, \ charges = 6, \ - drain_antimagic = CALLBACK(src, PROC_REF(drain_antimagic)), \ + block_magic = CALLBACK(src, PROC_REF(drain_antimagic)), \ expiration = CALLBACK(src, PROC_REF(warp_up)) \ ) diff --git a/code/modules/clothing/masks/_masks.dm b/code/modules/clothing/masks/_masks.dm index 9cafd6c1c3ac..bed6d8afab77 100644 --- a/code/modules/clothing/masks/_masks.dm +++ b/code/modules/clothing/masks/_masks.dm @@ -5,8 +5,8 @@ righthand_file = 'icons/mob/inhands/clothing/masks_righthand.dmi' body_parts_covered = HEAD slot_flags = ITEM_SLOT_MASK - strip_delay = 40 - equip_delay_other = 40 + strip_delay = 4 SECONDS + equip_delay_other = 4 SECONDS visor_vars_to_toggle = NONE unique_reskin_changes_base_icon_state = TRUE diff --git a/code/modules/clothing/masks/breath.dm b/code/modules/clothing/masks/breath.dm index 62ec778d49cc..a8a844a3a831 100644 --- a/code/modules/clothing/masks/breath.dm +++ b/code/modules/clothing/masks/breath.dm @@ -38,7 +38,7 @@ icon_state = "medical" inhand_icon_state = "m_mask" armor_type = /datum/armor/breath_medical - equip_delay_other = 10 + equip_delay_other = 1 SECONDS /datum/armor/breath_medical bio = 90 @@ -53,7 +53,7 @@ body_parts_covered = NONE flags_cover = NONE armor_type = /datum/armor/breath_muzzle - equip_delay_other = 25 // my sprite has 4 straps, a-la a head harness. takes a while to equip, longer than a muzzle + equip_delay_other = 2.5 SECONDS // my sprite has 4 straps, a-la a head harness. takes a while to equip, longer than a muzzle /obj/item/clothing/mask/breath/muzzle/Initialize(mapload) . = ..() diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index 64970387bf71..2dd08960bfa8 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -273,7 +273,7 @@ GLOBAL_LIST_INIT(clown_mask_options, list( icon_state = "syndicate" inhand_icon_state = "syndicate_gasmask" resistance_flags = FIRE_PROOF | ACID_PROOF - strip_delay = 60 + strip_delay = 6 SECONDS w_class = WEIGHT_CLASS_SMALL fishing_modifier = 0 pepper_tint = FALSE diff --git a/code/modules/clothing/masks/muzzle.dm b/code/modules/clothing/masks/muzzle.dm index b6dd6faf7ba8..9508036902ad 100644 --- a/code/modules/clothing/masks/muzzle.dm +++ b/code/modules/clothing/masks/muzzle.dm @@ -7,7 +7,7 @@ righthand_file = 'icons/mob/inhands/clothing/glasses_righthand.dmi' flags_cover = MASKCOVERSMOUTH w_class = WEIGHT_CLASS_SMALL - equip_delay_other = 20 + equip_delay_other = 2 SECONDS /obj/item/clothing/mask/muzzle/Initialize(mapload) . = ..() @@ -28,8 +28,8 @@ inhand_icon_state = null w_class = WEIGHT_CLASS_TINY clothing_flags = INEDIBLE_CLOTHING - equip_delay_other = 40 - strip_delay = 40 + equip_delay_other = 4 SECONDS + strip_delay = 4 SECONDS icon = 'icons/map_icons/clothing/mask.dmi' icon_state = "/obj/item/clothing/mask/muzzle/tape" post_init_icon_state = "tape_piece" @@ -76,15 +76,15 @@ desc = "A piece of tape that can be put over someone's mouth. This one has extra strength." icon_state = "/obj/item/clothing/mask/muzzle/tape/super" greyscale_colors = "#4D4D4D" - strip_delay = 80 + strip_delay = 8 SECONDS /obj/item/clothing/mask/muzzle/tape/surgical name = "surgical tape piece" desc = "A piece of tape that can be put over someone's mouth. As long as you apply this to your patient, you won't hear their screams of pain!" icon_state = "/obj/item/clothing/mask/muzzle/tape/surgical" greyscale_colors = "#70BAE7" - equip_delay_other = 30 - strip_delay = 30 + equip_delay_other = 3 SECONDS + strip_delay = 3 SECONDS /obj/item/clothing/mask/muzzle/tape/pointy name = "pointy tape piece" @@ -104,5 +104,5 @@ desc = "A piece of tape that can be put over someone's mouth. This thing could rip your face into a thousand pieces if ripped off." icon_state = "/obj/item/clothing/mask/muzzle/tape/pointy/super" greyscale_colors = "#8C0A00#300008" - strip_delay = 60 + strip_delay = 6 SECONDS stripping_damage = 20 diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm index 236238a22725..3a5982712bd2 100644 --- a/code/modules/clothing/neck/_neck.dm +++ b/code/modules/clothing/neck/_neck.dm @@ -4,8 +4,8 @@ body_parts_covered = NECK slot_flags = ITEM_SLOT_NECK interaction_flags_click = NEED_DEXTERITY - strip_delay = 40 - equip_delay_other = 40 + strip_delay = 4 SECONDS + equip_delay_other = 4 SECONDS /obj/item/clothing/neck/worn_overlays(mutable_appearance/standing, isinhands = FALSE) . = ..() @@ -131,7 +131,7 @@ icon_state = "tie_greyscale_untied" strip_delay = 1 SECONDS equip_delay_other = 1 SECONDS - equip_delay_self = 0 + equip_delay_self = 0 SECONDS /obj/item/clothing/neck/tie/add_context(atom/source, list/context, obj/item/held_item, mob/user) . = ..() diff --git a/code/modules/clothing/outfits/ert.dm b/code/modules/clothing/outfits/ert.dm index 0d964b4e5549..f6774e9b2aa9 100644 --- a/code/modules/clothing/outfits/ert.dm +++ b/code/modules/clothing/outfits/ert.dm @@ -248,7 +248,7 @@ /obj/item/storage/box/lights/mixed = 1, ) belt = /obj/item/storage/belt/janitor/full - glasses = /obj/item/clothing/glasses/night/colorless + glasses = /obj/item/clothing/glasses/night l_pocket = /obj/item/grenade/chem_grenade/cleaner r_pocket = /obj/item/grenade/chem_grenade/cleaner l_hand = /obj/item/storage/bag/trash/bluespace diff --git a/code/modules/clothing/shoes/boots.dm b/code/modules/clothing/shoes/boots.dm index d0c9b1fcd447..e221a857fd00 100644 --- a/code/modules/clothing/shoes/boots.dm +++ b/code/modules/clothing/shoes/boots.dm @@ -6,7 +6,7 @@ supports_variations_flags = CLOTHING_DIGITIGRADE_MASK body_parts_covered = FEET|LEGS armor_type = /datum/armor/shoes_combat - strip_delay = 40 + strip_delay = 4 SECONDS resistance_flags = NONE lace_time = 12 SECONDS @@ -47,8 +47,8 @@ icon_state = "jackboots" inhand_icon_state = "jackboots" supports_variations_flags = CLOTHING_DIGITIGRADE_MASK - strip_delay = 30 - equip_delay_other = 50 + strip_delay = 3 SECONDS + equip_delay_other = 5 SECONDS resistance_flags = NONE armor_type = /datum/armor/shoes_jackboots fastening_type = SHOES_SLIPON @@ -136,8 +136,8 @@ inhand_icon_state = "jackboots" armor_type = /datum/armor/shoes_workboots supports_variations_flags = CLOTHING_DIGITIGRADE_MASK - strip_delay = 20 - equip_delay_other = 40 + strip_delay = 2 SECONDS + equip_delay_other = 4 SECONDS lace_time = 8 SECONDS /datum/armor/shoes_workboots @@ -196,7 +196,7 @@ /obj/item/clothing/shoes/pirate/armored armor_type = /datum/armor/shoes_pirate - strip_delay = 40 + strip_delay = 4 SECONDS resistance_flags = NONE lace_time = 12 SECONDS body_parts_covered = FEET|LEGS diff --git a/code/modules/clothing/shoes/costume.dm b/code/modules/clothing/shoes/costume.dm index c836af89a9d6..58b8e07f6a2e 100644 --- a/code/modules/clothing/shoes/costume.dm +++ b/code/modules/clothing/shoes/costume.dm @@ -3,8 +3,8 @@ desc = "Sandals with buckled leather straps on it." icon_state = "roman" inhand_icon_state = "wizshoe" - strip_delay = 100 - equip_delay_other = 100 + strip_delay = 10 SECONDS + equip_delay_other = 10 SECONDS armor_type = /datum/armor/shoes_roman fastening_type = SHOES_STRAPS @@ -27,13 +27,13 @@ name = "yellow performer's boots" desc = "These boots were made for dancing." icon_state = "ysing" - equip_delay_other = 50 + equip_delay_other = 5 SECONDS /obj/item/clothing/shoes/singerb name = "blue performer's boots" desc = "These boots were made for dancing." icon_state = "bsing" - equip_delay_other = 50 + equip_delay_other = 5 SECONDS /obj/item/clothing/shoes/bronze name = "bronze boots" diff --git a/code/modules/clothing/shoes/galoshes.dm b/code/modules/clothing/shoes/galoshes.dm index 5e785f20a682..7b866d3ef413 100644 --- a/code/modules/clothing/shoes/galoshes.dm +++ b/code/modules/clothing/shoes/galoshes.dm @@ -5,8 +5,8 @@ inhand_icon_state = "galoshes" clothing_traits = list(TRAIT_NO_SLIP_WATER) slowdown = SHOES_SLOWDOWN+1 - strip_delay = 30 - equip_delay_other = 50 + strip_delay = 3 SECONDS + equip_delay_other = 5 SECONDS resistance_flags = NONE armor_type = /datum/armor/shoes_galoshes can_be_bloody = FALSE diff --git a/code/modules/clothing/shoes/jumpboots.dm b/code/modules/clothing/shoes/jumpboots.dm index 1816a68cefd3..d91a792533ed 100644 --- a/code/modules/clothing/shoes/jumpboots.dm +++ b/code/modules/clothing/shoes/jumpboots.dm @@ -6,7 +6,7 @@ resistance_flags = FIRE_PROOF actions_types = list(/datum/action/item_action/bhop) armor_type = /datum/armor/shoes_bhop - strip_delay = 30 + strip_delay = 3 SECONDS var/jumpdistance = 5 //-1 from to see the actual distance, e.g 4 goes over 3 tiles var/jumpspeed = 3 var/recharging_rate = 60 //default 6 seconds between each dash diff --git a/code/modules/clothing/shoes/laceup.dm b/code/modules/clothing/shoes/laceup.dm index 808bf22f5080..0ef4f4555bc4 100644 --- a/code/modules/clothing/shoes/laceup.dm +++ b/code/modules/clothing/shoes/laceup.dm @@ -2,7 +2,7 @@ name = "laceup shoes" desc = "The height of fashion, and they're pre-polished!" icon_state = "laceups" - equip_delay_other = 50 + equip_delay_other = 5 SECONDS /obj/item/clothing/shoes/laceup/Initialize(mapload) . = ..() diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm index 2210eff12a62..b6227c6266f3 100644 --- a/code/modules/clothing/shoes/magboots.dm +++ b/code/modules/clothing/shoes/magboots.dm @@ -9,8 +9,8 @@ inhand_icon_state = "magboots" armor_type = /datum/armor/shoes_magboots actions_types = list(/datum/action/item_action/toggle) - strip_delay = 70 - equip_delay_other = 70 + strip_delay = 7 SECONDS + equip_delay_other = 7 SECONDS resistance_flags = FIRE_PROOF clothing_flags = parent_type::clothing_flags | STOPSPRESSUREDAMAGE slowdown = SHOES_SLOWDOWN diff --git a/code/modules/clothing/shoes/sandals.dm b/code/modules/clothing/shoes/sandals.dm index c31ad6f3d5e6..a529839b91a5 100644 --- a/code/modules/clothing/shoes/sandals.dm +++ b/code/modules/clothing/shoes/sandals.dm @@ -5,8 +5,8 @@ inhand_icon_state = "wizshoe" custom_materials = list(/datum/material/wood = SHEET_MATERIAL_AMOUNT * 0.5) resistance_flags = FLAMMABLE - strip_delay = 5 - equip_delay_other = 50 + strip_delay = 0.5 SECONDS + equip_delay_other = 5 SECONDS armor_type = /datum/armor/shoes_sandal fastening_type = SHOES_SLIPON species_exception = list(/datum/species/golem) diff --git a/code/modules/clothing/shoes/sneakers.dm b/code/modules/clothing/shoes/sneakers.dm index a431544298a2..5a1826d55e70 100644 --- a/code/modules/clothing/shoes/sneakers.dm +++ b/code/modules/clothing/shoes/sneakers.dm @@ -196,8 +196,8 @@ greyscale_config = /datum/greyscale_config/sneakers_marisa greyscale_config_worn = /datum/greyscale_config/sneakers_marisa/worn greyscale_colors = "#2d2d33#ffffff" - strip_delay = 5 - equip_delay_other = 50 + strip_delay = 0.5 SECONDS + equip_delay_other = 5 SECONDS fastening_type = SHOES_SLIPON resistance_flags = FIRE_PROOF | ACID_PROOF diff --git a/code/modules/clothing/spacesuits/_spacesuits.dm b/code/modules/clothing/spacesuits/_spacesuits.dm index af27cc3f995f..66e98ba27a96 100644 --- a/code/modules/clothing/spacesuits/_spacesuits.dm +++ b/code/modules/clothing/spacesuits/_spacesuits.dm @@ -19,8 +19,8 @@ heat_protection = HEAD max_heat_protection_temperature = SPACE_HELM_MAX_TEMP_PROTECT flash_protect = FLASH_PROTECTION_WELDER - strip_delay = 50 - equip_delay_other = 50 + strip_delay = 5 SECONDS + equip_delay_other = 5 SECONDS flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH | PEPPERPROOF resistance_flags = NONE dog_fashion = null @@ -73,8 +73,8 @@ min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT_OFF heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT - strip_delay = 80 - equip_delay_other = 80 + strip_delay = 8 SECONDS + equip_delay_other = 8 SECONDS resistance_flags = NONE actions_types = list(/datum/action/item_action/toggle_spacesuit) interaction_flags_click = NEED_DEXTERITY|ALLOW_RESTING diff --git a/code/modules/clothing/spacesuits/bountyhunter.dm b/code/modules/clothing/spacesuits/bountyhunter.dm index cb8498dac14c..1284f89dabae 100644 --- a/code/modules/clothing/spacesuits/bountyhunter.dm +++ b/code/modules/clothing/spacesuits/bountyhunter.dm @@ -5,7 +5,7 @@ inhand_icon_state = "swat_suit" allowed = list(/obj/item/gun, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/knife/combat) armor_type = /datum/armor/space_hunter - strip_delay = 130 + strip_delay = 13 SECONDS resistance_flags = FIRE_PROOF | ACID_PROOF cell = /obj/item/stock_parts/power_store/cell/hyper diff --git a/code/modules/clothing/spacesuits/freedom.dm b/code/modules/clothing/spacesuits/freedom.dm index dfc54db118a3..c43ff6c90d70 100644 --- a/code/modules/clothing/spacesuits/freedom.dm +++ b/code/modules/clothing/spacesuits/freedom.dm @@ -6,7 +6,7 @@ icon_state = "griffinhat" inhand_icon_state = null armor_type = /datum/armor/space_freedom - strip_delay = 130 + strip_delay = 13 SECONDS max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = ACID_PROOF | FIRE_PROOF fishing_modifier = 0 @@ -29,7 +29,7 @@ inhand_icon_state = null allowed = list(/obj/item/gun, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals) armor_type = /datum/armor/space_freedom - strip_delay = 130 + strip_delay = 13 SECONDS max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = ACID_PROOF | FIRE_PROOF slowdown = 0 diff --git a/code/modules/clothing/spacesuits/pirate.dm b/code/modules/clothing/spacesuits/pirate.dm index b7f4640c63bb..1a0dcca025db 100644 --- a/code/modules/clothing/spacesuits/pirate.dm +++ b/code/modules/clothing/spacesuits/pirate.dm @@ -4,8 +4,8 @@ icon_state = "spacepirate" inhand_icon_state = "space_pirate_helmet" armor_type = /datum/armor/space_pirate - strip_delay = 40 - equip_delay_other = 20 + strip_delay = 4 SECONDS + equip_delay_other = 2 SECONDS fishing_modifier = -2 visor_dirt = null @@ -30,8 +30,8 @@ allowed = list(/obj/item/gun, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/melee/energy/sword/pirate, /obj/item/clothing/glasses/eyepatch, /obj/item/reagent_containers/cup/glass/bottle/rum) slowdown = 0 armor_type = /datum/armor/space_pirate - strip_delay = 40 - equip_delay_other = 20 + strip_delay = 4 SECONDS + equip_delay_other = 2 SECONDS fishing_modifier = -3 /obj/item/clothing/head/helmet/space/pirate/tophat diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm index eafcc66b5ee2..0a6affdafd11 100644 --- a/code/modules/clothing/spacesuits/plasmamen.dm +++ b/code/modules/clothing/spacesuits/plasmamen.dm @@ -78,7 +78,7 @@ clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | SNUG_FIT | STACKABLE_HELMET_EXEMPT | PLASMAMAN_PREVENT_IGNITION | HEADINTERNALS icon_state = "plasmaman-helm" inhand_icon_state = "plasmaman-helm" - strip_delay = 80 + strip_delay = 8 SECONDS flash_protect = FLASH_PROTECTION_WELDER tint = 2 armor_type = /datum/armor/space_plasmaman diff --git a/code/modules/clothing/spacesuits/softsuit.dm b/code/modules/clothing/spacesuits/softsuit.dm index 445af2ea1b66..72841de62df0 100644 --- a/code/modules/clothing/spacesuits/softsuit.dm +++ b/code/modules/clothing/spacesuits/softsuit.dm @@ -73,7 +73,7 @@ icon_state = "syndicate-helm-orange" inhand_icon_state = "syndicate-helm-orange" //resprite? armor_type = /datum/armor/space_fragile - strip_delay = 65 + strip_delay = 6.5 SECONDS /obj/item/clothing/suit/space/fragile name = "emergency space suit" @@ -83,7 +83,7 @@ inhand_icon_state = "syndicate-orange" slowdown = 2 armor_type = /datum/armor/space_fragile - strip_delay = 65 + strip_delay = 6.5 SECONDS /datum/armor/space_fragile melee = 5 diff --git a/code/modules/clothing/spacesuits/specialops.dm b/code/modules/clothing/spacesuits/specialops.dm index 066a80cddd58..d0f06f89a67e 100644 --- a/code/modules/clothing/spacesuits/specialops.dm +++ b/code/modules/clothing/spacesuits/specialops.dm @@ -11,7 +11,7 @@ clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | SNUG_FIT flags_inv = 0 armor_type = /datum/armor/space_beret - strip_delay = 130 + strip_delay = 13 SECONDS max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | ACID_PROOF fishing_modifier = 0 @@ -42,7 +42,7 @@ w_class = WEIGHT_CLASS_NORMAL allowed = list(/obj/item/gun, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals) armor_type = /datum/armor/space_officer - strip_delay = 130 + strip_delay = 13 SECONDS max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | ACID_PROOF fishing_modifier = 0 diff --git a/code/modules/clothing/suits/ablativecoat.dm b/code/modules/clothing/suits/ablativecoat.dm index 32233f23400c..3d4b793c6631 100644 --- a/code/modules/clothing/suits/ablativecoat.dm +++ b/code/modules/clothing/suits/ablativecoat.dm @@ -6,7 +6,7 @@ icon_state = "ablativehood" flags_inv = HIDEHAIR|HIDEEARS armor_type = /datum/armor/hooded_ablative - strip_delay = 30 + strip_delay = 3 SECONDS var/hit_reflect_chance = 50 /datum/armor/hooded_ablative @@ -33,8 +33,8 @@ body_parts_covered = CHEST|GROIN|LEGS|ARMS armor_type = /datum/armor/hooded_ablative hoodtype = /obj/item/clothing/head/hooded/ablative - strip_delay = 30 - equip_delay_other = 40 + strip_delay = 3 SECONDS + equip_delay_other = 4 SECONDS var/hit_reflect_chance = 50 /obj/item/clothing/suit/hooded/ablative/Initialize(mapload) diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index fcce4675d077..939912dd95e7 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -8,8 +8,8 @@ min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT heat_protection = CHEST|GROIN max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT - strip_delay = 60 - equip_delay_other = 40 + strip_delay = 6 SECONDS + equip_delay_other = 4 SECONDS max_integrity = 250 resistance_flags = NONE armor_type = /datum/armor/suit_armor @@ -67,7 +67,7 @@ /obj/item/clothing/suit/armor/vest/press/worn_overlays(mutable_appearance/standing, isinhands, icon_file) . = ..() if(!isinhands) - . += emissive_appearance(icon_file, "[icon_state]-emissive", src, alpha = src.alpha) + . += emissive_appearance(icon_file, "[icon_state]-emissive", src, alpha = src.alpha, effect_type = EMISSIVE_SPECULAR) /obj/item/clothing/suit/armor/vest/marine name = "tactical armor vest" @@ -158,7 +158,7 @@ armor_type = /datum/armor/armor_hos cold_protection = CHEST|GROIN|LEGS|ARMS heat_protection = CHEST|GROIN|LEGS|ARMS - strip_delay = 80 + strip_delay = 8 SECONDS /datum/armor/armor_hos melee = 30 @@ -176,7 +176,7 @@ icon_state = "hostrench" inhand_icon_state = "hostrench" flags_inv = 0 - strip_delay = 80 + strip_delay = 8 SECONDS /obj/item/clothing/suit/armor/hos/trenchcoat/winter name = "head of security's winter trenchcoat" @@ -203,7 +203,7 @@ body_parts_covered = CHEST|GROIN|ARMS cold_protection = CHEST|GROIN|ARMS|HANDS heat_protection = CHEST|GROIN|ARMS|HANDS - strip_delay = 70 + strip_delay = 7 SECONDS resistance_flags = FLAMMABLE dog_fashion = null @@ -227,7 +227,7 @@ /obj/item/clothing/suit/armor/vest/secjacket/worn_overlays(mutable_appearance/standing, isinhands, icon_file) . = ..() if(!isinhands) - . += emissive_appearance(icon_file, "[icon_state]-emissive", src, alpha = src.alpha) + . += emissive_appearance(icon_file, "[icon_state]-emissive", src, alpha = src.alpha, effect_type = EMISSIVE_SPECULAR) /datum/armor/armor_secjacket //Gotta compensate those extra covered limbs melee = 25 @@ -294,8 +294,8 @@ cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS armor_type = /datum/armor/armor_riot - strip_delay = 80 - equip_delay_other = 60 + strip_delay = 8 SECONDS + equip_delay_other = 6 SECONDS clothing_traits = list(TRAIT_BRAWLING_KNOCKDOWN_BLOCKED) /obj/item/clothing/suit/armor/riot/Initialize(mapload) @@ -323,8 +323,8 @@ blood_overlay_type = "armor" armor_type = /datum/armor/balloon_vest siemens_coefficient = 0 - strip_delay = 70 - equip_delay_other = 50 + strip_delay = 7 SECONDS + equip_delay_other = 5 SECONDS /datum/armor/balloon_vest melee = 10 @@ -356,8 +356,8 @@ inhand_icon_state = "armor" blood_overlay_type = "armor" armor_type = /datum/armor/armor_bulletproof - strip_delay = 70 - equip_delay_other = 50 + strip_delay = 7 SECONDS + equip_delay_other = 5 SECONDS /datum/armor/armor_bulletproof melee = 15 @@ -414,7 +414,7 @@ icon_state = "heavy" inhand_icon_state = "swat_suit" armor_type = /datum/armor/armor_swat - strip_delay = 120 + strip_delay = 12 SECONDS resistance_flags = FIRE_PROOF | ACID_PROOF clothing_flags = THICKMATERIAL cold_protection = CHEST | GROIN | LEGS | FEET | ARMS | HANDS @@ -569,8 +569,8 @@ desc = "A vest made of durathread with strips of leather acting as trauma plates." icon_state = "durathread" inhand_icon_state = null - strip_delay = 60 - equip_delay_other = 40 + strip_delay = 6 SECONDS + equip_delay_other = 4 SECONDS max_integrity = 200 resistance_flags = FLAMMABLE armor_type = /datum/armor/vest_durathread @@ -765,8 +765,8 @@ inhand_icon_state = null body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS armor_type = /datum/armor/watermelon - strip_delay = 60 - equip_delay_other = 40 + strip_delay = 6 SECONDS + equip_delay_other = 4 SECONDS clothing_traits = list(TRAIT_BRAWLING_KNOCKDOWN_BLOCKED) max_integrity = 15 @@ -799,8 +799,8 @@ inhand_icon_state = null body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS armor_type = /datum/armor/watermelon - strip_delay = 60 - equip_delay_other = 40 + strip_delay = 6 SECONDS + equip_delay_other = 4 SECONDS clothing_traits = list(TRAIT_BRAWLING_KNOCKDOWN_BLOCKED) max_integrity = 15 @@ -816,7 +816,7 @@ antimagic_flags = MAGIC_RESISTANCE|MAGIC_RESISTANCE_HOLY, \ inventory_flags = ITEM_SLOT_OCLOTHING, \ charges = 1, \ - drain_antimagic = CALLBACK(src, PROC_REF(drain_antimagic)), \ + block_magic = CALLBACK(src, PROC_REF(drain_antimagic)), \ expiration = CALLBACK(src, PROC_REF(decay)) \ ) @@ -834,8 +834,8 @@ inhand_icon_state = null body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS armor_type = /datum/armor/barrelmelon - strip_delay = 60 - equip_delay_other = 40 + strip_delay = 6 SECONDS + equip_delay_other = 4 SECONDS clothing_traits = list(TRAIT_BRAWLING_KNOCKDOWN_BLOCKED) max_integrity = 10 diff --git a/code/modules/clothing/suits/bio.dm b/code/modules/clothing/suits/bio.dm index a14b3fcd77bd..a6f0e7807bde 100644 --- a/code/modules/clothing/suits/bio.dm +++ b/code/modules/clothing/suits/bio.dm @@ -40,8 +40,8 @@ allowed = list(/obj/item/tank/internals, /obj/item/reagent_containers/dropper, /obj/item/flashlight/pen, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/reagent_containers/cup/beaker, /obj/item/gun/syringe) armor_type = /datum/armor/suit_bio_suit flags_inv = HIDEGLOVES|HIDEJUMPSUIT|HIDEBELT - strip_delay = 70 - equip_delay_other = 70 + strip_delay = 7 SECONDS + equip_delay_other = 7 SECONDS resistance_flags = ACID_PROOF /obj/item/clothing/suit/bio_suit/Initialize(mapload) @@ -135,8 +135,8 @@ desc = "It protected doctors from the Black Death, back then. You bet your arse it's gonna help you against viruses." icon_state = "plaguedoctor" inhand_icon_state = "bio_suit" - strip_delay = 40 - equip_delay_other = 20 + strip_delay = 4 SECONDS + equip_delay_other = 2 SECONDS /obj/item/clothing/suit/bio_suit/plaguedoctorsuit/Initialize(mapload) . = ..() diff --git a/code/modules/clothing/suits/costume.dm b/code/modules/clothing/suits/costume.dm index a85a0f78603c..77c3478abdb9 100644 --- a/code/modules/clothing/suits/costume.dm +++ b/code/modules/clothing/suits/costume.dm @@ -42,8 +42,8 @@ /obj/item/clothing/suit/costume/pirate/armored armor_type = /datum/armor/pirate_armored - strip_delay = 40 - equip_delay_other = 20 + strip_delay = 4 SECONDS + equip_delay_other = 2 SECONDS species_exception = null /obj/item/clothing/suit/costume/pirate/captain @@ -54,8 +54,8 @@ /obj/item/clothing/suit/costume/pirate/captain/armored armor_type = /datum/armor/pirate_armored - strip_delay = 40 - equip_delay_other = 20 + strip_delay = 4 SECONDS + equip_delay_other = 2 SECONDS species_exception = null /obj/item/clothing/suit/costume/cyborg_suit diff --git a/code/modules/clothing/suits/jobs.dm b/code/modules/clothing/suits/jobs.dm index 5314776f2c4d..c7fd3ea0a3c7 100644 --- a/code/modules/clothing/suits/jobs.dm +++ b/code/modules/clothing/suits/jobs.dm @@ -196,7 +196,7 @@ /obj/item/clothing/suit/hazardvest/worn_overlays(mutable_appearance/standing, isinhands, icon_file) . = ..() if(!isinhands) - . += emissive_appearance(icon_file, "[icon_state]-emissive", src, alpha = src.alpha, apply_bloom = FALSE) + . += emissive_appearance(icon_file, "[icon_state]-emissive", src, alpha = src.alpha, effect_type = EMISSIVE_SPECULAR) /obj/item/clothing/suit/hazardvest/press // Variant used by the Curator name = "press hazard vest" @@ -442,4 +442,4 @@ /obj/item/clothing/suit/atmos_overalls/worn_overlays(mutable_appearance/standing, isinhands, icon_file) . = ..() if(!isinhands) - . += emissive_appearance(icon_file, "[icon_state]-emissive", src, alpha = src.alpha) + . += emissive_appearance(icon_file, "[icon_state]-emissive", src, alpha = src.alpha, effect_type = EMISSIVE_SPECULAR) diff --git a/code/modules/clothing/suits/straightjacket.dm b/code/modules/clothing/suits/straightjacket.dm index 4ef22a1a438d..5212aec6eeda 100644 --- a/code/modules/clothing/suits/straightjacket.dm +++ b/code/modules/clothing/suits/straightjacket.dm @@ -5,8 +5,8 @@ inhand_icon_state = "straight_jacket" body_parts_covered = CHEST|GROIN|LEGS|ARMS|HANDS flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT - equip_delay_self = 50 - strip_delay = 60 + equip_delay_self = 5 SECONDS + strip_delay = 6 SECONDS breakouttime = 5 MINUTES /obj/item/clothing/suit/jacket/straight_jacket/Initialize(mapload) diff --git a/code/modules/clothing/suits/utility.dm b/code/modules/clothing/suits/utility.dm index 3b1d4e48ed1a..b16526d29be9 100644 --- a/code/modules/clothing/suits/utility.dm +++ b/code/modules/clothing/suits/utility.dm @@ -35,8 +35,8 @@ max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT - strip_delay = 60 - equip_delay_other = 60 + strip_delay = 6 SECONDS + equip_delay_other = 6 SECONDS resistance_flags = FIRE_PROOF /obj/item/clothing/suit/utility/fire/Initialize(mapload) @@ -56,7 +56,7 @@ /obj/item/clothing/suit/utility/fire/worn_overlays(mutable_appearance/standing, isinhands, icon_file) . = ..() if(!isinhands) - . += emissive_appearance(icon_file, "[icon_state]-emissive", src, alpha = src.alpha) + . += emissive_appearance(icon_file, "[icon_state]-emissive", src, alpha = src.alpha, effect_type = EMISSIVE_SPECULAR) /obj/item/clothing/suit/utility/fire/firefighter icon_state = "firesuit" @@ -99,8 +99,8 @@ min_cold_protection_temperature = HELMET_MIN_TEMP_PROTECT heat_protection = HEAD max_heat_protection_temperature = HELMET_MAX_TEMP_PROTECT - strip_delay = 70 - equip_delay_other = 70 + strip_delay = 7 SECONDS + equip_delay_other = 7 SECONDS flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH | PEPPERPROOF resistance_flags = NONE @@ -134,8 +134,8 @@ max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT - strip_delay = 70 - equip_delay_other = 70 + strip_delay = 7 SECONDS + equip_delay_other = 7 SECONDS resistance_flags = NONE /obj/item/clothing/suit/utility/bomb_suit/Initialize(mapload) @@ -179,8 +179,8 @@ clothing_flags = THICKMATERIAL | SNUG_FIT flags_inv = HIDEMASK|HIDEEARS|HIDEFACE|HIDEEYES|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT armor_type = /datum/armor/utility_radiation - strip_delay = 60 - equip_delay_other = 60 + strip_delay = 6 SECONDS + equip_delay_other = 6 SECONDS flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH | PEPPERPROOF resistance_flags = NONE @@ -211,8 +211,8 @@ ) slowdown = 1.5 armor_type = /datum/armor/utility_radiation - strip_delay = 60 - equip_delay_other = 60 + strip_delay = 6 SECONDS + equip_delay_other = 6 SECONDS flags_inv = HIDEJUMPSUIT resistance_flags = NONE diff --git a/code/modules/clothing/suits/wintercoats.dm b/code/modules/clothing/suits/wintercoats.dm index fb9320297e43..be7bc64420cf 100644 --- a/code/modules/clothing/suits/wintercoats.dm +++ b/code/modules/clothing/suits/wintercoats.dm @@ -536,7 +536,7 @@ /obj/item/clothing/suit/hooded/wintercoat/engineering/worn_overlays(mutable_appearance/standing, isinhands, icon_file) . = ..() if(!isinhands) - . += emissive_appearance(icon_file, "[icon_state]-emissive", src, alpha = src.alpha) + . += emissive_appearance(icon_file, "[icon_state]-emissive", src, alpha = src.alpha, effect_type = EMISSIVE_SPECULAR) /obj/item/clothing/head/hooded/winterhood/engineering desc = "A yellow winter coat hood. Definitely not a replacement for a hard hat." @@ -549,7 +549,7 @@ /obj/item/clothing/head/hooded/winterhood/engineering/worn_overlays(mutable_appearance/standing, isinhands, icon_file) . = ..() if(!isinhands) - . += emissive_appearance(icon_file, "[icon_state]-emissive", src, alpha = src.alpha) + . += emissive_appearance(icon_file, "[icon_state]-emissive", src, alpha = src.alpha, effect_type = EMISSIVE_SPECULAR) // Chief Engineer /obj/item/clothing/suit/hooded/wintercoat/engineering/ce diff --git a/code/modules/clothing/suits/wiz_robe.dm b/code/modules/clothing/suits/wiz_robe.dm index 4c3de4475f57..fedcbc28b024 100644 --- a/code/modules/clothing/suits/wiz_robe.dm +++ b/code/modules/clothing/suits/wiz_robe.dm @@ -6,8 +6,8 @@ icon_state = "wizard" inhand_icon_state = "wizhat" armor_type = /datum/armor/head_wizard - strip_delay = 50 - equip_delay_other = 50 + strip_delay = 5 SECONDS + equip_delay_other = 5 SECONDS clothing_flags = SNUG_FIT | CASTING_CLOTHES resistance_flags = FIRE_PROOF | ACID_PROOF dog_fashion = /datum/dog_fashion/head/blue_wizard @@ -119,8 +119,8 @@ armor_type = /datum/armor/suit_wizrobe allowed = list(/obj/item/teleportation_scroll, /obj/item/highfrequencyblade/wizard) flags_inv = HIDEJUMPSUIT - strip_delay = 50 - equip_delay_other = 50 + strip_delay = 5 SECONDS + equip_delay_other = 5 SECONDS clothing_flags = CASTING_CLOTHES resistance_flags = FIRE_PROOF | ACID_PROOF ///How much this robe affects fishing difficulty diff --git a/code/modules/clothing/under/costume.dm b/code/modules/clothing/under/costume.dm index a3246ff4da48..dfa93c6862f3 100644 --- a/code/modules/clothing/under/costume.dm +++ b/code/modules/clothing/under/costume.dm @@ -8,7 +8,7 @@ icon_state = "roman" inhand_icon_state = "armor" can_adjust = FALSE - strip_delay = 100 + strip_delay = 10 SECONDS resistance_flags = NONE /obj/item/clothing/under/costume/jabroni @@ -297,7 +297,7 @@ worn_icon = 'icons/mob/clothing/under/security.dmi' alt_covers_chest = TRUE armor_type = /datum/armor/clothing_under/costume_russian_officer - strip_delay = 50 + strip_delay = 5 SECONDS sensor_mode = SENSOR_COORDS random_sensor = FALSE can_adjust = FALSE diff --git a/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm b/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm index 10bf4e66e156..bd2c358551a2 100644 --- a/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm +++ b/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm @@ -10,7 +10,7 @@ armor_type = /datum/armor/clothing_under/plasmaman body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS can_adjust = FALSE - strip_delay = 80 + strip_delay = 8 SECONDS COOLDOWN_DECLARE(extinguish_timer) var/extinguish_cooldown = 100 var/extinguishes_left = 5 diff --git a/code/modules/clothing/under/jobs/security.dm b/code/modules/clothing/under/jobs/security.dm index 2730ed47a6db..1753c9311e1e 100644 --- a/code/modules/clothing/under/jobs/security.dm +++ b/code/modules/clothing/under/jobs/security.dm @@ -13,7 +13,7 @@ icon = 'icons/obj/clothing/under/security.dmi' worn_icon = 'icons/mob/clothing/under/security.dmi' armor_type = /datum/armor/clothing_under/rank_security - strip_delay = 50 + strip_delay = 5 SECONDS sensor_mode = SENSOR_COORDS random_sensor = FALSE @@ -145,7 +145,7 @@ icon_state = "rhos" inhand_icon_state = "r_suit" armor_type = /datum/armor/clothing_under/security_head_of_security - strip_delay = 60 + strip_delay = 6 SECONDS /datum/armor/clothing_under/security_head_of_security melee = 10 diff --git a/code/modules/events/scrubber_overflow.dm b/code/modules/events/scrubber_overflow.dm index 16a455de0cf6..9f06881ac1bd 100644 --- a/code/modules/events/scrubber_overflow.dm +++ b/code/modules/events/scrubber_overflow.dm @@ -32,8 +32,6 @@ /datum/reagent/consumable/condensedcapsaicin, /datum/reagent/drug/mushroomhallucinogen, /datum/reagent/lube, - /datum/reagent/glitter/blue, - /datum/reagent/glitter/pink, /datum/reagent/cryptobiolin, /datum/reagent/blood, /datum/reagent/medicine/c2/multiver, @@ -53,7 +51,7 @@ /datum/reagent/consumable/ethanol/beer, /datum/reagent/hair_dye, /datum/reagent/consumable/sugar, - /datum/reagent/glitter/white, + /datum/reagent/glitter/random, /datum/reagent/gravitum, /datum/reagent/growthserum, /datum/reagent/yuck, diff --git a/code/modules/events/shuttle_catastrophe.dm b/code/modules/events/shuttle_catastrophe.dm index ed64c52a836a..5203af1daa90 100644 --- a/code/modules/events/shuttle_catastrophe.dm +++ b/code/modules/events/shuttle_catastrophe.dm @@ -54,6 +54,13 @@ return SSshuttle.shuttle_purchased = SHUTTLEPURCHASE_FORCED SSshuttle.unload_preview() + // We need to move our docking port back in case a crashlanding shuttle has been purchased previously + for(var/obj/docking_port/stationary/port as anything in SSshuttle.stationary_docking_ports) + if(port.shuttle_id != "emergency_home") + continue + var/turf/initial_loc = locate(port.initial_x, port.initial_y, port.initial_z) + port.forceMove(initial_loc) + break SSshuttle.existing_shuttle = SSshuttle.emergency SSshuttle.action_load(new_shuttle, replace = TRUE) log_shuttle("Shuttle Catastrophe set a new shuttle, [new_shuttle.name].") diff --git a/code/modules/events/space_vines/vine_mutations.dm b/code/modules/events/space_vines/vine_mutations.dm index 57c5c003fd74..8a9d922ee822 100644 --- a/code/modules/events/space_vines/vine_mutations.dm +++ b/code/modules/events/space_vines/vine_mutations.dm @@ -12,6 +12,20 @@ holder.mutations |= src holder.add_atom_colour(hue, FIXED_COLOUR_PRIORITY) +/datum/spacevine_mutation/proc/on_buckle(obj/structure/spacevine/holder, mob/living/buckled) + SHOULD_CALL_PARENT(TRUE) + buckled.layer = SPACEVINE_MOB_LAYER + RegisterSignal(buckled, COMSIG_MOB_UNBUCKLED, PROC_REF(on_unbuckle)) + +/datum/spacevine_mutation/proc/on_unbuckle(datum/source) + SHOULD_CALL_PARENT(TRUE) + SIGNAL_HANDLER + if(!isliving(source)) + return + var/mob/living/buckled = source + buckled.layer = initial(buckled.layer) + UnregisterSignal(buckled, COMSIG_MOB_UNBUCKLED) + /datum/spacevine_mutation/proc/process_mutation(obj/structure/spacevine/holder) return @@ -39,9 +53,6 @@ /datum/spacevine_mutation/proc/on_spread(obj/structure/spacevine/holder, turf/target) return -/datum/spacevine_mutation/proc/on_buckle(obj/structure/spacevine/holder, mob/living/buckled) - return - /datum/spacevine_mutation/proc/on_explosion(severity, target, obj/structure/spacevine/holder) return FALSE @@ -168,6 +179,7 @@ /// What happens if an aggr spreading vine buckles a mob. /datum/spacevine_mutation/aggressive_spread/on_buckle(obj/structure/spacevine/holder, mob/living/buckled) + . = ..() aggrospread_act(holder, buckled) /// Hurts mobs. To be used when a vine with aggressive spread mutation spreads into the mob's tile or buckles them. diff --git a/code/modules/fishing/aquarium/fish_analyzer.dm b/code/modules/fishing/aquarium/fish_analyzer.dm index 95b6b0f16c1b..a89ac1456a67 100644 --- a/code/modules/fishing/aquarium/fish_analyzer.dm +++ b/code/modules/fishing/aquarium/fish_analyzer.dm @@ -118,7 +118,7 @@ "fish_name" = fishie.name, "fish_icon" = fishie.icon, "fish_icon_state" = fishie.base_icon_state, - "fish_health" = fishie.status == FISH_DEAD ? 0 : PERCENT(fishie.health/initial(fishie.health)), + "fish_health" = fishie.status == FISH_DEAD ? 0 : PERCENT(fishie.get_health_percentage()), "fish_size" = fishie.size, "fish_weight" = fishie.weight, "fish_food" = fishie.food.name, diff --git a/code/modules/fishing/fish/_fish.dm b/code/modules/fishing/fish/_fish.dm index 09664c1923c4..cee4898000fc 100644 --- a/code/modules/fishing/fish/_fish.dm +++ b/code/modules/fishing/fish/_fish.dm @@ -37,6 +37,9 @@ GLOBAL_LIST_INIT(fish_compatible_fluid_types, list( //we handle slowdowns internally, and the fish weight modifier from materials already contributes to it. material_flags = MATERIAL_EFFECTS|MATERIAL_AFFECT_STATISTICS|MATERIAL_COLOR|MATERIAL_ADD_PREFIX|MATERIAL_NO_SLOWDOWN|MATERIAL_NO_EDIBILITY + max_integrity = 200 + integrity_failure = 0.5 + /// Flags for fish variables that would otherwise be TRUE/FALSE var/fish_flags = FISH_FLAG_SHOW_IN_CATALOG|FISH_DO_FLOP_ANIM|FISH_FLAG_EXPERIMENT_SCANNABLE @@ -75,8 +78,6 @@ GLOBAL_LIST_INIT(fish_compatible_fluid_types, list( ///icon used when the fish is dead, ifset. var/icon_state_dead - /// Current fish health. Dies at 0. - var/health = 100 /// The message shown when the fish dies. var/death_text = "%SRC dies." @@ -210,14 +211,14 @@ GLOBAL_LIST_INIT(fish_compatible_fluid_types, list( RegisterSignal(src, COMSIG_ATOM_TEMPORARY_ANIMATION_START, PROC_REF(on_temp_animation)) check_flopping() if(status != FISH_DEAD) - ADD_TRAIT(src, TRAIT_UNCOMPOSTABLE, REF(src)) //Composting a food that is not real food wouldn't work anyway. + ADD_TRAIT(src, TRAIT_UNCOMPOSTABLE, REF(src)) //Compost fish only when it's dead. START_PROCESSING(SSobj, src) RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_FISH_STASIS), PROC_REF(enter_stasis)) RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_FISH_STASIS), PROC_REF(exit_stasis)) //Adding this because not all fish have the gore foodtype that makes them automatically eligible for dna infusion. - ADD_TRAIT(src, TRAIT_VALID_DNA_INFUSION, INNATE_TRAIT) + add_traits(list(TRAIT_DUCT_TAPE_UNREPAIRABLE, TRAIT_VALID_DNA_INFUSION), INNATE_TRAIT) //stops new fish from being able to reproduce right away. breeding_wait = world.time + (breeding_timeout * NEW_FISH_BREEDING_TIMEOUT_MULT) @@ -343,7 +344,7 @@ GLOBAL_LIST_INIT(fish_compatible_fluid_types, list( /obj/item/fish/proc/on_fish_cooked(datum/source, cooking_time) SIGNAL_HANDLER SHOULD_NOT_OVERRIDE(TRUE) - adjust_health(0) + damage_fish(max_integrity) //Remove the blood from the reagents holder and reward the player with some extra nutriment added to the fish. var/datum/reagent/consumable/nutriment/protein/protein = reagents.has_reagent(/datum/reagent/consumable/nutriment/protein, check_subtypes = TRUE) @@ -376,7 +377,7 @@ GLOBAL_LIST_INIT(fish_compatible_fluid_types, list( /obj/item/fish/proc/on_fish_cooked_again(datum/source, cooking_time) SIGNAL_HANDLER if(!HAS_TRAIT(src, TRAIT_FISH_SURVIVE_COOKING)) - adjust_health(0) + damage_fish(max_integrity) if(cooking_time >= FISH_SAFE_COOKING_DURATION) well_cooked() @@ -409,7 +410,7 @@ GLOBAL_LIST_INIT(fish_compatible_fluid_types, list( return bites_amount++ var/bites_to_finish = weight / FISH_WEIGHT_BITE_DIVISOR - adjust_health(health - (initial(health) / bites_to_finish) * 3) + damage_fish((max_integrity / bites_to_finish) * 3) flinch_on_eat(eater, feeder) /obj/item/fish/proc/flinch_on_eat(mob/living/eater, mob/living/feeder) @@ -466,8 +467,8 @@ GLOBAL_LIST_INIT(fish_compatible_fluid_types, list( . = ..() if(!reagents) return - reagents.convert_reagent(/datum/reagent/consumable/nutriment/protein, /datum/reagent/consumable/liquidgibs, 0.4, include_source_subtypes = TRUE) - reagents.convert_reagent(/datum/reagent/consumable/nutriment/protein, /datum/reagent/blood, 0.2, include_source_subtypes = TRUE) + reagents.convert_reagent(/datum/reagent/consumable/nutriment/protein, /datum/reagent/consumable/liquidgibs, multiplier = 0.4, include_source_subtypes = TRUE) + reagents.convert_reagent(/datum/reagent/consumable/nutriment/protein, /datum/reagent/blood, multiplier = 0.2, include_source_subtypes = TRUE) ///When processed, the reagents inside this fish will be passed to the created atoms. /obj/item/fish/UsedforProcessing(mob/living/user, obj/item/used_item, list/chosen_option, list/created_atoms) @@ -533,7 +534,7 @@ GLOBAL_LIST_INIT(fish_compatible_fluid_types, list( if(!HAS_TRAIT(src, TRAIT_FISH_STASIS) && !proper_environment()) warnings += "drowning" - var/health_ratio = health / initial(health) + var/health_ratio = get_health_percentage() switch(health_ratio) if(0 to 0.25) warnings += "dying" @@ -992,7 +993,7 @@ GLOBAL_LIST_INIT(fish_compatible_fluid_types, list( switch(new_status) if(FISH_ALIVE) status = FISH_ALIVE - health = initial(health) // since the fishe has been revived + repair_damage(max_integrity) regenerate_bites(bites_amount) last_feeding = world.time //reset hunger check_flopping() @@ -1027,10 +1028,6 @@ GLOBAL_LIST_INIT(fish_compatible_fluid_types, list( if(!isnum(var_value) || var_value == 0) return FALSE update_size_and_weight(size, var_value) - if(NAMEOF(src, health)) - if(!isnum(var_value)) - return FALSE - adjust_health(health) if(NAMEOF(src, fish_flags)) var/old_fish_flags = fish_flags fish_flags = var_value @@ -1204,33 +1201,47 @@ GLOBAL_LIST_INIT(fish_compatible_fluid_types, list( return TRUE /obj/item/fish/proc/process_health(seconds_per_tick) - var/health_change_per_second = 0 + var/health_change = 0 if(!proper_environment()) - health_change_per_second -= 2.5 //Dying here + health_change -= 2.5 //Dying here var/starvation_mult = get_starvation_mult() if(starvation_mult) - health_change_per_second -= 0.25 * starvation_mult //Starving + health_change -= 0.25 * starvation_mult //Starving else - health_change_per_second += 0.5 //Slowly healing + health_change += 0.5 //Slowly healing if(HAS_TRAIT(src, TRAIT_FISH_ON_TESLIUM)) - health_change_per_second -= 0.65 + health_change -= 0.65 - adjust_health(health + health_change_per_second * seconds_per_tick) - -/obj/item/fish/proc/adjust_health(amount) - if(status == FISH_DEAD || amount == health) + if(!health_change) return - var/pre_health = health - var/initial_health = initial(health) - health = clamp(amount, 0, initial_health) - if(health <= 0) - set_status(FISH_DEAD) + + health_change *= seconds_per_tick + if(health_change < 0) + damage_fish(-health_change) + else + repair_damage(health_change) + +///Used to damage this fish while it's still alive. Prevents the fish from taking damage beyond the integrity_failure threshold +/obj/item/fish/proc/damage_fish(amount) + if(status == FISH_DEAD || amount <= 0) return - if(amount < pre_health || !bites_amount) + var/current_integrity = get_integrity() + take_damage(min(amount, current_integrity - max_integrity * integrity_failure), sound_effect = FALSE, armour_penetration = 100) + +/// fish dies when its integrity reaches 50% +/obj/item/fish/atom_break(damage_flag) + . = ..() + set_status(FISH_DEAD) + +/obj/item/fish/repair_damage(amount) + . = ..() + if(!. || !bites_amount) return - var/health_to_pre_health_diff = amount - pre_health - var/init_health_to_pre_diff = initial_health - pre_health - var/bites_to_recover = bites_amount * (health_to_pre_health_diff / init_health_to_pre_diff) + var/current_integrity = get_integrity() + var/old_integrity = current_integrity - amount + var/old_max_integrity_diff = max_integrity - old_integrity + var/percent = (max_integrity - current_integrity) / old_max_integrity_diff + var/bites_to_recover = bites_amount * percent regenerate_bites(bites_to_recover) /obj/item/fish/proc/regenerate_bites(amount) @@ -1240,6 +1251,12 @@ GLOBAL_LIST_INIT(fish_compatible_fluid_types, list( bites_amount -= amount generate_fish_reagents(amount) +/// returns a value between 0 and 1 representing how much integrity the fish has before dying (atom_break) +/obj/item/fish/proc/get_health_percentage() + var/max_health = max_integrity * (1 - integrity_failure) + var/death_thres = max_integrity - max_health + return CLAMP01((get_integrity() - death_thres) / max_health) + /// Returns tracked_fish_by_type but flattened and without the items in the blacklist, also shuffled if shuffle is TRUE. /obj/item/fish/proc/get_aquarium_fishes(shuffle = FALSE, blacklist) . = list() @@ -1257,7 +1274,7 @@ GLOBAL_LIST_INIT(fish_compatible_fluid_types, list( return FALSE if(!being_targeted && length(get_aquarium_fishes()) >= AQUARIUM_MAX_BREEDING_POPULATION) return FALSE - return !HAS_TRAIT(loc, TRAIT_STOP_FISH_REPRODUCTION_AND_GROWTH) && health >= initial(health) * 0.8 && stable_population >= 1 && world.time >= breeding_wait + return !HAS_TRAIT(loc, TRAIT_STOP_FISH_REPRODUCTION_AND_GROWTH) && get_health_percentage() >= 0.8 && stable_population >= 1 && world.time >= breeding_wait /obj/item/fish/proc/try_to_reproduce() if(!loc || !HAS_TRAIT(loc, TRAIT_IS_AQUARIUM)) @@ -1490,7 +1507,7 @@ GLOBAL_LIST_INIT(fish_compatible_fluid_types, list( happiness_value += 2 if(bites_amount) // ouch happiness_value -= 2 - if(health < initial(health) * 0.6) + if(get_health_percentage() < 0.6) happiness_value -= 1 return clamp(happiness_value, FISH_SAD, FISH_VERY_HAPPY) diff --git a/code/modules/fishing/fish/fish_evolution.dm b/code/modules/fishing/fish/fish_evolution.dm index 37ed269970f6..baff1c329164 100644 --- a/code/modules/fishing/fish/fish_evolution.dm +++ b/code/modules/fishing/fish/fish_evolution.dm @@ -56,7 +56,7 @@ GLOBAL_LIST_EMPTY(fishes_by_fish_evolution) /datum/fish_evolution/proc/growth_checks(obj/item/fish/source, seconds_per_tick, growth) SIGNAL_HANDLER SHOULD_CALL_PARENT(TRUE) - if(source.health < initial(source.health) * 0.5) + if(source.get_health_percentage() < 0.5) return COMPONENT_DONT_GROW if(source.get_hunger() >= 0.5) //too hungry to grow return COMPONENT_DONT_GROW diff --git a/code/modules/fishing/fish/fish_traits.dm b/code/modules/fishing/fish/fish_traits.dm index 4aad9b002f56..d81cde8f85d2 100644 --- a/code/modules/fishing/fish/fish_traits.dm +++ b/code/modules/fishing/fish/fish_traits.dm @@ -187,7 +187,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits()) var/turf/turf = get_turf(source) var/light_amount = turf.get_lumcount() if(light_amount > SHADOW_SPECIES_LIGHT_THRESHOLD) - source.adjust_health(source.health - 0.5 * seconds_per_tick) + source.damage_fish(0.5 * seconds_per_tick) /datum/fish_trait/nocturnal/apply_to_mob(mob/living/basic/mob) . = ..() @@ -301,10 +301,10 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits()) for(var/trait in resistance_traits) if(HAS_TRAIT(victim, trait)) continue - victim.adjust_health(victim.health - 3 * seconds_per_tick) //the victim may heal a bit but this will quickly kill + victim.damage_fish(3 * seconds_per_tick) //the victim may heal a bit but this will quickly kill emulsified = TRUE if(emulsified) - source.adjust_health(source.health + 3 * seconds_per_tick) + source.repair_damage(3 * seconds_per_tick) source.sate_hunger() /datum/fish_trait/emulsijack/apply_to_mob(mob/living/basic/mob) @@ -487,7 +487,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits()) /datum/fish_trait/toxic/proc/damage_predator(obj/item/fish/source, seconds_per_tick) SIGNAL_HANDLER - source.adjust_health(source.health - 3 * seconds_per_tick) + source.damage_fish(3 * seconds_per_tick) /datum/fish_trait/toxic/proc/stop_damaging(obj/item/fish/source) SIGNAL_HANDLER @@ -543,7 +543,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits()) continue source.loc.visible_message(span_warning("[source] violently [pick("whips", "bites", "attacks", "slams")] [victim]")) var/damage = round(rand(4, 20) * (source.size / victim.size)) //smaller fishes take extra damage. - victim.adjust_health(victim.health - damage) + victim.damage_fish(damage) return /datum/fish_trait/lubed diff --git a/code/modules/fishing/fish/types/air_space.dm b/code/modules/fishing/fish/types/air_space.dm index 3da406d366c8..82587fca6fc7 100644 --- a/code/modules/fishing/fish/types/air_space.dm +++ b/code/modules/fishing/fish/types/air_space.dm @@ -102,7 +102,7 @@ /obj/item/fish/starfish/proc/add_emissive() if(status == FISH_ALIVE) - return emissive_appearance(icon, "starfish_emissive", src) + return emissive_appearance(icon, "starfish_emissive", src, effect_type = EMISSIVE_NO_BLOOM) ///It spins, and dimly glows in the dark. /obj/item/fish/starfish/flop_animation() @@ -215,7 +215,7 @@ /obj/item/fish/baby_carp/proc/growth_checks(datum/source, seconds_per_tick, growth, result_path) SIGNAL_HANDLER var/hunger = CLAMP01((world.time - last_feeding) / feeding_frequency) - if(health <= initial(health) * 0.6 || hunger >= 0.6) //if too hurt or hungry, don't grow. + if(get_health_percentage() <= 0.6 || hunger >= 0.6) //if too hurt or hungry, don't grow. return COMPONENT_DONT_GROW if(!loc || !HAS_TRAIT(loc, TRAIT_IS_AQUARIUM)) diff --git a/code/modules/fishing/fish/types/anadromous.dm b/code/modules/fishing/fish/types/anadromous.dm index a46ef055c62a..c00263315639 100644 --- a/code/modules/fishing/fish/types/anadromous.dm +++ b/code/modules/fishing/fish/types/anadromous.dm @@ -47,7 +47,7 @@ average_size = 100 average_weight = 2000 breeding_timeout = 4 MINUTES - health = 150 + max_integrity = 300 beauty = FISH_BEAUTY_GOOD required_fluid_type = AQUARIUM_FLUID_ANADROMOUS random_case_rarity = FISH_RARITY_RARE diff --git a/code/modules/fishing/fish/types/freshwater.dm b/code/modules/fishing/fish/types/freshwater.dm index 01c51b59b695..56f4b4d56bc8 100644 --- a/code/modules/fishing/fish/types/freshwater.dm +++ b/code/modules/fishing/fish/types/freshwater.dm @@ -188,7 +188,7 @@ average_weight = 10 sprite_width = 3 sprite_height = 1 - health = 50 + max_integrity = 100 feeding_frequency = 1.5 MINUTES required_temperature_min = MIN_AQUARIUM_TEMP+15 required_temperature_max = MIN_AQUARIUM_TEMP+20 diff --git a/code/modules/fishing/fish/types/mining.dm b/code/modules/fishing/fish/types/mining.dm index bc515d667458..4a701dd72cc2 100644 --- a/code/modules/fishing/fish/types/mining.dm +++ b/code/modules/fishing/fish/types/mining.dm @@ -71,7 +71,7 @@ /obj/item/fish/chasm_crab/proc/growth_checks(datum/source, seconds_per_tick, growth, result_path) SIGNAL_HANDLER var/hunger = get_hunger() - if(health <= initial(health) * 0.6 || hunger >= 0.6) //if too hurt or hungry, don't grow. + if(get_health_percentage() <= 0.6 || hunger >= 0.6) //if too hurt or hungry, don't grow. anger += growth * 2 return COMPONENT_DONT_GROW @@ -124,7 +124,7 @@ random_case_rarity = FISH_RARITY_GOOD_LUCK_FINDING_THIS required_fluid_type = AQUARIUM_FLUID_ANY_WATER min_pressure = HAZARD_LOW_PRESSURE - health = 150 + max_integrity = 300 stable_population = 3 grind_results = list(/datum/reagent/bone_dust = 10) fillet_type = /obj/item/stack/sheet/bone diff --git a/code/modules/fishing/fish/types/rift.dm b/code/modules/fishing/fish/types/rift.dm index 38da61dff65b..eb72c82ac448 100644 --- a/code/modules/fishing/fish/types/rift.dm +++ b/code/modules/fishing/fish/types/rift.dm @@ -28,7 +28,7 @@ average_weight = 1500 food = /datum/reagent/bluespace feeding_frequency = 10 MINUTES - health = 50 + max_integrity = 100 death_text = "%SRC splinters apart into shards!" random_case_rarity = FISH_RARITY_GOOD_LUCK_FINDING_THIS fillet_type = /obj/item/stack/ore/bluespace_crystal @@ -136,7 +136,8 @@ required_temperature_min = BODYTEMP_COLD_DAMAGE_LIMIT // you mean just like a human? that's odd... required_temperature_max = BODYTEMP_HEAT_DAMAGE_LIMIT food = /datum/reagent/blood - health = 600 // apex predator + max_integrity = 800 // apex predator + integrity_failure = 0.25 random_case_rarity = FISH_RARITY_GOOD_LUCK_FINDING_THIS fillet_type = /obj/item/food/fishmeat/fish_tail num_fillets = 1 @@ -339,7 +340,7 @@ for(var/mob/living/fallen_mob in falling_movables) visible_message(span_danger("[src] flattens like a pancake as [fallen_mob] lands on top of it!")) - adjust_health(initial(health) * 0.1) // very durable + damage_fish(max_integrity * integrity_failure * 0.9) // very "durable" AddElement(/datum/element/squish, 15 SECONDS) fallen_mob.Paralyze(0.5 SECONDS) playsound(src, 'sound/effects/cartoon_sfx/cartoon_splat.ogg', 75) @@ -367,7 +368,7 @@ food = /datum/reagent/silicon feeding_frequency = 30 SECONDS - health = 160 + max_integrity = 320 death_text = "%SRC calcifies." random_case_rarity = FISH_RARITY_GOOD_LUCK_FINDING_THIS fillet_type = /obj/item/stack/sheet/mineral/diamond @@ -429,7 +430,8 @@ sprite_width = 12 sprite_height = 13 - health = 500 + max_integrity = 750 + integrity_failure = 0.33 death_text = "%SRC decomposes." random_case_rarity = FISH_RARITY_NOPE // hand-tuned to be a your worst enemy @@ -521,7 +523,7 @@ death_text = span_big(span_alertalien("%SRC emits a horrendous wailing as it perishes!")) random_case_rarity = FISH_RARITY_NOPE - health = 250 + max_integrity = 500 average_size = 30 average_weight = 2000 fillet_type = /obj/item/food/fishmeat/quality @@ -772,7 +774,7 @@ antimagic_flags = MAGIC_RESISTANCE_MIND, \ inventory_flags = null, \ charges = maxHealth * 0.1, \ - drain_antimagic = CALLBACK(src, PROC_REF(on_drain_magic)), \ + block_magic = CALLBACK(src, PROC_REF(on_drain_magic)), \ expiration = CALLBACK(src, PROC_REF(on_expire)), \ ) diff --git a/code/modules/fishing/fish/types/ruins.dm b/code/modules/fishing/fish/types/ruins.dm index 627bb5136a8a..83d890ea9919 100644 --- a/code/modules/fishing/fish/types/ruins.dm +++ b/code/modules/fishing/fish/types/ruins.dm @@ -14,7 +14,7 @@ fishing_difficulty_modifier = 30 required_fluid_type = AQUARIUM_FLUID_ANY_WATER min_pressure = HAZARD_LOW_PRESSURE - health = 300 + max_integrity = 600 stable_population = 1 //This means they can only crossbreed. grind_results = list(/datum/reagent/bone_dust = 5, /datum/reagent/consumable/liquidgibs = 5) fillet_type = /obj/item/stack/sheet/bone diff --git a/code/modules/fishing/fish/types/saltwater.dm b/code/modules/fishing/fish/types/saltwater.dm index 522befdeb506..cf1f1fa889a2 100644 --- a/code/modules/fishing/fish/types/saltwater.dm +++ b/code/modules/fishing/fish/types/saltwater.dm @@ -167,7 +167,7 @@ average_weight = 4000 breeding_timeout = 4.5 MINUTES feeding_frequency = 4 MINUTES - health = 180 + max_integrity = 360 beauty = FISH_BEAUTY_EXCELLENT random_case_rarity = FISH_RARITY_GOOD_LUCK_FINDING_THIS required_fluid_type = AQUARIUM_FLUID_SALTWATER diff --git a/code/modules/fishing/fish/types/station.dm b/code/modules/fishing/fish/types/station.dm index a6842daf318e..40196c375ec5 100644 --- a/code/modules/fishing/fish/types/station.dm +++ b/code/modules/fishing/fish/types/station.dm @@ -51,7 +51,7 @@ stable_population = 8 average_size = 20 average_weight = 400 - health = 50 + max_integrity = 100 breeding_timeout = 2.5 MINUTES fish_traits = list(/datum/fish_trait/parthenogenesis, /datum/fish_trait/no_mating) required_temperature_min = MIN_AQUARIUM_TEMP+10 @@ -82,7 +82,7 @@ random_case_rarity = FISH_RARITY_VERY_RARE required_fluid_type = AQUARIUM_FLUID_ANADROMOUS stable_population = 4 - health = 150 + max_integrity = 300 fillet_type = /obj/item/slime_extract/grey fish_traits = list(/datum/fish_trait/toxin_immunity, /datum/fish_trait/crossbreeder) favorite_bait = list( @@ -263,7 +263,7 @@ sprite_height = 4 average_size = 150 average_weight = 6000 - health = 125 + max_integrity = 250 feeding_frequency = 5 MINUTES breeding_timeout = 5 MINUTES random_case_rarity = FISH_RARITY_NOPE diff --git a/code/modules/fishing/fish/types/syndicate.dm b/code/modules/fishing/fish/types/syndicate.dm index 83147031c4d3..1d290aa1e18a 100644 --- a/code/modules/fishing/fish/types/syndicate.dm +++ b/code/modules/fishing/fish/types/syndicate.dm @@ -104,7 +104,7 @@ average_weight = 2500 breeding_timeout = 4.25 MINUTES feeding_frequency = 3 MINUTES - health = 180 + max_integrity = 360 beauty = FISH_BEAUTY_GREAT random_case_rarity = FISH_RARITY_GOOD_LUCK_FINDING_THIS required_fluid_type = AQUARIUM_FLUID_FRESHWATER @@ -236,7 +236,7 @@ average_weight = 3000 breeding_timeout = 5 MINUTES feeding_frequency = 4 MINUTES - health = 180 + max_integrity = 360 random_case_rarity = FISH_RARITY_GOOD_LUCK_FINDING_THIS beauty = FISH_BEAUTY_GREAT fishing_difficulty_modifier = 20 diff --git a/code/modules/fishing/fishing_minigame.dm b/code/modules/fishing/fishing_minigame.dm index 0d42be519c2a..923c496371ac 100644 --- a/code/modules/fishing/fishing_minigame.dm +++ b/code/modules/fishing/fishing_minigame.dm @@ -512,7 +512,7 @@ GLOBAL_LIST_EMPTY(fishing_challenges_by_user) SIGNAL_HANDLER if(istype(reward)) var/damage = CEILING((world.time - start_time)/10 * FISH_DAMAGE_PER_SECOND, 1) - reward.adjust_health(reward.health - damage) + reward.damage_fish(damage) /datum/fishing_challenge/proc/get_difficulty() var/list/difficulty_holder = list(0) @@ -599,7 +599,7 @@ GLOBAL_LIST_EMPTY(fishing_challenges_by_user) deltimer(next_phase_timer) if((FISHING_MINIGAME_RULE_KILL in special_effects) && ispath(reward_path,/obj/item/fish)) var/obj/item/fish/fish = reward_path - var/wait_time = (initial(fish.health) / FISH_DAMAGE_PER_SECOND) SECONDS + var/wait_time = ((initial(fish.max_integrity) * (1 - initial(fish.integrity_failure))) / FISH_DAMAGE_PER_SECOND) SECONDS addtimer(CALLBACK(src, PROC_REF(win_anyway)), wait_time, TIMER_DELETE_ME) else if(ismovable(reward_path)) var/atom/movable/reward = reward_path @@ -926,7 +926,7 @@ GLOBAL_LIST_EMPTY(fishing_challenges_by_user) var/mutable_appearance/overlay = mutable_appearance(icon, "lure_light") overlay.color = spin_ready ? COLOR_GREEN : COLOR_RED . += overlay - . += emissive_appearance(icon, "lure_light_emissive", src, alpha = src.alpha) + . += emissive_appearance(icon, "lure_light_emissive", src, alpha = src.alpha, effect_type = EMISSIVE_NO_BLOOM) #undef WAIT_PHASE #undef BITING_PHASE diff --git a/code/modules/fishing/sources/subtypes/structures.dm b/code/modules/fishing/sources/subtypes/structures.dm index 70afbc182ee2..2adf204cc141 100644 --- a/code/modules/fishing/sources/subtypes/structures.dm +++ b/code/modules/fishing/sources/subtypes/structures.dm @@ -385,19 +385,24 @@ /datum/fish_source/vending/custom catalog_description = null //no duplicate entries on autowiki or catalog -/datum/fish_source/vending/custom/get_vending_table(obj/item/fishing_rod/rod, mob/fisherman, obj/machinery/vending/location) +/datum/fish_source/vending/custom/get_vending_table(obj/item/fishing_rod/rod, mob/fisherman, obj/machinery/vending/custom/location) var/list/table = list() ///Create a list of products, ordered by price from highest to lowest - var/list/products = location.vending_machine_input.Copy() + var/list/products = location.contents - location.component_parts sortTim(products, GLOBAL_PROC_REF(cmp_item_vending_prices)) var/bait_value = rod.bait?.get_item_credit_value() || 1 var/highest_record_price = 0 for(var/obj/item/stocked as anything in products) - if(location.vending_machine_input[stocked] <= 0) - products -= stocked - table[FISHING_DUD] += PAYCHECK_LOWER //it gets harder the emptier the machine is + //count how many items of this type are in the machine + var/item_count = 1 + for(var/obj/item/thing as anything in products) + if(stocked.type == thing.type) + item_count += 1 + //find what percentage of the total storage space this item occupies. + if(ROUND_UP((item_count / location.max_loaded_items) * 100) <= 20) + table[FISHING_DUD] += PAYCHECK_LOWER //it gets harder if it occupies less than 20% of the available space i.e the more free space is inside this machine continue if(!highest_record_price) highest_record_price = stocked.custom_price @@ -405,7 +410,7 @@ var/low = min(highest_record_price, bait_value) //the smaller the difference between product price and bait value, the more likely you're to get it. - table[stocked] = low/high * 1000 //multiply the value by 1000 for accuracy. pick_weight() doesn't work with zero decimals yet. + table[stocked] = (low / high) * 1000 //multiply the value by 1000 for accuracy. pick_weight() doesn't work with zero decimals yet. add_risks(table, bait_value, highest_record_price, length(products) * 0.5) return table diff --git a/code/modules/food_and_drinks/machinery/processor.dm b/code/modules/food_and_drinks/machinery/processor.dm index 374a5ed92bbd..859628abc987 100644 --- a/code/modules/food_and_drinks/machinery/processor.dm +++ b/code/modules/food_and_drinks/machinery/processor.dm @@ -72,7 +72,7 @@ var/atom/processed_food = new recipe.output(drop_location()) if(processed_food.reagents && what.reagents) processed_food.reagents.clear_reagents() - what.reagents.copy_to(processed_food, what.reagents.total_volume, multiplier = 1 / cached_multiplier) + what.reagents.trans_to(processed_food, what.reagents.total_volume, multiplier = 1 / cached_multiplier, copy_only = TRUE) if(cached_mats) processed_food.set_custom_materials(cached_mats, 1 / cached_multiplier) diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_bread.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_bread.dm index c09767282c3c..574b70ce41f7 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_bread.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_bread.dm @@ -88,7 +88,7 @@ /datum/crafting_recipe/food/garlicbread name = "Garlic Bread" - time = 40 + time = 4 SECONDS reqs = list(/obj/item/food/grown/garlic = 1, /obj/item/food/breadslice/plain = 1, /obj/item/food/butterslice = 1 @@ -117,7 +117,7 @@ /datum/crafting_recipe/food/baguette name = "Baguette" - time = 40 + time = 4 SECONDS reqs = list(/datum/reagent/consumable/salt = 1, /datum/reagent/consumable/blackpepper = 1, /obj/item/food/doughslice = 2, diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_drink.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_drink.dm index 74c1ce5f6d3d..3f62c324a128 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_drink.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_drink.dm @@ -4,7 +4,7 @@ /datum/crafting_recipe/lizardwine name = "Lizard Wine" - time = 40 + time = 4 SECONDS reqs = list( /obj/item/organ/tail/lizard = 1, /datum/reagent/consumable/ethanol = 100 @@ -15,7 +15,7 @@ /datum/crafting_recipe/moonshinejug name = "Moonshine Jug" - time = 30 + time = 3 SECONDS reqs = list( /obj/item/reagent_containers/cup/glass/bottle = 1, /datum/reagent/consumable/ethanol/moonshine = 100 @@ -25,7 +25,7 @@ /datum/crafting_recipe/hoochbottle name = "Hooch Bottle" - time = 30 + time = 3 SECONDS reqs = list( /obj/item/reagent_containers/cup/glass/bottle = 1, /obj/item/storage/box/papersack = 1, @@ -36,7 +36,7 @@ /datum/crafting_recipe/blazaambottle name = "Blazaam Bottle" - time = 20 + time = 2 SECONDS reqs = list( /obj/item/reagent_containers/cup/glass/bottle = 1, /datum/reagent/consumable/ethanol/blazaam = 100 @@ -46,7 +46,7 @@ /datum/crafting_recipe/champagnebottle name = "Champagne Bottle" - time = 30 + time = 3 SECONDS reqs = list( /obj/item/reagent_containers/cup/glass/bottle = 1, /datum/reagent/consumable/ethanol/champagne = 100 @@ -56,7 +56,7 @@ /datum/crafting_recipe/trappistbottle name = "Trappist Bottle" - time = 15 + time = 1.5 SECONDS reqs = list( /obj/item/reagent_containers/cup/glass/bottle/small = 1, /datum/reagent/consumable/ethanol/trappist = 50 @@ -66,7 +66,7 @@ /datum/crafting_recipe/goldschlagerbottle name = "Goldschlager Bottle" - time = 30 + time = 3 SECONDS reqs = list( /obj/item/reagent_containers/cup/glass/bottle = 1, /datum/reagent/consumable/ethanol/goldschlager = 100 @@ -76,7 +76,7 @@ /datum/crafting_recipe/patronbottle name = "Patron Bottle" - time = 30 + time = 3 SECONDS reqs = list( /obj/item/reagent_containers/cup/glass/bottle = 1, /datum/reagent/consumable/ethanol/patron = 100 @@ -88,7 +88,7 @@ /datum/crafting_recipe/holybottle name = "Holy Water Flask" - time = 30 + time = 3 SECONDS reqs = list( /obj/item/reagent_containers/cup/glass/bottle = 1, /datum/reagent/water/holywater = 100 @@ -100,7 +100,7 @@ /datum/crafting_recipe/nothingbottle name = "Nothing Bottle" - time = 30 + time = 3 SECONDS reqs = list( /obj/item/reagent_containers/cup/glass/bottle = 1, /datum/reagent/consumable/nothing = 100 @@ -111,14 +111,14 @@ /datum/crafting_recipe/smallcarton name = "Small Carton" result = /obj/item/reagent_containers/cup/glass/bottle/juice/smallcarton - time = 10 + time = 1 SECONDS reqs = list(/obj/item/stack/sheet/cardboard = 1) category = CAT_CONTAINERS /datum/crafting_recipe/candycornliquor name = "candy corn liquor" result = /obj/item/reagent_containers/cup/glass/bottle/candycornliquor - time = 30 + time = 3 SECONDS reqs = list(/datum/reagent/consumable/ethanol/whiskey = 100, /obj/item/food/candy_corn = 1, /obj/item/reagent_containers/cup/glass/bottle = 1) @@ -127,7 +127,7 @@ /datum/crafting_recipe/kong name = "Kong" result = /obj/item/reagent_containers/cup/glass/bottle/kong - time = 30 + time = 3 SECONDS reqs = list(/datum/reagent/consumable/ethanol/whiskey = 100, /obj/item/food/monkeycube = 1, /obj/item/reagent_containers/cup/glass/bottle = 1) @@ -136,7 +136,7 @@ /datum/crafting_recipe/pruno name = "pruno mix" result = /obj/item/reagent_containers/cup/glass/bottle/pruno - time = 30 + time = 3 SECONDS reqs = list(/obj/item/storage/bag/trash = 1, /obj/item/food/breadslice/moldy = 1, /obj/item/food/grown = 4, diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_lizard.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_lizard.dm index 5a0ba09e413c..24f951cbfe37 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_lizard.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_lizard.dm @@ -196,6 +196,7 @@ result = /obj/item/food/rootdough added_foodtypes = NUTS category = CAT_LIZARD + crafting_flags = CRAFT_CLEARS_REAGENTS /datum/crafting_recipe/food/rootdough/with_eggs name = "Rootdough (With Eggs)" @@ -207,6 +208,7 @@ ) result = /obj/item/food/rootdough/egg removed_foodtypes = RAW + crafting_flags = CRAFT_CLEARS_REAGENTS /datum/crafting_recipe/food/snail_nizaya name = "Desert snail nizaya" diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_mexican.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_mexican.dm index 2991d9d5c118..a9ad9debd011 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_mexican.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_mexican.dm @@ -107,7 +107,7 @@ /datum/crafting_recipe/food/stuffedlegion name = "Stuffed legion" - time = 40 + time = 4 SECONDS reqs = list( /obj/item/food/meat/steak/goliath = 1, /obj/item/organ/monster_core/regenerative_core/legion = 1, diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm index 40051d67cb59..1dead375c9fe 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm @@ -72,7 +72,7 @@ /datum/crafting_recipe/food/beans name = "Beans" - time = 40 + time = 4 SECONDS reqs = list(/datum/reagent/consumable/ketchup = 5, /obj/item/food/grown/soybeans = 2 ) @@ -111,7 +111,7 @@ /datum/crafting_recipe/food/powercrepe name = "Powercrepe" - time = 40 + time = 4 SECONDS reqs = list( /obj/item/food/flatdough = 1, /datum/reagent/consumable/milk = 1, 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 d3c761a64f1e..acf3109431cb 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm @@ -4,7 +4,7 @@ ////////////////////////////////////////////////DONUTS//////////////////////////////////////////////// /datum/crafting_recipe/food/donut - time = 15 + time = 1.5 SECONDS name = "Donut" reqs = list( /datum/reagent/consumable/sugar = 1, @@ -26,7 +26,7 @@ result = /obj/item/food/donut/chaos /datum/crafting_recipe/food/donut/meat - time = 15 + time = 1.5 SECONDS name = "Meat donut" reqs = list( /obj/item/food/meat/rawcutlet = 1, @@ -287,7 +287,7 @@ ////////////////////////////////////////////////WAFFLES//////////////////////////////////////////////// /datum/crafting_recipe/food/waffles - time = 15 + time = 1.5 SECONDS name = "Waffles" reqs = list( /obj/item/food/pastrybase = 2 @@ -330,7 +330,7 @@ ////////////////////////////////////////////////DONKPOCCKETS//////////////////////////////////////////////// /datum/crafting_recipe/food/donkpocket - time = 15 + time = 1.5 SECONDS name = "Donk-pocket" reqs = list( /obj/item/food/doughslice = 1, @@ -340,7 +340,7 @@ category = CAT_PASTRY /datum/crafting_recipe/food/dankpocket - time = 15 + time = 1.5 SECONDS name = "Dank-pocket" reqs = list( /obj/item/food/doughslice = 1, @@ -350,7 +350,7 @@ category = CAT_PASTRY /datum/crafting_recipe/food/donkpocket/spicy - time = 15 + time = 1.5 SECONDS name = "Spicy-pocket" reqs = list( /obj/item/food/doughslice = 1, @@ -361,7 +361,7 @@ category = CAT_PASTRY /datum/crafting_recipe/food/donkpocket/teriyaki - time = 15 + time = 1.5 SECONDS name = "Teriyaki-pocket" reqs = list( /obj/item/food/doughslice = 1, @@ -372,7 +372,7 @@ category = CAT_PASTRY /datum/crafting_recipe/food/donkpocket/pizza - time = 15 + time = 1.5 SECONDS name = "Pizza-pocket" reqs = list( /obj/item/food/doughslice = 1, @@ -383,7 +383,7 @@ category = CAT_PASTRY /datum/crafting_recipe/food/donkpocket/honk - time = 15 + time = 1.5 SECONDS name = "Honk-Pocket" reqs = list( /obj/item/food/doughslice = 1, @@ -395,7 +395,7 @@ category = CAT_PASTRY /datum/crafting_recipe/food/donkpocket/berry - time = 15 + time = 1.5 SECONDS name = "Berry-pocket" reqs = list( /obj/item/food/doughslice = 1, @@ -406,7 +406,7 @@ category = CAT_PASTRY /datum/crafting_recipe/food/donkpocket/gondola - time = 15 + time = 1.5 SECONDS name = "Gondola-pocket" reqs = list( /obj/item/food/doughslice = 1, @@ -417,7 +417,7 @@ category = CAT_PASTRY /datum/crafting_recipe/food/donkpocket/deluxe - time = 15 + time = 1.5 SECONDS name = "Deluxe Donk-pocket" reqs = list( /obj/item/food/doughslice = 1, @@ -431,7 +431,7 @@ crafting_flags = parent_type::crafting_flags | CRAFT_MUST_BE_LEARNED /datum/crafting_recipe/food/donkpocket/deluxe/nocarb - time = 15 + time = 1.5 SECONDS name = "Deluxe Meat-pocket" reqs = list( /obj/item/organ/heart = 1, @@ -444,7 +444,7 @@ category = CAT_PASTRY /datum/crafting_recipe/food/donkpocket/deluxe/vegan - time = 15 + time = 1.5 SECONDS name = "Deluxe Donk-roll" reqs = list( /obj/item/food/doughslice = 1, @@ -459,7 +459,7 @@ ////////////////////////////////////////////////MUFFINS//////////////////////////////////////////////// /datum/crafting_recipe/food/muffin - time = 15 + time = 1.5 SECONDS name = "Muffin" reqs = list( /datum/reagent/consumable/milk = 5, @@ -508,7 +508,7 @@ category = CAT_PASTRY /datum/crafting_recipe/food/sugarcookie - time = 15 + time = 1.5 SECONDS name = "Sugar cookie" reqs = list( /datum/reagent/consumable/sugar = 5, @@ -519,7 +519,7 @@ category = CAT_PASTRY /datum/crafting_recipe/food/spookyskull - time = 15 + time = 1.5 SECONDS name = "Skull cookie" reqs = list( /obj/item/food/pastrybase = 1, @@ -531,7 +531,7 @@ category = CAT_PASTRY /datum/crafting_recipe/food/spookycoffin - time = 15 + time = 1.5 SECONDS name = "Coffin cookie" reqs = list( /obj/item/food/pastrybase = 1, @@ -543,7 +543,7 @@ category = CAT_PASTRY /datum/crafting_recipe/food/fortunecookie - time = 15 + time = 1.5 SECONDS name = "Fortune cookie" reqs = list( /obj/item/food/pastrybase = 1, @@ -557,7 +557,7 @@ category = CAT_PASTRY /datum/crafting_recipe/food/poppypretzel - time = 15 + time = 1.5 SECONDS name = "Poppy pretzel" reqs = list( /obj/item/seeds/poppy = 1, @@ -568,7 +568,7 @@ category = CAT_PASTRY /datum/crafting_recipe/food/plumphelmetbiscuit - time = 15 + time = 1.5 SECONDS name = "Plumphelmet biscuit" reqs = list( /obj/item/food/pastrybase = 1, @@ -578,7 +578,7 @@ category = CAT_PASTRY /datum/crafting_recipe/food/cracker - time = 15 + time = 1.5 SECONDS name = "Cracker" reqs = list( /datum/reagent/consumable/salt = 1, diff --git a/code/modules/hydroponics/unique_plant_genes.dm b/code/modules/hydroponics/unique_plant_genes.dm index c35bf6e7a0e7..1691dbecfb13 100644 --- a/code/modules/hydroponics/unique_plant_genes.dm +++ b/code/modules/hydroponics/unique_plant_genes.dm @@ -21,7 +21,7 @@ antimagic_flags = MAGIC_RESISTANCE|MAGIC_RESISTANCE_HOLY, \ inventory_flags = ITEM_SLOT_HANDS, \ charges = shield_uses, \ - drain_antimagic = CALLBACK(src, PROC_REF(drain_antimagic)), \ + block_magic = CALLBACK(src, PROC_REF(drain_antimagic)), \ expiration = CALLBACK(src, PROC_REF(expire)), \ ) diff --git a/code/modules/instruments/piano_synth.dm b/code/modules/instruments/piano_synth.dm index 25c65e656c37..f0357eb789c9 100644 --- a/code/modules/instruments/piano_synth.dm +++ b/code/modules/instruments/piano_synth.dm @@ -63,7 +63,7 @@ worn_icon = 'icons/mob/clothing/ears.dmi' inhand_icon_state = null slot_flags = ITEM_SLOT_EARS - strip_delay = 100 //air pods don't fall out + strip_delay = 10 SECONDS //air pods don't fall out instrument_range = 0 //you're paying for quality here custom_premium_price = PAYCHECK_CREW * 36 //Save up 5 shifts worth of pay just to lose it down a drainpipe on the sidewalk diff --git a/code/modules/instruments/stationary.dm b/code/modules/instruments/stationary.dm index c9b826392402..621ecc664ed3 100644 --- a/code/modules/instruments/stationary.dm +++ b/code/modules/instruments/stationary.dm @@ -46,6 +46,8 @@ /obj/structure/musician/piano/Initialize(mapload) . = ..() AddElement(/datum/element/falling_hazard, damage = 60, wound_bonus = 10, hardhat_safety = FALSE, crushes = TRUE, impact_sound = 'sound/effects/piano_hit.ogg') + AddElement(/datum/element/climbable) + AddElement(/datum/element/elevation, pixel_shift = 10) /obj/structure/musician/piano/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) switch(damage_type) diff --git a/code/modules/jobs/access.dm b/code/modules/jobs/access.dm index 9d2d443fd37d..d384bac67e03 100644 --- a/code/modules/jobs/access.dm +++ b/code/modules/jobs/access.dm @@ -79,8 +79,8 @@ /obj/item/proc/GetID() return null -/obj/item/proc/RemoveID() +/obj/item/proc/remove_id() return null -/obj/item/proc/InsertID() +/obj/item/proc/insert_id() return FALSE diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm index 59078c8507fe..869c59c7044e 100644 --- a/code/modules/jobs/job_types/_job.dm +++ b/code/modules/jobs/job_types/_job.dm @@ -411,7 +411,7 @@ card.registered_account = account account.bank_cards += card - equipped.sec_hud_set_ID() + equipped.update_ID_card() var/obj/item/modular_computer/pda/pda = equipped.get_item_by_slot(pda_slot) diff --git a/code/modules/jobs/job_types/chaplain/chaplain_costumes.dm b/code/modules/jobs/job_types/chaplain/chaplain_costumes.dm index 9bd6436994df..2bc8ffdaf32c 100644 --- a/code/modules/jobs/job_types/chaplain/chaplain_costumes.dm +++ b/code/modules/jobs/job_types/chaplain/chaplain_costumes.dm @@ -14,8 +14,8 @@ cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS armor_type = /datum/armor/chaplainsuit_armor - strip_delay = 80 - equip_delay_other = 60 + strip_delay = 8 SECONDS + equip_delay_other = 6 SECONDS /datum/armor/chaplainsuit_armor melee = 50 @@ -130,20 +130,10 @@ desc = "It has the unyielding gaze of a god eternally forgotten." icon_state = "clockwork_helmet" inhand_icon_state = null - armor_type = /datum/armor/chaplain_clock flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH - strip_delay = 8 SECONDS dog_fashion = null -/datum/armor/chaplain_clock - melee = 50 - bullet = 10 - laser = 10 - energy = 10 - fire = 80 - acid = 80 - /obj/item/clothing/suit/chaplainsuit/armor/clock name = "forgotten armour" desc = "It sounds like hissing steam, ticking cogs, gone silent, It looks like a dead machine, trying to tick with life." @@ -162,20 +152,12 @@ worn_icon = 'icons/mob/clothing/head/chaplain.dmi' icon_state = "knight_templar" inhand_icon_state = null - armor_type = /datum/armor/helmet_chaplain + armor_type = /datum/armor/chaplainsuit_armor flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH - strip_delay = 80 + strip_delay = 8 SECONDS dog_fashion = null -/datum/armor/helmet_chaplain - melee = 50 - bullet = 10 - laser = 10 - energy = 10 - fire = 80 - acid = 80 - /obj/item/clothing/suit/chaplainsuit/armor/templar name = "crusader armour" desc = "God wills it!" @@ -206,6 +188,7 @@ desc = "Defend the treasure..." icon_state = "knight_ancient" inhand_icon_state = null + body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS /obj/item/clothing/suit/chaplainsuit/armor/ancient/Initialize(mapload) . = ..() @@ -232,6 +215,7 @@ desc = "The ideal outfit for burning the unfaithful." icon_state = "crusader" inhand_icon_state = null + body_parts_covered = CHEST|GROIN|LEGS /obj/item/clothing/suit/chaplainsuit/armor/crusader name = "crusader's armour" diff --git a/code/modules/jobs/job_types/chaplain/chaplain_divine_archer.dm b/code/modules/jobs/job_types/chaplain/chaplain_divine_archer.dm index 3eea5f79aa5c..c0c2a499d3f0 100644 --- a/code/modules/jobs/job_types/chaplain/chaplain_divine_archer.dm +++ b/code/modules/jobs/job_types/chaplain/chaplain_divine_archer.dm @@ -16,12 +16,12 @@ desc = "Outer coat for divine archers. Offers some protection." icon_state = "archercoat" inhand_icon_state = "archercoat" - body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + body_parts_covered = CHEST|GROIN|LEGS cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS armor_type = /datum/armor/chaplainsuit_armor_weaker - strip_delay = 80 - equip_delay_other = 60 + strip_delay = 8 SECONDS + equip_delay_other = 6 SECONDS hoodtype = /obj/item/clothing/head/hooded/chaplain_hood/divine_archer hood_up_affix = "" @@ -47,9 +47,11 @@ desc = "Bracers, a wise choice for archers who do not want their outfit to get in the way of drawing and firing their weapon." icon_state = "archerbracers" inhand_icon_state = "archerbracers" - strip_delay = 40 - equip_delay_other = 20 + body_parts_covered = ARMS|HANDS + strip_delay = 4 SECONDS + equip_delay_other = 2 SECONDS resistance_flags = NONE + armor_type = /datum/armor/chaplainsuit_armor_weaker /// boots /obj/item/clothing/shoes/divine_archer @@ -57,7 +59,18 @@ desc = "Boots, For steady footing while aiming." icon_state = "archerboots" inhand_icon_state = "archerboots" - strip_delay = 30 - equip_delay_other = 50 + body_parts_covered = LEGS|FEET + strip_delay = 3 SECONDS + equip_delay_other = 5 SECONDS resistance_flags = NONE fastening_type = SHOES_SLIPON + armor_type = /datum/armor/shoes_divine_archer + +/datum/armor/shoes_divine_archer + melee = 10 + bullet = 5 + laser = 5 + energy = 5 + fire = 60 + acid = 60 + wound = 10 diff --git a/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm b/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm index 2c512ba59fae..de65b4e7021a 100644 --- a/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm +++ b/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm @@ -36,26 +36,33 @@ effects_we_clear = list(/obj/effect/rune, /obj/effect/heretic_rune, /obj/effect/cosmic_rune), \ ) AddElement(/datum/element/bane, mob_biotypes = MOB_SPIRIT, damage_multiplier = 0, added_damage = 25, requires_combat_mode = FALSE) + ADD_TRAIT(src, TRAIT_NULLROD_ITEM, INNATE_TRAIT) - if((!GLOB.holy_weapon_type || !station_holy_item) && type == /obj/item/nullrod) - var/list/rods = list() - for(var/obj/item/nullrod/nullrod_type as anything in typesof(/obj/item/nullrod)) - if(!initial(nullrod_type.chaplain_spawnable)) - continue - rods[nullrod_type] = initial(nullrod_type.menu_description) - //special non-nullrod subtyped shit - rods[/obj/item/gun/ballistic/bow/divine/with_quiver] = "A divine bow and 10 quivered holy arrows." - rods[/obj/item/organ/cyberimp/arm/toolkit/shard/scythe] = "A shard that implants itself into your arm, \ - allowing you to conjure forth a vorpal scythe. \ - Allows you to behead targets for empowered strikes. \ - Harms you if you dismiss the scythe without first causing harm to a creature. \ - The shard also causes you to become Morbid, shifting your interests towards the macabre." - rods[/obj/item/melee/skateboard/holyboard] = "A skateboard that grants you flight and anti-magic abilities while ridden. Fits in your bag." - AddComponent(/datum/component/subtype_picker, rods, CALLBACK(src, PROC_REF(on_holy_weapon_picked))) + if((GLOB.holy_weapon_type && station_holy_item) || type != /obj/item/nullrod) + return + + var/list/rods = list() + for(var/obj/item/nullrod/nullrod_type as anything in typesof(/obj/item/nullrod)) + if(!initial(nullrod_type.chaplain_spawnable)) + continue + rods[nullrod_type] = initial(nullrod_type.menu_description) + //special non-nullrod subtyped shit + rods[/obj/item/gun/ballistic/bow/divine/with_quiver] = "A divine bow and 10 quivered holy arrows." + rods[/obj/item/organ/cyberimp/arm/toolkit/shard/scythe] = "A shard that implants itself into your arm, \ + allowing you to conjure forth a vorpal scythe. \ + Allows you to behead targets for empowered strikes. \ + Harms you if you dismiss the scythe without first causing harm to a creature. \ + The shard also causes you to become Morbid, shifting your interests towards the macabre." + rods[/obj/item/melee/skateboard/holyboard] = "A skateboard that grants you flight and anti-magic abilities while ridden. Fits in your bag." + AddComponent(/datum/component/subtype_picker, rods, CALLBACK(src, PROC_REF(on_holy_weapon_picked))) /// Callback for subtype picker, invoked when the chaplain picks a new nullrod /obj/item/nullrod/proc/on_holy_weapon_picked(obj/item/nullrod/new_holy_weapon, mob/living/picker) - new_holy_weapon.on_selected(src, picker) + // Some nullrod variants aren't nullrod subtypes + if(istype(new_holy_weapon)) + new_holy_weapon.on_selected(src, picker) + else // In which case they still need to be marked as one + ADD_TRAIT(new_holy_weapon, TRAIT_NULLROD_ITEM, INNATE_TRAIT) if(!station_holy_item) return GLOB.holy_weapon_type = new_holy_weapon.type diff --git a/code/modules/jobs/job_types/chaplain/chaplain_vorpal_scythe.dm b/code/modules/jobs/job_types/chaplain/chaplain_vorpal_scythe.dm index 57a786bd20dd..f521b7603ec5 100644 --- a/code/modules/jobs/job_types/chaplain/chaplain_vorpal_scythe.dm +++ b/code/modules/jobs/job_types/chaplain/chaplain_vorpal_scythe.dm @@ -11,6 +11,11 @@ If the scythe isn't empowered when you sheath it, you take a heap of damage and items_to_create = list(/obj/item/vorpalscythe) organ_traits = list(TRAIT_MORBID) +/obj/item/organ/cyberimp/arm/toolkit/shard/scythe/Initialize(mapload) + . = ..() + for (var/obj/item/scythe as anything in items_list) + ADD_TRAIT(scythe, TRAIT_NULLROD_ITEM, INNATE_TRAIT) + /obj/item/organ/cyberimp/arm/toolkit/shard/scythe/Retract() var/obj/item/vorpalscythe/scythe = active_item if(!scythe) diff --git a/code/modules/jobs/job_types/head_of_personnel.dm b/code/modules/jobs/job_types/head_of_personnel.dm index ba5930dcd83b..4cd19feec4f8 100644 --- a/code/modules/jobs/job_types/head_of_personnel.dm +++ b/code/modules/jobs/job_types/head_of_personnel.dm @@ -123,26 +123,3 @@ for(var/mob/living/basic/pet/dog/corgi/ian/staff_pet in GLOB.dead_mob_list) . += list(/datum/reagent/medicine/strange_reagent = 20) break - -/obj/item/paper/fluff/ids_for_dummies - name = "Memo: New IDs and You" - desc = "It looks like this was left by the last Head of Personnel to man this station. It explains some information about new IDs." - default_raw_text = {" -

Dummy's Guide To New IDs

-

The Basics

-

Card Trim - This is the job assigned to the card. The card's trim decides what Basic accesses the card can hold. Basic accesses cost nothing! Grey ID cards cannot hold Head of Staff or Captain trims. Silver ID cards can hold Head of Staff trims but not Captain trims and are in a box in the Head of Personnel's office and orderable from cargo. Gold ID cards can hold all access. The only guaranteed Gold ID card is the Captain's Spare, held in a golden safe on the bridge with access codes given to the station's highest ranking officer. All other gold ID cards are carried exclusively by Captains.

-

Wildcards - These are any additional accesses a card has that are not part of the card's trim. Lower quality ID cards have fewer wildcards and the wildcards they do have are of lower rarity.

-

Job Changes - To change a job, you need to go to the PDA & ID Painter that's in every Head of Personnel office. This can be used to apply a new trim to an ID card, but this will wipe all that card's accesses in the process. You then take this ID card to any modular computer with the Plexagon Access Management app and when logged in with the appropriate Head of Staff or ID Console access can then select from Templates to quick-fill accesses or apply them manually.

-

Firing Staff - Terminating a staff member's employment will wipe any trim from their card, remove all access and instantly set them as demoted.

-

Changing Jobs - Step by Step

-
    -
  1. Grab an appropriate ID card. Head of Staff jobs require a silver ID card. Captain requires a gold ID card.
  2. -
  3. Insert the ID card into the combined PDA Painter and ID Trimmer in the HoP office.
  4. -
  5. Select to appropriate trim then hit the button to apply it to the card. This will wipe all the card's access.
  6. -
  7. Remove the ID from the PDA/ID Painter and open up any modular computer with the Plexagon Access Management application downloaded.
  8. -
  9. Login to the app using an ID card with any Head of Staff private office access for limited access or the ID Console access for unlimited access.
  10. -
  11. Select a template from the drop-down. This will apply as many basic accesses as possible based on the trim of the ID card and may apply wildcard accesses for Head of Staff and Captain trims. For best results, match the template to the ID card's trim.
  12. -
  13. Manually tweak any other accesses as necessary. Add wildcard accesses. Tweak basic accesses.
  14. -
  15. Don't forget to set a custom occupation! SecHUDs now interface direct with the ID card's trim and display the trim's job icon even when a custom assignment is set.
  16. -
- "} diff --git a/code/modules/jobs/job_types/security_officer.dm b/code/modules/jobs/job_types/security_officer.dm index 27503d38c260..87bfd0b18c93 100644 --- a/code/modules/jobs/job_types/security_officer.dm +++ b/code/modules/jobs/job_types/security_officer.dm @@ -121,7 +121,7 @@ GLOBAL_LIST_EMPTY(security_officer_distribution) if(dep_trim) var/obj/item/card/id/worn_id = spawning.get_idcard(hand_first = FALSE) SSid_access.apply_trim_to_card(worn_id, dep_trim) - spawning.sec_hud_set_ID() + spawning.update_ID_card() // Update PDA to match new trim. var/obj/item/modular_computer/pda/pda = spawning.get_item_by_slot(ITEM_SLOT_BELT) diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm index edf77d4873ed..622664816594 100644 --- a/code/modules/library/lib_machines.dm +++ b/code/modules/library/lib_machines.dm @@ -507,12 +507,8 @@ GLOBAL_VAR_INIT(library_table_modified, 0) return if(!GLOB.news_network) say("No news network found on station. Aborting.") - var/channelexists = FALSE - for(var/datum/feed_channel/feed in GLOB.news_network.network_channels) - if(feed.channel_name == LIBRARY_NEWSFEED) - channelexists = TRUE - break - if(!channelexists) + var/datum/feed_channel/library_channel = GLOB.news_network.network_channels_by_name[LIBRARY_NEWSFEED] + if(isnull(library_channel)) GLOB.news_network.create_feed_channel(LIBRARY_NEWSFEED, "Library", "The official station book club!", null) var/obj/machinery/libraryscanner/scan = get_scanner() diff --git a/code/modules/library/skill_learning/generic_skillchips/point.dm b/code/modules/library/skill_learning/generic_skillchips/point.dm index ba6a2e3e236e..8b26e413b7e2 100644 --- a/code/modules/library/skill_learning/generic_skillchips/point.dm +++ b/code/modules/library/skill_learning/generic_skillchips/point.dm @@ -53,7 +53,7 @@ . = ..() arrow_overlay = null -/datum/action/change_pointer_color/Trigger(trigger_flags) +/datum/action/change_pointer_color/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return diff --git a/code/modules/loadout/categories/shoes.dm b/code/modules/loadout/categories/shoes.dm index 8e58dac0aa6e..22ef52d62be0 100644 --- a/code/modules/loadout/categories/shoes.dm +++ b/code/modules/loadout/categories/shoes.dm @@ -42,3 +42,7 @@ /datum/loadout_item/shoes/glow_shoes name = "Shoes (Glowing, Colourable)" item_path = /obj/item/clothing/shoes/glow + +/datum/loadout_item/shoes/jackboots + name = "Workboots (Black)" + item_path = /obj/item/clothing/shoes/workboots/black diff --git a/code/modules/lost_crew/body_bags.dm b/code/modules/lost_crew/body_bags.dm index 2a23d5f7253b..ab94fea27580 100644 --- a/code/modules/lost_crew/body_bags.dm +++ b/code/modules/lost_crew/body_bags.dm @@ -7,15 +7,21 @@ /obj/structure/closet/body_bag/lost_crew name = "long-term body bag" desc = "A plastic bag designed for the long-term storage and transportation of cadavers." - icon_state = "bodybag_lost" - foldedbag_path = /obj/item/bodybag/lost_crew /// Filled with one body. If folded, gives the parent type so we dont make infinite corpses /obj/structure/closet/body_bag/lost_crew/with_body /// Whether or not we spawn a paper with everything thats happened to the body var/debug = FALSE + /// Have we spawned a body yet? + var/body_spawned = FALSE + +/obj/structure/closet/body_bag/lost_crew/with_body/attempt_fold(mob/living/carbon/human/the_folder) + if (!body_spawned) + to_chat(the_folder, span_warning("The body inside of [src] prevents you from folding it up!")) + return FALSE + return ..() /obj/structure/closet/body_bag/lost_crew/with_body/PopulateContents() . = ..() @@ -26,6 +32,7 @@ var/mob/living/corpse = GLOB.lost_crew_manager.create_lost_crew(revivable = TRUE, recovered_items = recovered_items, protected_items = protected_items, body_data = lost_crew_data) corpse.mind_initialize() corpse.forceMove(src) + body_spawned = TRUE // Drop stuff like dropped limbs and organs with them in the bag for(var/obj/object in recovered_items) diff --git a/code/modules/mafia/_defines.dm b/code/modules/mafia/_defines.dm index ef24645bb053..eeca692766d6 100644 --- a/code/modules/mafia/_defines.dm +++ b/code/modules/mafia/_defines.dm @@ -24,31 +24,34 @@ ///How fast the game will speed up when half the players are gone. #define MAFIA_SPEEDUP_INCREASE 2 -#define MAFIA_TEAM_TOWN "town" -#define MAFIA_TEAM_MAFIA "mafia" -#define MAFIA_TEAM_SOLO "solo" +//'Team' flags, used to know which alliance your role is part of. +#define MAFIA_TEAM_TOWN (1<<0) +#define MAFIA_TEAM_MAFIA (1<<1) +#define MAFIA_TEAM_SOLO (1<<2) +//those part of the 'dead' faction can hear dead chat, not a "faction" of players. +#define MAFIA_TEAM_DEAD (1<<3) //types of town roles for random setup gen /// Add this if you don't want a role to be a choice in the selection -#define TOWN_OVERFLOW "overflow" +#define TOWN_OVERFLOW "town overflow" /// roles that learn info about others in the game (chaplain, detective, psych) -#define TOWN_INVEST "invest" +#define TOWN_INVEST "town invest" /// roles that keep other roles safe (doctor, sec officer, and weirdly enough lawyer counts) -#define TOWN_PROTECT "protect" +#define TOWN_PROTECT "town protect" /// roles that are only there to kill bad guys. -#define TOWN_KILLING "killing" +#define TOWN_KILLING "town killing" /// roles that don't fit into anything else (hop) -#define TOWN_SUPPORT "support" +#define TOWN_SUPPORT "town support" //other types (mafia team, neutrals) /// normal vote kill changelings -#define MAFIA_REGULAR "regular" +#define MAFIA_REGULAR "mafia" /// every other changeling role that has extra abilities -#define MAFIA_SPECIAL "special" +#define MAFIA_SPECIAL "mafia special" /// role that wins solo that nobody likes -#define NEUTRAL_KILL "kill" +#define NEUTRAL_KILL "neutral killing" /// role that upsets the game aka obsessed, usually worse for town than mafia but they can vote against mafia -#define NEUTRAL_DISRUPT "disrupt" +#define NEUTRAL_DISRUPT "neutral chaos" //role flags (special status of roles like detection immune) ///to all forms of detection, shows themselves as an assistant. diff --git a/code/modules/mafia/abilities/abilities.dm b/code/modules/mafia/abilities/abilities.dm index deba0f670ff3..cb1127711b85 100644 --- a/code/modules/mafia/abilities/abilities.dm +++ b/code/modules/mafia/abilities/abilities.dm @@ -17,12 +17,12 @@ ///The mafia role this ability is targeting, if necessary. var/datum/mafia_role/target_role -/datum/mafia_ability/New(datum/mafia_controller/game, datum/mafia_role/host_role) +/datum/mafia_ability/New(datum/mafia_role/host_role) . = ..() src.host_role = host_role if(action_priority) - RegisterSignal(game, action_priority, PROC_REF(perform_action_target)) - RegisterSignal(game, COMSIG_MAFIA_NIGHT_END, PROC_REF(clean_action_refs)) + RegisterSignal(host_role.mafia_game_controller, action_priority, PROC_REF(perform_action_target)) + RegisterSignal(host_role.mafia_game_controller, COMSIG_MAFIA_NIGHT_END, PROC_REF(clean_action_refs)) /datum/mafia_ability/Destroy(force) host_role = null @@ -35,7 +35,7 @@ return FALSE /** - * Called when refs need to be cleared, when the target is no longer set. + * Called when refs need to be cleared, the last thing that is called in a night cycle. */ /datum/mafia_ability/proc/clean_action_refs(datum/mafia_controller/game) SIGNAL_HANDLER @@ -51,16 +51,16 @@ * potential_target - The player we are attempting to validate the action on. * silent - Whether to give feedback to the player about why the action cannot be used. */ -/datum/mafia_ability/proc/validate_action_target(datum/mafia_controller/game, datum/mafia_role/potential_target, silent = FALSE) +/datum/mafia_ability/proc/validate_action_target(datum/mafia_role/potential_target, silent = FALSE) SHOULD_CALL_PARENT(TRUE) - if(game.phase != valid_use_period) + if(host_role.game_status == MAFIA_DEAD) + return FALSE + if(host_role.mafia_game_controller.phase != valid_use_period) return FALSE if(host_role.role_flags & ROLE_ROLEBLOCKED) host_role.send_message_to_player(span_warning("You were roleblocked!")) return FALSE - if(host_role.game_status == MAFIA_DEAD) - return FALSE if(potential_target) if(use_flags & CAN_USE_ON_DEAD) @@ -95,9 +95,7 @@ if(!using_ability) return FALSE - if(host_role.game_status == MAFIA_DEAD) - return FALSE - if(!validate_action_target(game, target_role)) + if(!validate_action_target(target_role)) return FALSE if(target_role) @@ -114,8 +112,8 @@ * Sets the ability's target, which will cause the action to be performed on them at the end of the night. * Subtypes can override this for things like self-abilities (such as shooting visitors). */ -/datum/mafia_ability/proc/set_target(datum/mafia_controller/game, datum/mafia_role/new_target) - if(!validate_action_target(game, new_target)) +/datum/mafia_ability/proc/set_target(datum/mafia_role/new_target) + if(!validate_action_target(new_target)) return FALSE var/feedback_text = "You will %WILL_PERFORM% [ability_action]%SELF%" diff --git a/code/modules/mafia/abilities/investigative/autopsy.dm b/code/modules/mafia/abilities/investigative/autopsy.dm new file mode 100644 index 000000000000..9e5cef2ae515 --- /dev/null +++ b/code/modules/mafia/abilities/investigative/autopsy.dm @@ -0,0 +1,18 @@ +/** + * Autopsy + * + * During the night, choose someone to check their role. + */ +/datum/mafia_ability/autopsy + name = "Autopsy" + ability_action = "perform an autopsy on" + use_flags = CAN_USE_ON_OTHERS|CAN_USE_ON_DEAD + +/datum/mafia_ability/autopsy/perform_action_target(datum/mafia_controller/game, datum/mafia_role/day_target) + . = ..() + if(!.) + return FALSE + + to_chat(host_role.body, span_warning("Your autopsy report on [target_role.body.real_name] \ + reveals their role was [target_role.name].")) + return TRUE diff --git a/code/modules/mafia/abilities/investigative/pray.dm b/code/modules/mafia/abilities/investigative/pray.dm deleted file mode 100644 index cbf8459f9f2a..000000000000 --- a/code/modules/mafia/abilities/investigative/pray.dm +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Pray - * - * During the night, revealing someone will announce their role when day comes. - * This is one time use, we'll delete ourselves once done. - */ -/datum/mafia_ability/seance - name = "Seance" - ability_action = "commune with the spirit of" - use_flags = CAN_USE_ON_OTHERS|CAN_USE_ON_DEAD - -/datum/mafia_ability/seance/perform_action_target(datum/mafia_controller/game, datum/mafia_role/day_target) - . = ..() - if(!.) - return FALSE - - host_role.send_message_to_player(span_warning("You invoke spirit of [target_role.body.real_name] and learn their role was [target_role.name].")) - return TRUE diff --git a/code/modules/mafia/abilities/killing/alert.dm b/code/modules/mafia/abilities/killing/alert.dm index 74710087137b..1024f90a20c5 100644 --- a/code/modules/mafia/abilities/killing/alert.dm +++ b/code/modules/mafia/abilities/killing/alert.dm @@ -8,7 +8,7 @@ ability_action = "send any visitors home with buckshot tonight" use_flags = CAN_USE_ON_SELF -/datum/mafia_ability/attack_visitors/set_target(datum/mafia_controller/game, datum/mafia_role/new_target) +/datum/mafia_ability/attack_visitors/set_target(datum/mafia_role/new_target) . = ..() if(!.) return FALSE diff --git a/code/modules/mafia/abilities/killing/kill.dm b/code/modules/mafia/abilities/killing/kill.dm index d02fd6c287de..8c4382db9649 100644 --- a/code/modules/mafia/abilities/killing/kill.dm +++ b/code/modules/mafia/abilities/killing/kill.dm @@ -21,7 +21,7 @@ host_role.send_message_to_player(span_danger("Your attempt at killing [target_role.body.real_name] was prevented!")) else target_role.send_message_to_player(span_userdanger("You have been [attack_action] \a [host_role.name]!")) - if(honorable && (target_role.team != MAFIA_TEAM_TOWN)) + if(honorable && (target_role.team & MAFIA_TEAM_TOWN)) host_role.send_message_to_player(span_userdanger("You have killed an innocent crewmember. You will die tomorrow night.")) RegisterSignal(game, COMSIG_MAFIA_SUNDOWN, PROC_REF(internal_affairs)) return TRUE diff --git a/code/modules/mafia/abilities/protective/heal.dm b/code/modules/mafia/abilities/protective/heal.dm index 4c47d1c85ab5..b1be91e5dc3e 100644 --- a/code/modules/mafia/abilities/protective/heal.dm +++ b/code/modules/mafia/abilities/protective/heal.dm @@ -13,7 +13,7 @@ ///The message sent when you've successfully saved someone. var/saving_message = "someone nursed you back to health" -/datum/mafia_ability/heal/set_target(datum/mafia_controller/game, datum/mafia_role/new_target) +/datum/mafia_ability/heal/set_target(datum/mafia_role/new_target) . = ..() if(!.) return FALSE diff --git a/code/modules/mafia/abilities/protective/vest.dm b/code/modules/mafia/abilities/protective/vest.dm index b65a8cb73ba2..e8cb41671ffe 100644 --- a/code/modules/mafia/abilities/protective/vest.dm +++ b/code/modules/mafia/abilities/protective/vest.dm @@ -13,7 +13,7 @@ ///Amount of vests that can be used until the power deletes itself. var/charges = STARTING_VEST_AMOUNT -/datum/mafia_ability/vest/set_target(datum/mafia_controller/game, datum/mafia_role/new_target) +/datum/mafia_ability/vest/set_target(datum/mafia_role/new_target) . = ..() if(!.) return FALSE diff --git a/code/modules/mafia/abilities/support/seance.dm b/code/modules/mafia/abilities/support/seance.dm new file mode 100644 index 000000000000..39b86d955353 --- /dev/null +++ b/code/modules/mafia/abilities/support/seance.dm @@ -0,0 +1,24 @@ +/** + * Seance + * + * An ability that doesn't give you any actions, instead grants the ability to speak with the dead during the Night. + */ +/datum/mafia_ability/seance + name = "Speak with the Dead" + action_priority = null + use_flags = NONE + +/** + * handle_message + * + * During the night, Seancers speaking will instead be talking to deadchat. + */ +/datum/mafia_ability/seance/handle_speech(datum/source, list/speech_args) + . = ..() + if(host_role.mafia_game_controller.phase != MAFIA_PHASE_NIGHT) + return FALSE + + var/message = span_changeling("\[DEAD CHAT - CHAPLAIN\] [source]: [html_decode(speech_args[SPEECH_MESSAGE])]") + host_role.mafia_game_controller.send_message(message, team = MAFIA_TEAM_DEAD) + speech_args[SPEECH_MESSAGE] = "" + return TRUE diff --git a/code/modules/mafia/abilities/voting/changeling_kill.dm b/code/modules/mafia/abilities/voting/changeling_kill.dm index bb1b1e76c811..261474a54c37 100644 --- a/code/modules/mafia/abilities/voting/changeling_kill.dm +++ b/code/modules/mafia/abilities/voting/changeling_kill.dm @@ -34,28 +34,25 @@ game.send_message(span_danger("[host_role.body.real_name] was selected to attack [target_role.body.real_name] tonight!"), MAFIA_TEAM_MAFIA) return TRUE -/datum/mafia_ability/changeling_kill/set_target(datum/mafia_controller/game, datum/mafia_role/new_target) - if(new_target.team == MAFIA_TEAM_MAFIA) +/datum/mafia_ability/changeling_kill/set_target(datum/mafia_role/new_target) + if(new_target.team & MAFIA_TEAM_MAFIA) return FALSE - if(!validate_action_target(game, new_target)) + if(!validate_action_target(new_target)) return FALSE using_ability = TRUE - game.vote_for(host_role, new_target, "Mafia", MAFIA_TEAM_MAFIA) + host_role.mafia_game_controller.vote_for(host_role, new_target, "Mafia", MAFIA_TEAM_MAFIA) /** - * handle_message + * handle_speech * * During the night, Changelings talking will instead redirect it to Changeling chat. */ /datum/mafia_ability/changeling_kill/handle_speech(datum/source, list/speech_args) . = ..() - var/datum/mafia_controller/mafia_game = GLOB.mafia_game - if(!mafia_game) - return FALSE - if (mafia_game.phase != MAFIA_PHASE_NIGHT) + if (host_role.mafia_game_controller.phase != MAFIA_PHASE_NIGHT) return FALSE - var/phrase = html_decode(speech_args[SPEECH_MESSAGE]) - mafia_game.send_message(span_changeling("[host_role.body.real_name]: [phrase]"), MAFIA_TEAM_MAFIA) + var/message = span_changeling("\[CHANGELING CHAT\] [source]: [html_decode(speech_args[SPEECH_MESSAGE])]") + host_role.mafia_game_controller.send_message(message, MAFIA_TEAM_MAFIA) speech_args[SPEECH_MESSAGE] = "" return TRUE diff --git a/code/modules/mafia/controller.dm b/code/modules/mafia/controller.dm index 957f7f2bc42a..1d978be3dfe1 100644 --- a/code/modules/mafia/controller.dm +++ b/code/modules/mafia/controller.dm @@ -88,7 +88,7 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment()) /proc/setup_mafia_roles_by_name() var/list/rolelist_dict = list() for(var/datum/mafia_role/mafia_role as anything in typesof(/datum/mafia_role)) - rolelist_dict[initial(mafia_role.name) + " ([uppertext(initial(mafia_role.team))])"] = mafia_role + rolelist_dict[initial(mafia_role.name) + " ([uppertext(initial(mafia_role.role_type))])"] = mafia_role return rolelist_dict /proc/setup_mafia_role_by_alignment() @@ -170,11 +170,23 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment()) role.player_pda = selected_player ready_ghosts_and_pdas -= selected_player -///Sends a global message to all players, or just 'team' if set. +/** + * send_message + * By default, this will send a message to every single role in the game, and putting it in their role message history + * to view on their PDA/Mafia panel. + * Args: + * - msg: The message being sent. + * - team: A specific team flag that will receive the message, so people not part of it will not get it. Ex: Changeling-only messages. + * - log_only: Will not send the message to the player's chat, only their PDA/Mafia panel, for messages that aren't + * needed to be flooding their chat for people who are there physically, such as Day/Night starting. + */ /datum/mafia_controller/proc/send_message(msg, team, log_only = FALSE) for(var/datum/mafia_role/role as anything in all_roles) - if(team && role.team != team) + if(team && !(role.team & team)) continue + //people who can "hear" the dead, but are alive, can only hear at night. + if((team & MAFIA_TEAM_DEAD) && role.game_status == MAFIA_ALIVE && phase != MAFIA_PHASE_NIGHT) + return role.role_messages += msg if(!log_only) to_chat(role.body, msg) @@ -336,20 +348,21 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment()) var/town_can_kill = FALSE for(var/datum/mafia_role/R as anything in living_roles) - switch(R.team) - if(MAFIA_TEAM_MAFIA) - living_mafia += R - if(MAFIA_TEAM_TOWN) - living_town += R - anti_mafia_power += R.vote_power - //the game cannot autoresolve with killing roles (unless a solo wins anyways, like traitors who are immune) - if(R.role_flags & ROLE_CAN_KILL) - town_can_kill = TRUE - if(MAFIA_TEAM_SOLO) - living_neutrals += R - anti_mafia_power += R.vote_power - if(R.role_flags & ROLE_CAN_KILL) - neutral_killers += R + if(R.team & MAFIA_TEAM_MAFIA) + living_mafia += R + else if(R.team & MAFIA_TEAM_TOWN) + living_town += R + anti_mafia_power += R.vote_power + //the game cannot autoresolve with killing roles (unless a solo wins anyways, like traitors who are immune) + if(R.role_flags & ROLE_CAN_KILL) + town_can_kill = TRUE + else if(R.team & MAFIA_TEAM_SOLO) + living_neutrals += R + anti_mafia_power += R.vote_power + if(R.role_flags & ROLE_CAN_KILL) + neutral_killers += R + else + stack_trace("[R] somehow lacks a faction while alive in a Mafia match!") if(living_mafia.len && living_town.len && living_neutrals.len) return FALSE @@ -581,7 +594,7 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment()) if(phase != MAFIA_PHASE_VOTING) return - var/v = get_vote_count(get_role_player(source),"Day") + var/v = get_vote_count(get_role_player(source), "Day") var/mutable_appearance/MA = mutable_appearance('icons/obj/mafia.dmi',"vote_[v > 12 ? "over_12" : v]") overlay_list += MA diff --git a/code/modules/mafia/controller_ui.dm b/code/modules/mafia/controller_ui.dm index 83857f668373..ceeea9e7ce18 100644 --- a/code/modules/mafia/controller_ui.dm +++ b/code/modules/mafia/controller_ui.dm @@ -17,6 +17,7 @@ "desc" = user_role.desc, "hud_icon" = user_role.hud_icon, "revealed_icon" = user_role.revealed_icon, + "role_dead" = (user_role.game_status == MAFIA_DEAD), ) return data @@ -68,7 +69,7 @@ if(user_role) //not observer player_info["is_you"] = (role.body.real_name == user_role.body.real_name) for(var/datum/mafia_ability/action as anything in user_role.role_unique_actions) - if(action.validate_action_target(src, potential_target = role, silent = TRUE)) + if(action.validate_action_target(potential_target = role, silent = TRUE)) player_info["possible_actions"] += list(list("name" = action, "ref" = REF(action))) data["players"] += list(player_info) @@ -88,6 +89,7 @@ var/obj/item/modular_computer/modpc = ui.src_object if(!istype(modpc)) modpc = null + //Admin actions if(ui.user.client.holder) switch(action) @@ -147,21 +149,10 @@ if("start_now") forced_setup() - switch(action) //both living and dead - if("mf_lookup") - var/role_lookup = params["role_name"] - var/datum/mafia_role/helper - for(var/datum/mafia_role/role as anything in all_roles) - if(role_lookup == role.name) - helper = role - break - helper.show_help(usr) - - if(!user_role)//just the dead + if(!user_role) // non-player & pre-game actions. switch(action) if("mf_signup") - if(signup_mafia(usr, ui.user.client, modpc)) - return TRUE + signup_mafia(ui.user, ui.user.client, modpc) if("vote_to_start") var/client/ghost_client = ui.user.client if(phase != MAFIA_PHASE_SETUP) @@ -191,35 +182,41 @@ to_chat(usr, span_notice("You vote to start the game early ([length(GLOB.mafia_early_votes)] out of [max(round(length(GLOB.mafia_signup + GLOB.pda_mafia_signup) / 2), round(MAFIA_MIN_PLAYER_COUNT / 2))]).")) if(check_start_votes()) //See if we have enough votes to start forced_setup() - return TRUE - - if(user_role && user_role.game_status == MAFIA_DEAD) - return + return TRUE - //User actions (just living) - switch(action) + switch(action) //actions that both living and dead players can perform. + if("mf_lookup") + var/role_lookup = params["role_name"] + var/datum/mafia_role/helper + for(var/datum/mafia_role/role as anything in all_roles) + if(role_lookup == role.name) + helper = role + break + helper.show_help(usr) if("change_notes") - if(user_role.game_status == MAFIA_DEAD) - return TRUE user_role.written_notes = sanitize_text(params["new_notes"]) user_role.send_message_to_player("notes saved", balloon_alert = TRUE) return TRUE - if("send_message_to_chat") - if(user_role.game_status == MAFIA_DEAD) - return TRUE - var/message_said = sanitize_text(params["message"]) - user_role.body.say(message_said, forced = "mafia chat (sent by [ui.user.client])") - return TRUE if("send_notes_to_chat") - if(user_role.game_status == MAFIA_DEAD || !user_role.written_notes) - return TRUE - if(phase == MAFIA_PHASE_NIGHT) + if(!user_role.written_notes) return TRUE if(!COOLDOWN_FINISHED(user_role, note_chat_sending_cooldown)) return FALSE COOLDOWN_START(user_role, note_chat_sending_cooldown, MAFIA_NOTE_SENDING_COOLDOWN) - user_role.body.say("[user_role.written_notes]", forced = "mafia notes sending") + var/list/message_mods = list() + message_mods[MANNEQUIN_CONTROLLED] = ui.user + user_role.body.say("[user_role.written_notes]", forced = "mafia notes sending", message_mods = message_mods) return TRUE + if("send_message_to_chat") + var/message_said = sanitize_text(params["message"]) + var/list/message_mods = list() + message_mods[MANNEQUIN_CONTROLLED] = ui.user + user_role.body.say(message_said, forced = "mafia chat (sent by [ui.user.client])", message_mods = message_mods) + + if(user_role.game_status == MAFIA_DEAD) + return TRUE + + switch(action) //actions that only living players can perform. if("perform_action") var/datum/mafia_role/target = locate(params["target"]) in all_roles if(!istype(target)) @@ -232,11 +229,11 @@ used_action.using_ability = TRUE used_action.perform_action_target(src, target) if(MAFIA_PHASE_NIGHT) - used_action.set_target(src, target) + used_action.set_target(target) return TRUE if(user_role != on_trial) - switch(action) + switch(action) // actions that can only be done while someone is on stand (that isn't you) if("vote_abstain") if(phase != MAFIA_PHASE_JUDGEMENT || (user_role in judgement_abstain_votes)) return diff --git a/code/modules/mafia/map_pieces.dm b/code/modules/mafia/map_pieces.dm index 78b2b284061c..62f0fd2ca40a 100644 --- a/code/modules/mafia/map_pieces.dm +++ b/code/modules/mafia/map_pieces.dm @@ -1,10 +1,8 @@ /obj/effect/landmark/mafia_game_area //locations where mafia will be loaded by the datum name = "Mafia Area Spawn" - var/game_id = "mafia" /obj/effect/landmark/mafia name = "Mafia Player Spawn" - var/game_id = "mafia" /obj/effect/landmark/mafia/town_center name = "Mafia Town Center" @@ -15,7 +13,6 @@ icon = 'icons/obj/mafia.dmi' icon_state = "board" anchored = TRUE - var/game_id = "mafia" var/datum/mafia_controller/MF /obj/mafia_game_board/attack_ghost(mob/user) diff --git a/code/modules/mafia/outfits.dm b/code/modules/mafia/outfits.dm index 2fbd07d516a6..f82f9de40cb4 100644 --- a/code/modules/mafia/outfits.dm +++ b/code/modules/mafia/outfits.dm @@ -77,6 +77,7 @@ name = "Mafia Chaplain" uniform = /obj/item/clothing/under/rank/civilian/chaplain + shoes = /obj/item/clothing/shoes/sneakers/black /datum/outfit/mafia/md name = "Mafia Medical Doctor" @@ -101,6 +102,14 @@ suit = /obj/item/clothing/suit/toggle/lawyer shoes = /obj/item/clothing/shoes/laceup +/datum/outfit/mafia/coroner + name = "Mafia Coroner" + + gloves = /obj/item/clothing/gloves/latex/coroner + head = /obj/item/clothing/head/utility/surgerycap/black + uniform = /obj/item/clothing/under/rank/medical/scrubs/coroner + shoes = /obj/item/clothing/shoes/sneakers/black + /datum/outfit/mafia/hop name = "Mafia Head of Personnel" diff --git a/code/modules/mafia/roles/changelings/changeling.dm b/code/modules/mafia/roles/changelings/changeling.dm index 8e650515ffbc..cf9039fa5005 100644 --- a/code/modules/mafia/roles/changelings/changeling.dm +++ b/code/modules/mafia/roles/changelings/changeling.dm @@ -1,6 +1,6 @@ /datum/mafia_role/mafia name = "Changeling" - desc = "You're a member of the changeling hive. You may speak with your fellow Changelings at night." + desc = "You're a member of the changeling hive. Talk during the Night period to coordinate with your allies, and kill all non-Changelings." team = MAFIA_TEAM_MAFIA role_type = MAFIA_REGULAR role_flags = ROLE_CAN_KILL @@ -25,10 +25,10 @@ /datum/mafia_role/mafia/thoughtfeeder name = "Thoughtfeeder" - desc = "You're a changeling variant that feeds on the memories of others. Use ':j' talk prefix to talk to your fellow lings, and visit people at night to learn their role." + desc = "You're a changeling variant that feeds on the memories of others. Talk during the Night period to coordinate with your allies, \ + and kill all non-Changelings, using your ability to learn people's roles to your advantage." role_type = MAFIA_SPECIAL hud_icon = "hudthoughtfeeder" - revealed_icon = "thoughtfeeder" winner_award = /datum/award/achievement/mafia/thoughtfeeder role_unique_actions = list(/datum/mafia_ability/changeling_kill, /datum/mafia_ability/thoughtfeeder) diff --git a/code/modules/mafia/roles/neutral/neutral_chaos.dm b/code/modules/mafia/roles/neutral/neutral_chaos.dm index de2c7fc4833a..64ce9cf4252c 100644 --- a/code/modules/mafia/roles/neutral/neutral_chaos.dm +++ b/code/modules/mafia/roles/neutral/neutral_chaos.dm @@ -23,7 +23,7 @@ var/list/all_roles_shuffle = shuffle(game.living_roles) - src for(var/datum/mafia_role/possible as anything in all_roles_shuffle) - if(possible.team == MAFIA_TEAM_TOWN) + if(possible.team & MAFIA_TEAM_TOWN) obsession = possible break if(!obsession) @@ -59,7 +59,7 @@ team = MAFIA_TEAM_SOLO role_type = NEUTRAL_DISRUPT special_ui_theme = "neutral" - hud_icon = "hudclown" + hud_icon = SECHUD_CLOWN revealed_icon = "clown" winner_award = /datum/award/achievement/mafia/clown diff --git a/code/modules/mafia/roles/roles.dm b/code/modules/mafia/roles/roles.dm index 85d1170d1a96..5f22153a03e7 100644 --- a/code/modules/mafia/roles/roles.dm +++ b/code/modules/mafia/roles/roles.dm @@ -7,6 +7,8 @@ var/role_type = TOWN_OVERFLOW ///role flags (special status of roles like detection immune) var/role_flags = NONE + ///The mafia controller board this mafia role is tied to, in case there's several Mafia games at once. + var/datum/mafia_controller/mafia_game_controller ///The mafia popup we edit text to give different alerts for (such as when to vote). var/atom/movable/screen/mafia_popup/mafia_alert @@ -41,7 +43,7 @@ var/game_status = MAFIA_ALIVE ///icon state in the mafia dmi of the hud of the role, used in the mafia ui - var/hud_icon = "hudassistant" + var/hud_icon = SECHUD_ASSISTANT ///icon state in the mafia dmi of the hud of the role, used in the mafia ui var/revealed_icon = "assistant" ///set this to something cool for antagonists and their window will look different @@ -50,15 +52,16 @@ ///The cooldown between being able to send your will in chat. COOLDOWN_DECLARE(note_chat_sending_cooldown) -/datum/mafia_role/New(datum/mafia_controller/game) +/datum/mafia_role/New(datum/mafia_controller/new_game) . = ..() - mafia_panel = new(null, game) + src.mafia_game_controller = new_game + mafia_panel = new(null, new_game) for(var/datum/mafia_ability/abilities as anything in role_unique_actions + /datum/mafia_ability/voting) - role_unique_actions += new abilities(game, src) + role_unique_actions += new abilities(src) role_unique_actions -= abilities /datum/mafia_role/Destroy(force) - UnregisterSignal(body, COMSIG_MOB_SAY) + UnregisterSignal(body, list(COMSIG_MOB_SAY, COMSIG_MOB_DEADSAY)) QDEL_NULL(mafia_alert) QDEL_NULL(mafia_panel) QDEL_LIST(role_unique_actions) @@ -70,10 +73,11 @@ /datum/mafia_role/proc/register_body(mob/living/carbon/human/new_body) if(body) - UnregisterSignal(new_body, COMSIG_MOB_SAY) + UnregisterSignal(new_body, list(COMSIG_MOB_SAY, COMSIG_MOB_DEADSAY)) mafia_panel.Remove(body) body = new_body RegisterSignal(new_body, COMSIG_MOB_SAY, PROC_REF(handle_speech)) + RegisterSignal(new_body, COMSIG_MOB_DEADSAY, PROC_REF(handle_speech_dead)) mafia_panel.Grant(new_body) /** @@ -97,19 +101,25 @@ * handle_speech * * Handles Mafia roles talking in chat. - * First it will go through their abilities for Ability-specific speech, - * if none affects it, we will go to day chat. + * First we'll go through their abilities for Ability-specific speech, + * if none affects it, we will go to day chat (if it is indeed day). */ /datum/mafia_role/proc/handle_speech(datum/source, list/speech_args) SIGNAL_HANDLER for(var/datum/mafia_ability/abilities as anything in role_unique_actions) if(abilities.handle_speech(source, speech_args)) return - var/datum/mafia_controller/mafia_game = GLOB.mafia_game - if(!mafia_game || mafia_game.phase == MAFIA_PHASE_NIGHT) + if(mafia_game_controller.phase == MAFIA_PHASE_NIGHT) return var/message = "[source]: [html_decode(speech_args[SPEECH_MESSAGE])]" - mafia_game.send_message(message, log_only = TRUE) + mafia_game_controller.send_message(message, log_only = TRUE) + +///Same as handle_speech, but for dead players. +/datum/mafia_role/proc/handle_speech_dead(datum/source, message) + SIGNAL_HANDLER + var/message_sent = span_changeling("\[DEAD CHAT\] [source]: [message]") + mafia_game_controller.send_message(message_sent, team = MAFIA_TEAM_DEAD) + return MOB_DEADSAY_SIGNAL_INTERCEPT /** * Puts the player in their body and keeps track of their previous one to put them back in later. @@ -123,6 +133,7 @@ old_body = player.mob.mind.current, \ ) body.PossessByPlayer(player.key) + ADD_TRAIT(body, TRAIT_CORPSELOCKED, MAFIA_TRAIT) /** * Tests kill immunities, if nothing prevents the kill, kills this role. @@ -137,6 +148,8 @@ if(SEND_SIGNAL(src, COMSIG_MAFIA_ON_KILL, game, attacker, lynch) & MAFIA_PREVENT_KILL) return FALSE game_status = MAFIA_DEAD + //can now hear dead chat speaking. + team |= MAFIA_TEAM_DEAD body.death() if(lynch) reveal_role(game, verbose = TRUE) diff --git a/code/modules/mafia/roles/town/town_investigative.dm b/code/modules/mafia/roles/town/town_investigative.dm index 76b81eab3bd1..003d911612b9 100644 --- a/code/modules/mafia/roles/town/town_investigative.dm +++ b/code/modules/mafia/roles/town/town_investigative.dm @@ -5,7 +5,7 @@ role_type = TOWN_INVEST winner_award = /datum/award/achievement/mafia/detective - hud_icon = "huddetective" + hud_icon = SECHUD_DETECTIVE revealed_icon = "detective" role_unique_actions = list(/datum/mafia_ability/investigate) @@ -17,18 +17,18 @@ role_type = TOWN_INVEST winner_award = /datum/award/achievement/mafia/psychologist - hud_icon = "hudpsychologist" + hud_icon = SECHUD_PSYCHOLOGIST revealed_icon = "psychologist" role_unique_actions = list(/datum/mafia_ability/reveal_role) -/datum/mafia_role/chaplain - name = "Chaplain" - desc = "You can communicate with spirits of the dead each night to discover dead crewmember roles." - revealed_outfit = /datum/outfit/mafia/chaplain +/datum/mafia_role/coroner + name = "Coroner" + desc = "You can perform autopsies on the dead each night to discover their role." + revealed_outfit = /datum/outfit/mafia/coroner role_type = TOWN_INVEST - hud_icon = "hudchaplain" - revealed_icon = "chaplain" - winner_award = /datum/award/achievement/mafia/chaplain + hud_icon = SECHUD_CORONER + revealed_icon = "coroner" + winner_award = /datum/award/achievement/mafia/coroner - role_unique_actions = list(/datum/mafia_ability/seance) + role_unique_actions = list(/datum/mafia_ability/autopsy) diff --git a/code/modules/mafia/roles/town/town_killing.dm b/code/modules/mafia/roles/town/town_killing.dm index 777581d04022..ea0211028749 100644 --- a/code/modules/mafia/roles/town/town_killing.dm +++ b/code/modules/mafia/roles/town/town_killing.dm @@ -5,7 +5,7 @@ role_flags = ROLE_CAN_KILL | ROLE_UNIQUE revealed_outfit = /datum/outfit/mafia/hos revealed_icon = "headofsecurity" - hud_icon = "hudheadofsecurity" + hud_icon = SECHUD_HEAD_OF_SECURITY winner_award = /datum/award/achievement/mafia/hos role_unique_actions = list(/datum/mafia_ability/attack_player/execution) @@ -18,7 +18,7 @@ role_flags = ROLE_CAN_KILL revealed_outfit = /datum/outfit/mafia/warden revealed_icon = "warden" - hud_icon = "hudwarden" + hud_icon = SECHUD_WARDEN winner_award = /datum/award/achievement/mafia/warden role_unique_actions = list(/datum/mafia_ability/attack_visitors) diff --git a/code/modules/mafia/roles/town/town_protective.dm b/code/modules/mafia/roles/town/town_protective.dm index 53e01c43418d..a8433779991d 100644 --- a/code/modules/mafia/roles/town/town_protective.dm +++ b/code/modules/mafia/roles/town/town_protective.dm @@ -3,7 +3,7 @@ desc = "You can protect a single person each night from killing. You can heal yourself once." revealed_outfit = /datum/outfit/mafia/md role_type = TOWN_PROTECT - hud_icon = "hudmedicaldoctor" + hud_icon = SECHUD_MEDICAL_DOCTOR revealed_icon = "medicaldoctor" winner_award = /datum/award/achievement/mafia/md @@ -14,7 +14,7 @@ desc = "You can protect a single person each night. If they are attacked, you will retaliate, killing yourself and the attacker. You can protect yourself once." revealed_outfit = /datum/outfit/mafia/security revealed_icon = "securityofficer" - hud_icon = "hudsecurityofficer" + hud_icon = SECHUD_SECURITY_OFFICER role_type = TOWN_PROTECT role_flags = ROLE_CAN_KILL winner_award = /datum/award/achievement/mafia/officer diff --git a/code/modules/mafia/roles/town/town_support.dm b/code/modules/mafia/roles/town/town_support.dm index f508831720e7..c95f93fcebd8 100644 --- a/code/modules/mafia/roles/town/town_support.dm +++ b/code/modules/mafia/roles/town/town_support.dm @@ -3,7 +3,7 @@ desc = "You can choose a person to provide extensive legal advice to, preventing night actions." revealed_outfit = /datum/outfit/mafia/lawyer role_type = TOWN_SUPPORT - hud_icon = "hudlawyer" + hud_icon = SECHUD_LAWYER revealed_icon = "lawyer" winner_award = /datum/award/achievement/mafia/lawyer @@ -15,9 +15,21 @@ role_type = TOWN_SUPPORT role_flags = ROLE_UNIQUE role_flags = ROLE_CAN_KILL - hud_icon = "hudheadofpersonnel" + hud_icon = SECHUD_HEAD_OF_PERSONNEL revealed_icon = "headofpersonnel" revealed_outfit = /datum/outfit/mafia/hop winner_award = /datum/award/achievement/mafia/hop role_unique_actions = list(/datum/mafia_ability/self_reveal) + +/datum/mafia_role/chaplain + name = "Chaplain" + desc = "You can communicate with spirits of the dead each night to discover dead crewmember roles." + role_type = TOWN_INVEST + team = MAFIA_TEAM_TOWN | MAFIA_TEAM_DEAD + hud_icon = SECHUD_CHAPLAIN + revealed_icon = "chaplain" + revealed_outfit = /datum/outfit/mafia/chaplain + winner_award = /datum/award/achievement/mafia/chaplain + + role_unique_actions = list(/datum/mafia_ability/seance) diff --git a/code/modules/manufactorio/machines/lathe.dm b/code/modules/manufactorio/machines/lathe.dm index 351e5c25030a..d2a4e65f677a 100644 --- a/code/modules/manufactorio/machines/lathe.dm +++ b/code/modules/manufactorio/machines/lathe.dm @@ -143,7 +143,14 @@ var/atom/movable/created if(is_stack) var/obj/item/stack/stack_item = initial(design.build_path) - created = new stack_item(null, 1) + var/max_stack_amount = initial(stack_item.max_amount) + var/amount = initial(stack_item.amount) + while(amount > max_stack_amount) + var/obj/item/stack/new_stack = new stack_item(null, max_stack_amount) + if(!send_resource(new_stack, dir)) + withheld = new_stack + amount -= max_stack_amount + created = new stack_item(null, amount) else created = new design.build_path(null) split_materials_uniformly(materials_needed, target_object = created) @@ -155,7 +162,6 @@ if(!send_resource(created, dir)) withheld = created - /obj/machinery/power/manufacturing/lathe/proc/finalize_build() print_sound.stop() deltimer(busy) diff --git a/code/modules/mapfluff/ruins/lavalandruin_code/syndicate_base.dm b/code/modules/mapfluff/ruins/lavalandruin_code/syndicate_base.dm index 3ff54df736c4..01d4ccf6f92b 100644 --- a/code/modules/mapfluff/ruins/lavalandruin_code/syndicate_base.dm +++ b/code/modules/mapfluff/ruins/lavalandruin_code/syndicate_base.dm @@ -1,25 +1,4 @@ //lavaland_surface_syndicate_base1.dmm and it's modules - -/obj/machinery/vending/syndichem - name = "\improper SyndiChem" - desc = "A vending machine full of grenades and grenade accessories. Sponsored by Donk Co." - products = list(/obj/item/stack/cable_coil = 5, - /obj/item/assembly/igniter = 20, - /obj/item/assembly/prox_sensor = 5, - /obj/item/assembly/signaler = 5, - /obj/item/assembly/timer = 5, - /obj/item/assembly/voice = 5, - /obj/item/assembly/health = 5, - /obj/item/assembly/infra = 5, - /obj/item/grenade/chem_grenade = 5, - /obj/item/grenade/chem_grenade/large = 5, - /obj/item/grenade/chem_grenade/pyro = 5, - /obj/item/grenade/chem_grenade/cryo = 5, - /obj/item/grenade/chem_grenade/adv_release = 5, - /obj/item/reagent_containers/cup/glass/bottle/holywater = 1) - product_slogans = "It's not pyromania if you're getting paid!;You smell that? Plasma, son. Nothing else in the world smells like that.;I love the smell of Plasma in the morning." - resistance_flags = FIRE_PROOF - /obj/modular_map_root/syndicatebase config_file = "strings/modular_maps/syndicatebase.toml" diff --git a/code/modules/mapfluff/ruins/spaceruin_code/cyborgmothership.dm b/code/modules/mapfluff/ruins/spaceruin_code/cyborgmothership.dm index cad1c8488f91..46f2b0c3d77a 100644 --- a/code/modules/mapfluff/ruins/spaceruin_code/cyborgmothership.dm +++ b/code/modules/mapfluff/ruins/spaceruin_code/cyborgmothership.dm @@ -15,7 +15,7 @@ width = 23 height = 23 launch_status = 0 - callTime = 250 + callTime = 25 SECONDS movement_force = list("KNOCKDOWN" = 0,"THROW" = 0) /obj/item/circuitboard/computer/cyborg_mothership diff --git a/code/modules/mapfluff/ruins/spaceruin_code/hilbertshotel.dm b/code/modules/mapfluff/ruins/spaceruin_code/hilbertshotel.dm index b11a1d3deecb..71a14d8a97d0 100644 --- a/code/modules/mapfluff/ruins/spaceruin_code/hilbertshotel.dm +++ b/code/modules/mapfluff/ruins/spaceruin_code/hilbertshotel.dm @@ -378,7 +378,7 @@ GLOBAL_VAR_INIT(hhMysteryRoomNumber, rand(1, 999999)) desc = "Stop looking through the bluespace peephole." button_icon_state = "cancel_peephole" -/datum/action/peephole_cancel/Trigger(trigger_flags) +/datum/action/peephole_cancel/Trigger(mob/clicker, trigger_flags) . = ..() to_chat(owner, span_warning("You move away from the peephole.")) owner.reset_perspective() diff --git a/code/modules/mining/abandoned_crates.dm b/code/modules/mining/abandoned_crates.dm index 89fd3361a06b..bbec54ed3561 100644 --- a/code/modules/mining/abandoned_crates.dm +++ b/code/modules/mining/abandoned_crates.dm @@ -38,6 +38,8 @@ var/length_input = length(input) for(var/i = 1, i <= length_input, i += length(char)) //put the guess into a list char = input[i] + if(!(char >= "0" && char <= "9")) + sanitycheck = FALSE //if a non-digit is found, reject the input sanitised += text2num(char) for(var/i in 1 to length(sanitised) - 1) //compare each digit in the guess to all those following it for(var/j in i + 1 to length(sanitised)) diff --git a/code/modules/mining/equipment/explorer_gear.dm b/code/modules/mining/equipment/explorer_gear.dm index fa2717ca5d13..4c3a9cb529bc 100644 --- a/code/modules/mining/equipment/explorer_gear.dm +++ b/code/modules/mining/equipment/explorer_gear.dm @@ -205,7 +205,7 @@ desc = "An intimidating tribal helmet, it doesn't look very comfortable." icon_state = "skull" inhand_icon_state = null - strip_delay = 100 + strip_delay = 10 SECONDS flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDESNOUT flags_cover = HEADCOVERSEYES cold_protection = HEAD diff --git a/code/modules/mining/equipment/monster_organs/monster_organ.dm b/code/modules/mining/equipment/monster_organs/monster_organ.dm index 01bf553c4ca2..a76002959a20 100644 --- a/code/modules/mining/equipment/monster_organs/monster_organ.dm +++ b/code/modules/mining/equipment/monster_organs/monster_organ.dm @@ -61,6 +61,7 @@ /obj/item/organ/monster_core/Initialize(mapload) . = ..() decay_timer = addtimer(CALLBACK(src, PROC_REF(go_inert)), time_to_decay, TIMER_STOPPABLE) + AddElement(/datum/element/above_mob_drop) /obj/item/organ/monster_core/examine(mob/user) . = ..() diff --git a/code/modules/mining/lavaland/ash_flora.dm b/code/modules/mining/lavaland/ash_flora.dm index 4aa17da2b6e6..e5d6e82cf747 100644 --- a/code/modules/mining/lavaland/ash_flora.dm +++ b/code/modules/mining/lavaland/ash_flora.dm @@ -377,7 +377,7 @@ name = "Mushroom Bowl" result = /obj/item/reagent_containers/cup/bowl/mushroom_bowl reqs = list(/obj/item/food/grown/ash_flora/shavings = 5) - time = 30 + time = 3 SECONDS category = CAT_CONTAINERS /obj/item/reagent_containers/cup/bowl/mushroom_bowl diff --git a/code/modules/mining/lavaland/mining_loot/clothing.dm b/code/modules/mining/lavaland/mining_loot/clothing.dm index f64bda23672d..360388b61b6c 100644 --- a/code/modules/mining/lavaland/mining_loot/clothing.dm +++ b/code/modules/mining/lavaland/mining_loot/clothing.dm @@ -95,8 +95,8 @@ icon_state = "concussive_gauntlets" inhand_icon_state = null toolspeed = 0.1 - strip_delay = 40 - equip_delay_other = 20 + strip_delay = 4 SECONDS + equip_delay_other = 2 SECONDS cold_protection = HANDS min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT heat_protection = HANDS diff --git a/code/modules/mining/lavaland/mining_loot/godslayer.dm b/code/modules/mining/lavaland/mining_loot/godslayer.dm index ba5dbaa6813a..724aa212c675 100644 --- a/code/modules/mining/lavaland/mining_loot/godslayer.dm +++ b/code/modules/mining/lavaland/mining_loot/godslayer.dm @@ -21,10 +21,10 @@ var/static/list/damage_heal_order = list(BRUTE, BURN, OXY) /datum/armor/cloak_godslayer - melee = 50 - bullet = 25 - laser = 25 - energy = 25 + melee = 70 + bullet = 50 + laser = 30 + energy = 40 bomb = 50 bio = 50 fire = 100 diff --git a/code/modules/mining/lavaland/mining_loot/megafauna/colossus.dm b/code/modules/mining/lavaland/mining_loot/megafauna/colossus.dm index 5460287ac561..4215f6c1a53f 100644 --- a/code/modules/mining/lavaland/mining_loot/megafauna/colossus.dm +++ b/code/modules/mining/lavaland/mining_loot/megafauna/colossus.dm @@ -417,7 +417,7 @@ /datum/action/exit_possession/IsAvailable(feedback = FALSE) return ..() && isfloorturf(owner.loc) -/datum/action/exit_possession/Trigger(trigger_flags) +/datum/action/exit_possession/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return FALSE diff --git a/code/modules/mining/lavaland/mining_loot/megafauna/the_thing.dm b/code/modules/mining/lavaland/mining_loot/megafauna/the_thing.dm index d96bd6b02801..cea00930325a 100644 --- a/code/modules/mining/lavaland/mining_loot/megafauna/the_thing.dm +++ b/code/modules/mining/lavaland/mining_loot/megafauna/the_thing.dm @@ -4,7 +4,7 @@ button_icon = 'icons/mob/actions/actions_AI.dmi' button_icon_state = "ai_core" -/datum/action/innate/brain_undeployment/Trigger(trigger_flags) +/datum/action/innate/brain_undeployment/Trigger(mob/clicker, trigger_flags) if(!..()) return FALSE var/obj/item/organ/brain/cybernetic/ai/shell_to_disconnect = owner.get_organ_by_type(/obj/item/organ/brain/cybernetic/ai) diff --git a/code/modules/mining/machine_silo.dm b/code/modules/mining/machine_silo.dm index 3271f316df52..467b7786e083 100644 --- a/code/modules/mining/machine_silo.dm +++ b/code/modules/mining/machine_silo.dm @@ -207,6 +207,7 @@ if(!islist(user_data)) // Just allow to salvage the situation . = COMPONENT_ORE_SILO_ALLOW + user_data = ID_DATA(null) CRASH("Invalid data passed to check_permitted") if(user_data[SILICON_OVERRIDE] || user_data[CHAMELEON_OVERRIDE] || astype(user_data["accesses"], /list)?.Find(ACCESS_QM)) return COMPONENT_ORE_SILO_ALLOW diff --git a/code/modules/mob/living/basic/bots/repairbot/repairbot_abilities.dm b/code/modules/mob/living/basic/bots/repairbot/repairbot_abilities.dm index 4d65c62216ff..c18562701c15 100644 --- a/code/modules/mob/living/basic/bots/repairbot/repairbot_abilities.dm +++ b/code/modules/mob/living/basic/bots/repairbot/repairbot_abilities.dm @@ -53,7 +53,7 @@ /obj/item/stack/rods, )) -/datum/action/repairbot_resources/Trigger(trigger_flags) +/datum/action/repairbot_resources/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return diff --git a/code/modules/mob/living/basic/clown/clown.dm b/code/modules/mob/living/basic/clown/clown.dm index 4d891a4f7187..fb9e6caf995b 100644 --- a/code/modules/mob/living/basic/clown/clown.dm +++ b/code/modules/mob/living/basic/clown/clown.dm @@ -622,7 +622,7 @@ ///If we are currently activating our ability. var/activating = FALSE -/datum/action/cooldown/exquisite_bunch/Trigger(trigger_flags, atom/target) +/datum/action/cooldown/exquisite_bunch/Trigger(mob/clicker, trigger_flags, atom/target) if(activating) return var/bunch_turf = get_step(owner.loc, owner.dir) diff --git a/code/modules/mob/living/basic/drone/drone_say.dm b/code/modules/mob/living/basic/drone/drone_say.dm index af0bef41bb1c..3a006d8d1b2c 100644 --- a/code/modules/mob/living/basic/drone/drone_say.dm +++ b/code/modules/mob/living/basic/drone/drone_say.dm @@ -9,18 +9,24 @@ * * exact_faction_match - Passed to [/mob/proc/faction_check_atom] */ /proc/_alert_drones(msg, dead_can_hear = FALSE, atom/source, mob/living/faction_checked_mob, exact_faction_match) - if (dead_can_hear && source) - for (var/mob/dead_mob in GLOB.dead_mob_list) + if(dead_can_hear && source) + for(var/mob/dead_mob in GLOB.dead_mob_list) var/link = FOLLOW_LINK(dead_mob, source) to_chat(dead_mob, "[link] [msg]") for(var/global_drone in GLOB.drones_list) var/mob/living/basic/drone/drone = global_drone - if(istype(drone) && drone.stat != DEAD) - if(faction_checked_mob) - if(drone.faction_check_atom(faction_checked_mob, exact_faction_match)) - to_chat(drone, msg) - else - to_chat(drone, msg) + if(!istype(drone)) + continue + if(drone.stat == DEAD) + continue + if(faction_checked_mob && !drone.faction_check_atom(faction_checked_mob, exact_faction_match)) + continue + to_chat( + drone, + msg, + type = MESSAGE_TYPE_RADIO, + avoid_highlighting = (drone == source), + ) @@ -39,5 +45,7 @@ * * Shares the same radio code with binary */ -/mob/living/basic/drone/proc/drone_chat(msg) - alert_drones("Drone Chat: [span_name("[name]")] [say_quote(msg)]", TRUE) +/mob/living/basic/drone/proc/drone_chat(message, list/spans = list(), list/message_mods = list()) + log_sayverb_talk(message, message_mods, tag = "drone chat") + var/message_part = generate_messagepart(message, spans, message_mods) + alert_drones("Drone Chat: [span_name("[name]")] [message_part]", TRUE) diff --git a/code/modules/mob/living/basic/guardian/guardian_types/standard.dm b/code/modules/mob/living/basic/guardian/guardian_types/standard.dm index 9b4335898cfc..3e15caaa4274 100644 --- a/code/modules/mob/living/basic/guardian/guardian_types/standard.dm +++ b/code/modules/mob/living/basic/guardian/guardian_types/standard.dm @@ -54,7 +54,7 @@ return FALSE return ..() -/datum/action/select_guardian_battlecry/Trigger(trigger_flags) +/datum/action/select_guardian_battlecry/Trigger(mob/clicker, trigger_flags) . = ..() if (!.) return diff --git a/code/modules/mob/living/basic/lavaland/basilisk/basilisk_overheat.dm b/code/modules/mob/living/basic/lavaland/basilisk/basilisk_overheat.dm index 71e938c5164e..04961f7b2b52 100644 --- a/code/modules/mob/living/basic/lavaland/basilisk/basilisk_overheat.dm +++ b/code/modules/mob/living/basic/lavaland/basilisk/basilisk_overheat.dm @@ -52,7 +52,7 @@ qdel(src) /// Cool down if splashed with water -/datum/status_effect/basilisk_overheat/proc/on_splashed(atom/source, list/reagents, datum/reagents/source_reagents, methods, volume_modifier, show_message) +/datum/status_effect/basilisk_overheat/proc/on_splashed(atom/source, list/reagents, datum/reagents/source_reagents, methods, show_message) SIGNAL_HANDLER if(!(methods & (TOUCH|VAPOR))) return diff --git a/code/modules/mob/living/basic/pets/gondolas/gondolapod.dm b/code/modules/mob/living/basic/pets/gondolas/gondolapod.dm index da051f18b571..11cb75895d06 100644 --- a/code/modules/mob/living/basic/pets/gondolas/gondolapod.dm +++ b/code/modules/mob/living/basic/pets/gondolas/gondolapod.dm @@ -70,7 +70,7 @@ button_icon_state = "arrow" check_flags = AB_CHECK_PHASED -/datum/action/innate/deliver_gondola_package/Trigger(trigger_flags) +/datum/action/innate/deliver_gondola_package/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return @@ -90,7 +90,7 @@ button_icon_state = "storage" check_flags = AB_CHECK_PHASED -/datum/action/innate/check_gondola_contents/Trigger(trigger_flags) +/datum/action/innate/check_gondola_contents/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return diff --git a/code/modules/mob/living/basic/trader/trader_actions.dm b/code/modules/mob/living/basic/trader/trader_actions.dm index ded9fbd46d0d..2e21f9630bcf 100644 --- a/code/modules/mob/living/basic/trader/trader_actions.dm +++ b/code/modules/mob/living/basic/trader/trader_actions.dm @@ -34,7 +34,7 @@ src.shop_sound = sell_sound src.opening_lines = opening_lines -/datum/action/setup_shop/Trigger(trigger_flags) +/datum/action/setup_shop/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm index 2aa65797fa1c..17efdef14557 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -337,9 +337,15 @@ /obj/item/organ/brain/check_damage_thresholds(mob/M) . = ..() - //if we're not more injured than before, return without gambling for a trauma + // If we crossed blinking brain damage thresholds either way, update our blinking + if ((prev_damage > BRAIN_DAMAGE_ASYNC_BLINKING && damage < BRAIN_DAMAGE_ASYNC_BLINKING) || (prev_damage < BRAIN_DAMAGE_ASYNC_BLINKING && damage > BRAIN_DAMAGE_ASYNC_BLINKING)) + var/obj/item/organ/eyes/eyes = owner.get_organ_slot(ORGAN_SLOT_EYES) + eyes?.animate_eyelids(owner) + + // If we're not more injured than before, return without gambling for a trauma if(damage <= prev_damage) return + damage_delta = damage - prev_damage if(damage > BRAIN_DAMAGE_MILD) if(prob(damage_delta * (1 + max(0, (damage - BRAIN_DAMAGE_MILD)/100)))) //Base chance is the hit damage; for every point of damage past the threshold the chance is increased by 1% //learn how to do your bloody math properly goddamnit @@ -353,20 +359,22 @@ else gain_trauma_type(BRAIN_TRAUMA_SEVERE, natural_gain = TRUE) - if (owner) - if(owner.stat < UNCONSCIOUS) //conscious or soft-crit - var/brain_message - if(prev_damage < BRAIN_DAMAGE_MILD && damage >= BRAIN_DAMAGE_MILD) - brain_message = span_warning("You feel lightheaded.") - else if(prev_damage < BRAIN_DAMAGE_SEVERE && damage >= BRAIN_DAMAGE_SEVERE) - brain_message = span_warning("You feel less in control of your thoughts.") - else if(prev_damage < (BRAIN_DAMAGE_DEATH - 20) && damage >= (BRAIN_DAMAGE_DEATH - 20)) - brain_message = span_warning("You can feel your mind flickering on and off...") - - if(.) - . += "\n[brain_message]" - else - return brain_message + if (!owner || owner.stat > UNCONSCIOUS) + return + + // Conscious or soft-crit + var/brain_message + if(prev_damage < BRAIN_DAMAGE_MILD && damage >= BRAIN_DAMAGE_MILD) + brain_message = span_warning("You feel lightheaded.") + else if(prev_damage < BRAIN_DAMAGE_SEVERE && damage >= BRAIN_DAMAGE_SEVERE) + brain_message = span_warning("You feel less in control of your thoughts.") + else if(prev_damage < (BRAIN_DAMAGE_DEATH - 20) && damage >= (BRAIN_DAMAGE_DEATH - 20)) + brain_message = span_warning("You can feel your mind flickering on and off...") + + if(.) + . += "\n[brain_message]" + else + return brain_message /obj/item/organ/brain/before_organ_replacement(obj/item/organ/replacement) . = ..() diff --git a/code/modules/mob/living/carbon/alien/adult/adult.dm b/code/modules/mob/living/carbon/alien/adult/adult.dm index d09c196ec543..0ae07a4d3a1e 100644 --- a/code/modules/mob/living/carbon/alien/adult/adult.dm +++ b/code/modules/mob/living/carbon/alien/adult/adult.dm @@ -13,7 +13,7 @@ var/alt_icon = 'icons/mob/nonhuman-player/alienleap.dmi' //used to switch between the two alien icon files. var/leap_on_click = 0 var/pounce_cooldown = 0 - var/pounce_cooldown_time = 30 + var/pounce_cooldown_time = 3 SECONDS death_sound = 'sound/mobs/non-humanoids/hiss/hiss6.ogg' bodyparts = list( /obj/item/bodypart/chest/alien, diff --git a/code/modules/mob/living/carbon/alien/alien_say.dm b/code/modules/mob/living/carbon/alien/alien_say.dm index 43317ff59e7f..21655bfa1622 100644 --- a/code/modules/mob/living/carbon/alien/alien_say.dm +++ b/code/modules/mob/living/carbon/alien/alien_say.dm @@ -1,10 +1,10 @@ -/mob/living/proc/alien_talk(message, shown_name = real_name, big_voice = FALSE) - src.log_talk(message, LOG_SAY) +/mob/living/proc/alien_talk(message, list/spans = list(), list/message_mods = list(), shown_name = real_name, big_voice = FALSE) + log_sayverb_talk(message, message_mods, tag = "alien hivemind") message = trim(message) if(!message) return - var/message_a = say_quote(message) + var/message_a = generate_messagepart(message, spans, message_mods) var/hivemind_spans = "alien" if(big_voice) hivemind_spans += " big" @@ -16,8 +16,8 @@ var/link = FOLLOW_LINK(player, src) to_chat(player, "[link] [rendered]", type = MESSAGE_TYPE_RADIO) -/mob/living/carbon/alien/adult/royal/queen/alien_talk(message, shown_name = name) - ..(message, shown_name, TRUE) +/mob/living/carbon/alien/adult/royal/queen/alien_talk(message, list/spans = list(), list/message_mods = list(), shown_name = name, big_voice = TRUE) + ..(message, spans, message_mods, shown_name, TRUE) /mob/living/carbon/hivecheck() var/obj/item/organ/alien/hivenode/N = get_organ_by_type(/obj/item/organ/alien/hivenode) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 0d7d7a196fbb..32cd2f3cc6d0 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -247,7 +247,6 @@ W.layer = initial(W.layer) SET_PLANE_EXPLICIT(W, initial(W.plane), src) changeNext_move(0) - update_equipment_speed_mods() // In case cuffs ever change speed /mob/living/carbon/proc/clear_cuffs(obj/item/I, cuff_break) if(!I.loc || buckled) diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm index cb10924be78c..04cc20fc3dc8 100644 --- a/code/modules/mob/living/carbon/damage_procs.dm +++ b/code/modules/mob/living/carbon/damage_procs.dm @@ -94,6 +94,37 @@ amount += bodypart.burn_dam return round(amount, DAMAGE_PRECISION) + +/** + * Returns the amount of bruteloss across all bodyparts meeting the matching bodytype. + * Useful for if you would like to check the bruteloss for only organic bodyparts, for example. + * + * Arguments: + * * required_bodytype - The bodytype(s) to match against. + */ +/mob/living/carbon/proc/getBruteLossForType(required_bodytype = ALL) + var/amount = 0 + for(var/obj/item/bodypart/bodypart as anything in bodyparts) + if(!(bodypart.bodytype & required_bodytype)) + continue + amount += bodypart.brute_dam + return round(amount, DAMAGE_PRECISION) + +/** + * Returns the amount of fireloss across all bodyparts meeting the matching bodytype. + * Useful for if you would like to check the fireloss for only organic bodyparts, for example. + * + * Arguments: + * * required_bodytype - The bodytype(s) to match against. + */ +/mob/living/carbon/proc/getFireLossForType(required_bodytype = ALL) + var/amount = 0 + for(var/obj/item/bodypart/bodypart as anything in bodyparts) + if(!(bodypart.bodytype & required_bodytype)) + continue + amount += bodypart.burn_dam + return round(amount, DAMAGE_PRECISION) + /mob/living/carbon/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE, required_bodytype) if(!can_adjust_brute_loss(amount, forced, required_bodytype)) return 0 @@ -194,10 +225,13 @@ * * Arguments: * * slot - organ slot, like [ORGAN_SLOT_HEART] + * * required_organ_flag - if you only want to check the damage of organs with the specified organ_flag(s) then you can use this. */ -/mob/living/carbon/get_organ_loss(slot) +/mob/living/carbon/get_organ_loss(slot, required_organ_flag = NONE) var/obj/item/organ/affected_organ = get_organ_slot(slot) if(affected_organ) + if(required_organ_flag && !(affected_organ.organ_flags & required_organ_flag)) + return return affected_organ.damage //////////////////////////////////////////// diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index add4efd18050..759d379769e2 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -619,8 +619,6 @@ GLOBAL_LIST_EMPTY(features_by_species) /datum/species/proc/spec_life(mob/living/carbon/human/H, seconds_per_tick, times_fired) SHOULD_CALL_PARENT(TRUE) - if(H.stat == DEAD) - return if(HAS_TRAIT(H, TRAIT_NOBREATH) && (H.health < H.crit_threshold) && !HAS_TRAIT(H, TRAIT_NOCRITDAMAGE)) H.adjustBruteLoss(0.5 * seconds_per_tick) @@ -1121,19 +1119,19 @@ GLOBAL_LIST_EMPTY(features_by_species) * * humi (required)(type: /mob/living/carbon/human) The mob we will target */ /datum/species/proc/handle_body_temperature(mob/living/carbon/human/humi, seconds_per_tick, times_fired) - //when in a cryo unit we suspend all natural body regulation + // When in a cryo unit we suspend all natural body regulation if(istype(humi.loc, /obj/machinery/cryo_cell)) return - //Only stabilise core temp when alive and not in statis + // Only stabilise core temp when alive and not in statis if(humi.stat < DEAD && !HAS_TRAIT(humi, TRAIT_STASIS)) body_temperature_core(humi, seconds_per_tick, times_fired) - //These do run in statis + // These do run in statis body_temperature_skin(humi, seconds_per_tick, times_fired) body_temperature_alerts(humi, seconds_per_tick, times_fired) - //Do not cause more damage in statis + // Do not cause more damage in statis if(!HAS_TRAIT(humi, TRAIT_STASIS)) body_temperature_damage(humi, seconds_per_tick, times_fired) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 6f1e83bb474c..d2c86f4da5f7 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -23,7 +23,6 @@ . = ..() - RegisterSignal(src, COMSIG_COMPONENT_CLEAN_FACE_ACT, PROC_REF(clean_face)) AddComponent(/datum/component/personal_crafting, ui_human_crafting) AddElement(/datum/element/footstep, FOOTSTEP_MOB_HUMAN, 1, -6) AddComponent(/datum/component/bloodysoles/feet) @@ -75,7 +74,7 @@ //Update med hud images... ..() //...sec hud images... - sec_hud_set_ID() + update_ID_card() sec_hud_set_implants() sec_hud_set_security_status() //...fan gear @@ -902,7 +901,7 @@ var/carrydelay = 5 SECONDS //if you have latex you are faster at grabbing var/skills_space var/fitness_level = mind?.get_skill_level(/datum/skill/athletics) - 1 - var/experience_reward = 5 + var/experience_reward = ATHLETICS_SKILL_MISC_EXP if(HAS_TRAIT(src, TRAIT_QUICKER_CARRY)) carrydelay -= 2 SECONDS experience_reward *= 3 @@ -934,7 +933,7 @@ visible_message(span_warning("[src] fails to fireman carry [target]!")) return - mind?.adjust_experience(/datum/skill/athletics, experience_reward) //Get a bit fitter every time we fireman carry successfully. Deadlift your friends for gains! + mind?.adjust_experience(/datum/skill/athletics, round(experience_reward/(fitness_level || 1), 1)) //Get a bit fitter every time we fireman carry successfully. Deadlift your friends for gains! return buckle_mob(target, TRUE, TRUE, CARRIER_NEEDS_ARM) diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index 8e5903b1d969..5c4140223be8 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -34,7 +34,12 @@ return pda.saved_identification return if_no_id -//repurposed proc. Now it combines get_id_name() and get_face_name() to determine a mob's name variable. Made into a separate proc as it'll be useful elsewhere +/// Used to update our name based on whether our face is obscured/disfigured +/mob/living/carbon/human/proc/update_visible_name() + SIGNAL_HANDLER + name = get_visible_name() + +/// Combines get_id_name() and get_face_name() to determine a mob's name variable. Made into a separate proc as it'll be useful elsewhere /mob/living/carbon/human/get_visible_name(add_id_name = TRUE, force_real_name = FALSE) var/list/identity = list(null, null, null) SEND_SIGNAL(src, COMSIG_HUMAN_GET_VISIBLE_NAME, identity) @@ -99,7 +104,7 @@ else var/obj/item/card/id/id = astype(wear_id, /obj/item/card/id) \ || astype(wear_id, /obj/item/storage/wallet)?.front_id \ - || astype(wear_id, /obj/item/modular_computer)?.computer_id_slot + || astype(wear_id, /obj/item/modular_computer)?.stored_id . = id?.registered_name if(!.) . = if_no_id //to prevent null-names making the mob unclickable diff --git a/code/modules/mob/living/carbon/human/init_signals.dm b/code/modules/mob/living/carbon/human/init_signals.dm index 8e6465cf0f3f..4bea0e925eac 100644 --- a/code/modules/mob/living/carbon/human/init_signals.dm +++ b/code/modules/mob/living/carbon/human/init_signals.dm @@ -1,7 +1,7 @@ /mob/living/carbon/human/register_init_signals() . = ..() - RegisterSignals(src, list(SIGNAL_ADDTRAIT(TRAIT_UNKNOWN), SIGNAL_REMOVETRAIT(TRAIT_UNKNOWN)), PROC_REF(on_unknown_trait)) + RegisterSignals(src, list(SIGNAL_ADDTRAIT(TRAIT_UNKNOWN), SIGNAL_REMOVETRAIT(TRAIT_UNKNOWN)), PROC_REF(update_ID_card)) RegisterSignals(src, list(SIGNAL_ADDTRAIT(TRAIT_DWARF), SIGNAL_REMOVETRAIT(TRAIT_DWARF)), PROC_REF(on_dwarf_trait)) RegisterSignals(src, list(SIGNAL_ADDTRAIT(TRAIT_TOO_TALL), SIGNAL_REMOVETRAIT(TRAIT_TOO_TALL)), PROC_REF(on_tootall_trait)) RegisterSignal(src, COMSIG_MOVABLE_MESSAGE_GET_NAME_PART, PROC_REF(get_name_part)) @@ -11,12 +11,17 @@ RegisterSignal(src, COMSIG_ATOM_CONTENTS_WEIGHT_CLASS_CHANGED, PROC_REF(check_pocket_weght)) -/// Gaining or losing [TRAIT_UNKNOWN] updates our name and our sechud -/mob/living/carbon/human/proc/on_unknown_trait(datum/source) - SIGNAL_HANDLER + RegisterSignal(src, COMSIG_COMPONENT_CLEAN_FACE_ACT, PROC_REF(clean_face)) - name = get_visible_name() - sec_hud_set_ID() + // List of signals which force a visible name update + // TRAIT_UNKNOWN is excluded as it calls update_ID_card which also calls update_visible_name + var/static/list/name_update_signals = list( + SIGNAL_ADDTRAIT(TRAIT_INVISIBLE_MAN), + SIGNAL_REMOVETRAIT(TRAIT_INVISIBLE_MAN), + SIGNAL_ADDTRAIT(TRAIT_DISFIGURED), + SIGNAL_REMOVETRAIT(TRAIT_DISFIGURED), + ) + RegisterSignals(src, name_update_signals, PROC_REF(update_visible_name)) /// Gaining or losing [TRAIT_DWARF] updates our height and grants passtable /mob/living/carbon/human/proc/on_dwarf_trait(datum/source) diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 3dec8022e58e..0805e2a11694 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -148,7 +148,7 @@ if(wear_id) return wear_id = equipping - sec_hud_set_ID() + update_ID_card() update_worn_id() if(ITEM_SLOT_EARS) if(ears) @@ -265,7 +265,7 @@ update_worn_belt() else if(item_dropping == wear_id) wear_id = null - sec_hud_set_ID() + update_ID_card() if(!QDELETED(src)) update_worn_id() else if(item_dropping == r_store) @@ -420,3 +420,9 @@ new_bodypart.try_attach_limb(src, TRUE) hand_bodyparts[i] = new_bodypart ..() //Don't redraw hands until we have organs for them + +/mob/living/carbon/human/update_equipment(obj/item/source) + . = ..() + // If the item we equipped/unequipped hides our face, we (potentially) need to update our name + if (source.flags_inv & HIDEFACE) + update_visible_name() diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index de8b87733ea0..7990bbb3219c 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -23,33 +23,31 @@ return . = ..() + if(QDELETED(src)) return FALSE - //Body temperature stability and damage + // Body temperature stability and damage dna.species.handle_body_temperature(src, seconds_per_tick, times_fired) - if(!HAS_TRAIT(src, TRAIT_STASIS)) - if(stat != DEAD) - //handle active mutations - for(var/datum/mutation/mutation as anything in dna.mutations) - mutation.on_life(seconds_per_tick, times_fired) - //heart attack stuff - handle_heart(seconds_per_tick, times_fired) - //handles liver failure effects, if we lack a liver - handle_liver(seconds_per_tick, times_fired) - - // for special species interactions - dna.species.spec_life(src, seconds_per_tick, times_fired) - else + if(HAS_TRAIT(src, TRAIT_STASIS)) for(var/datum/wound/iter_wound as anything in all_wounds) iter_wound.on_stasis(seconds_per_tick, times_fired) + return stat != DEAD - //Update our name based on whether our face is obscured/disfigured - name = get_visible_name() - - if(stat != DEAD) - return TRUE + if(stat == DEAD) + return FALSE + // Handle active mutations + for(var/datum/mutation/mutation as anything in dna.mutations) + mutation.on_life(seconds_per_tick, times_fired) + + // Heart attack stuff + handle_heart(seconds_per_tick, times_fired) + // Handles liver failure effects, if we lack a liver + handle_liver(seconds_per_tick, times_fired) + // For special species interactions + dna.species.spec_life(src, seconds_per_tick, times_fired) + return stat != DEAD /mob/living/carbon/human/calculate_affecting_pressure(pressure) var/chest_covered = !get_bodypart(BODY_ZONE_CHEST) 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 38ef68e5272a..6cf669ec83ac 100644 --- a/code/modules/mob/living/carbon/human/species_types/zombies.dm +++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm @@ -135,6 +135,8 @@ /datum/species/zombie/infectious/on_species_gain(mob/living/carbon/human/new_zombie, datum/species/old_species, pref_load, regenerate_icons) . = ..() new_zombie.set_combat_mode(TRUE) + // Needs to be added after combat mode is set + ADD_TRAIT(new_zombie, TRAIT_COMBAT_MODE_LOCK, SPECIES_TRAIT) // Deal with the source of this zombie corruption // Infection organ needs to be handled separately from mutant_organs @@ -160,6 +162,7 @@ /datum/species/zombie/infectious/on_species_loss(mob/living/carbon/human/was_zombie, datum/species/new_species, pref_load) . = ..() + REMOVE_TRAIT(was_zombie, TRAIT_COMBAT_MODE_LOCK, SPECIES_TRAIT) qdel(was_zombie.GetComponent(/datum/component/mutant_hands)) qdel(was_zombie.GetComponent(/datum/component/regenerator)) @@ -171,8 +174,6 @@ /datum/species/zombie/infectious/spec_life(mob/living/carbon/carbon_mob, seconds_per_tick, times_fired) . = ..() - carbon_mob.set_combat_mode(TRUE) // THE SUFFERING MUST FLOW - if(!HAS_TRAIT(carbon_mob, TRAIT_CRITICAL_CONDITION) && SPT_PROB(2, seconds_per_tick)) playsound(carbon_mob, pick(spooks), 50, TRUE, 10) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 672914f5c43f..02e67d04d16b 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -485,13 +485,17 @@ if(blood_type.reagent_type != chem.type) return + var/blood_stream_volume = min(round(reac_volume, CHEMICAL_VOLUME_ROUNDING), BLOOD_VOLUME_MAXIMUM - blood_volume) + if(blood_stream_volume > 0) //remove reagents from mob that has now entered the bloodstream + reagents.remove_reagent(chem.type, blood_stream_volume) + blood_volume += blood_stream_volume + if(chem.data?["blood_type"]) var/datum/blood_type/donor_type = chem.data["blood_type"] if(!(donor_type.type_key() in blood_type.compatible_types)) reagents.add_reagent(/datum/reagent/toxin, reac_volume * 0.5) return COMPONENT_NO_EXPOSE_REAGENTS - blood_volume = min(blood_volume + round(reac_volume, 0.1), BLOOD_VOLUME_MAXIMUM) return COMPONENT_NO_EXPOSE_REAGENTS /mob/living/carbon/proc/handle_bodyparts(seconds_per_tick, times_fired) diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index f40f26f59e1f..fe2b3b92e960 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -439,7 +439,7 @@ /mob/living/proc/setOrganLoss(slot, amount, maximum, required_organ_flag) return -/mob/living/proc/get_organ_loss(slot) +/mob/living/proc/get_organ_loss(slot, required_organ_flag) return /mob/living/proc/getStaminaLoss() diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 76a501ae7af2..45e3f8834829 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -42,19 +42,18 @@ return if(!HAS_TRAIT(src, TRAIT_STASIS)) - if(stat != DEAD) //Mutations and radiation handle_mutations(seconds_per_tick, times_fired) //Breathing, if applicable handle_breathing(seconds_per_tick, times_fired) - handle_diseases(seconds_per_tick, times_fired)// DEAD check is in the proc itself; we want it to spread even if the mob is dead, but to handle its disease-y properties only if you're not. + handle_diseases(seconds_per_tick, times_fired) // DEAD check is in the proc itself; we want it to spread even if the mob is dead, but to handle its disease-y properties only if you're not. - if (QDELETED(src)) // diseases can qdel the mob via transformations + if (QDELETED(src)) // Diseases can qdel the mob via transformations return - //Handle temperature/pressure differences between body and environment + // Handle temperature/pressure differences between body and environment var/datum/gas_mixture/environment = loc.return_air() if(environment) handle_environment(environment, seconds_per_tick, times_fired) @@ -67,7 +66,7 @@ living_flags &= ~QUEUE_NUTRITION_UPDATE if(stat != DEAD) - return 1 + return TRUE /mob/living/proc/handle_breathing(seconds_per_tick, times_fired) SEND_SIGNAL(src, COMSIG_LIVING_HANDLE_BREATHING, seconds_per_tick, times_fired) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 496dd0cf035f..04d72de80644 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -572,6 +572,9 @@ return FALSE if(!(flags & SHOCK_ILLUSION)) adjustFireLoss(shock_damage) + if(getFireLoss() > 100) + add_shared_particles(/particles/smoke/burning) + addtimer(CALLBACK(src, TYPE_PROC_REF(/atom/movable, remove_shared_particles), /particles/smoke/burning), 10 SECONDS) else adjustStaminaLoss(shock_damage) if(!(flags & SHOCK_SUPPRESS_MESSAGE)) diff --git a/code/modules/mob/living/living_say.dm b/code/modules/mob/living/living_say.dm index 37695af09c5e..69c548ab9379 100644 --- a/code/modules/mob/living/living_say.dm +++ b/code/modules/mob/living/living_say.dm @@ -116,8 +116,8 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list( var/original_message = message message = get_message_mods(message, message_mods) - saymode = SSradio.saymodes[message_mods[RADIO_KEY]] - if (!forced && !saymode) + saymode = SSradio.get_available_say_mode(src, message_mods[RADIO_KEY]) + if(!forced && (isnull(saymode) || saymode.allows_custom_say_emotes)) message = check_for_custom_say_emote(message, message_mods) if(!message) @@ -152,7 +152,7 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list( if(!message_mods[WHISPER_MODE]) return if(DEAD) - say_dead(original_message) + say_dead(original_message, message_mods[MANNEQUIN_CONTROLLED]) return if(HAS_TRAIT(src, TRAIT_SOFTSPOKEN) && !HAS_TRAIT(src, TRAIT_SIGN_LANG)) // softspoken trait only applies to spoken languages @@ -171,15 +171,10 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list( var/succumbed = FALSE - // If there's a custom say emote it gets logged differently. - if(message_mods[MODE_CUSTOM_SAY_EMOTE]) - log_message(message_mods[MODE_CUSTOM_SAY_EMOTE], LOG_RADIO_EMOTE) - // If it's not erasing the input portion, then something is being said and this isn't a pure custom say emote. if(!message_mods[MODE_CUSTOM_SAY_ERASE_INPUT]) if(message_mods[WHISPER_MODE] == MODE_WHISPER) message_range = 1 - log_talk(message, LOG_WHISPER, forced_by = forced, custom_say_emote = message_mods[MODE_CUSTOM_SAY_EMOTE]) if(stat == HARD_CRIT) var/health_diff = round(-HEALTH_THRESHOLD_DEAD + health) // If we cut our message short, abruptly end it with a-.. @@ -189,8 +184,8 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list( last_words = message message_mods[WHISPER_MODE] = MODE_WHISPER_CRIT succumbed = TRUE - else - log_talk(message, LOG_SAY, forced_by = forced, custom_say_emote = message_mods[MODE_CUSTOM_SAY_EMOTE]) + + log_sayverb_talk(message, message_mods, forced_by = forced) #ifdef UNIT_TESTS // Saves a ref() to our arglist specifically. @@ -231,7 +226,7 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list( message_mods[SAY_MOD_VERB] = say_mod(message, message_mods) //This is before anything that sends say a radio message, and after all important message type modifications, so you can scumb in alien chat or something - if(saymode && !saymode.handle_message(src, message, language)) + if(saymode && (saymode.handle_message(src, message, spans, language, message_mods) & SAYMODE_MESSAGE_HANDLED)) return var/radio_return = radio(message, message_mods, spans, language)//roughly 27% of living/say()'s total cost diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 6cfdcc6ec9c9..ceb44acca226 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -797,7 +797,7 @@ /mob/living/silicon/ai/proc/relay_speech(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list()) var/raw_translation = translate_language(speaker, message_language, raw_message, spans, message_mods) var/atom/movable/source = speaker.GetSource() || speaker // is the speaker virtual/radio - var/treated_message = source.say_quote(raw_translation, spans, message_mods) + var/treated_message = source.generate_messagepart(raw_translation, spans, message_mods) var/start = "Relayed Speech: " var/namepart @@ -989,7 +989,7 @@ button_icon = 'icons/mob/actions/actions_AI.dmi' button_icon_state = "ai_shell" -/datum/action/innate/deploy_shell/Trigger(trigger_flags) +/datum/action/innate/deploy_shell/Trigger(mob/clicker, trigger_flags) var/mob/living/silicon/ai/AI = owner if(!AI) return @@ -1002,7 +1002,7 @@ button_icon_state = "ai_last_shell" var/mob/living/silicon/robot/last_used_shell -/datum/action/innate/deploy_last_shell/Trigger(trigger_flags) +/datum/action/innate/deploy_last_shell/Trigger(mob/clicker, trigger_flags) if(!owner) return if(last_used_shell) diff --git a/code/modules/mob/living/silicon/ai/ai_say.dm b/code/modules/mob/living/silicon/ai/ai_say.dm index b6f4d4ded368..26f2cc2f64a5 100644 --- a/code/modules/mob/living/silicon/ai/ai_say.dm +++ b/code/modules/mob/living/silicon/ai/ai_say.dm @@ -42,25 +42,24 @@ return FALSE //For holopads only. Usable by AI. -/mob/living/silicon/ai/proc/holopad_talk(message, language) +/mob/living/silicon/ai/proc/holopad_talk(message, list/spans = list(), language, list/message_mods = list()) message = trim(message) if (!message) return var/obj/machinery/holopad/active_pad = current - if(istype(active_pad) && active_pad.masters[src])//If there is a hologram and its master is the user. - var/obj/effect/overlay/holo_pad_hologram/ai_holo = active_pad.masters[src] - var/turf/padturf = get_turf(active_pad) - var/padloc - if(padturf) - padloc = AREACOORD(padturf) - else - padloc = "(UNKNOWN)" - src.log_talk(message, LOG_SAY, tag="HOLOPAD in [padloc]") - ai_holo.say(message, sanitize = FALSE, language = language) - else + // Only continue if there is a hologram and its master is the user. + if(!istype(active_pad) || !active_pad.masters[src]) to_chat(src, span_alert("No holopad connected.")) + return + + var/obj/effect/overlay/holo_pad_hologram/ai_holo = active_pad.masters[src] + var/turf/pad_turf = get_turf(active_pad) + var/pad_loc = pad_turf ? AREACOORD(pad_turf) : "(UNKNOWN)" + + log_sayverb_talk(message, message_mods, tag = "HOLOPAD in [pad_loc]") + ai_holo.say(message, spans = spans, sanitize = FALSE, language = language, message_mods = message_mods) // Make sure that the code compiles with AI_VOX undefined diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 329b09282fe6..4f910463b9b3 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -908,7 +908,7 @@ button_icon = 'icons/mob/actions/actions_AI.dmi' button_icon_state = "ai_core" -/datum/action/innate/undeployment/Trigger(trigger_flags) +/datum/action/innate/undeployment/Trigger(mob/clicker, trigger_flags) if(!..()) return FALSE var/mob/living/silicon/robot/shell_to_disconnect = owner diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm index b74a4ff05853..0306e8b56649 100644 --- a/code/modules/mob/living/silicon/robot/robot_defense.dm +++ b/code/modules/mob/living/silicon/robot/robot_defense.dm @@ -172,7 +172,7 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real balloon_alert(user, "toner filled") return ITEM_INTERACT_SUCCESS - if(istype(tool, /obj/item/flashlight)) + if(istype(tool, /obj/item/flashlight) && !istype(tool, /obj/item/flashlight/emp)) //subtypes my behated. OOP was a dumb idea if(user.combat_mode) return NONE if(!opened) diff --git a/code/modules/mob/living/silicon/robot/robot_model.dm b/code/modules/mob/living/silicon/robot/robot_model.dm index a2d74e6bd16e..d473cf205fd0 100644 --- a/code/modules/mob/living/silicon/robot/robot_model.dm +++ b/code/modules/mob/living/silicon/robot/robot_model.dm @@ -490,7 +490,7 @@ return FALSE return ..() -/datum/action/toggle_buffer/Trigger(trigger_flags) +/datum/action/toggle_buffer/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return diff --git a/code/modules/mob/living/silicon/silicon_defense.dm b/code/modules/mob/living/silicon/silicon_defense.dm index 89d687cfd77c..6fb367dc223c 100644 --- a/code/modules/mob/living/silicon/silicon_defense.dm +++ b/code/modules/mob/living/silicon/silicon_defense.dm @@ -109,9 +109,9 @@ return switch(severity) if(1) - src.take_bodypart_damage(20) + src.take_bodypart_damage(burn = 20) if(2) - src.take_bodypart_damage(10) + src.take_bodypart_damage(burn = 10) to_chat(src, span_userdanger("*BZZZT*")) for(var/mob/living/M in buckled_mobs) if(prob(severity*50)) @@ -121,12 +121,14 @@ flash_act(affect_silicon = 1) /mob/living/silicon/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit = FALSE) + if(hitting_projectile.damage_type == BURN) + hitting_projectile.damage_type = BRUTE //Burn is for wire damage. Brute is the outer chassis. . = ..() if(. != BULLET_ACT_HIT) return . var/prob_of_knocking_dudes_off = 0 - if(hitting_projectile.damage_type == BRUTE || hitting_projectile.damage_type == BURN) + if(hitting_projectile.damage_type == BRUTE) prob_of_knocking_dudes_off = hitting_projectile.damage * 1.5 if(hitting_projectile.stun || hitting_projectile.knockdown || hitting_projectile.paralyze) prob_of_knocking_dudes_off = 100 diff --git a/code/modules/mob/living/silicon/silicon_say.dm b/code/modules/mob/living/silicon/silicon_say.dm index d2b838901717..7e806bbdf8c9 100644 --- a/code/modules/mob/living/silicon/silicon_say.dm +++ b/code/modules/mob/living/silicon/silicon_say.dm @@ -1,8 +1,8 @@ -/mob/living/proc/robot_talk(message) - log_talk(message, LOG_SAY, tag="binary") +/mob/living/proc/robot_talk(message, list/spans = list(), list/message_mods = list()) + log_sayverb_talk(message, message_mods, tag="binary") var/designation = "Default Cyborg" - var/spans = list(SPAN_ROBOT) + spans |= SPAN_ROBOT if(issilicon(src)) var/mob/living/silicon/player = src @@ -15,9 +15,10 @@ // AIs are loud and ugly spans |= SPAN_COMMAND - var/quoted_message = say_quote( + var/messagepart = generate_messagepart( message, - spans + spans, + message_mods, ) var/namepart = name @@ -31,31 +32,31 @@ namepart = brain.mainframe.name designation = brain.mainframe.job - for(var/mob/M in GLOB.player_list) - if(M.binarycheck()) - if(isAI(M)) + for(var/mob/hearing_mob in GLOB.player_list) + if(hearing_mob.binarycheck()) + if(isAI(hearing_mob)) to_chat( - M, + hearing_mob, span_binarysay("\ Robotic Talk, \ - [span_name("[namepart] ([designation])")] \ - [quoted_message]\ + [span_name("[namepart] ([designation])")] \ + [messagepart]\ "), type = MESSAGE_TYPE_RADIO, - avoid_highlighting = src == M + avoid_highlighting = (src == hearing_mob) ) else to_chat( - M, + hearing_mob, span_binarysay("\ Robotic Talk, \ - [span_name("[namepart]")] [quoted_message]\ + [span_name("[namepart]")] [messagepart]\ "), type = MESSAGE_TYPE_RADIO, - avoid_highlighting = src == M + avoid_highlighting = (src == hearing_mob) ) - if(isobserver(M)) + if(isobserver(hearing_mob)) var/following = src // If the AI talks on binary chat, we still want to follow @@ -65,17 +66,17 @@ var/mob/living/silicon/ai/ai = src following = ai.eyeobj - var/follow_link = FOLLOW_LINK(M, following) + var/follow_link = FOLLOW_LINK(hearing_mob, following) to_chat( - M, + hearing_mob, span_binarysay("\ [follow_link] \ Robotic Talk, \ - [span_name("[namepart]")] [quoted_message]\ + [span_name("[namepart]")] [messagepart]\ "), type = MESSAGE_TYPE_RADIO, - avoid_highlighting = src == M + avoid_highlighting = (src == hearing_mob) ) /mob/living/silicon/binarycheck() diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 770cca76ea4a..c6e03028a263 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -48,7 +48,7 @@ ///What the current cooldown on ranged attacks is, generally world.time + ranged_cooldown_time var/ranged_cooldown = 0 ///How long, in deciseconds, the cooldown of ranged attacks is - var/ranged_cooldown_time = 30 + var/ranged_cooldown_time = 3 SECONDS ///if it'll fire ranged attacks even if it lacks vision on its target, only works with environment smash var/ranged_ignores_vision = FALSE ///Should the ranged mob check for friendlies when shooting @@ -71,7 +71,7 @@ ///Timer for regaining our old search_objects value after being attacked var/search_objects_timer_id ///The delay between being attacked and gaining our old search_objects value back - var/search_objects_regain_time = 30 + var/search_objects_regain_time = 3 SECONDS ///A typecache of objects types that will be checked against to attack, should we have search_objects enabled var/list/wanted_objects = list() ///Mobs ignore mob/living targets with a stat lower than that of stat_attack. If set to DEAD, then they'll include corpses in their targets, if to HARD_CRIT they'll keep attacking until they kill, and so on. @@ -90,7 +90,7 @@ ///id for a timer to call LoseTarget(), used to stop mobs fixating on a target they can't reach var/lose_patience_timer_id ///30 seconds by default, so there's no major changes to AI behaviour, beyond actually bailing if stuck forever - var/lose_patience_timeout = 300 + var/lose_patience_timeout = 30 SECONDS /mob/living/simple_animal/hostile/Initialize(mapload) . = ..() diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm index d829d704c008..9746fef46754 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm @@ -47,7 +47,7 @@ /datum/action/innate/elite_attack/aoe_squares) var/sing_shot_length = 8 - var/cooldown_time = 20 + var/cooldown_time = 2 SECONDS /datum/action/innate/elite_attack/singular_shot name = "Singular Shot" diff --git a/code/modules/mob/living/simple_animal/hostile/ooze.dm b/code/modules/mob/living/simple_animal/hostile/ooze.dm index 8f53f2066c00..511300d56ac9 100644 --- a/code/modules/mob/living/simple_animal/hostile/ooze.dm +++ b/code/modules/mob/living/simple_animal/hostile/ooze.dm @@ -221,7 +221,7 @@ RegisterSignal(owner, COMSIG_LIVING_DEATH, PROC_REF(stop_consuming)) ///Try to consume the pulled mob -/datum/action/consume/Trigger(trigger_flags) +/datum/action/consume/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index ef85ac35c409..a047f0dc1ed9 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1502,7 +1502,12 @@ else living_flags |= QUEUE_NUTRITION_UPDATE -///Apply a proper movespeed modifier based on items we have equipped +/// Update mob stats based on equipment we are wearing when an item is equipped/dropped, to be overriden by children +/// source - Item that caused the update by being equipped/dropped +/mob/proc/update_equipment(obj/item/source) + update_equipment_speed_mods() + +/// Apply a proper movespeed modifier based on items we have equipped /mob/proc/update_equipment_speed_mods() var/speedies = 0 var/immutable_speedies = 0 diff --git a/code/modules/mob/mob_say.dm b/code/modules/mob/mob_say.dm index 1a27f9f6c6bc..5442dddc72b6 100644 --- a/code/modules/mob/mob_say.dm +++ b/code/modules/mob/mob_say.dm @@ -108,8 +108,14 @@ return ..() -///Speak as a dead person (ghost etc) -/mob/proc/say_dead(message) +/** + * say_dead + * allows you to speak as a dead person + * Args: + * - message: The message you're sending to chat. + * - mannequin_controller: If someone else is forcing you to speak, this is the mob doing it. + */ +/mob/proc/say_dead(message, mob/mannequin_controller) var/name = real_name var/alt_name = "" @@ -117,7 +123,7 @@ to_chat(usr, span_danger("Speech is currently admin-disabled.")) return - var/jb = is_banned_from(ckey, "Deadchat") + var/jb = is_banned_from(mannequin_controller?.ckey || ckey, "Deadchat") if(QDELETED(src)) return @@ -150,7 +156,7 @@ if(name != real_name) alt_name = " (died as [real_name])" - var/spanned = say_quote(apply_message_emphasis(message)) + var/spanned = generate_messagepart(message) var/source = "DEAD: [name][alt_name]" var/rendered = " [emoji_parse(spanned)]" log_talk(message, LOG_SAY, tag="DEAD") diff --git a/code/modules/mob/say_readme.md b/code/modules/mob/say_readme.md index 5284012de297..e39dfb9fbcf3 100644 --- a/code/modules/mob/say_readme.md +++ b/code/modules/mob/say_readme.md @@ -53,7 +53,7 @@ global procs languages live either in datum/languages_holder or in the mind. verb_say/verb_ask/verb_exclaim/verb_yell/verb_sing - These determine what the verb is for their respective action. Used in say_quote(). + These determine what the verb is for their respective action. Used in generate_messagepart(). say(message, bubble_type, var/list/spans, sanitize, datum/language/language, ignore_spam, forced) Say() is the "mother-proc". It calls all the other procs required for speaking, but does little itself. @@ -82,8 +82,8 @@ global procs Modifies the message by comparing the languages of the speaker with the languages of the hearer. Called on the hearer. - say_quote(input, spans, list/message_mods) - Adds a verb and quotes to a message. Also attaches span classes to a message. + generate_messagepart(input, spans, list/message_mods) + Either adds a lone custom say verb, or a verb and quotes to a message. Also attaches span classes to a message. Verbs are determined by verb_say/verb_ask/verb_yell/verb_sing variables. Called on the speaker. /mob diff --git a/code/modules/mob_spawn/ghost_roles/unused_roles.dm b/code/modules/mob_spawn/ghost_roles/unused_roles.dm index df651eb29c77..18f5aabb7dba 100644 --- a/code/modules/mob_spawn/ghost_roles/unused_roles.dm +++ b/code/modules/mob_spawn/ghost_roles/unused_roles.dm @@ -308,7 +308,7 @@ /datum/outfit/syndicatespace/syndicrew name = "Syndicate Ship Crew Member" - glasses = /obj/item/clothing/glasses/night/colorless + glasses = /obj/item/clothing/glasses/night mask = /obj/item/clothing/mask/gas/syndicate l_pocket = /obj/item/gun/ballistic/automatic/pistol r_pocket = /obj/item/knife/combat/survival diff --git a/code/modules/mod/mod_link.dm b/code/modules/mod/mod_link.dm index 2002469a16ec..3d21558a54db 100644 --- a/code/modules/mod/mod_link.dm +++ b/code/modules/mod/mod_link.dm @@ -122,7 +122,7 @@ . = ..() if(speaker != wearer && speaker != ai_assistant) return - mod_link.visual.say(raw_message, sanitize = FALSE, message_range = 2) + mod_link.visual.say(raw_message, spans = spans, sanitize = FALSE, language = message_language, message_range = 2, message_mods = message_mods) /obj/item/mod/control/proc/on_overlay_change(atom/source, cache_index, overlay) SIGNAL_HANDLER @@ -302,7 +302,7 @@ . = ..() if(speaker != loc) return - mod_link.visual.say(raw_message, sanitize = FALSE, message_range = 3) + mod_link.visual.say(raw_message, spans = spans, sanitize = FALSE, language = message_language, message_range = 3, message_mods = message_mods) /obj/item/clothing/neck/link_scryer/proc/on_overlay_change(atom/source, cache_index, overlay) SIGNAL_HANDLER diff --git a/code/modules/mod/modules/modules_antag.dm b/code/modules/mod/modules/modules_antag.dm index 2c8e2e7e0082..d8449338f7bf 100644 --- a/code/modules/mod/modules/modules_antag.dm +++ b/code/modules/mod/modules/modules_antag.dm @@ -465,7 +465,7 @@ device = /obj/item/gun/medbeam/mod incompatible_modules = list(/obj/item/mod/module/medbeam) removable = TRUE - cooldown_time = 0.5 + cooldown_time = 0.05 SECONDS required_slots = list(ITEM_SLOT_BACK) /obj/item/gun/medbeam/mod diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm index b84cc43c4be9..07faf3b32d26 100644 --- a/code/modules/mod/modules/modules_general.dm +++ b/code/modules/mod/modules/modules_general.dm @@ -1044,7 +1044,7 @@ /obj/item/mod/module/hearing_protection/on_part_activation() var/obj/item/clothing/head_cover = mod.get_part_from_slot(ITEM_SLOT_HEAD) || mod.get_part_from_slot(ITEM_SLOT_MASK) || mod.get_part_from_slot(ITEM_SLOT_EYES) if(istype(head_cover)) - head_cover.AddComponent(/datum/component/wearertargeting/earprotection, list(ITEM_SLOT_HEAD)) + head_cover.AddComponent(/datum/component/wearertargeting/earprotection) var/datum/component/wearertargeting/earprotection/protection = head_cover.GetComponent(/datum/component/wearertargeting/earprotection) protection.on_equip(src, mod.wearer, ITEM_SLOT_HEAD) diff --git a/code/modules/mod/modules/modules_maint.dm b/code/modules/mod/modules/modules_maint.dm index 3d4f17b7f7ab..17804dcd4067 100644 --- a/code/modules/mod/modules/modules_maint.dm +++ b/code/modules/mod/modules/modules_maint.dm @@ -54,7 +54,7 @@ set_off = TRUE ///Calls snap_signal() when exposed to a reagent via VAPOR, PATCH or TOUCH -/obj/item/mod/module/springlock/proc/on_wearer_exposed(atom/source, list/reagents, datum/reagents/source_reagents, methods, volume_modifier, show_message) +/obj/item/mod/module/springlock/proc/on_wearer_exposed(atom/source, list/reagents, datum/reagents/source_reagents, methods, show_message) SIGNAL_HANDLER if(!(methods & (VAPOR|PATCH|TOUCH))) diff --git a/code/modules/mod/modules/modules_visor.dm b/code/modules/mod/modules/modules_visor.dm index 572094627326..7897ac404f27 100644 --- a/code/modules/mod/modules/modules_visor.dm +++ b/code/modules/mod/modules/modules_visor.dm @@ -92,9 +92,9 @@ required_slots = list(ITEM_SLOT_HEAD|ITEM_SLOT_EYES|ITEM_SLOT_MASK) /obj/item/mod/module/night/on_activation() - mod.wearer.add_traits(TRAIT_TRUE_NIGHT_VISION, REF(src)) + ADD_TRAIT(mod.wearer, TRAIT_TRUE_NIGHT_VISION, REF(src)) mod.wearer.update_sight() /obj/item/mod/module/night/on_deactivation(display_message = TRUE, deleting = FALSE) - mod.wearer.remove_traits(TRAIT_TRUE_NIGHT_VISION, REF(src)) + REMOVE_TRAIT(mod.wearer, TRAIT_TRUE_NIGHT_VISION, REF(src)) mod.wearer.update_sight() diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm index a12935ca2b89..011484b5bb96 100644 --- a/code/modules/modular_computers/computers/item/computer.dm +++ b/code/modules/modular_computers/computers/item/computer.dm @@ -15,7 +15,9 @@ interaction_flags_mouse_drop = NEED_HANDS | ALLOW_RESTING ///The ID currently stored in the computer. - var/obj/item/card/id/computer_id_slot + var/obj/item/card/id/stored_id + ///The alt slot, only used by certain UIs like the access app. + var/obj/item/card/id/alt_stored_id ///The disk in this PDA. If set, this will be inserted on Initialize. var/obj/item/computer_disk/inserted_disk ///The power cell the computer uses to run on. @@ -189,8 +191,9 @@ QDEL_NULL(inserted_disk) if(istype(inserted_pai)) QDEL_NULL(inserted_pai) - if(computer_id_slot) - QDEL_NULL(computer_id_slot) + + QDEL_NULL(stored_id) + QDEL_NULL(alt_stored_id) shell = null physical = null @@ -230,7 +233,7 @@ if(issilicon(user)) return NONE - if(RemoveID(user)) + if(remove_id(user)) return CLICK_ACTION_SUCCESS if(istype(inserted_pai)) // Remove pAI @@ -239,22 +242,31 @@ return CLICK_ACTION_BLOCKING +/obj/item/modular_computer/click_alt_secondary(mob/user) + if(issilicon(user)) + return NONE + + if(remove_secondary_id(user)) + return CLICK_ACTION_SUCCESS + + return NONE + // Gets IDs/access levels from card slot. Would be useful when/if PDAs would become modular PCs. //guess what /obj/item/modular_computer/GetAccess() - if(computer_id_slot) - return computer_id_slot.GetAccess() + if(stored_id) + return stored_id.GetAccess() return ..() /obj/item/modular_computer/GetID() - if(computer_id_slot) - return computer_id_slot + if(stored_id) + return stored_id return ..() /obj/item/modular_computer/get_id_examine_strings(mob/user) . = ..() - if(computer_id_slot) - . += "[src] is displaying [computer_id_slot]:" - . += computer_id_slot.get_id_examine_strings(user) + if(stored_id) + . += "[src] is displaying [stored_id]:" + . += stored_id.get_id_examine_strings(user) /obj/item/modular_computer/proc/print_text(text_to_print, paper_title = "") if(!stored_paper) @@ -269,23 +281,23 @@ return TRUE /** - * InsertID * Attempt to insert the ID in either card slot, if ID is present - attempts swap + * * Args: * inserting_id - the ID being inserted * user - The person inserting the ID */ -/obj/item/modular_computer/InsertID(obj/item/card/inserting_id, mob/user) +/obj/item/modular_computer/insert_id(obj/item/card/inserting_id, mob/user) if(!isnull(user) && !user.transferItemToLoc(inserting_id, src)) return FALSE else inserting_id.forceMove(src) - if(!isnull(computer_id_slot)) - RemoveID(user, silent = TRUE) + if(!isnull(stored_id)) + remove_id(user, silent = TRUE) - computer_id_slot = inserting_id + stored_id = inserting_id if(!isnull(user)) to_chat(user, span_notice("You insert \the [inserting_id] into the card slot.")) @@ -296,42 +308,91 @@ if(ishuman(loc)) var/mob/living/carbon/human/human_wearer = loc if(human_wearer.wear_id == src) - human_wearer.sec_hud_set_ID() + human_wearer.update_ID_card() update_appearance() update_slot_icon() SEND_SIGNAL(src, COMSIG_MODULAR_COMPUTER_INSERTED_ID, inserting_id, user) return TRUE +/** + * Attempts to insert a secondary ID card into the computer. If there is already a secondary ID card, attempts to swap + * + * Args: + * * secondary_id - The ID card to insert into the secondary slot. + * * user - The mob trying to insert the ID, if there is one. + */ +/obj/item/modular_computer/proc/insert_secondary_id(obj/item/card/id/secondary_id, mob/user) + if(!isnull(alt_stored_id)) + remove_secondary_id(user, silent = TRUE) + + if(!user.transferItemToLoc(secondary_id, src)) + return FALSE + + alt_stored_id = secondary_id + if(!isnull(user)) + to_chat(user, span_notice("You insert \the [secondary_id] into the secondary card slot.")) + balloon_alert(user, "inserted secondary ID") + playsound(src, 'sound/machines/terminal/terminal_insert_disc.ogg', 50, FALSE) + + return TRUE + +/** + * Removes the alt ID card from the computer, and puts it in loc's hand if it's a mob + * + * Args: + * * user - The mob trying to remove the ID, if there is one + * * silent - Boolean, determines whether fluff text would be printed + */ +/obj/item/modular_computer/proc/remove_secondary_id(mob/user, silent = FALSE) + if(!alt_stored_id) + return FALSE + + if(!issilicon(user) && in_range(src, user)) + user.put_in_hands(alt_stored_id) + else + alt_stored_id.forceMove(drop_location()) + + var/obj/item/lost_id = alt_stored_id + alt_stored_id = null + + if(!silent && !isnull(user)) + to_chat(user, span_notice("You remove \the [lost_id] from the secondary card slot.")) + balloon_alert(user, "removed secondary ID") + playsound(src, 'sound/machines/terminal/terminal_insert_disc.ogg', 50, FALSE) + + return TRUE + /** * Removes the ID card from the computer, and puts it in loc's hand if it's a mob * Args: - * user - The mob trying to remove the ID, if there is one - * silent - Boolean, determines whether fluff text would be printed + * * user - The mob trying to remove the ID, if there is one + * * silent - Boolean, determines whether fluff text would be printed */ -/obj/item/modular_computer/RemoveID(mob/user, silent = FALSE) - if(!computer_id_slot) +/obj/item/modular_computer/remove_id(mob/user, silent = FALSE) + if(!stored_id) return ..() if(crew_manifest_update) - GLOB.manifest.modify(computer_id_slot.registered_name, computer_id_slot.assignment, computer_id_slot.get_trim_assignment()) + GLOB.manifest.modify(stored_id.registered_name, stored_id.assignment, stored_id.get_trim_assignment()) if(user && !issilicon(user) && in_range(src, user)) - user.put_in_hands(computer_id_slot) + user.put_in_hands(stored_id) else - computer_id_slot.forceMove(drop_location()) + stored_id.forceMove(drop_location()) - computer_id_slot = null + var/obj/item/lost_id = stored_id + stored_id = null if(!silent && !isnull(user)) - to_chat(user, span_notice("You remove the card from the card slot.")) - playsound(src, 'sound/machines/terminal/terminal_insert_disc.ogg', 50, FALSE) + to_chat(user, span_notice("You remove \the [lost_id] from the card slot.")) balloon_alert(user, "removed ID") + playsound(src, 'sound/machines/terminal/terminal_insert_disc.ogg', 50, FALSE) if(ishuman(loc)) var/mob/living/carbon/human/human_wearer = loc if(human_wearer.wear_id == src) - human_wearer.sec_hud_set_ID() + human_wearer.update_ID_card() update_slot_icon() update_appearance() @@ -391,15 +452,20 @@ . += "It is upgraded with an experimental long-ranged network capabilities, picking up NTNet frequencies while further away." . += span_notice("It has [max_capacity] GQ of storage capacity.") - if(computer_id_slot) + if(stored_id) if(Adjacent(user)) - . += "It has \the [computer_id_slot] card installed in its card slot." + . += "It has \the [stored_id] card inserted in its card slot.[alt_stored_id ? "" : " [span_info("Alt-click to eject it.")]"]" else . += "Its identification card slot is currently occupied." - . += span_info("Alt-click [src] to eject the identification card.") + + if(alt_stored_id) + if(Adjacent(user)) + . += "It has \the [alt_stored_id] card stored in its secondary card slot. [span_info("Alt-click to eject it.")]" + else + . += "Its secondary identification card slot is currently occupied." if(internal_cell) - . += span_info("Right-click it with a screwdriver to eject the [internal_cell]") + . += span_info("Right-click it with a screwdriver to eject the [internal_cell].") /obj/item/modular_computer/examine_more(mob/user) . = ..() @@ -415,8 +481,10 @@ /obj/item/modular_computer/add_context(atom/source, list/context, obj/item/held_item, mob/living/user) . = ..() - if(computer_id_slot && isidcard(held_item)) - context[SCREENTIP_CONTEXT_LMB] = "Swap ID" + if(isidcard(held_item)) + context[SCREENTIP_CONTEXT_LMB] = stored_id ? "Swap ID" : "Insert ID" + if(HAS_TRAIT(src, TRAIT_MODPC_TWO_ID_SLOTS)) + context[SCREENTIP_CONTEXT_RMB] = alt_stored_id ? "Swap Secondary ID" : "Insert Secondary ID" . = CONTEXTUAL_SCREENTIP_SET if(held_item?.tool_behaviour == TOOL_SCREWDRIVER && internal_cell) @@ -426,7 +494,10 @@ context[SCREENTIP_CONTEXT_RMB] = "Deconstruct" . = CONTEXTUAL_SCREENTIP_SET - if(computer_id_slot) // ID get removed first before pAIs + if(alt_stored_id) + context[SCREENTIP_CONTEXT_ALT_RMB] = "Remove Secondary ID" + . = CONTEXTUAL_SCREENTIP_SET + if(stored_id) // ID get removed first before pAIs context[SCREENTIP_CONTEXT_ALT_LMB] = "Remove ID" . = CONTEXTUAL_SCREENTIP_SET else if(inserted_pai) @@ -457,12 +528,14 @@ internal_cell = null if(enabled && !use_energy()) shutdown_computer() - if(computer_id_slot == gone) - computer_id_slot = null + if(stored_id == gone) + stored_id = null update_slot_icon() if(ishuman(loc)) var/mob/living/carbon/human/human_wearer = loc - human_wearer.sec_hud_set_ID() + human_wearer.update_ID_card() + if(alt_stored_id == gone) + alt_stored_id = null if(inserted_pai == gone) update_appearance(UPDATE_ICON) if(inserted_disk == gone) @@ -718,8 +791,8 @@ ///Imprints name and job into the modular computer, and calls back to necessary functions. ///Acts as a replacement to directly setting the imprints fields. All fields are optional, the proc will try to fill in missing gaps. /obj/item/modular_computer/proc/imprint_id(name = null, job_name = null) - saved_identification = name || computer_id_slot?.registered_name || saved_identification - saved_job = job_name || computer_id_slot?.assignment || saved_job + saved_identification = name || stored_id?.registered_name || saved_identification + saved_job = job_name || stored_id?.assignment || saved_job SEND_SIGNAL(src, COMSIG_MODULAR_PDA_IMPRINT_UPDATED, saved_identification, saved_job) UpdateDisplay() @@ -823,9 +896,15 @@ update_appearance() return ITEM_INTERACT_SUCCESS +/obj/item/modular_computer/item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers) + if(isidcard(tool) && HAS_TRAIT(src, TRAIT_MODPC_TWO_ID_SLOTS)) + return insert_secondary_id(tool, user) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING + + return item_interaction(user, tool, modifiers) + /obj/item/modular_computer/item_interaction(mob/living/user, obj/item/tool, list/modifiers) if(isidcard(tool)) - return InsertID(tool, user) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING + return insert_id(tool, user) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING if(iscash(tool)) return money_act(user, tool) @@ -854,8 +933,10 @@ if(istype(tool, /obj/item/computer_disk)) return computer_disk_act(user, tool) + return NONE + /obj/item/modular_computer/proc/money_act(mob/user, obj/item/money) - var/obj/item/card/id/inserted_id = computer_id_slot?.GetID() + var/obj/item/card/id/inserted_id = stored_id?.GetID() if(!inserted_id) balloon_alert(user, "no ID!") return ITEM_INTERACT_BLOCKING @@ -934,16 +1015,16 @@ return ITEM_INTERACT_SUCCESS /obj/item/modular_computer/atom_deconstruct(disassembled = TRUE) + var/atom/droploc = drop_location() remove_pai() eject_aicard() - if (disassembled) - internal_cell?.forceMove(drop_location()) - computer_id_slot?.forceMove(drop_location()) - inserted_disk?.forceMove(drop_location()) - new /obj/item/stack/sheet/iron(drop_location(), steel_sheet_cost) - else + internal_cell?.forceMove(droploc) + stored_id?.forceMove(droploc) + alt_stored_id?.forceMove(droploc) + inserted_disk?.forceMove(droploc) + if (!disassembled) physical.visible_message(span_notice("\The [src] breaks apart!")) - new /obj/item/stack/sheet/iron(drop_location(), round(steel_sheet_cost * 0.5)) + new /obj/item/stack/sheet/iron(droploc, steel_sheet_cost * (disassembled ? 1 : 0.5)) relay_qdel() // Ejects the inserted intellicard, if one exists. Used when the computer is deconstructed. @@ -998,7 +1079,7 @@ if(SEC_LEVEL_RED) // all-hands-on-deck situations, everyone is responsible for combatting a threat return ALERT_RELEVANCY_PERTINENT if(SEC_LEVEL_BLUE) // suspected threat. security needs to be alert and possibly preparing for it, no further concerns - if(ACCESS_SECURITY in computer_id_slot?.access) + if(ACCESS_SECURITY in stored_id?.access) return ALERT_RELEVANCY_PERTINENT else return ALERT_RELEVANCY_WARN diff --git a/code/modules/modular_computers/computers/item/computer_ui.dm b/code/modules/modular_computers/computers/item/computer_ui.dm index 3a260df77998..16a0a5915ffa 100644 --- a/code/modules/modular_computers/computers/item/computer_ui.dm +++ b/code/modules/modular_computers/computers/item/computer_ui.dm @@ -97,9 +97,9 @@ ) data["proposed_login"] = list( - IDInserted = computer_id_slot ? TRUE : FALSE, - IDName = computer_id_slot?.registered_name, - IDJob = computer_id_slot?.assignment, + IDInserted = stored_id ? TRUE : FALSE, + IDName = stored_id?.registered_name, + IDJob = stored_id?.assignment, ) data["removable_media"] = list() @@ -211,7 +211,7 @@ return TRUE if("ID") - if(RemoveID(user)) + if(remove_id(user)) playsound(src, 'sound/machines/card_slide.ogg', 50) return TRUE diff --git a/code/modules/modular_computers/computers/item/pda.dm b/code/modules/modular_computers/computers/item/pda.dm index 325907b0b71c..6d01aa7e3f5b 100644 --- a/code/modules/modular_computers/computers/item/pda.dm +++ b/code/modules/modular_computers/computers/item/pda.dm @@ -76,7 +76,7 @@ /obj/item/modular_computer/pda/update_overlays() . = ..() - if(computer_id_slot) + if(stored_id) . += mutable_appearance(overlays_icon, "id_overlay") if(light_on) . += mutable_appearance(overlays_icon, "light_overlay") diff --git a/code/modules/modular_computers/computers/item/role_tablet_presets.dm b/code/modules/modular_computers/computers/item/role_tablet_presets.dm index 17eebde4cd44..c70f18db874f 100644 --- a/code/modules/modular_computers/computers/item/role_tablet_presets.dm +++ b/code/modules/modular_computers/computers/item/role_tablet_presets.dm @@ -337,7 +337,7 @@ lube_flags = NO_SLIP_WHEN_WALKING,\ on_slip_callback = CALLBACK(src, PROC_REF(AfterSlip)),\ can_slip_callback = CALLBACK(src, PROC_REF(try_slip)),\ - slot_whitelist = list(ITEM_SLOT_ID, ITEM_SLOT_BELT),\ + slot_whitelist = ITEM_SLOT_ID | ITEM_SLOT_BELT,\ ) AddComponent(/datum/component/wearertargeting/sitcomlaughter, CALLBACK(src, PROC_REF(after_sitcom_laugh))) diff --git a/code/modules/modular_computers/computers/machinery/modular_computer.dm b/code/modules/modular_computers/computers/machinery/modular_computer.dm index cf68507adeb7..00411f280d2e 100644 --- a/code/modules/modular_computers/computers/machinery/modular_computer.dm +++ b/code/modules/modular_computers/computers/machinery/modular_computer.dm @@ -50,10 +50,16 @@ return ..() /obj/machinery/modular_computer/add_context(atom/source, list/context, obj/item/held_item, mob/user) - . = ..() + . = NONE + if(isnull(held_item)) context[SCREENTIP_CONTEXT_RMB] = "Toggle processor interaction" - return CONTEXTUAL_SCREENTIP_SET + . |= CONTEXTUAL_SCREENTIP_SET + + if(CPU_INTERACTABLE(user)) + . |= cpu?.add_context(source, context, held_item, user) + + return . /obj/machinery/modular_computer/attack_hand_secondary(mob/user, list/modifiers) . = ..() @@ -117,11 +123,17 @@ return update_icon(updates) /obj/machinery/modular_computer/click_alt(mob/user) - if(CPU_INTERACTABLE(user) || !can_interact(user)) + if(!CPU_INTERACTABLE(user) || !can_interact(user)) return NONE cpu.click_alt(user) return CLICK_ACTION_SUCCESS +/obj/machinery/modular_computer/click_alt_secondary(mob/user) + if(!CPU_INTERACTABLE(user) || !can_interact(user)) + return NONE + cpu.click_alt_secondary(user) + return CLICK_ACTION_SUCCESS + //ATTACK HAND IGNORING PARENT RETURN VALUE // On-click handling. Turns on the computer if it's off and opens the GUI. /obj/machinery/modular_computer/interact(mob/user) @@ -157,6 +169,9 @@ /obj/machinery/modular_computer/item_interaction(mob/living/user, obj/item/tool, list/modifiers) return (CPU_INTERACTABLE(user) && !user.combat_mode) ? cpu.item_interaction(user, tool, modifiers) : ..() +/obj/machinery/modular_computer/item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers) + return (CPU_INTERACTABLE(user) && !user.combat_mode) ? cpu.item_interaction_secondary(user, tool, modifiers) : ..() + /obj/machinery/modular_computer/attacked_by(obj/item/attacking_item, mob/living/user, list/modifiers, list/attack_modifiers) return CPU_INTERACTABLE(user) ? cpu.attacked_by(attacking_item, user, modifiers, attack_modifiers) : ..() diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm index 64516fa30bdf..eed37d68cde2 100644 --- a/code/modules/modular_computers/file_system/program.dm +++ b/code/modules/modular_computers/file_system/program.dm @@ -173,7 +173,7 @@ if(!length(access)) var/obj/item/card/id/accesscard if(computer) - accesscard = computer.computer_id_slot?.GetID() + accesscard = computer.stored_id?.GetID() if(!accesscard) if(loud && user) @@ -202,7 +202,7 @@ if(!can_run(user, loud = TRUE)) return FALSE if(program_flags & PROGRAM_REQUIRES_NTNET) - var/obj/item/card/id/ID = computer.computer_id_slot?.GetID() + var/obj/item/card/id/ID = computer.stored_id?.GetID() generate_network_log("Connection opened -- Program ID:[filename] User:[ID?"[ID.registered_name]":"None"]") SEND_SIGNAL(src, COMSIG_COMPUTER_PROGRAM_START, user) return TRUE @@ -228,7 +228,7 @@ return FALSE if(program_flags & PROGRAM_REQUIRES_NTNET) - var/obj/item/card/id/ID = computer.computer_id_slot?.GetID() + var/obj/item/card/id/ID = computer.stored_id?.GetID() generate_network_log("Connection closed -- Program ID: [filename] User:[ID ? "[ID.registered_name]" : "None"]") computer.update_appearance(UPDATE_ICON) diff --git a/code/modules/modular_computers/file_system/programs/betting.dm b/code/modules/modular_computers/file_system/programs/betting.dm index 8d132e052172..d368d15e8e70 100644 --- a/code/modules/modular_computers/file_system/programs/betting.dm +++ b/code/modules/modular_computers/file_system/programs/betting.dm @@ -40,17 +40,17 @@ GLOBAL_LIST_EMPTY_TYPED(active_bets, /datum/active_bet) "description" = bets.description, "owner" = bets == created_bet, "creator" = bets.bet_owner, - "current_bets" = bets.get_bets(computer.computer_id_slot?.registered_account), + "current_bets" = bets.get_bets(computer.stored_id?.registered_account), "locked" = bets.locked, )) data["can_create_bet"] = !!isnull(created_bet) - if(isnull(computer.computer_id_slot)) + if(isnull(computer.stored_id)) data["bank_name"] = null data["bank_money"] = null else - data["bank_name"] = computer.computer_id_slot.registered_account.account_holder - data["bank_money"] = computer.computer_id_slot.registered_account.account_balance + data["bank_name"] = computer.stored_id.registered_account.account_holder + data["bank_money"] = computer.stored_id.registered_account.account_balance return data @@ -63,7 +63,7 @@ GLOBAL_LIST_EMPTY_TYPED(active_bets, /datum/active_bet) /datum/computer_file/program/betting/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) . = ..() var/mob/user = ui.user - if(isnull(computer.computer_id_slot)) + if(isnull(computer.stored_id)) to_chat(user, span_danger("\The [computer] flashes an \"RFID Error - Unable to scan ID\" warning.")) return switch(action) @@ -102,14 +102,14 @@ GLOBAL_LIST_EMPTY_TYPED(active_bets, /datum/active_bet) var/option = params["option_selected"] if(isnull(bet_placed_on)) return - bet_placed_on.bet_money(computer.computer_id_slot.registered_account, money_betting, option) + bet_placed_on.bet_money(computer.stored_id.registered_account, money_betting, option) return TRUE if("cancel_bet") var/datum/active_bet/bet_cancelling for(var/datum/active_bet/bets as anything in GLOB.active_bets) if(bets.name == params["bet_selected"]) bet_cancelling = bets - bet_cancelling.cancel_bet(computer.computer_id_slot.registered_account) + bet_cancelling.cancel_bet(computer.stored_id.registered_account) return TRUE if("select_winner") var/datum/active_bet/bets_ending @@ -170,19 +170,32 @@ GLOBAL_LIST_EMPTY_TYPED(active_bets, /datum/active_bet) for(var/option in options) if(!length(options[option])) options[option] = list() - //we'll only advertise it on the first bet of the round, as to not make this overly annoying. - var/should_alert = FALSE - for(var/datum/feed_channel/FC in GLOB.news_network.network_channels) - if(FC.channel_name == NEWSCASTER_SPACE_BETTING) - if(!length(FC.messages)) - should_alert = TRUE - newscaster_message = GLOB.news_network.submit_article("The bet [name] has started, place your bets now!", "NtOS Space Betting App", NEWSCASTER_SPACE_BETTING, null, update_alert = should_alert) + advertise_bet() /datum/active_bet/Destroy(force) GLOB.active_bets -= src newscaster_message = null return ..() +/// Place a feed article advertising our bet. +/datum/active_bet/proc/advertise_bet() + var/datum/feed_channel/betting_channel = GLOB.news_network.network_channels_by_name[NEWSCASTER_SPACE_BETTING] + if(isnull(betting_channel)) + return + // We'll only advertise it on the first bet of the round, as to not make this overly annoying. + var/should_alert = !length(betting_channel.messages) + newscaster_message = GLOB.news_network.submit_article("The bet [name] has started, place your bets now!", "NtOS Space Betting App", NEWSCASTER_SPACE_BETTING, null, update_alert = should_alert) + +/// Reply to our previously placed advertisement feed article. +/datum/active_bet/proc/reply_to_feed(winning_option) + if(isnull(newscaster_message)) + return + GLOB.news_network.submit_comment( + comment_text = "The bet [name] has ended, the winner was [winning_option]!", + newscaster_username = "NtOS Betting Results", + current_message = newscaster_message, + ) + ///Returns how many bets there is per option /datum/active_bet/proc/get_bets(datum/bank_account/user_account) var/list/bets_per_option = list() @@ -206,11 +219,8 @@ GLOBAL_LIST_EMPTY_TYPED(active_bets, /datum/active_bet) var/datum/bank_account/refunded_account = existing_bets[1] refunded_account.adjust_money(text2num(existing_bets[2]), "Refund: [name] gamble cancelled.") return - GLOB.news_network.submit_comment( - comment_text = "The bet [name] has ended, the winner was [winning_option]!", - newscaster_username = "NtOS Betting Results", - current_message = newscaster_message, - ) + + reply_to_feed(winning_option) var/list/winners = options[winning_option] if(!length(winners)) return diff --git a/code/modules/modular_computers/file_system/programs/bounty_board.dm b/code/modules/modular_computers/file_system/programs/bounty_board.dm index da86b112689c..1b1320544731 100644 --- a/code/modules/modular_computers/file_system/programs/bounty_board.dm +++ b/code/modules/modular_computers/file_system/programs/bounty_board.dm @@ -39,8 +39,8 @@ if(!networked) GLOB.allbountyboards += computer networked = TRUE - if(computer.computer_id_slot) - current_user = computer.computer_id_slot?.registered_account + if(computer.stored_id) + current_user = computer.stored_id?.registered_account for(var/i in GLOB.request_list) if(!i) continue diff --git a/code/modules/modular_computers/file_system/programs/budgetordering.dm b/code/modules/modular_computers/file_system/programs/budgetordering.dm index b05237436a13..7ca2a8b0bbdb 100644 --- a/code/modules/modular_computers/file_system/programs/budgetordering.dm +++ b/code/modules/modular_computers/file_system/programs/budgetordering.dm @@ -48,7 +48,7 @@ //Aquire access from the inserted ID card. if(!length(access)) - var/obj/item/card/id/D = computer?.computer_id_slot?.GetID() + var/obj/item/card/id/D = computer?.stored_id?.GetID() if(!D) return FALSE access = D.GetAccess() @@ -63,7 +63,7 @@ data["location"] = SSshuttle.supply.getStatusText() data["department"] = "Cargo" var/datum/bank_account/buyer = SSeconomy.get_dep_account(cargo_account) - var/obj/item/card/id/id_card = computer.computer_id_slot?.GetID() + var/obj/item/card/id/id_card = computer.stored_id?.GetID() if(id_card?.registered_account) if((ACCESS_COMMAND in id_card.access)) requestonly = FALSE @@ -109,7 +109,6 @@ )) //Data regarding the User's capability to buy things. - data["has_id"] = id_card data["away"] = SSshuttle.supply.getDockedId() == docking_away data["self_paid"] = self_paid data["docked"] = SSshuttle.supply.mode == SHUTTLE_IDLE @@ -244,7 +243,7 @@ return var/reason = "" - if((requestonly && !self_paid) || !(computer.computer_id_slot?.GetID())) + if((requestonly && !self_paid) || !(computer.stored_id?.GetID())) reason = tgui_input_text(usr, "Reason", name, max_length = MAX_MESSAGE_LEN) if(isnull(reason) || ..()) return @@ -260,13 +259,13 @@ return if(!requestonly && !self_paid && ishuman(usr) && !account) - var/obj/item/card/id/id_card = computer.computer_id_slot?.GetID() + var/obj/item/card/id/id_card = computer.stored_id?.GetID() account = SSeconomy.get_dep_account(id_card?.registered_account?.account_job.paycheck_department) var/turf/T = get_turf(computer) var/datum/supply_order/SO = new(pack, name, rank, ckey, reason, account) SO.generateRequisition(T) - if((requestonly && !self_paid) || !(computer.computer_id_slot?.GetID())) + if((requestonly && !self_paid) || !(computer.stored_id?.GetID())) SSshuttle.request_list += SO else SSshuttle.shopping_list += SO @@ -290,7 +289,7 @@ var/id = text2num(params["id"]) for(var/datum/supply_order/SO in SSshuttle.request_list) if(SO.id == id) - var/obj/item/card/id/id_card = computer.computer_id_slot?.GetID() + var/obj/item/card/id/id_card = computer.stored_id?.GetID() if(id_card && id_card?.registered_account) SO.paying_account = SSeconomy.get_dep_account(id_card?.registered_account?.account_job.paycheck_department) SSshuttle.request_list -= SO diff --git a/code/modules/modular_computers/file_system/programs/card.dm b/code/modules/modular_computers/file_system/programs/card.dm index fe5fbbdfce10..e8dd5320fcb3 100644 --- a/code/modules/modular_computers/file_system/programs/card.dm +++ b/code/modules/modular_computers/file_system/programs/card.dm @@ -26,6 +26,15 @@ /// Which departments this program has access to. See region defines. var/target_dept +/datum/computer_file/program/card_mod/on_install(datum/computer_file/source, obj/item/modular_computer/computer_installing) + . = ..() + ADD_TRAIT(computer_installing, TRAIT_MODPC_TWO_ID_SLOTS, REF(src)) + +/datum/computer_file/program/card_mod/Destroy() + if(computer) + REMOVE_TRAIT(computer, TRAIT_MODPC_TWO_ID_SLOTS, REF(src)) + return ..() + /** * Authenticates the program based on the specific ID card. * @@ -80,24 +89,25 @@ /datum/computer_file/program/card_mod/kill_program(mob/user) computer.crew_manifest_update = FALSE - var/obj/item/card/id/inserted_auth_card = computer.computer_id_slot - if(inserted_auth_card) - GLOB.manifest.modify(inserted_auth_card.registered_name, inserted_auth_card.assignment, inserted_auth_card.get_trim_assignment()) + var/obj/item/card/id/modified_id = computer.alt_stored_id + if(modified_id) + GLOB.manifest.modify(modified_id.registered_name, modified_id.assignment, modified_id.get_trim_assignment()) return ..() /datum/computer_file/program/card_mod/ui_act(action, params, datum/tgui/ui, datum/ui_state/state) . = ..() var/mob/user = usr - var/obj/item/card/id/inserted_auth_card = computer.computer_id_slot + var/obj/item/card/id/auth_card = computer.stored_id + var/obj/item/card/id/modified_id = computer.alt_stored_id switch(action) // Log in. if("PRG_authenticate") - if(!computer || !inserted_auth_card) + if(!computer || !auth_card) playsound(computer, 'sound/machines/terminal/terminal_prompt_deny.ogg', 50, FALSE) return TRUE - if(authenticate(user, inserted_auth_card)) + if(authenticate(user, auth_card)) playsound(computer, 'sound/machines/terminal/terminal_on.ogg', 50, FALSE) return TRUE // Log out. @@ -108,71 +118,61 @@ return TRUE // Print a report. if("PRG_print") - if(!computer) - return TRUE - if(!authenticated_card) + if(!computer || !authenticated_card || !modified_id) return TRUE var/contents = {"

Access Report

Prepared By: [authenticated_user]
- For: [inserted_auth_card.registered_name ? inserted_auth_card.registered_name : "Unregistered"]
+ For: [modified_id.registered_name || "Unregistered"]

- Assignment: [inserted_auth_card.assignment]
+ Assignment: [modified_id.assignment]
Access:
"} var/list/known_access_rights = SSid_access.get_region_access_list(list(REGION_ALL_STATION)) - for(var/A in inserted_auth_card.access) + for(var/A in modified_id.access) if(A in known_access_rights) contents += " [SSid_access.get_access_desc(A)]" - if(!computer.print_text(contents, "access report - [inserted_auth_card.registered_name ? inserted_auth_card.registered_name : "Unregistered"]")) + if(!computer.print_text(contents, "access report - [modified_id.registered_name || "Unregistered"]")) to_chat(usr, span_notice("Printer is out of paper.")) return TRUE else playsound(computer, 'sound/machines/terminal/terminal_on.ogg', 50, FALSE) computer.visible_message(span_notice("\The [computer] prints out a paper.")) return TRUE - if("PRG_eject_id") - if(inserted_auth_card) - return computer.RemoveID(usr) - else - var/obj/item/I = user.get_active_held_item() - if(isidcard(I)) - return computer.InsertID(I, user) - return TRUE // Used to fire someone. Wipes all access from their card and modifies their assignment. if("PRG_terminate") if(!computer || !authenticated_card) return TRUE if(minor) - if(!(inserted_auth_card.trim?.type in job_templates)) + if(!(modified_id.trim?.type in job_templates)) to_chat(usr, span_notice("Software error: You do not have the necessary permissions to demote this card.")) return TRUE // Set the new assignment then remove the trim. - inserted_auth_card.assignment = is_centcom ? "Fired" : "Demoted" - SSid_access.remove_trim_from_card(inserted_auth_card) + modified_id.assignment = is_centcom ? "Fired" : "Demoted" + SSid_access.remove_trim_from_card(modified_id) playsound(computer, 'sound/machines/terminal/terminal_prompt_deny.ogg', 50, FALSE) return TRUE // Change ID card assigned name. if("PRG_edit") - if(!computer || !authenticated_card || !inserted_auth_card) + if(!computer || !authenticated_card || !modified_id) return TRUE - var/old_name = inserted_auth_card.registered_name + var/old_name = modified_id.registered_name // Sanitize the name first. We're not using the full sanitize_name proc as ID cards can have a wider variety of things on them that // would not pass as a formal character name, but would still be valid on an ID card created by a player. var/new_name = sanitize(params["name"]) if(!new_name) - inserted_auth_card.registered_name = null + modified_id.registered_name = null playsound(computer, SFX_TERMINAL_TYPE, 50, FALSE) - inserted_auth_card.update_label() + modified_id.update_label() // We had a name before and now we have no name, so this will unassign the card and we update the icon. if(old_name) - inserted_auth_card.update_icon() + modified_id.update_icon() return TRUE // However, we are going to reject bad names overall including names with invalid characters in them, while allowing numbers. @@ -182,63 +182,63 @@ to_chat(usr, span_notice("Software error: The ID card rejected the new name as it contains prohibited characters.")) return TRUE - inserted_auth_card.registered_name = new_name + modified_id.registered_name = new_name playsound(computer, SFX_TERMINAL_TYPE, 50, FALSE) - inserted_auth_card.update_label() + modified_id.update_label() // Card wasn't assigned before and now it is, so update the icon accordingly. if(!old_name) - inserted_auth_card.update_icon() + modified_id.update_icon() return TRUE // Change age if("PRG_age") - if(!computer || !authenticated_card || !inserted_auth_card) + if(!computer || !authenticated_card || !modified_id) return TRUE var/new_age = params["id_age"] if(!isnum(new_age)) - stack_trace("[key_name(usr)] ([usr]) attempted to set invalid age \[[new_age]\] to [inserted_auth_card]") + stack_trace("[key_name(usr)] ([usr]) attempted to set invalid age \[[new_age]\] to [modified_id]") return TRUE - inserted_auth_card.registered_age = new_age + modified_id.registered_age = new_age playsound(computer, SFX_TERMINAL_TYPE, 50, FALSE) return TRUE // Change assignment if("PRG_assign") - if(!computer || !authenticated_card || !inserted_auth_card) + if(!computer || !authenticated_card || !modified_id) return TRUE var/new_asignment = trim(sanitize(params["assignment"]), MAX_NAME_LEN) - inserted_auth_card.assignment = new_asignment + modified_id.assignment = new_asignment playsound(computer, SFX_TERMINAL_TYPE, 50, FALSE) - inserted_auth_card.update_label() + modified_id.update_label() return TRUE // Add/remove access. if("PRG_access") - if(!computer || !authenticated_card || !inserted_auth_card) + if(!computer || !authenticated_card || !modified_id) return TRUE playsound(computer, SFX_TERMINAL_TYPE, 50, FALSE) var/access_type = params["access_target"] var/try_wildcard = params["access_wildcard"] if(!(access_type in valid_access)) - stack_trace("[key_name(usr)] ([usr]) attempted to add invalid access \[[access_type]\] to [inserted_auth_card]") + stack_trace("[key_name(usr)] ([usr]) attempted to add invalid access \[[access_type]\] to [modified_id]") return TRUE - if(access_type in inserted_auth_card.access) - inserted_auth_card.remove_access(list(access_type)) - LOG_ID_ACCESS_CHANGE(user, inserted_auth_card, "removed [SSid_access.get_access_desc(access_type)]") + if(access_type in modified_id.access) + modified_id.remove_access(list(access_type)) + LOG_ID_ACCESS_CHANGE(user, modified_id, "removed [SSid_access.get_access_desc(access_type)]") return TRUE - if(!inserted_auth_card.add_access(list(access_type), try_wildcard)) + if(!modified_id.add_access(list(access_type), try_wildcard)) to_chat(usr, span_notice("ID error: ID card rejected your attempted access modification.")) - LOG_ID_ACCESS_CHANGE(user, inserted_auth_card, "failed to add [SSid_access.get_access_desc(access_type)][try_wildcard ? " with wildcard [try_wildcard]" : ""]") + LOG_ID_ACCESS_CHANGE(user, modified_id, "failed to add [SSid_access.get_access_desc(access_type)][try_wildcard ? " with wildcard [try_wildcard]" : ""]") return TRUE if(access_type in ACCESS_ALERT_ADMINS) - message_admins("[ADMIN_LOOKUPFLW(user)] just added [SSid_access.get_access_desc(access_type)] to an ID card [ADMIN_VV(inserted_auth_card)] [(inserted_auth_card.registered_name) ? "belonging to [inserted_auth_card.registered_name]." : "with no registered name."]") - LOG_ID_ACCESS_CHANGE(user, inserted_auth_card, "added [SSid_access.get_access_desc(access_type)]") + message_admins("[ADMIN_LOOKUPFLW(user)] just added [SSid_access.get_access_desc(access_type)] to an ID card [ADMIN_VV(modified_id)] [(modified_id.registered_name) ? "belonging to [modified_id.registered_name]." : "with no registered name."]") + LOG_ID_ACCESS_CHANGE(user, modified_id, "added [SSid_access.get_access_desc(access_type)]") return TRUE // Apply template to ID card. if("PRG_template") - if(!computer || !authenticated_card || !inserted_auth_card) + if(!computer || !authenticated_card || !modified_id) return TRUE playsound(computer, SFX_TERMINAL_TYPE, 50, FALSE) @@ -252,18 +252,36 @@ if(trim.assignment != template_name) continue - SSid_access.add_trim_access_to_card(inserted_auth_card, trim_path) + SSid_access.add_trim_access_to_card(modified_id, trim_path) return TRUE - stack_trace("[key_name(usr)] ([usr]) attempted to apply invalid template \[[template_name]\] to [inserted_auth_card]") + stack_trace("[key_name(usr)] ([usr]) attempted to apply invalid template \[[template_name]\] to [modified_id]") return TRUE + if("PRG_insert_main_id") + var/obj/item/card/id/main_id = user.get_active_held_item() + if(!isidcard(main_id)) + return TRUE + computer.insert_id(main_id, user) + return TRUE + if("PRG_remove_main_id") + if(computer?.stored_id) + computer.remove_id(user) + return TRUE + if("PRG_insert_alt_id") + var/obj/item/card/id/alt_id = user.get_active_held_item() + if(!isidcard(alt_id)) + to_chat(user, span_notice("You must hold an ID card to insert it into the secondary slot.")) + return TRUE + computer.insert_secondary_id(alt_id, user) + return TRUE + if("PRG_remove_alt_id") + if(computer?.alt_stored_id) + computer.remove_secondary_id(user) + return TRUE /datum/computer_file/program/card_mod/ui_static_data(mob/user) var/list/data = list() - data["station_name"] = station_name() - data["centcom_access"] = is_centcom - data["minor"] = target_dept || minor ? TRUE : FALSE var/list/regions = list() var/list/tgui_region_data = SSid_access.all_region_access_tgui @@ -277,11 +295,10 @@ data["regions"] = regions - - data["accessFlags"] = SSid_access.flags_by_access - data["wildcardFlags"] = SSid_access.wildcard_flags_by_wildcard - data["accessFlagNames"] = SSid_access.access_flag_string_by_flag - data["showBasic"] = TRUE + data["access_flags"] = SSid_access.flags_by_access + data["wildcard_flags"] = SSid_access.wildcard_flags_by_wildcard + data["access_flag_names"] = SSid_access.access_flag_string_by_flag + data["show_basic"] = TRUE data["templates"] = job_templates return data @@ -289,27 +306,31 @@ /datum/computer_file/program/card_mod/ui_data(mob/user) var/list/data = list() - var/obj/item/card/id/inserted_id = computer.computer_id_slot - data["authIDName"] = inserted_id ? inserted_id.name : "-----" - data["authenticatedUser"] = authenticated_card - - data["has_id"] = !!inserted_id - data["id_name"] = inserted_id ? inserted_id.name : "-----" - if(inserted_id) - data["id_rank"] = inserted_id.assignment ? inserted_id.assignment : "Unassigned" - data["id_owner"] = inserted_id.registered_name ? inserted_id.registered_name : "-----" - data["access_on_card"] = inserted_id.access - data["wildcardSlots"] = inserted_id.wildcard_slots - data["id_age"] = inserted_id.registered_age - - if(inserted_id.trim) - var/datum/id_trim/card_trim = inserted_id.trim - data["hasTrim"] = TRUE - data["trimAssignment"] = card_trim.assignment ? card_trim.assignment : "" - data["trimAccess"] = card_trim.access ? card_trim.access : list() - else - data["hasTrim"] = FALSE - data["trimAssignment"] = "" - data["trimAccess"] = list() + data["authed_user"] = authenticated_card + + var/obj/item/card/id/auth_id = computer.stored_id + var/obj/item/card/id/modified_id = computer.alt_stored_id + + data["auth_card"] = auth_id ? get_id_ui_data(auth_id) : null + data["modified_card"] = modified_id ? get_id_ui_data(modified_id) : null + data["is_holding_id"] = isidcard(user.get_active_held_item()) + + return data + +/datum/computer_file/program/card_mod/proc/get_id_ui_data(obj/item/card/id/card) + var/list/data = list() + + var/datum/id_trim/card_trim = card.trim + + data["id_name"] = card.name + data["id_rank"] = card.assignment || "Unassigned" + data["id_owner"] = card.registered_name || "-----" + data["access_on_card"] = card.access || list() + data["wildcard_slots"] = card.wildcard_slots || list() + data["id_age"] = card.registered_age + + data["has_trim"] = !!card_trim + data["trim_assignment"] = card_trim?.assignment || "" + data["trim_access"] = card_trim?.access || list() return data diff --git a/code/modules/modular_computers/file_system/programs/cargoship.dm b/code/modules/modular_computers/file_system/programs/cargoship.dm index 9df7bbd56d3b..089bc334db84 100644 --- a/code/modules/modular_computers/file_system/programs/cargoship.dm +++ b/code/modules/modular_computers/file_system/programs/cargoship.dm @@ -19,26 +19,26 @@ /datum/computer_file/program/shipping/ui_data(mob/user) var/list/data = list() - data["has_id_slot"] = !!computer.computer_id_slot + data["has_id_slot"] = !!computer.stored_id data["paperamt"] = "[computer.stored_paper] / [computer.max_paper]" - data["card_owner"] = computer.computer_id_slot || "No Card Inserted." + data["card_owner"] = computer.stored_id || "No Card Inserted." data["current_user"] = payments_acc ? payments_acc.account_holder : null data["barcode_split"] = cut_multiplier * 100 return data /datum/computer_file/program/shipping/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) . = ..() - if(!computer.computer_id_slot) //We need an ID to successfully run + if(!computer.stored_id) //We need an ID to successfully run return FALSE switch(action) if("ejectid") - computer.RemoveID(usr) + computer.remove_id(usr) if("selectid") - if(!computer.computer_id_slot.registered_account) + if(!computer.stored_id.registered_account) playsound(get_turf(computer.ui_host()), 'sound/machines/buzz/buzz-sigh.ogg', 50, TRUE, -1) return TRUE - payments_acc = computer.computer_id_slot.registered_account + payments_acc = computer.stored_id.registered_account playsound(get_turf(computer.ui_host()), 'sound/machines/ping.ogg', 50, TRUE, -1) if("resetid") payments_acc = null diff --git a/code/modules/modular_computers/file_system/programs/coupon.dm b/code/modules/modular_computers/file_system/programs/coupon.dm index b5d49a258d89..53bc2b6fe232 100644 --- a/code/modules/modular_computers/file_system/programs/coupon.dm +++ b/code/modules/modular_computers/file_system/programs/coupon.dm @@ -30,7 +30,7 @@ data["printed_coupons"] = list() data["redeemed_coupons"] = list() data["valid_id"] = FALSE - var/obj/item/card/id/user_id = computer.computer_id_slot + var/obj/item/card/id/user_id = computer.stored_id if(user_id?.registered_account.add_to_accounts) for(var/datum/coupon_code/coupon as anything in user_id.registered_account.redeemed_coupons) var/list/coupon_data = list( @@ -46,7 +46,7 @@ /datum/computer_file/program/coupon/ui_act(action, params, datum/tgui/ui, datum/ui_state/state) . = ..() - var/obj/item/card/id/user_id = computer.computer_id_slot + var/obj/item/card/id/user_id = computer.stored_id if(!(user_id?.registered_account.add_to_accounts)) return TRUE switch(action) @@ -91,7 +91,7 @@ /datum/computer_file/program/coupon/tap(atom/tapped_atom, mob/living/user, list/modifiers) if(!istype(tapped_atom, /obj/machinery/photocopier)) return FALSE - var/obj/item/card/id/user_id = computer.computer_id_slot + var/obj/item/card/id/user_id = computer.stored_id if(!(user_id?.registered_account)) computer.balloon_alert(user, "no bank account found!") return TRUE diff --git a/code/modules/modular_computers/file_system/programs/dept_order.dm b/code/modules/modular_computers/file_system/programs/dept_order.dm index d8f3377114b1..e640d5ecb371 100644 --- a/code/modules/modular_computers/file_system/programs/dept_order.dm +++ b/code/modules/modular_computers/file_system/programs/dept_order.dm @@ -64,7 +64,7 @@ GLOBAL_VAR(department_cd_override) /datum/computer_file/program/department_order/ui_data(mob/user) var/list/data = list() data["no_link"] = !linked_department - data["id_inside"] = !!computer.computer_id_slot + data["id_inside"] = !!computer.stored_id data["time_left"] = department_cooldowns[linked_department] ? DisplayTimeText(max(department_cooldowns[linked_department] - world.time, 0), 1) : null data["can_override"] = !!department_order return data @@ -142,7 +142,7 @@ GLOBAL_VAR(department_cd_override) if(!isnull(linked_department)) return TRUE - var/new_dept_type = find_department_to_link(computer.computer_id_slot) + var/new_dept_type = find_department_to_link(computer.stored_id) if(isnull(new_dept_type)) computer.physical.balloon_alert(orderer, "no department found!") playsound(computer, 'sound/machines/buzz/buzz-sigh.ogg', 30, TRUE) @@ -155,7 +155,7 @@ GLOBAL_VAR(department_cd_override) if(isnull(linked_department)) return TRUE - var/obj/item/card/id/id_card = computer.computer_id_slot || orderer.get_idcard(hand_first = TRUE) + var/obj/item/card/id/id_card = computer.stored_id || orderer.get_idcard(hand_first = TRUE) var/list/id_card_access = id_card?.GetAccess() || list() if(length(use_access & id_card_access) <= 0) diff --git a/code/modules/modular_computers/file_system/programs/jobmanagement.dm b/code/modules/modular_computers/file_system/programs/jobmanagement.dm index fefb76c7f84e..5f499c0a4961 100644 --- a/code/modules/modular_computers/file_system/programs/jobmanagement.dm +++ b/code/modules/modular_computers/file_system/programs/jobmanagement.dm @@ -55,7 +55,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) /datum/computer_file/program/job_management/ui_act(action, params, datum/tgui/ui, datum/ui_state/state) . = ..() - var/obj/item/card/id/user_id = computer.computer_id_slot + var/obj/item/card/id/user_id = computer.stored_id if(!user_id || !(ACCESS_CHANGE_IDS in user_id.access)) return TRUE @@ -107,7 +107,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) var/list/data = list() var/authed = FALSE - var/obj/item/card/id/user_id = computer.computer_id_slot + var/obj/item/card/id/user_id = computer.stored_id if(user_id && (ACCESS_CHANGE_IDS in user_id.access)) authed = TRUE diff --git a/code/modules/modular_computers/file_system/programs/nt_pay.dm b/code/modules/modular_computers/file_system/programs/nt_pay.dm index 4e3fa5d3fb71..200b2cee3378 100644 --- a/code/modules/modular_computers/file_system/programs/nt_pay.dm +++ b/code/modules/modular_computers/file_system/programs/nt_pay.dm @@ -42,7 +42,7 @@ /datum/computer_file/program/nt_pay/ui_data(mob/user) var/list/data = list() - current_user = computer.computer_id_slot?.registered_account || null + current_user = computer.stored_id?.registered_account || null if(!current_user) data["name"] = null else @@ -127,14 +127,14 @@ var/obj/item/modular_computer/modpc = associated_program.computer RegisterSignal(modpc, COMSIG_MODULAR_COMPUTER_NT_PAY_RESULT, PROC_REF(on_payment_done)) RegisterSignal(modpc, COMSIG_MODULAR_COMPUTER_INSERTED_ID, PROC_REF(register_id)) - if(modpc.computer_id_slot) - register_id(inserted_id = modpc.computer_id_slot) + if(modpc.stored_id) + register_id(inserted_id = modpc.stored_id) /obj/item/circuit_component/mod_program/nt_pay/unregister_shell() var/obj/item/modular_computer/modpc = associated_program.computer UnregisterSignal(modpc, list(COMSIG_MODULAR_COMPUTER_NT_PAY_RESULT, COMSIG_MODULAR_COMPUTER_INSERTED_ID)) - if(modpc.computer_id_slot) - UnregisterSignal(modpc.computer_id_slot, list(COMSIG_ID_CARD_NTPAY_MONEY_RECEIVED, COMSIG_MOVABLE_MOVED)) + if(modpc.stored_id) + UnregisterSignal(modpc.stored_id, list(COMSIG_ID_CARD_NTPAY_MONEY_RECEIVED, COMSIG_MOVABLE_MOVED)) return ..() /obj/item/circuit_component/mod_program/nt_pay/proc/register_id(datum/source, obj/item/card/inserted_id, mob/user) diff --git a/code/modules/modular_computers/file_system/programs/restock_tracker.dm b/code/modules/modular_computers/file_system/programs/restock_tracker.dm index 8f2174ce97bb..c1e64d178284 100644 --- a/code/modules/modular_computers/file_system/programs/restock_tracker.dm +++ b/code/modules/modular_computers/file_system/programs/restock_tracker.dm @@ -14,16 +14,17 @@ var/list/data = list() var/list/vending_list = list() var/id_increment = 1 - for(var/obj/machinery/vending/vendor as anything in GLOB.vending_machines_to_restock) - var/stock = vendor.total_loaded_stock() - var/max_stock = vendor.total_max_stock() - if((max_stock == 0 || (stock >= max_stock)) && vendor.credits_contained == 0) + for(var/obj/machinery/vending/vendor as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/vending)) + if(vendor.all_products_free) + continue + var/list/total_legal_stock = vendor.total_stock(contrabrand = FALSE) + if((!total_legal_stock[2] || (total_legal_stock[1] >= total_legal_stock[2])) && !vendor.credits_contained) continue vending_list += list(list( "name" = vendor.name, "location" = get_area_name(vendor), "credits" = vendor.credits_contained, - "percentage" = (stock / max_stock) * 100, + "percentage" = (total_legal_stock[1] / total_legal_stock[2]) * 100, "id" = id_increment, )) id_increment++ diff --git a/code/modules/modular_computers/file_system/programs/robocontrol.dm b/code/modules/modular_computers/file_system/programs/robocontrol.dm index 75c6bb545f28..1176ce92114a 100644 --- a/code/modules/modular_computers/file_system/programs/robocontrol.dm +++ b/code/modules/modular_computers/file_system/programs/robocontrol.dm @@ -28,14 +28,14 @@ var/list/mulelist = list() if(computer) - data["id_owner"] = computer.computer_id_slot || "" + data["id_owner"] = computer.stored_id || "" botcount = 0 for(var/mob/living/simple_animal/bot/simple_bot as anything in GLOB.bots_list) if(!is_valid_z_level(current_turf, get_turf(simple_bot)) || !(simple_bot.bot_mode_flags & BOT_MODE_REMOTE_ENABLED)) //Only non-emagged bots on the same Z-level are detected! continue - if(!simple_bot.allowed(user) && !simple_bot.check_access(computer.computer_id_slot)) // Only check Bots we can access + if(!simple_bot.allowed(user) && !simple_bot.check_access(computer.stored_id)) // Only check Bots we can access continue var/list/newbot = list( "name" = simple_bot.name, @@ -86,7 +86,7 @@ /datum/computer_file/program/robocontrol/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) . = ..() var/mob/current_user = ui.user - var/obj/item/card/id/id_card = computer?.computer_id_slot + var/obj/item/card/id/id_card = computer?.stored_id var/static/list/standard_actions = list( "patroloff", @@ -116,15 +116,15 @@ if("summon") simple_bot.bot_control(action, current_user, id_card ? id_card.access : id_card?.GetAccess()) if("ejectcard") - if(!computer || !computer.computer_id_slot) + if(!computer || !computer.stored_id) return if(id_card) GLOB.manifest.modify(id_card.registered_name, id_card.assignment, id_card.get_trim_assignment()) - computer.RemoveID(usr) + computer.remove_id(usr) else playsound(get_turf(computer.ui_host()) , 'sound/machines/buzz/buzz-sigh.ogg', 25, FALSE) if("changedroneaccess") - if(!computer || !computer.computer_id_slot || !id_card) + if(!computer || !computer.stored_id || !id_card) to_chat(current_user, span_notice("No ID found, authorization failed.")) return if(isdrone(current_user)) diff --git a/code/modules/modular_computers/file_system/programs/techweb.dm b/code/modules/modular_computers/file_system/programs/techweb.dm index 2c32a65d1fe8..25bfd9a326b1 100644 --- a/code/modules/modular_computers/file_system/programs/techweb.dm +++ b/code/modules/modular_computers/file_system/programs/techweb.dm @@ -111,7 +111,7 @@ if(computer.obj_flags & EMAGGED) to_chat(usr, span_boldwarning("Security protocol error: Unable to access locking protocols.")) return TRUE - if(lock_access in computer?.computer_id_slot?.access) + if(lock_access in computer?.stored_id?.access) locked = !locked else to_chat(usr, span_boldwarning("Unauthorized Access. Please insert research ID card.")) diff --git a/code/modules/movespeed/modifiers/admin.dm b/code/modules/movespeed/modifiers/admin.dm new file mode 100644 index 000000000000..c2002dec2d3a --- /dev/null +++ b/code/modules/movespeed/modifiers/admin.dm @@ -0,0 +1,4 @@ +/datum/movespeed_modifier/admin_varedit + variable = TRUE + + diff --git a/code/modules/movespeed/modifiers/misc.dm b/code/modules/movespeed/modifiers/misc.dm deleted file mode 100644 index e3aba912966a..000000000000 --- a/code/modules/movespeed/modifiers/misc.dm +++ /dev/null @@ -1,6 +0,0 @@ -/datum/movespeed_modifier/admin_varedit - variable = TRUE - -/datum/movespeed_modifier/yellow_orb - multiplicative_slowdown = -0.65 - blacklisted_movetypes = (FLYING|FLOATING) diff --git a/code/modules/movespeed/modifiers/status_effects.dm b/code/modules/movespeed/modifiers/status_effects.dm index 26522d0793b9..951944944c55 100644 --- a/code/modules/movespeed/modifiers/status_effects.dm +++ b/code/modules/movespeed/modifiers/status_effects.dm @@ -63,6 +63,10 @@ /datum/movespeed_modifier/status_effect/guardian_shield multiplicative_slowdown = 1 +/datum/movespeed_modifier/status_effect/yellow_orb + multiplicative_slowdown = -0.65 + blacklisted_movetypes = (FLYING|FLOATING) + ///movespeed modifier that makes you go faster when wet and lying on the floor once past the fish organ set threshold. /datum/movespeed_modifier/fish_flopping blacklisted_movetypes = MOVETYPES_NOT_TOUCHING_GROUND diff --git a/code/modules/pai/actions.dm b/code/modules/pai/actions.dm index e067cca01e9a..7e1899cba2c4 100644 --- a/code/modules/pai/actions.dm +++ b/code/modules/pai/actions.dm @@ -3,7 +3,7 @@ button_icon = 'icons/mob/actions/actions_silicon.dmi' var/mob/living/silicon/pai/pai_owner -/datum/action/innate/pai/Trigger(trigger_flags) +/datum/action/innate/pai/Trigger(mob/clicker, trigger_flags) if(!ispAI(owner)) return FALSE pai_owner = owner @@ -14,7 +14,7 @@ background_icon_state = "bg_tech" overlay_icon_state = "bg_tech_border" -/datum/action/innate/pai/software/Trigger(trigger_flags) +/datum/action/innate/pai/software/Trigger(mob/clicker, trigger_flags) ..() pai_owner.ui_act() @@ -24,7 +24,7 @@ background_icon_state = "bg_tech" overlay_icon_state = "bg_tech_border" -/datum/action/innate/pai/shell/Trigger(trigger_flags) +/datum/action/innate/pai/shell/Trigger(mob/clicker, trigger_flags) ..() if(pai_owner.holoform) pai_owner.fold_in(0) @@ -37,7 +37,7 @@ background_icon_state = "bg_tech" overlay_icon_state = "bg_tech_border" -/datum/action/innate/pai/chassis/Trigger(trigger_flags) +/datum/action/innate/pai/chassis/Trigger(mob/clicker, trigger_flags) ..() pai_owner.choose_chassis() @@ -47,7 +47,7 @@ background_icon_state = "bg_tech" overlay_icon_state = "bg_tech_border" -/datum/action/innate/pai/rest/Trigger(trigger_flags) +/datum/action/innate/pai/rest/Trigger(mob/clicker, trigger_flags) ..() pai_owner.toggle_resting() @@ -58,7 +58,7 @@ background_icon_state = "bg_tech" overlay_icon_state = "bg_tech_border" -/datum/action/innate/pai/light/Trigger(trigger_flags) +/datum/action/innate/pai/light/Trigger(mob/clicker, trigger_flags) ..() pai_owner.toggle_integrated_light() @@ -68,7 +68,7 @@ background_icon_state = "bg_tech" overlay_icon_state = "bg_tech_border" -/datum/action/innate/pai/messenger/Trigger(trigger_flags) +/datum/action/innate/pai/messenger/Trigger(mob/clicker, trigger_flags) . = ..() var/obj/item/pai_card/pai_holder = owner.loc if(!istype(pai_holder.loc, /obj/item/modular_computer)) diff --git a/code/modules/paperwork/paper_premade.dm b/code/modules/paperwork/paper_premade.dm index 606d8fbc3da8..5ee9693b481a 100644 --- a/code/modules/paperwork/paper_premade.dm +++ b/code/modules/paperwork/paper_premade.dm @@ -376,7 +376,7 @@ be able to save yourself for a few seconds and keep fighting.

Secondly, the bomb can be activated posthumously. There is a small onboard, low-level AI built into the microbomb. Based on a series of arbitrary factors, the bomb can still be activated despite the presence of atropine by releasing a failsafe vial of monkey blood (notoriously volatile), the timing of which is determined by the onboard AI. -
The only factor is whether or not, and for give me for what I'm about to write, your 'animating spirit' still resides within your body to guide the AI and activate the bomb manually. +
The only factor is whether or not, and forgive me for what I'm about to write, your 'animating spirit' still resides within your body to guide the AI and activate the bomb manually.
Please, do not ask your fellow operatives what this means.

They'll probably say something absurd like 'your ghost needs to still be in your body to use the microbomb'. That's stupid, do not listen to these ridiculous assertions. It is likely Nanotrasen propaganda. diff --git a/code/modules/plumbing/plumbers/_plumb_reagents.dm b/code/modules/plumbing/plumbers/_plumb_reagents.dm index 1f9a2e5e9612..4e18a0fbca54 100644 --- a/code/modules/plumbing/plumbers/_plumb_reagents.dm +++ b/code/modules/plumbing/plumbers/_plumb_reagents.dm @@ -27,7 +27,8 @@ remove_blacklisted = FALSE, //unused for plumbing, we don't care what reagents are inside us methods = LINEAR, //default round robin technique for transferring reagents show_message = TRUE, //unused for plumbing, used for logging only - ignore_stomach = FALSE //unused for plumbing, reagents flow only between machines & is not injected to mobs at any point in time + ignore_stomach = FALSE, //unused for plumbing, reagents flow only between machines & is not injected to mobs at any point in time + copy_only = FALSE //unused ) if(QDELETED(target) || !total_volume) return FALSE @@ -85,8 +86,6 @@ transfer_amount = reagent.volume * part if(reagent.intercept_reagents_transfer(target_holder, amount)) - update_total() - target_holder.update_total() continue transfered_amount = target_holder.add_reagent(reagent.type, transfer_amount, copy_data(reagent), chem_temp, reagent.purity, reagent.ph, no_react = TRUE) //we only handle reaction after every reagent has been transferred. @@ -156,7 +155,8 @@ remove_blacklisted = FALSE, methods = LINEAR, show_message = TRUE, - ignore_stomach = FALSE + ignore_stomach = FALSE, + copy_only = FALSE ) var/obj/machinery/plumbing/reaction_chamber/reactor = my_atom var/list/datum/reagent/catalysts = reactor.catalysts @@ -233,8 +233,6 @@ transfer_amount = working_volume * part if(reagent.intercept_reagents_transfer(target_holder, amount)) - update_total() - target_holder.update_total() continue transfered_amount = target_holder.add_reagent(reagent.type, transfer_amount, copy_data(reagent), chem_temp, reagent.purity, reagent.ph, no_react = TRUE) //we only handle reaction after every reagent has been transferred. diff --git a/code/modules/power/lighting/light.dm b/code/modules/power/lighting/light.dm index 4c9c8cc7bea2..acdc59fb47eb 100644 --- a/code/modules/power/lighting/light.dm +++ b/code/modules/power/lighting/light.dm @@ -502,22 +502,24 @@ /obj/machinery/light/proc/flicker(amount = rand(10, 20)) set waitfor = FALSE - if(flickering) + if(flickering || !on || status != LIGHT_OK) return + + . = TRUE // did we actually flicker? Send this now because we expect immediate response, before sleeping. flickering = TRUE - if(on && status == LIGHT_OK) - . = TRUE //did we actually flicker? Send this now because we expect immediate response, before sleeping. - for(var/i in 1 to amount) - if(status != LIGHT_OK || !has_power()) - break - on = !on - update(FALSE) - sleep(rand(5, 15)) - if(has_power()) - on = (status == LIGHT_OK) - else - on = FALSE + for(var/i in 1 to amount) + if(status != LIGHT_OK || !has_power()) + break + on = !on update(FALSE) + stoplag(rand(0.5 SECONDS, 1.5 SECONDS)) + + if(has_power()) + on = (status == LIGHT_OK) + else + on = FALSE + + update(FALSE) flickering = FALSE // ai attack - make lights flicker, because why not diff --git a/code/modules/power/power_store.dm b/code/modules/power/power_store.dm index 9dd60708a37e..c03b5b9590c6 100644 --- a/code/modules/power/power_store.dm +++ b/code/modules/power/power_store.dm @@ -267,13 +267,14 @@ return SHAME playsound(user, 'sound/effects/sparks/sparks1.ogg', charge / maxcharge) var/damage = charge / (1 KILO JOULES) + var/discharged_energy = charge user.electrocute_act(damage, src, 1, SHOCK_IGNORE_IMMUNITY|SHOCK_DELAY_STUN|SHOCK_NOGLOVES) charge = 0 update_appearance() if(user.stat != DEAD) to_chat(user, span_suicide("There's not enough charge in [src] to kill you!")) return SHAME - addtimer(CALLBACK(src, PROC_REF(gib_user), user, charge), 3 SECONDS) + addtimer(CALLBACK(src, PROC_REF(gib_user), user, discharged_energy), 3 SECONDS) return MANUAL_SUICIDE /obj/item/stock_parts/power_store/proc/gib_user(mob/living/user, discharged_energy) diff --git a/code/modules/power/powernet.dm b/code/modules/power/powernet.dm index 810b01533d64..f09b175878f4 100644 --- a/code/modules/power/powernet.dm +++ b/code/modules/power/powernet.dm @@ -106,7 +106,7 @@ * * flicker_source - The center of the flicker. If null the whole powernet will flicker * * falloff_distance - Only relevant if you passed a source. Areas beyond this distance will be less and less likely to flicker. */ -/datum/powernet/proc/propagate_light_flicker(atom/flicker_source, falloff_distance = 64) +/datum/powernet/proc/propagate_light_flicker(atom/flicker_source, falloff_distance = 32) if(flickering || !length(nodes)) return @@ -116,20 +116,19 @@ if(!istype(terminal.master, /obj/machinery/power/apc)) continue - if(isnull(flicker_source)) - if(!prob(95)) - continue - else - var/flicker_prob = 95 + (3 * (falloff_distance - get_dist(flicker_source, terminal))) - if(!prob(min(95, flicker_prob))) - continue + var/flicker_prob = 85 + if(!isnull(flicker_source)) + flicker_prob = 85 + min(3 * (falloff_distance - get_dist(flicker_source, terminal)), 0) + + if(!prob(flicker_prob)) + continue var/flicker_count = rand(1, 3) most_flickers = max(most_flickers, flicker_count) var/obj/machinery/power/apc/apc = terminal.master for(var/obj/machinery/light/light as anything in apc.get_lights()) light.flicker(flicker_count) - CHECK_TICK + CHECK_TICK // don't let another flicker propagation until our slowest area is done (with some added leeway) addtimer(VARSET_CALLBACK(src, flickering, FALSE), most_flickers * 2 SECONDS) diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index 522ee7c2697d..33106ba7ae32 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -27,6 +27,10 @@ var/maximum_fire_delay = 10 SECONDS ///Min delay before firing var/minimum_fire_delay = 2 SECONDS + ///Modifier to the preceeding two numbers + var/fire_rate_mod = 1 + ///Deactivates the "pause every 3 shots" system + var/no_shot_counter = FALSE ///When was the last shot var/last_shot = 0 ///Number of shots made (gets reset every few shots) @@ -57,6 +61,8 @@ var/charge = 0 ///stores the direction and orientation of the last projectile var/last_projectile_params + //the disk in the gun + var/obj/item/emitter_disk/diskie /obj/machinery/power/emitter/Initialize(mapload) . = ..() @@ -125,7 +131,7 @@ else if(!powered) . += span_notice("Its status display is glowing faintly.") else - . += span_notice("Its status display reads: Emitting one beam between [DisplayTimeText(minimum_fire_delay)] and [DisplayTimeText(maximum_fire_delay)].") + . += span_notice("Its status display reads: Emitting one beam between [DisplayTimeText(minimum_fire_delay * fire_rate_mod)] and [DisplayTimeText(maximum_fire_delay * fire_rate_mod)].") . += span_notice("Power consumption at [display_power(active_power_usage, convert = FALSE)].") /obj/machinery/power/emitter/should_have_node() @@ -246,11 +252,11 @@ projectile.fire(dir2angle(dir)) if(!manual) last_shot = world.time - if(shot_number < 3) - fire_delay = 20 + if(shot_number < 3 || no_shot_counter) + fire_delay = 20 * fire_rate_mod shot_number ++ else - fire_delay = rand(minimum_fire_delay,maximum_fire_delay) + fire_delay = rand(minimum_fire_delay,maximum_fire_delay) * fire_rate_mod shot_number = 0 return projectile @@ -311,6 +317,8 @@ /obj/machinery/power/emitter/crowbar_act(mob/living/user, obj/item/item) if(panel_open && gun) return remove_gun(user) + if(panel_open && diskie) + return remove_disk(user) default_deconstruction_crowbar(item) return TRUE @@ -343,8 +351,30 @@ wires.interact(user) return if(panel_open && !gun && istype(item,/obj/item/gun/energy)) + if(diskie) + to_chat(user, span_warning("Remove the Diode Disk before inserting a gun.")) + return if(integrate(item,user)) return + if(panel_open && !gun && istype(item,/obj/item/emitter_disk)) + var/obj/item/emitter_disk/config_disk = item + if(!user.transferItemToLoc(config_disk, src)) + balloon_alert(user, "stuck in hand!") + return + if(diskie) + user.put_in_hands(diskie) + balloon_alert(user, "disks swapped!") + else + balloon_alert(user, "disk inserted") + diskie = config_disk + projectile_type = diskie.stored_proj + projectile_sound = diskie.stored_sound + fire_rate_mod = diskie.fire_rate_mod + no_shot_counter = diskie.no_shot_counter + playsound(src, 'sound/machines/card_slide.ogg', 50) + to_chat(user, span_notice("You update the [src]'s diode configuration with the [config_disk].")) + if(diskie.consumable) + qdel(diskie) return ..() @@ -371,6 +401,19 @@ set_projectile() return TRUE +/obj/machinery/power/emitter/proc/remove_disk(mob/user) + if(!diskie) + return + if(diskie.consumed_on_removal) + qdel(diskie) + else + user.put_in_hands(diskie) + diskie = null + playsound(src, 'sound/machines/card_slide.ogg', 50, TRUE) + set_projectile() + return TRUE + + /obj/machinery/power/emitter/proc/set_projectile() if(LAZYLEN(gun_properties)) if(mode || !gun_properties["lethal_projectile"]) @@ -382,6 +425,8 @@ return projectile_type = initial(projectile_type) projectile_sound = initial(projectile_sound) + fire_rate_mod = initial(fire_rate_mod) + no_shot_counter = initial(no_shot_counter) /obj/machinery/power/emitter/emag_act(mob/user, obj/item/card/emag/emag_card) if(obj_flags & EMAGGED) @@ -567,3 +612,58 @@ req_access = list("science") welded = TRUE use_power = NO_POWER_USE + +/obj/item/emitter_disk + name = "/improper Diode Disk: Debugger" + desc = "This disk can be used on an emitter with an open panel to reset its projectile. Unless this was handed to you by an admin, you should report this on github." + icon = 'icons/obj/devices/circuitry_n_data.dmi' + icon_state = "datadisk6" + var/stored_proj = /obj/projectile/beam/emitter/hitscan + var/stored_sound = 'sound/items/weapons/emitter.ogg' + var/consumed_on_removal = TRUE + var/consumable = TRUE + var/fire_rate_mod = 1 + var/no_shot_counter = FALSE + +/obj/item/emitter_disk/stamina + name = "/improper Diode Disk: Electrodisruptive" + desc = "This disk can be used on an emitter with an open panel to make it shoot lasers which will increase the integrity of supermatter crystals and exhaust living creatures. The disk will be consumed in the process." + stored_proj = /obj/projectile/beam/emitter/hitscan/bluelens + consumed_on_removal = FALSE + consumable = FALSE + +/obj/item/emitter_disk/healing + name = "/improper Diode Disk: Bioregenerative" + desc = "This disk can be installed into an emitter with an open panel to make it shoot lasers which will heal the physical damages of living creatures." + stored_proj = /obj/projectile/beam/emitter/hitscan/bioregen + consumed_on_removal = FALSE + consumable = FALSE + +/obj/item/emitter_disk/incendiary + name = "/improper Diode Disk: Conflagratory" + desc = "This disk can be used on an emitter with an open panel to make it shoot lasers which will set living creatures ablaze." + stored_proj = /obj/projectile/beam/emitter/hitscan/incend + consumed_on_removal = FALSE + consumable = FALSE + +/obj/item/emitter_disk/sanity + name = "/improper Diode Disk: Psychosiphoning" + desc = "This disk can be used on an emitter with an open panel to make it shoot lasers which will depress living creatures and calm supermatter crystals." + stored_proj = /obj/projectile/beam/emitter/hitscan/psy + consumed_on_removal = FALSE + consumable = FALSE + +/obj/item/emitter_disk/magnetic + name = "/improper Diode Disk: Magnetogenerative" + desc = "This disk can be used on an emitter with an open panel to make it shoot lasers which will attract nearby objects." + stored_proj = /obj/projectile/beam/emitter/hitscan/magnetic + consumed_on_removal = FALSE + consumable = FALSE + +/obj/item/emitter_disk/blast + name = "/improper Diode Disk: Hyperconcussive" + desc = "This disk, loaded with proprietary syndicate firmware, can be used on an emitter with an open panel to make it shoot beams of concussive force which will cause small explosions." + stored_proj = /obj/projectile/beam/emitter/hitscan/blast + consumed_on_removal = FALSE + consumable = FALSE + fire_rate_mod = 2 diff --git a/code/modules/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm index 09e380aca17f..2e2d90580878 100644 --- a/code/modules/power/singularity/narsie.dm +++ b/code/modules/power/singularity/narsie.dm @@ -146,8 +146,11 @@ log_admin("[key_name(usr)] has triggered the Nar'Sie roundender.") start_ending_the_round() -/obj/narsie/attack_ghost(mob/user) - make_new_construct(/mob/living/basic/construct/harvester, user, cultoverride = TRUE, loc_override = loc) +/obj/narsie/attack_ghost(mob/dead/observer/user) + if(is_banned_from(user.ckey, ROLE_CULTIST)) + return + if(tgui_alert(user, "Do you wish to become an occult harvester?", "Become Harvester?", list("Yes", "No"), timeout = 10 SECONDS) == "Yes") + make_new_construct(/mob/living/basic/construct/harvester, user, cultoverride = TRUE, loc_override = loc, ghost_activated = TRUE) /obj/narsie/process() var/datum/component/singularity/singularity_component = singularity.resolve() diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm index 73f691946c7d..db5c1d0ac584 100644 --- a/code/modules/power/supermatter/supermatter.dm +++ b/code/modules/power/supermatter/supermatter.dm @@ -366,6 +366,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) update_appearance() delamination_strategy.lights(src) delamination_strategy.filters(src) + absorption_ratio = clamp(absorption_ratio - 0.05, 0.15, 1) return TRUE // SupermatterMonitor UI for ghosts only. Inherited attack_ghost will call this. diff --git a/code/modules/power/supermatter/supermatter_extra_effects.dm b/code/modules/power/supermatter/supermatter_extra_effects.dm index fe3f69ef60b9..0724667300fb 100644 --- a/code/modules/power/supermatter/supermatter_extra_effects.dm +++ b/code/modules/power/supermatter/supermatter_extra_effects.dm @@ -165,7 +165,7 @@ return switch(type) if(FLUX_ANOMALY) - var/explosive = has_changed_lifespan ? FLUX_NO_EXPLOSION : FLUX_LOW_EXPLOSIVE + var/explosive = has_changed_lifespan ? FLUX_NO_EMP : FLUX_LIGHT_EMP new /obj/effect/anomaly/flux(local_turf, has_changed_lifespan ? rand(25 SECONDS, 35 SECONDS) : null, FALSE, explosive) if(GRAVITATIONAL_ANOMALY) new /obj/effect/anomaly/grav(local_turf, has_changed_lifespan ? rand(20 SECONDS, 30 SECONDS) : null, FALSE) diff --git a/code/modules/power/supermatter/supermatter_hit_procs.dm b/code/modules/power/supermatter/supermatter_hit_procs.dm index 1f929ba0ed27..056081bda7e8 100644 --- a/code/modules/power/supermatter/supermatter_hit_procs.dm +++ b/code/modules/power/supermatter/supermatter_hit_procs.dm @@ -24,7 +24,6 @@ if(projectile.armor_flag != BULLET || kiss_power) if(kiss_power) psy_coeff = 1 - external_power_immediate += projectile.damage * bullet_energy + kiss_power log_activation(who = projectile.firer, how = projectile.fired_from) else external_damage_immediate += projectile.damage * bullet_energy * 0.1 @@ -34,6 +33,17 @@ if(damage_to_be > danger_point) visible_message(span_notice("[src] compresses under stress, resisting further impacts!")) playsound(src, 'sound/effects/supermatter.ogg', 50, TRUE) + if(istype(projectile, /obj/projectile/beam/emitter/hitscan)) + var/obj/projectile/beam/emitter/hitscan/mahlaser = projectile + if(mahlaser?.integrity_heal) + damage = max(0, damage - mahlaser?.integrity_heal) + if(mahlaser?.energy_reduction) + internal_energy = max(0, internal_energy - mahlaser?.energy_reduction) + if(mahlaser?.psi_change) + psy_coeff = clamp(psy_coeff + mahlaser?.psi_change, 0, 1) + external_power_immediate += projectile.damage * bullet_energy + kiss_power + if(istype(projectile, /obj/projectile/beam/emitter/hitscan/magnetic)) + absorption_ratio = clamp(absorption_ratio + 0.05, 0.15, 1) qdel(projectile) return COMPONENT_BULLET_BLOCKED diff --git a/code/modules/projectiles/ammunition/_ammunition.dm b/code/modules/projectiles/ammunition/_ammunition.dm index 86650123f13c..e0cc6e089204 100644 --- a/code/modules/projectiles/ammunition/_ammunition.dm +++ b/code/modules/projectiles/ammunition/_ammunition.dm @@ -147,7 +147,7 @@ continue if (boolets > 0) box.update_appearance() - to_chat(user, span_notice("You collect [boolets] shell\s. [box] now contains [box.stored_ammo.len] shell\s.")) + to_chat(user, span_notice("You collect [boolets] [box.casing_phrasing]\s. [box] now contains [box.stored_ammo.len] [box.casing_phrasing]\s.")) else to_chat(user, span_warning("You fail to collect anything!")) else diff --git a/code/modules/projectiles/ammunition/ballistic/rifle.dm b/code/modules/projectiles/ammunition/ballistic/rifle.dm index 3e0e18d58bd2..2ec850950b03 100644 --- a/code/modules/projectiles/ammunition/ballistic/rifle.dm +++ b/code/modules/projectiles/ammunition/ballistic/rifle.dm @@ -2,7 +2,7 @@ /obj/item/ammo_casing/strilka310 name = ".310 Strilka bullet casing" - desc = "A .310 Strilka bullet casing. Casing is a bit of a fib, there is no case, it's just a block of red powder." + desc = "A .310 Strilka bullet casing. Casing is a bit of a fib; there is no case, it's just a block of red powder." icon_state = "310-casing" caliber = CALIBER_STRILKA310 projectile_type = /obj/projectile/bullet/strilka310 @@ -14,7 +14,7 @@ /obj/item/ammo_casing/strilka310/surplus name = ".310 Strilka surplus bullet casing" - desc = "A surplus .310 Strilka bullet casing. Casing is a bit of a fib, there is no case, it's just a block of red powder. Damp red powder at that." + desc = parent_type::desc + " Damp red powder at that." projectile_type = /obj/projectile/bullet/strilka310/surplus /obj/item/ammo_casing/strilka310/enchanted @@ -22,13 +22,14 @@ /obj/item/ammo_casing/strilka310/phasic name = ".310 Strilka phasic bullet casing" - desc = "A phasic .310 Strilka bullet casing. " + desc = "A phasic .310 Strilka bullet casing." projectile_type = /obj/projectile/bullet/strilka310/phasic // .223 (M-90gl Carbine) /obj/item/ammo_casing/a223 name = ".223 bullet casing" desc = "A .223 bullet casing." + icon_state = "223-casing" caliber = CALIBER_A223 projectile_type = /obj/projectile/bullet/a223 diff --git a/code/modules/projectiles/ammunition/energy/special.dm b/code/modules/projectiles/ammunition/energy/special.dm index 95ecf05228e7..7ed56c0ddd0d 100644 --- a/code/modules/projectiles/ammunition/energy/special.dm +++ b/code/modules/projectiles/ammunition/energy/special.dm @@ -63,11 +63,11 @@ harmful = FALSE /obj/item/ammo_casing/energy/tesla_cannon - fire_sound = 'sound/effects/magic/lightningshock.ogg' + fire_sound = null e_cost = LASER_SHOTS(33, STANDARD_CELL_CHARGE) select_name = "shock" projectile_type = /obj/projectile/energy/tesla_cannon - firing_effect_type = /obj/effect/temp_visual/dir_setting/firing_effect/blue + firing_effect_type = null /obj/item/ammo_casing/energy/shrink projectile_type = /obj/projectile/magic/shrink/alien diff --git a/code/modules/projectiles/boxes_magazines/_box_magazine.dm b/code/modules/projectiles/boxes_magazines/_box_magazine.dm index 655a6cae18ef..4194badcc0e3 100644 --- a/code/modules/projectiles/boxes_magazines/_box_magazine.dm +++ b/code/modules/projectiles/boxes_magazines/_box_magazine.dm @@ -29,14 +29,15 @@ var/multiple_sprite_use_base = FALSE ///String, used for checking if ammo of different types but still fits can fit inside it; generally used for magazines var/caliber - ///Allows multiple bullets to be loaded in from one click of another box/magazine - var/multiload = TRUE + /// Determines whether ammo boxes can multiload in or out. + var/ammo_box_multiload = AMMO_BOX_MULTILOAD_BOTH + ///Whether the magazine should start with nothing in it var/start_empty = FALSE /// If this and ammo_band_icon aren't null, run update_ammo_band(). Is the color of the band, such as blue on the detective's Iceblox. var/ammo_band_color - /// If this and ammo_band_color aren't null, run update_ammo_band() Is the greyscale icon used for the ammo band. + /// If this and ammo_band_color aren't null, run update_ammo_band(). Is the greyscale icon used for the ammo band. var/ammo_band_icon /// Is the greyscale icon used for the ammo band when it's empty of bullets, only if it's not null. var/ammo_band_icon_empty @@ -161,8 +162,7 @@ /obj/item/ammo_box/proc/can_load(mob/user) return TRUE -/obj/item/ammo_box/attackby(obj/item/tool, mob/user, params, silent = FALSE, replace_spent = 0) - +/obj/item/ammo_box/item_interaction(mob/living/user, obj/item/tool, list/modifiers) if(IS_WRITING_UTENSIL(tool)) if(!ammo_band_icon) balloon_alert(user, "no indicator support!") @@ -173,6 +173,10 @@ update_appearance() return + if(try_load(user, tool)) + return ITEM_INTERACT_SUCCESS + +/obj/item/ammo_box/proc/try_load(mob/living/user, obj/item/tool, silent = FALSE, replace_spent = FALSE) var/num_loaded = 0 if(!can_load(user)) return @@ -184,7 +188,7 @@ if(did_load) other_box.stored_ammo -= casing num_loaded++ - if(!did_load || !multiload) + if(!did_load || !(ammo_box_multiload & AMMO_BOX_MULTILOAD_IN) || !(other_box.ammo_box_multiload & AMMO_BOX_MULTILOAD_OUT)) break if(num_loaded) @@ -253,7 +257,8 @@ /obj/item/ammo_box/magazine name = "A magazine (what?)" - desc = "A magazine of rounds, they look like error signs..." + desc = "A magazine of rounds, they look like error signs... this should probably be reported somewhere." + ammo_box_multiload = AMMO_BOX_MULTILOAD_IN // so you can't use a magazine like a bootleg speedloader drop_sound = 'sound/items/handling/gun/ballistics/magazine/magazine_drop1.ogg' pickup_sound = 'sound/items/handling/gun/ballistics/magazine/magazine_pickup1.ogg' diff --git a/code/modules/projectiles/boxes_magazines/external/toy.dm b/code/modules/projectiles/boxes_magazines/external/toy.dm index 695388280ebc..ff45d604ebc4 100644 --- a/code/modules/projectiles/boxes_magazines/external/toy.dm +++ b/code/modules/projectiles/boxes_magazines/external/toy.dm @@ -1,5 +1,6 @@ /obj/item/ammo_box/magazine/toy name = "foam force META magazine" + desc = "A magazine specifically designed for foam force \"firearms\". Probably not great for actually killing your fellow spaceman." ammo_type = /obj/item/ammo_casing/foam_dart caliber = CALIBER_FOAM diff --git a/code/modules/projectiles/boxes_magazines/internal/revolver.dm b/code/modules/projectiles/boxes_magazines/internal/revolver.dm index 1e891abeef28..630e91ab12f2 100644 --- a/code/modules/projectiles/boxes_magazines/internal/revolver.dm +++ b/code/modules/projectiles/boxes_magazines/internal/revolver.dm @@ -15,7 +15,7 @@ ammo_type = /obj/item/ammo_casing/c357 caliber = CALIBER_357 max_ammo = 6 - multiload = FALSE + ammo_box_multiload = AMMO_BOX_MULTILOAD_NONE // presumably so you don't teleport in a full cylinder and end up shooting yourself immediately start_empty = TRUE /obj/item/ammo_box/magazine/internal/cylinder/rus357/Initialize(mapload) diff --git a/code/modules/projectiles/boxes_magazines/internal/rifle.dm b/code/modules/projectiles/boxes_magazines/internal/rifle.dm index fd643a8e6e5e..2853cecc9bfa 100644 --- a/code/modules/projectiles/boxes_magazines/internal/rifle.dm +++ b/code/modules/projectiles/boxes_magazines/internal/rifle.dm @@ -4,7 +4,6 @@ ammo_type = /obj/item/ammo_casing/strilka310 caliber = CALIBER_STRILKA310 max_ammo = 5 - multiload = TRUE /obj/item/ammo_box/magazine/internal/boltaction/surplus ammo_type = /obj/item/ammo_casing/strilka310/surplus @@ -69,7 +68,6 @@ ammo_type = /obj/item/ammo_casing/strilka310 caliber = CALIBER_STRILKA310 max_ammo = 10 - multiload = TRUE /obj/item/ammo_box/magazine/internal/sks/empty start_empty = TRUE diff --git a/code/modules/projectiles/boxes_magazines/internal/shotgun.dm b/code/modules/projectiles/boxes_magazines/internal/shotgun.dm index 649cb9eb536b..ef14b2701a39 100644 --- a/code/modules/projectiles/boxes_magazines/internal/shotgun.dm +++ b/code/modules/projectiles/boxes_magazines/internal/shotgun.dm @@ -3,7 +3,8 @@ ammo_type = /obj/item/ammo_casing/shotgun/beanbag caliber = CALIBER_SHOTGUN max_ammo = 4 - multiload = FALSE + // this inherits regular magazines' AMMO_BOX_MULTILOAD_IN, which means that regular shotguns shouldn't be multiloading from Bulldog magazines + // if someone has the bright idea to add shotgun speedloaders, i certainly hope they know what they're inviting by doing so /obj/item/ammo_box/magazine/internal/shot/tube name = "dual feed shotgun internal tube" diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm index 83f03c90e54d..c963f524c3bf 100644 --- a/code/modules/projectiles/guns/ballistic.dm +++ b/code/modules/projectiles/guns/ballistic.dm @@ -549,7 +549,7 @@ magazine.stored_ammo -= chambered chambered = null - var/num_loaded = magazine?.attackby(ammo, user, silent = TRUE) + var/num_loaded = magazine?.try_load(user, ammo, silent = TRUE) if (!num_loaded) return FALSE diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm index 2820fbec3e7a..426d8ef0a608 100644 --- a/code/modules/projectiles/guns/ballistic/automatic.dm +++ b/code/modules/projectiles/guns/ballistic/automatic.dm @@ -148,7 +148,6 @@ selector_switch_icon = TRUE accepted_magazine_type = /obj/item/ammo_box/magazine/m223 can_suppress = FALSE - var/obj/item/gun/ballistic/revolver/grenadelauncher/underbarrel burst_size = 3 burst_delay = 2 spread = 5 @@ -156,10 +155,12 @@ mag_display = TRUE empty_indicator = TRUE fire_sound = 'sound/items/weapons/gun/smg/shot_alt.ogg' + /// Attached underbarrel grenade launcher + var/obj/item/gun/ballistic/revolver/grenadelauncher/underbarrel/underbarrel /obj/item/gun/ballistic/automatic/m90/Initialize(mapload) . = ..() - underbarrel = new /obj/item/gun/ballistic/revolver/grenadelauncher(src) + underbarrel = new(src) update_appearance() /obj/item/gun/ballistic/automatic/m90/Destroy() diff --git a/code/modules/projectiles/guns/ballistic/launchers.dm b/code/modules/projectiles/guns/ballistic/launchers.dm index 1003b208ac68..a9e1cb184a74 100644 --- a/code/modules/projectiles/guns/ballistic/launchers.dm +++ b/code/modules/projectiles/guns/ballistic/launchers.dm @@ -1,9 +1,9 @@ //KEEP IN MIND: These are different from gun/grenadelauncher. These are designed to shoot premade rocket and grenade projectiles, not flashbangs or chemistry casings etc. //Put handheld rocket launchers here if someone ever decides to make something so hilarious ~Paprika -/obj/item/gun/ballistic/revolver/grenadelauncher//this is only used for underbarrel grenade launchers at the moment, but admins can still spawn it if they feel like being assholes - desc = "A break-operated grenade launcher." +/obj/item/gun/ballistic/revolver/grenadelauncher name = "grenade launcher" + desc = "A break-operated grenade launcher." icon_state = "dshotgun_sawn" inhand_icon_state = "gun" accepted_magazine_type = /obj/item/ammo_box/magazine/internal/grenadelauncher @@ -20,6 +20,27 @@ if(istype(A, /obj/item/ammo_box) || isammocasing(A)) chamber_round() +/obj/item/gun/ballistic/revolver/grenadelauncher/underbarrel + name = "underbarrel grenade launcher" + pin = null + +/obj/item/gun/ballistic/revolver/grenadelauncher/underbarrel/Initialize(mapload) + . = ..() + var/obj/item/gun/gun = loc + if (!istype(gun)) + return INITIALIZE_HINT_QDEL + pin = gun.pin + RegisterSignal(gun, COMSIG_GUN_PIN_INSERTED, PROC_REF(on_pin_inserted)) + RegisterSignal(gun, COMSIG_GUN_PIN_REMOVED, PROC_REF(on_pin_removed)) + +/obj/item/gun/ballistic/revolver/grenadelauncher/underbarrel/proc/on_pin_inserted(obj/item/gun/source, obj/item/firing_pin/new_pin, mob/living/user) + SIGNAL_HANDLER + pin = new_pin + +/obj/item/gun/ballistic/revolver/grenadelauncher/underbarrel/proc/on_pin_removed(obj/item/gun/source, obj/item/firing_pin/old_pin, mob/living/user) + SIGNAL_HANDLER + pin = null + /obj/item/gun/ballistic/revolver/grenadelauncher/cyborg desc = "A 6-shot grenade launcher." name = "multi grenade launcher" diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index 49965b7d734b..1c27ccc1ccf5 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -360,18 +360,72 @@ return FALSE return ..() +/** +-----------------Tesla Cannon-------------------------------- + +An advanced weapon that provides extremely high dps output at pinpoint accuracy due to its hitscan nature. + +Due to its normal w_class when folded it is suitable as a heavy reinforcement weapon, since the cell drains very quickly when firing. + +The power level is somewhat tempered by several drawbacks such as research requirements, anomalock, two handed firing requirement, and insultation providing damage reduction. + +it is often confused with the mech weapon of the same name, since it is a bit more obscure despite being very powerful. Formerly called the tesla revolver. +**/ /obj/item/gun/energy/tesla_cannon name = "tesla cannon" + icon = 'icons/obj/weapons/guns/wide_guns.dmi' icon_state = "tesla" - inhand_icon_state = "tesla" - desc = "A gun powered by a flux anomaly that shoots lightning bolts. Electrically insulating clothing may protect from some of the damage." + lefthand_file = 'icons/mob/inhands/weapons/64x_guns_left.dmi' + righthand_file = 'icons/mob/inhands/weapons/64x_guns_right.dmi' + inhand_icon_state = null //null so we build the correct inhand. + desc = "A high voltage flux projector prototype created using the latest advancements in the anomaly science.\n\nThe anomalous nature of the flux core allows the tesla arc to be guided from the electrode to the target without being diverted to stray conductors outside the target field." + SET_BASE_VISUAL_PIXEL(-8, 0) ammo_type = list(/obj/item/ammo_casing/energy/tesla_cannon) + inhand_x_dimension = 64 shaded_charge = TRUE + charge_sections = 2 + display_empty = FALSE weapon_weight = WEAPON_HEAVY + w_class = WEIGHT_CLASS_BULKY + ///if our stpck is extended and we are ready to fire. + var/ready_to_fire = FALSE /obj/item/gun/energy/tesla_cannon/Initialize(mapload) . = ..() - AddComponent(/datum/component/automatic_fire, 0.1 SECONDS) + AddComponent(/datum/component/automatic_fire, autofire_shot_delay = 100 MILLISECONDS, firing_sound_loop = /datum/looping_sound/tesla_cannon) + +/obj/item/gun/energy/tesla_cannon/can_trigger_gun(mob/living/user, akimbo_usage) + if(ready_to_fire) + return ..() + //If we have charge, but the stock is folded, do sparks. + if(can_shoot()) + balloon_alert(user, "electricity arcing to stock!") + + if(prob(75)) //fake sparks to cut on spark spam + playsound(user, 'sound/effects/sparks/sparks1.ogg', 50, TRUE) + else + do_sparks(3, FALSE, user) + return FALSE + +/obj/item/gun/energy/tesla_cannon/attack_self(mob/living/user) + . = ..() + if(ready_to_fire) + w_class = WEIGHT_CLASS_NORMAL + ready_to_fire = FALSE + icon_state = "tesla" + playsound(user, 'sound/items/weapons/gun/tesla/squeak_latch.ogg', 100) + + else + playsound(user, 'sound/items/weapons/gun/tesla/click_creak.ogg', 100) + if(!do_after(user, 1.5 SECONDS)) + return + w_class = WEIGHT_CLASS_BULKY + ready_to_fire = TRUE + icon_state = "tesla_unfolded" + playsound(user, 'sound/items/weapons/gun/tesla/squeak_latch.ogg', 100) + + update_appearance() + balloon_alert_to_viewers("[ready_to_fire ? "unfolded" : "folded"] stock") /obj/item/gun/energy/marksman_revolver name = "marksman revolver" diff --git a/code/modules/projectiles/pins.dm b/code/modules/projectiles/pins.dm index a965defcd3b6..a7c306778423 100644 --- a/code/modules/projectiles/pins.dm +++ b/code/modules/projectiles/pins.dm @@ -20,6 +20,11 @@ var/pin_removable = TRUE var/obj/item/gun/gun +/obj/item/firing_pin/Destroy() + if(gun) + gun_remove() + return ..() + /obj/item/firing_pin/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!isgun(interacting_with)) return NONE @@ -57,10 +62,12 @@ gun = new_gun forceMove(gun) gun.pin = src + SEND_SIGNAL(gun, COMSIG_GUN_PIN_INSERTED, src, user) return TRUE /obj/item/firing_pin/proc/gun_remove(mob/living/user) gun.pin = null + SEND_SIGNAL(gun, COMSIG_GUN_PIN_REMOVED, src, user) gun = null return @@ -380,9 +387,3 @@ playsound(src, SFX_SCREECH, 75, TRUE) return FALSE return TRUE - -/obj/item/firing_pin/Destroy() - if(gun) - gun.pin = null - gun = null - return ..() diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index 27ac40c62b95..fe4f9c47d39c 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -243,6 +243,124 @@ impact_light_intensity = 7 impact_light_range = 2.5 impact_light_color_override = COLOR_LIME + // Subtract this from SM damage on hit for lasers + var/integrity_heal + // Subtract this from SM energy on hit for lasers + var/energy_reduction + // Add this to SM psi coefficient on hit for lasers + var/psi_change + +/obj/projectile/beam/emitter/hitscan/bluelens + name = "electrodisruptive beam" + light_color = LIGHT_COLOR_BLUE + muzzle_type = /obj/effect/projectile/muzzle/pulse + tracer_type = /obj/effect/projectile/tracer/laser/emitter/bluelens + impact_type = /obj/effect/projectile/impact/pulse + hitscan_light_color_override = COLOR_BLUE_LIGHT + muzzle_flash_color_override = COLOR_BLUE_LIGHT + impact_light_color_override = COLOR_BLUE_LIGHT + damage_type = STAMINA + integrity_heal = 0.25 + energy_reduction = 60 + +/obj/projectile/beam/emitter/hitscan/bioregen + name = "bioregenerative beam" + light_color = LIGHT_COLOR_BRIGHT_YELLOW + muzzle_type = /obj/effect/projectile/muzzle/solar + tracer_type = /obj/effect/projectile/tracer/laser/emitter/bioregen + impact_type = /obj/effect/projectile/impact/solar + hitscan_light_color_override = COLOR_LIGHT_YELLOW + muzzle_flash_color_override = COLOR_LIGHT_YELLOW + impact_light_color_override = COLOR_LIGHT_YELLOW + damage_type = STAMINA + damage = 0 + var/healing_done = 5 + +/obj/projectile/beam/emitter/hitscan/bioregen/on_hit(atom/target, blocked, pierce_hit) + . = ..() + if(!iscarbon(target)) + return + var/mob/living/carbon/healed_guy = target + healed_guy.heal_bodypart_damage(brute = healing_done, burn = healing_done, updating_health = FALSE) + +/obj/projectile/beam/emitter/hitscan/incend + name = "conflagratory beam" + light_color = LIGHT_COLOR_ORANGE + muzzle_type = /obj/effect/projectile/muzzle/heavy_laser + tracer_type = /obj/effect/projectile/tracer/laser/emitter/redlens + impact_type = /obj/effect/projectile/impact/heavy_laser + hitscan_light_color_override = COLOR_ORANGE + muzzle_flash_color_override = COLOR_ORANGE + impact_light_color_override = COLOR_ORANGE + damage = 20 + integrity_heal = -0.15 + energy_reduction = -150 + psi_change = -0.1 + +/obj/projectile/beam/emitter/hitscan/incend/on_hit(atom/target, blocked, pierce_hit) + . = ..() + if(!isliving(target)) + return + var/mob/living/burnt_guy = target + burnt_guy.adjust_fire_stacks(5) + burnt_guy.ignite_mob() + +/obj/projectile/beam/emitter/hitscan/psy + name = "psychosiphoning beam" + light_color = LIGHT_COLOR_PINK + muzzle_type = /obj/effect/projectile/muzzle/laser/emitter/psy + tracer_type = /obj/effect/projectile/tracer/laser/emitter/psy + impact_type = /obj/effect/projectile/impact/laser/emitter/psy + hitscan_light_color_override = COLOR_BLUSH_PINK + muzzle_flash_color_override = COLOR_BLUSH_PINK + impact_light_color_override = COLOR_BLUSH_PINK + damage = 0 + energy_reduction = -25 + psi_change = 0.25 + +/obj/projectile/beam/emitter/hitscan/psy/on_hit(atom/target, blocked, pierce_hit) + . = ..() + if(!isliving(target)) + return + var/mob/living/siphoned = target + siphoned.mob_mood.adjust_sanity(-25) + to_chat(siphoned, span_warning("Suddenly, everything feels just a little bit worse!")) + +/obj/projectile/beam/emitter/hitscan/magnetic + name = "magnetogenerative beam" + light_color = COLOR_SILVER + muzzle_type = /obj/effect/projectile/muzzle/laser/emitter/magnetic + tracer_type = /obj/effect/projectile/tracer/laser/emitter/magnetic + impact_type = /obj/effect/projectile/impact/laser/emitter/magnetic + hitscan_light_color_override = COLOR_SILVER + muzzle_flash_color_override = COLOR_SILVER + impact_light_color_override = COLOR_SILVER + damage = 0 + +/obj/projectile/beam/emitter/hitscan/magnetic/on_hit(atom/target, blocked, pierce_hit) + . = ..() + var/turf/turf_to_magnet = get_turf(target) + goonchem_vortex(turf_to_magnet, FALSE, 4) + +/obj/projectile/beam/emitter/hitscan/blast + name = "hyperconcussive beam" + light_color = LIGHT_COLOR_ORANGE + muzzle_type = /obj/effect/projectile/muzzle/laser/emitter/magnetic + tracer_type = /obj/effect/projectile/tracer/laser/emitter/magnetic + impact_type = /obj/effect/projectile/impact/laser/emitter/magnetic + hitscan_light_color_override = COLOR_ORANGE + muzzle_flash_color_override = COLOR_ORANGE + impact_light_color_override = COLOR_ORANGE + damage = 0 + integrity_heal = -2 + energy_reduction = -500 + + +/obj/projectile/beam/emitter/hitscan/blast/on_hit(atom/target, blocked, pierce_hit) + . = ..() + var/turf/turf_to_explode = get_turf(target) + explosion(turf_to_explode, 0, 1, 2) + /obj/projectile/beam/lasertag name = "laser tag beam" diff --git a/code/modules/projectiles/projectile/energy/tesla.dm b/code/modules/projectiles/projectile/energy/tesla.dm index 928b3f31271e..6bbb514f2220 100644 --- a/code/modules/projectiles/projectile/energy/tesla.dm +++ b/code/modules/projectiles/projectile/energy/tesla.dm @@ -29,13 +29,14 @@ name = "tesla bolt" icon_state = null hitscan = TRUE - tracer_type = /obj/effect/projectile/tracer/lightning impact_effect_type = null damage = 5 var/shock_damage = 10 /obj/projectile/energy/tesla_cannon/on_hit(atom/target, blocked = 0, pierce_hit) . = ..() + firer.Beam(target, icon_state = "tesla", time = 1, icon_state_variants = 24) + if(isliving(target)) var/mob/living/victim = target victim.electrocute_act(shock_damage, src, siemens_coeff = 1, flags = SHOCK_NOSTUN|SHOCK_TESLA) diff --git a/code/modules/reagents/chemistry/holder/holder.dm b/code/modules/reagents/chemistry/holder/holder.dm index 526f4e43c4c8..179e328928b0 100644 --- a/code/modules/reagents/chemistry/holder/holder.dm +++ b/code/modules/reagents/chemistry/holder/holder.dm @@ -3,7 +3,7 @@ /// Holder for a bunch of [/datum/reagent] /datum/reagents /// The reagents being held - var/list/datum/reagent/reagent_list = new/list() + var/list/datum/reagent/reagent_list = list() /// Current volume of all the reagents var/total_volume = 0 /// Max volume of this holder @@ -80,7 +80,7 @@ * * added_purity - override to force a purity when added * * added_ph - override to force a pH when added * * override_base_ph - ingore the present pH of the reagent, and instead use the default (i.e. if buffers/reactions alter it) - * * list/reagent_added - If not null use this as an holder to store and retrive the reagent datum that was just added without having to locate it after this proc returns. Clear the list to erase old values + * * list/reagent_added - If not null will contain an map of [reagent datum->amount added] which holds the inverse chems added to mobs. Clear the list to erase old values * * creation_callback - Callback to invoke when the reagent is created */ /datum/reagents/proc/add_reagent( @@ -154,7 +154,7 @@ set_temperature(reagtemp) if(!isnull(reagent_added)) - reagent_added += iter_reagent + reagent_added[iter_reagent] = amount if(!no_react && !is_reacting) //To reduce the amount of calculations for a reaction the reaction list is only updated on a reagents addition. handle_reactions() return amount @@ -185,7 +185,7 @@ set_temperature(reagtemp) if(!isnull(reagent_added)) - reagent_added += new_reagent + reagent_added[new_reagent] = amount if(!no_react) handle_reactions() return amount @@ -325,12 +325,14 @@ * * * [source_reagent_typepath][/datum/reagent] - the typepath of the reagent you are trying to convert * * [target_reagent_typepath][/datum/reagent] - the final typepath the source_reagent_typepath will be converted into + * * conversion_volume - how much of the reagent volume to convert. -1 for all * * multiplier - the multiplier applied on the source_reagent_typepath volume before converting * * include_source_subtypes- if TRUE will convert all subtypes of source_reagent_typepath into target_reagent_typepath as well */ /datum/reagents/proc/convert_reagent( datum/reagent/source_reagent_typepath, datum/reagent/target_reagent_typepath, + conversion_volume = -1, multiplier = 1, include_source_subtypes = FALSE, keep_data = FALSE, @@ -358,6 +360,17 @@ else if(!istype(cached_reagent, source_reagent_typepath)) continue + if(conversion_volume != -1) + if(cached_reagent.volume > conversion_volume) + remove_reagent(cached_reagent.type, conversion_volume) + weighted_volume += conversion_volume + break + + weighted_volume += cached_reagent.volume + conversion_volume -= cached_reagent.volume + del_reagent(cached_reagent.type) + continue + //compute average of everything reagent_volume = cached_reagent.volume weighted_purity += cached_reagent.purity * reagent_volume @@ -409,6 +422,7 @@ * * methods - passed through to [/datum/reagents/proc/expose] and [/datum/reagent/proc/on_transfer] * * show_message - passed through to [/datum/reagents/proc/expose] * * ignore_stomach - when using methods INGEST will not use the stomach as the target + * * copy_only - transfers the reagents without removing it from this holder */ /datum/reagents/proc/trans_to( atom/target, @@ -421,7 +435,8 @@ remove_blacklisted = FALSE, methods = NONE, show_message = TRUE, - ignore_stomach = FALSE + ignore_stomach = FALSE, + copy_only = FALSE ) if(QDELETED(target) || !total_volume) return FALSE @@ -463,14 +478,9 @@ if(amount <= 0) return FALSE - //Set up new reagents to inherit the old ongoing reactions - if(!no_react) - transfer_reactions(target_holder) - var/trans_data = null var/list/r_to_send = methods ? list() : null // Validated list of reagents to be exposed var/list/transfer_log = list() - var/list/reagents_to_remove = list() var/part = isnull(target_id) ? (amount / total_volume) : 1 var/transfer_amount @@ -493,31 +503,25 @@ if(preserve_data) trans_data = copy_data(reagent) - if(reagent.intercept_reagents_transfer(target_holder, amount)) - update_total() - target_holder.update_total() + if(reagent.intercept_reagents_transfer(target_holder, transfer_amount, copy_only)) continue transfered_amount = target_holder.add_reagent(reagent.type, transfer_amount * multiplier, trans_data, chem_temp, reagent.purity, reagent.ph, no_react = TRUE, reagent_added = r_to_send, creation_callback = CALLBACK(src, PROC_REF(_on_transfer_creation), reagent, target_holder)) //we only handle reaction after every reagent has been transferred. if(!transfered_amount) continue - reagents_to_remove[reagent] = transfer_amount + total_transfered_amount += transfered_amount + if(!copy_only) + reagent.volume -= transfer_amount + transfer_log += "[reagent.type] ([transfered_amount]u, [reagent.purity] purity)" if(!isnull(target_id)) break + if(!copy_only) + update_total() //expose target to reagent changes if(methods) - target_holder.expose(isorgan(target_atom) ? target : target_atom, methods, part, show_message, r_to_send) - - //remove chemicals that were added above - for(var/datum/reagent/reagent as anything in reagents_to_remove) - transfer_amount = reagents_to_remove[reagent] - if(methods) - reagent.on_transfer(target_atom, methods, transfer_amount) - reagent.volume -= transfer_amount - update_total() - transfer_log += "[reagent.type] ([transfer_amount]u, [reagent.purity] purity)" + target_holder.expose(isorgan(target_atom) ? target : target_atom, methods, 1, show_message, r_to_send) //combat log if(transferred_by && target_atom) @@ -532,8 +536,10 @@ log_combat(transferred_by, log_target, "transferred reagents to", my_atom, "which had [english_list(transfer_log)]") if(!no_react) + transfer_reactions(target_holder) + if(!copy_only) + handle_reactions() target_holder.handle_reactions() - handle_reactions() return total_transfered_amount @@ -543,69 +549,6 @@ SEND_SIGNAL(reagent, COMSIG_REAGENT_ON_TRANSFER, target_holder, new_reagent) -/** - * Copies the reagents to the target object - * Arguments - * - * * [target][obj] - the target to transfer reagents to - * * multiplier - multiplies each reagent amount by this number well byond their available volume before transfering. used to create reagents from thin air if you ever need to - * * preserve_data - preserve user data of all reagents after transfering - * * no_react - if TRUE will not handle reactions - * * copy_methods - forwards reagent exposure method flags like INGEST & INHALE to reagent.on_transfer to trigger transfer effects. - */ -/datum/reagents/proc/copy_to( - atom/target, - amount = 1, - multiplier = 1, - preserve_data = TRUE, - no_react = FALSE, - copy_methods -) - if(QDELETED(target) || !total_volume) - return - - if(!IS_FINITE(amount)) - stack_trace("non finite amount passed to copy_to [amount] amount of reagents") - return FALSE - - var/datum/reagents/target_holder - if(istype(target, /datum/reagents)) - target_holder = target - else - if(!target.reagents) - return - target_holder = target.reagents - - // Prevents small amount problems, as well as zero and below zero amounts. - amount = round(min(amount, total_volume, target_holder.maximum_volume - target_holder.total_volume), CHEMICAL_QUANTISATION_LEVEL) - if(amount <= 0) - return - - var/list/cached_reagents = reagent_list - var/part = amount / total_volume - var/transfer_amount - var/transfered_amount = 0 - var/total_transfered_amount = 0 - var/trans_data = null - - for(var/datum/reagent/reagent as anything in cached_reagents) - transfer_amount = reagent.volume * part * multiplier - if(preserve_data) - trans_data = copy_data(reagent) - transfered_amount = target_holder.add_reagent(reagent.type, transfer_amount, trans_data, chem_temp, reagent.purity, reagent.ph, no_react = TRUE) - if(copy_methods && !no_react) - reagent.on_transfer(target, copy_methods, transfer_amount) - if(!transfered_amount) - continue - total_transfered_amount += transfered_amount - - if(!no_react) - // pass over previous ongoing reactions before handle_reactions is called - transfer_reactions(target_holder) - target_holder.handle_reactions() - - return total_transfered_amount - /** * Multiplies reagents inside this holder by a specific amount * Arguments @@ -804,23 +747,27 @@ * Arguments * - Atom/target: What mob/turf/object is being exposed to reagents? This is your reaction target. * - Methods: What reaction type is the reagent itself going to call on the reaction target? Types are TOUCH, INGEST, VAPOR, PATCH, INJECT and INHALE. - * - Volume_modifier: What is the reagent volume multiplied by when exposed? Note that this is called on the volume of EVERY reagent in the base body, so factor in your Maximum_Volume if necessary! + * - Volume_modifier: reagent volume modifier applied to the reagents(passed to r_to_expose or this holder) before exposing. Must be between 0->1 * - Show_message: Whether to display anything to mobs when they are exposed. - * - list/datum/reagent/r_to_expose: list of reagents to expose. if null will expose the reagents present in this holder instead + * - list/datum/reagent/r_to_expose: map of[/datum/reagent -> amount] when you to want to expose specific reagents with precise amounts */ /datum/reagents/proc/expose(atom/target, methods = TOUCH, volume_modifier = 1, show_message = 1, list/datum/reagent/r_to_expose = null) if(isnull(target)) - return null + return - var/list/target_reagents = isnull(r_to_expose) ? reagent_list : r_to_expose - if(!target_reagents.len) - return null + if(volume_modifier <= 0) + stack_trace("Volume modifier [volume_modifier] must be +ve") + return var/list/datum/reagent/reagents = list() - for(var/datum/reagent/reagent as anything in target_reagents) - reagents[reagent] = reagent.volume * volume_modifier + if(isnull(r_to_expose)) + for(var/datum/reagent/reagent as anything in reagent_list) + reagents[reagent] = reagent.volume * volume_modifier + else + for(var/datum/reagent/reagent as anything in r_to_expose) + reagents[reagent] = r_to_expose[reagent] * volume_modifier - return target.expose_reagents(reagents, src, methods, volume_modifier, show_message) + return target.expose_reagents(reagents, src, methods, show_message) /** * Applies heat to this holder diff --git a/code/modules/reagents/chemistry/machinery/smoke_machine.dm b/code/modules/reagents/chemistry/machinery/smoke_machine.dm index 53c8ca490566..54358350d5cf 100644 --- a/code/modules/reagents/chemistry/machinery/smoke_machine.dm +++ b/code/modules/reagents/chemistry/machinery/smoke_machine.dm @@ -35,7 +35,7 @@ src.location = get_turf(location) src.amount = amount if(carry) - carry.copy_to(chemholder, 20) + carry.trans_to(chemholder, 20, copy_only = TRUE) carry.remove_all(amount / efficiency) /obj/machinery/smoke_machine/Initialize(mapload) diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index 4e0544f6ba28..d26272934cc4 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -189,17 +189,19 @@ /datum/reagent/proc/on_burn_wound_processing(datum/wound/burn/flesh/burn_wound) return -/* -Used to run functions before a reagent is transferred. Returning TRUE will block the transfer attempt. -Primarily used in reagents/reaction_agents +/** + * Intercepts the reagent transfer/copy operation to do some work before it takes place. + * Used to perform some reaction work. Return TRUE To cancel the operation + * + * Arguments + * + * * datum/reagents/target - the target holder we are being transferred to + * * amount - the amount of reagent being transferred + * * copy_only - if TRUE we don't remove ourself from the holder because its a reagent copy & not transfer operation */ -/datum/reagent/proc/intercept_reagents_transfer(datum/reagents/target, amount) +/datum/reagent/proc/intercept_reagents_transfer(datum/reagents/target, amount, copy_only) return FALSE -///Called after a reagent is transferred -/datum/reagent/proc/on_transfer(atom/A, methods=TOUCH, trans_volume) - return - /// Called when this reagent is first added to a mob /datum/reagent/proc/on_mob_add(mob/living/affected_mob, amount) // Scale the overdose threshold of the chem by the difference between the default and creation purity. @@ -230,7 +232,13 @@ Primarily used in reagents/reaction_agents /datum/reagent/proc/on_mob_dead(mob/living/carbon/affected_mob, seconds_per_tick) SHOULD_CALL_PARENT(TRUE) -/// Called after add_reagents creates a new reagent. +/** + * Called after add_reagents creates a new reagent. + * + * Arguments + * * data - if not null, contains reagent data which will be applied to the newly created reagent (this will override any pre-set data). + */ + /datum/reagent/proc/on_new(data) if(data) src.data = data diff --git a/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm index 300840c5d697..3099051c1065 100644 --- a/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm @@ -154,14 +154,14 @@ if(need_mob_update) return UPDATE_MOB_HEALTH -/datum/reagent/medicine/c2/probital/on_transfer(atom/A, methods=INGEST, trans_volume) - if(!(methods & INGEST) || (!iscarbon(A) && !istype(A, /obj/item/organ/stomach)) ) +/datum/reagent/medicine/c2/probital/expose_mob(mob/living/exposed_mob, methods, reac_volume, show_message, touch_protection) + . = ..() + if(!(methods & INGEST) || !iscarbon(exposed_mob)) return - A.reagents.remove_reagent(/datum/reagent/medicine/c2/probital, trans_volume * 0.05) - A.reagents.add_reagent(/datum/reagent/medicine/metafactor, trans_volume * 0.25) - - ..() + var/datum/reagents/mob_reagents = exposed_mob.reagents + mob_reagents.remove_reagent(/datum/reagent/medicine/c2/probital, reac_volume * 0.05) + mob_reagents.add_reagent(/datum/reagent/medicine/metafactor, reac_volume * 0.25) /******BURN******/ /*Suffix: -uri*/ @@ -406,19 +406,21 @@ var/conversion_amount chemical_flags = REAGENT_CAN_BE_SYNTHESIZED -/datum/reagent/medicine/c2/syriniver/on_transfer(atom/A, methods=INJECT, trans_volume) - if(!(methods & INJECT) || !iscarbon(A)) +/datum/reagent/medicine/c2/syriniver/expose_mob(mob/living/carbon/exposed_mob, methods, trans_volume, show_message, touch_protection) + . = ..() + if(!(methods & INJECT) || !iscarbon(exposed_mob)) return - var/mob/living/carbon/C = A + if(trans_volume >= 0.4) //prevents cheesing with ultralow doses. - C.adjustToxLoss((-3 * min(2, trans_volume) * REM) * normalise_creation_purity(), required_biotype = affected_biotype) //This is to promote iv pole use for that chemotherapy feel. - var/obj/item/organ/liver/L = C.organs_slot[ORGAN_SLOT_LIVER] + exposed_mob.adjustToxLoss((-3 * min(2, trans_volume) * REM) * normalise_creation_purity(), required_biotype = affected_biotype) //This is to promote iv pole use for that chemotherapy feel. + var/obj/item/organ/liver/L = exposed_mob.organs_slot[ORGAN_SLOT_LIVER] if(!L || L.organ_flags & ORGAN_FAILING) return - conversion_amount = (trans_volume * (min(100 -C.get_organ_loss(ORGAN_SLOT_LIVER), 80) / 100)*normalise_creation_purity()) //the more damaged the liver the worse we metabolize. - C.reagents.remove_reagent(/datum/reagent/medicine/c2/syriniver, conversion_amount) - C.reagents.add_reagent(/datum/reagent/medicine/c2/musiver, conversion_amount) - ..() + conversion_amount = (trans_volume * (min(100 -exposed_mob.get_organ_loss(ORGAN_SLOT_LIVER), 80) / 100)*normalise_creation_purity()) //the more damaged the liver the worse we metabolize. + + var/datum/reagents/mob_reagents = exposed_mob.reagents + mob_reagents.remove_reagent(/datum/reagent/medicine/c2/syriniver, conversion_amount) + mob_reagents.add_reagent(/datum/reagent/medicine/c2/musiver, conversion_amount) /datum/reagent/medicine/c2/syriniver/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() diff --git a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm index e66a542a4d67..b7cda4cd113d 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm @@ -501,14 +501,16 @@ return ..() -/datum/reagent/consumable/ethanol/goldschlager/on_transfer(atom/atom, methods = TOUCH, trans_volume) +/datum/reagent/consumable/ethanol/goldschlager/expose_mob(mob/living/exposed_mob, methods, reac_volume) + . = ..() if(!(methods & INGEST)) - return ..() + return - var/convert_amount = trans_volume * min(GOLDSCHLAGER_GOLD_RATIO, 1) - atom.reagents.remove_reagent(/datum/reagent/consumable/ethanol/goldschlager, convert_amount) - atom.reagents.add_reagent(/datum/reagent/gold, convert_amount) - return ..() + var/convert_amount = reac_volume * min(GOLDSCHLAGER_GOLD_RATIO, 1) + var/datum/reagents/mob_reagents = exposed_mob.reagents + + mob_reagents.remove_reagent(/datum/reagent/consumable/ethanol/goldschlager, convert_amount) + mob_reagents.add_reagent(/datum/reagent/gold, convert_amount) /datum/reagent/consumable/ethanol/patron name = "Patron" diff --git a/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm index bb6697a39094..0be0ca2b75f4 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm @@ -228,7 +228,7 @@ /datum/reagent/milk/used_on_fish(obj/item/fish/fish) if(HAS_TRAIT(fish, TRAIT_FISH_MADE_OF_BONE)) - fish.adjust_health(fish.health + initial(fish.health) * max(fish.get_hunger() * 0.5, 0.12)) + fish.repair_damage(fish.max_integrity * max(fish.get_hunger() * 0.5, 0.12)) fish.sate_hunger() return TRUE @@ -998,12 +998,12 @@ . = ..() if(IS_REVOLUTIONARY(drinker)) to_chat(drinker, span_warning("Antioxidants are weakening your radical spirit!")) - + /datum/reagent/consumable/grenadine/on_mob_life(mob/living/carbon/drinker, seconds_per_tick, times_fired) . = ..() if(IS_REVOLUTIONARY(drinker)) drinker.set_dizzy_if_lower(10 SECONDS * REM * seconds_per_tick) - if(drinker.getStaminaLoss() < 80) + if(drinker.getStaminaLoss() < 80) drinker.adjustStaminaLoss(12, required_biotype = affected_biotype) //The pomegranate stops free radicals! Har har. /datum/reagent/consumable/parsnipjuice diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm index 4f373c2cf9d7..039e6a2898b3 100644 --- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm @@ -816,11 +816,11 @@ If you have at over 25u in your body you restore more than 20 stamina per cycle, if(!kronkaine_fiend.stat) kronkaine_fiend.stop_sound_channel(CHANNEL_HEARTBEAT) -/datum/reagent/drug/kronkaine/on_transfer(atom/kronkaine_receptacle, methods, trans_volume) +/datum/reagent/drug/kronkaine/expose_mob(mob/living/carbon/druggo, methods, trans_volume, show_message, touch_protection) . = ..() - if(!iscarbon(kronkaine_receptacle)) + if(!iscarbon(druggo)) return - var/mob/living/carbon/druggo = kronkaine_receptacle + //The drug is more effective if smoked or injected, restoring more stamina per unit. var/stamina_heal_per_unit if(methods & (INJECT|INHALE)) @@ -833,9 +833,7 @@ If you have at over 25u in your body you restore more than 20 stamina per cycle, to_chat(druggo, span_nicegreen(pick("You feel the cowardice melt away...", "You feel unbothered by the judgements of others.", "My life feels lovely!", "You lower your snout... and suddenly feel more charitable!"))) else stamina_heal_per_unit = 6 - if(druggo.adjustStaminaLoss(-stamina_heal_per_unit * trans_volume)) - return UPDATE_MOB_HEALTH - + druggo.adjustStaminaLoss(-stamina_heal_per_unit * trans_volume) /datum/reagent/drug/kronkaine/on_mob_life(mob/living/carbon/kronkaine_fiend, seconds_per_tick, times_fired) . = ..() diff --git a/code/modules/reagents/chemistry/reagents/impure_reagents.dm b/code/modules/reagents/chemistry/reagents/impure_reagents.dm index 09da3851e22a..e21c0eada33f 100644 --- a/code/modules/reagents/chemistry/reagents/impure_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/impure_reagents.dm @@ -97,18 +97,13 @@ chemical_flags = REAGENT_DEAD_PROCESS | REAGENT_IGNORE_STASIS | REAGENT_UNAFFECTED_BY_METABOLISM metabolization_rate = 1 * REM -/datum/reagent/inverse/cryostylane/on_transfer(atom/transfered_thing, methods, trans_volume) +/datum/reagent/inverse/cryostylane/expose_mob(mob/living/carbon/human/human_thing, methods, reac_volume, show_message, touch_protection) . = ..() - if(methods & INGEST) + if((methods & INGEST) || !ishuman(human_thing)) return - if(!ishuman(transfered_thing)) - return - - var/mob/living/carbon/human/human_thing = transfered_thing - if(HAS_TRAIT(human_thing, TRAIT_RESISTCOLD)) - holder.remove_reagent(type, volume) + holder.del_reagent(type) return human_thing.apply_status_effect(/datum/status_effect/frozenstasis/irresistable) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 17ad295a1e85..6ce06761170f 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -2525,46 +2525,81 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/glitter - name = "Generic Glitter" - description = "if you can see this description, contact a coder." + name = "Glitter" + description = "The herpes of arts and crafts." + data = list("colors"=list(COLOR_WHITE = 100)) color = COLOR_WHITE //pure white taste_description = "plastic" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED - var/glitter_type = /obj/effect/decal/cleanable/glitter + +/datum/reagent/glitter/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) + . = ..() + if(SPT_PROB(25, seconds_per_tick)) + affected_mob.emote("cough") + expose_turf(get_turf(affected_mob), 0) /datum/reagent/glitter/expose_turf(turf/exposed_turf, reac_volume) . = ..() if(!istype(exposed_turf)) return - exposed_turf.spawn_unique_cleanable(glitter_type) + exposed_turf.spawn_glitter(data["colors"]) -/datum/reagent/glitter/pink - name = "Pink Glitter" - description = "pink sparkles that get everywhere" - color = "#ff8080" //A light pink color - glitter_type = /obj/effect/decal/cleanable/glitter/pink - chemical_flags = REAGENT_CAN_BE_SYNTHESIZED +/datum/reagent/glitter/on_new(data) + . = ..() -/datum/reagent/glitter/white - name = "White Glitter" - description = "white sparkles that get everywhere" - glitter_type = /obj/effect/decal/cleanable/glitter/white - chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + if(src.data["colors"]) + color = pick(src.data["colors"]) + else + color = COLOR_WHITE -/datum/reagent/glitter/blue - name = "Blue Glitter" - description = "blue sparkles that get everywhere" - color = "#4040FF" //A blueish color - glitter_type = /obj/effect/decal/cleanable/glitter/blue - chemical_flags = REAGENT_CAN_BE_SYNTHESIZED +/datum/reagent/glitter/on_merge(list/mix_data, amount) + . = ..() + + var/prop_current = (volume-amount)/(volume) + + if(mix_data) + data["colors"] = blend_weighted_lists(mix_data["colors"], data["colors"], prop_current) + + if(data["colors"]) + color = pick(data["colors"]) + else + color = COLOR_WHITE + +/datum/reagent/glitter/random + name = "Unrandomised Randomised Glitter" + description = "You shouldn't be seeing this, please make an issue report describing how you found it." + + var/list/possible_colors = list( + list(COLOR_WHITE = 100), + list("#ff8080" = 100), + list("#4040ff" = 100), + list("#ff5555" = 34, "#55ff55" = 33, "#5555ff" = 33), + ) + +/datum/reagent/glitter/random/on_new(data) + . = ..() + + var/list/color_list = pick(possible_colors) -/datum/reagent/glitter/confetti + var/datum/reagents/our_holder = src.holder + var/our_volume = src.volume + var/list/our_data = list("colors" = color_list) + + our_holder.remove_reagent(/datum/reagent/glitter/random, our_volume) + our_holder.add_reagent(/datum/reagent/glitter, our_volume, data = our_data) + +/datum/reagent/confetti name = "Confetti" description = "Tiny plastic flakes that are impossible to sweep up." color = "#7dd87b" - glitter_type = /obj/effect/decal/cleanable/confetti chemical_flags = REAGENT_CAN_BE_SYNTHESIZED +/datum/reagent/confetti/expose_turf(turf/exposed_turf, reac_volume) + . = ..() + if(!istype(exposed_turf)) + return + exposed_turf.spawn_unique_cleanable(/obj/effect/decal/cleanable/confetti) + /datum/reagent/pax name = "Pax" description = "A colorless liquid that suppresses violence in its subjects." @@ -2697,15 +2732,15 @@ . = ..() yuck_cycle = 0 // reset vomiting -/datum/reagent/yuck/on_transfer(atom/A, methods=TOUCH, trans_volume) - if((methods & INGEST) || !iscarbon(A)) - return ..() - - A.reagents.remove_reagent(type, trans_volume) - A.reagents.add_reagent(/datum/reagent/fuel, trans_volume * 0.75) - A.reagents.add_reagent(/datum/reagent/water, trans_volume * 0.25) +/datum/reagent/yuck/expose_mob(mob/living/carbon/exposed_mob, methods, expose_volume, show_message, touch_protection) + . = ..() + if(!(methods & INGEST) || !iscarbon(exposed_mob)) + return - return ..() + var/datum/reagents/mob_reagents = exposed_mob.reagents + mob_reagents.remove_reagent(type, expose_volume) + mob_reagents.add_reagent(/datum/reagent/fuel, expose_volume * 0.75) + mob_reagents.add_reagent(/datum/reagent/water, expose_volume * 0.25) //monkey powder heehoo /datum/reagent/monkey_powder diff --git a/code/modules/reagents/chemistry/reagents/reaction_agents_reagents.dm b/code/modules/reagents/chemistry/reagents/reaction_agents_reagents.dm index eac83c5efc9e..2a7ce91cc8df 100644 --- a/code/modules/reagents/chemistry/reagents/reaction_agents_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/reaction_agents_reagents.dm @@ -2,14 +2,14 @@ name = "Reaction Agent" description = "Hello! I am a bugged reagent. Please report me for my crimes. Thank you!!" -/datum/reagent/reaction_agent/intercept_reagents_transfer(datum/reagents/target, amount) +/datum/reagent/reaction_agent/intercept_reagents_transfer(datum/reagents/target, amount, copy_only) if(!target) return FALSE if(target.flags & NO_REACT) return FALSE if(target.has_reagent(/datum/reagent/stabilizing_agent)) return FALSE - if(LAZYLEN(target.reagent_list) == 0) + if(!target.total_volume) return FALSE if(LAZYLEN(target.reagent_list) == 1) if(target.has_reagent(type)) //Allow dispensing into self @@ -27,7 +27,7 @@ glass_price = DRINK_PRICE_HIGH //Consumes self on addition and shifts ph -/datum/reagent/reaction_agent/acidic_buffer/intercept_reagents_transfer(datum/reagents/target, amount) +/datum/reagent/reaction_agent/acidic_buffer/intercept_reagents_transfer(datum/reagents/target, amount, copy_only) . = ..() if(!.) return @@ -39,11 +39,14 @@ else message = "The beaker froths as the pH changes!" target.adjust_all_reagents_ph((-(amount / target.total_volume) * BUFFER_IONIZING_STRENGTH)) + target.update_total() //give feedback & remove from holder because it's not transferred target.my_atom.audible_message(span_warning(message)) playsound(target.my_atom, 'sound/effects/chemistry/bufferadd.ogg', 50, TRUE) - holder.remove_reagent(type, amount) + if(!copy_only) + volume -= amount + holder.update_total() /datum/reagent/reaction_agent/basic_buffer name = "Strong Basic Buffer" @@ -55,7 +58,7 @@ fallback_icon_state = "base_buffer_fallback" glass_price = DRINK_PRICE_HIGH -/datum/reagent/reaction_agent/basic_buffer/intercept_reagents_transfer(datum/reagents/target, amount) +/datum/reagent/reaction_agent/basic_buffer/intercept_reagents_transfer(datum/reagents/target, amount, copy_only) . = ..() if(!.) return @@ -67,11 +70,14 @@ else message = "The beaker froths as the pH changes!" target.adjust_all_reagents_ph(((amount / target.total_volume) * BUFFER_IONIZING_STRENGTH)) + target.update_total() //give feedback & remove from holder because it's not transferred target.my_atom.audible_message(span_warning(message)) playsound(target.my_atom, 'sound/effects/chemistry/bufferadd.ogg', 50, TRUE) - holder.remove_reagent(type, amount) + if(!copy_only) + volume -= amount + holder.update_total() //purity testor/reaction agent prefactors @@ -91,7 +97,7 @@ ph = 3 color = "#ffffff" -/datum/reagent/reaction_agent/purity_tester/intercept_reagents_transfer(datum/reagents/target, amount) +/datum/reagent/reaction_agent/purity_tester/intercept_reagents_transfer(datum/reagents/target, amount, copy_only) . = ..() if(!.) return @@ -105,7 +111,9 @@ playsound(target.my_atom, 'sound/effects/chemistry/bufferadd.ogg', 50, TRUE) else target.my_atom.audible_message(span_warning("The added reagent doesn't seem to do much.")) - holder.remove_reagent(type, amount) + if(!copy_only) + volume -= amount + holder.update_total() ///How much the reaction speed is sped up by - for 5u added to 100u, an additional step of 1 will be done up to a max of 2x #define SPEED_REAGENT_STRENGTH 20 @@ -116,7 +124,7 @@ ph = 10 color = "#e61f82" -/datum/reagent/reaction_agent/speed_agent/intercept_reagents_transfer(datum/reagents/target, amount) +/datum/reagent/reaction_agent/speed_agent/intercept_reagents_transfer(datum/reagents/target, amount, copy_only) . = ..() if(!.) return FALSE @@ -131,6 +139,8 @@ power *= creation_purity power = clamp(power, 0, 2) reaction.react_timestep(power, creation_purity) - holder.remove_reagent(type, amount) + if(!copy_only) + volume -= amount + holder.update_total() #undef SPEED_REAGENT_STRENGTH diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index a2a050d5ca64..6c9ae29d4c3e 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -74,7 +74,7 @@ mytray.mutation_roll(user) mytray.adjust_toxic(3) //It is still toxic, mind you, but not to the same degree. -/datum/reagent/mutagen/used_on_fish(obj/item/fish/fish) +/datum/reagent/toxin/mutagen/used_on_fish(obj/item/fish/fish) ADD_TRAIT(fish, TRAIT_FISH_MUTAGENIC, type) addtimer(TRAIT_CALLBACK_REMOVE(fish, TRAIT_FISH_MUTAGENIC, type), fish.feeding_frequency * 0.8, TIMER_UNIQUE|TIMER_OVERRIDE) return TRUE @@ -269,13 +269,15 @@ . = ..() affected_mob.cure_fakedeath(type) -/datum/reagent/toxin/zombiepowder/on_transfer(atom/target_atom, methods, trans_volume) +/datum/reagent/toxin/zombiepowder/expose_mob(mob/living/exposed_mob, methods, reac_volume, show_message, touch_protection) . = ..() - var/datum/reagent/zombiepowder = target_atom.reagents.has_reagent(/datum/reagent/toxin/zombiepowder) - if(!zombiepowder || !(methods & (INGEST|INHALE))) + if(!(methods & (INGEST|INHALE))) return - LAZYINITLIST(zombiepowder.data) - zombiepowder.data["method"] |= (INGEST|INHALE) + + var/datum/reagent/zombiepowder = exposed_mob.reagents.has_reagent(/datum/reagent/toxin/zombiepowder) + if(zombiepowder) + LAZYINITLIST(zombiepowder.data) + zombiepowder.data["method"] |= (INGEST|INHALE) /datum/reagent/toxin/zombiepowder/on_mob_life(mob/living/affected_mob, seconds_per_tick, times_fired) . = ..() @@ -450,25 +452,19 @@ taste_description = "spores" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED|REAGENT_NO_RANDOM_RECIPE -/datum/reagent/toxin/spore/on_transfer(atom/A, methods, trans_volume) +/datum/reagent/toxin/spore/expose_mob(mob/living/spore_lung_victim, methods, reac_volume, show_message, touch_protection) . = ..() - if(!isliving(A)) - return if(!(methods & INHALE)) return - - var/mob/living/spore_lung_victim = A - if(!(spore_lung_victim.mob_biotypes & (MOB_HUMANOID | MOB_BEAST))) return - if(prob(min(trans_volume * 10, 80))) + if(prob(min(reac_volume * 10, 80))) to_chat(spore_lung_victim, span_danger("[pick("You have a coughing fit!", "You hack and cough!", "Your lungs burn!")]")) spore_lung_victim.Stun(1 SECONDS) spore_lung_victim.emote("cough") - /datum/reagent/toxin/spore/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() affected_mob.damageoverlaytemp = 60 @@ -1273,7 +1269,7 @@ /datum/reagent/toxin/bonehurtingjuice/used_on_fish(obj/item/fish/fish) if(HAS_TRAIT(fish, TRAIT_FISH_MADE_OF_BONE)) - fish.adjust_health(fish.health - 30) + fish.damage_fish(30) return TRUE /datum/reagent/toxin/bungotoxin diff --git a/code/modules/reagents/chemistry/recipes/others.dm b/code/modules/reagents/chemistry/recipes/others.dm index ab648158bb72..7ab199a2d015 100644 --- a/code/modules/reagents/chemistry/recipes/others.dm +++ b/code/modules/reagents/chemistry/recipes/others.dm @@ -741,12 +741,17 @@ reaction_tags = REACTION_TAG_EASY | REACTION_TAG_UNIQUE /datum/chemical_reaction/plastic_polymers + results = list(/datum/reagent/plastic_polymers = 10) required_reagents = list(/datum/reagent/fuel/oil = 5, /datum/reagent/toxin/acid = 2, /datum/reagent/ash = 3) + reaction_tags = REACTION_TAG_EASY | REACTION_TAG_CHEMICAL + +/datum/chemical_reaction/plastic_polymer_hardening + required_reagents = list(/datum/reagent/plastic_polymers = 10) required_temp = 374 //lazily consistent with soap & other crafted objects generically created with heat. reaction_flags = REACTION_INSTANT reaction_tags = REACTION_TAG_EASY | REACTION_TAG_CHEMICAL -/datum/chemical_reaction/plastic_polymers/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume) +/datum/chemical_reaction/plastic_polymer_hardening/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume) new /obj/item/stack/sheet/plastic(get_turf(holder.my_atom), round(created_volume)) /datum/chemical_reaction/pax @@ -1046,3 +1051,41 @@ thermic_constant = 80 H_ion_release = 2 reaction_tags = REACTION_TAG_EASY + +/datum/chemical_reaction/glitter + results = list(/datum/reagent/glitter = 1) + required_reagents = list(/datum/reagent/plastic_polymers = 1, /datum/reagent/aluminium = 1) + required_catalysts = list(/datum/reagent/stabilizing_agent = 1) + reaction_tags = REACTION_TAG_EASY | REACTION_TAG_UNIQUE + +/datum/chemical_reaction/glitter_pigmentation + results = list(/datum/reagent/glitter = 1) + required_reagents = list(/datum/reagent/glitter = 1, /datum/reagent/acetone = 1) + mix_message = "the glitter rapidly changes colour!" + reaction_flags = REACTION_INSTANT + reaction_tags = REACTION_TAG_EASY | REACTION_TAG_UNIQUE + +/datum/chemical_reaction/glitter_pigmentation/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume) + . = ..() + + var/excluded_volume = 0 + var/accumulated_color + + for(var/datum/reagent/reagent in holder.reagent_list) + if(is_type_in_list(reagent, required_reagents)) + excluded_volume += reagent.volume + + for(var/datum/reagent/reagent in holder.reagent_list) + if(!is_type_in_list(reagent, required_reagents)) + + if(accumulated_color) + accumulated_color = BlendRGB(reagent.color, accumulated_color, (reagent.volume/(holder.total_volume-excluded_volume))) + else + accumulated_color = reagent.color + + var/datum/reagent/glitter/glitter = locate(/datum/reagent/glitter) in holder.reagent_list + + glitter.data["colors"] = list("[accumulated_color]" = 100) + glitter.color = accumulated_color + + diff --git a/code/modules/reagents/reagent_containers/cups/glassbottle.dm b/code/modules/reagents/reagent_containers/cups/glassbottle.dm index 2438be6bd9c3..391a1bfc241c 100644 --- a/code/modules/reagents/reagent_containers/cups/glassbottle.dm +++ b/code/modules/reagents/reagent_containers/cups/glassbottle.dm @@ -918,7 +918,7 @@ if(!bottle) return ..() icon_state = bottle.icon_state - bottle.reagents.copy_to(src, 100) + bottle.reagents.trans_to(src, 100, copy_only = TRUE) if(istype(bottle, /obj/item/reagent_containers/cup/glass/bottle/juice)) desc += " You're not sure if making this out of a carton was the brightest idea." isGlass = FALSE diff --git a/code/modules/reagents/reagent_containers/cups/mauna_mug.dm b/code/modules/reagents/reagent_containers/cups/mauna_mug.dm new file mode 100644 index 000000000000..b443229358b5 --- /dev/null +++ b/code/modules/reagents/reagent_containers/cups/mauna_mug.dm @@ -0,0 +1,117 @@ +/obj/item/reagent_containers/cup/maunamug + name = "mauna mug" + desc = "A drink served in a classy mug. Now with built-in heating!" + icon = 'icons/obj/devices/mauna_mug.dmi' + icon_state = "maunamug" + base_icon_state = "maunamug" + spillable = TRUE + reagent_flags = OPENCONTAINER + fill_icon_state = "maunafilling" + fill_icon_thresholds = list(25) + var/obj/item/stock_parts/power_store/cell + var/open = FALSE + var/on = FALSE + +/obj/item/reagent_containers/cup/maunamug/Initialize(mapload, vol) + . = ..() + cell = new /obj/item/stock_parts/power_store/cell(src) + +/obj/item/reagent_containers/cup/maunamug/get_cell() + return cell + +/obj/item/reagent_containers/cup/maunamug/examine(mob/user) + . = ..() + . += span_notice("The status display reads: Current temperature: [reagents.chem_temp]K Current Charge:[cell ? "[cell.charge / cell.maxcharge * 100]%" : "No cell found"].") + if(open) + . += span_notice("The battery case is open.") + if(cell && cell.charge > 0) + . += span_notice("Ctrl+Click to toggle the power.") + +/obj/item/reagent_containers/cup/maunamug/process(seconds_per_tick) + ..() + if(on && (!cell || cell.charge <= 0)) //Check if we ran out of power + change_power_status(FALSE) + return FALSE + cell.use(0.005 * STANDARD_CELL_RATE * seconds_per_tick) //Basic cell goes for like 200 seconds, bluespace for 8000 + if(!reagents.total_volume) + return FALSE + var/max_temp = min(500 + (500 * (0.2 * cell.rating)), 1000) // 373 to 1000 + reagents.adjust_thermal_energy(0.4 * cell.maxcharge * reagents.total_volume * seconds_per_tick, max_temp = max_temp) // 4 kelvin every tick on a basic cell. 160k on bluespace + reagents.handle_reactions() + update_appearance() + if(reagents.chem_temp >= max_temp) + change_power_status(FALSE) + audible_message(span_notice("The Mauna Mug lets out a happy beep and turns off!")) + playsound(src, 'sound/machines/chime.ogg', 50) + +/obj/item/reagent_containers/cup/maunamug/Destroy() + if(cell) + QDEL_NULL(cell) + STOP_PROCESSING(SSobj, src) + . = ..() + +/obj/item/reagent_containers/cup/maunamug/item_ctrl_click(mob/user) + if(on) + change_power_status(FALSE) + else + if(!cell || cell.charge <= 0) + return FALSE //No power, so don't turn on + change_power_status(TRUE) + return CLICK_ACTION_SUCCESS + +/obj/item/reagent_containers/cup/maunamug/proc/change_power_status(status) + on = status + if(on) + START_PROCESSING(SSobj, src) + else + STOP_PROCESSING(SSobj, src) + update_appearance() + +/obj/item/reagent_containers/cup/maunamug/screwdriver_act(mob/living/user, obj/item/I) + . = ..() + open = !open + to_chat(user, span_notice("You screw the battery case on [src] [open ? "open" : "closed"] .")) + update_appearance() + +/obj/item/reagent_containers/cup/maunamug/attackby(obj/item/I, mob/user, list/modifiers, list/attack_modifiers) + add_fingerprint(user) + if(!istype(I, /obj/item/stock_parts/power_store/cell)) + return ..() + if(!open) + to_chat(user, span_warning("The battery case must be open to insert a power cell!")) + return FALSE + if(cell) + to_chat(user, span_warning("There is already a power cell inside!")) + return FALSE + else if(!user.transferItemToLoc(I, src)) + return + cell = I + user.visible_message(span_notice("[user] inserts a power cell into [src]."), span_notice("You insert the power cell into [src].")) + update_appearance() + +/obj/item/reagent_containers/cup/maunamug/attack_hand(mob/living/user, list/modifiers) + if(cell && open) + user.put_in_hands(cell) + cell = null + to_chat(user, span_notice("You remove the power cell from [src].")) + on = FALSE + update_appearance() + return TRUE + return ..() + +/obj/item/reagent_containers/cup/maunamug/update_icon_state() + if(open) + icon_state = "[base_icon_state][cell ? null : "_no"]_bat" + return ..() + icon_state = "[base_icon_state][on ? "_on" : null]" + return ..() + +/obj/item/reagent_containers/cup/maunamug/update_overlays() + . = ..() + if(!reagents.total_volume || reagents.chem_temp < 400) + return + + var/intensity = (reagents.chem_temp - 400) * 1 / 600 //Get the opacity of the incandescent overlay. Ranging from 400 to 1000 + var/mutable_appearance/mug_glow = mutable_appearance(icon, "maunamug_incand") + mug_glow.alpha = 255 * intensity + . += mug_glow diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index e786badff1d7..bd953c1ec6ec 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -55,7 +55,7 @@ trans = reagents.trans_to(affected_mob, amount_per_transfer_from_this, transferred_by = user, methods = INJECT) else reagents.expose(affected_mob, INJECT, fraction) - trans = reagents.copy_to(affected_mob, amount_per_transfer_from_this, copy_methods = INJECT) + trans = reagents.trans_to(affected_mob, amount_per_transfer_from_this, methods = INJECT, copy_only = TRUE) to_chat(user, span_notice("[trans] unit\s injected. [reagents.total_volume] unit\s remaining in [src].")) log_combat(user, affected_mob, "injected", src, "([contained])") return TRUE diff --git a/code/modules/reagents/reagent_containers/misc.dm b/code/modules/reagents/reagent_containers/rag.dm similarity index 64% rename from code/modules/reagents/reagent_containers/misc.dm rename to code/modules/reagents/reagent_containers/rag.dm index 37185319b4d1..bd73f20fe1fd 100644 --- a/code/modules/reagents/reagent_containers/misc.dm +++ b/code/modules/reagents/reagent_containers/rag.dm @@ -1,121 +1,3 @@ -/obj/item/reagent_containers/cup/maunamug - name = "mauna mug" - desc = "A drink served in a classy mug. Now with built-in heating!" - icon = 'icons/obj/devices/mauna_mug.dmi' - icon_state = "maunamug" - base_icon_state = "maunamug" - spillable = TRUE - reagent_flags = OPENCONTAINER - fill_icon_state = "maunafilling" - fill_icon_thresholds = list(25) - var/obj/item/stock_parts/power_store/cell - var/open = FALSE - var/on = FALSE - -/obj/item/reagent_containers/cup/maunamug/Initialize(mapload, vol) - . = ..() - cell = new /obj/item/stock_parts/power_store/cell(src) - -/obj/item/reagent_containers/cup/maunamug/get_cell() - return cell - -/obj/item/reagent_containers/cup/maunamug/examine(mob/user) - . = ..() - . += span_notice("The status display reads: Current temperature: [reagents.chem_temp]K Current Charge:[cell ? "[cell.charge / cell.maxcharge * 100]%" : "No cell found"].") - if(open) - . += span_notice("The battery case is open.") - if(cell && cell.charge > 0) - . += span_notice("Ctrl+Click to toggle the power.") - -/obj/item/reagent_containers/cup/maunamug/process(seconds_per_tick) - ..() - if(on && (!cell || cell.charge <= 0)) //Check if we ran out of power - change_power_status(FALSE) - return FALSE - cell.use(0.005 * STANDARD_CELL_RATE * seconds_per_tick) //Basic cell goes for like 200 seconds, bluespace for 8000 - if(!reagents.total_volume) - return FALSE - var/max_temp = min(500 + (500 * (0.2 * cell.rating)), 1000) // 373 to 1000 - reagents.adjust_thermal_energy(0.4 * cell.maxcharge * reagents.total_volume * seconds_per_tick, max_temp = max_temp) // 4 kelvin every tick on a basic cell. 160k on bluespace - reagents.handle_reactions() - update_appearance() - if(reagents.chem_temp >= max_temp) - change_power_status(FALSE) - audible_message(span_notice("The Mauna Mug lets out a happy beep and turns off!")) - playsound(src, 'sound/machines/chime.ogg', 50) - -/obj/item/reagent_containers/cup/maunamug/Destroy() - if(cell) - QDEL_NULL(cell) - STOP_PROCESSING(SSobj, src) - . = ..() - -/obj/item/reagent_containers/cup/maunamug/item_ctrl_click(mob/user) - if(on) - change_power_status(FALSE) - else - if(!cell || cell.charge <= 0) - return FALSE //No power, so don't turn on - change_power_status(TRUE) - return CLICK_ACTION_SUCCESS - -/obj/item/reagent_containers/cup/maunamug/proc/change_power_status(status) - on = status - if(on) - START_PROCESSING(SSobj, src) - else - STOP_PROCESSING(SSobj, src) - update_appearance() - -/obj/item/reagent_containers/cup/maunamug/screwdriver_act(mob/living/user, obj/item/I) - . = ..() - open = !open - to_chat(user, span_notice("You screw the battery case on [src] [open ? "open" : "closed"] .")) - update_appearance() - -/obj/item/reagent_containers/cup/maunamug/attackby(obj/item/I, mob/user, list/modifiers, list/attack_modifiers) - add_fingerprint(user) - if(!istype(I, /obj/item/stock_parts/power_store/cell)) - return ..() - if(!open) - to_chat(user, span_warning("The battery case must be open to insert a power cell!")) - return FALSE - if(cell) - to_chat(user, span_warning("There is already a power cell inside!")) - return FALSE - else if(!user.transferItemToLoc(I, src)) - return - cell = I - user.visible_message(span_notice("[user] inserts a power cell into [src]."), span_notice("You insert the power cell into [src].")) - update_appearance() - -/obj/item/reagent_containers/cup/maunamug/attack_hand(mob/living/user, list/modifiers) - if(cell && open) - user.put_in_hands(cell) - cell = null - to_chat(user, span_notice("You remove the power cell from [src].")) - on = FALSE - update_appearance() - return TRUE - return ..() - -/obj/item/reagent_containers/cup/maunamug/update_icon_state() - if(open) - icon_state = "[base_icon_state][cell ? null : "_no"]_bat" - return ..() - icon_state = "[base_icon_state][on ? "_on" : null]" - return ..() - -/obj/item/reagent_containers/cup/maunamug/update_overlays() - . = ..() - if(!reagents.total_volume || reagents.chem_temp < 400) - return - - var/intensity = (reagents.chem_temp - 400) * 1 / 600 //Get the opacity of the incandescent overlay. Ranging from 400 to 1000 - var/mutable_appearance/mug_glow = mutable_appearance(icon, "maunamug_incand") - mug_glow.alpha = 255 * intensity - . += mug_glow - /obj/item/rag name = "damp rag" desc = "For cleaning up messes, you suppose." diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index e3f4e36a7a4f..a04044a50eb1 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -393,7 +393,7 @@ righthand_file = 'icons/mob/inhands/items_righthand.dmi' w_class = WEIGHT_CLASS_TINY reagent_flags = NONE - list_reagents = list(/datum/reagent/glitter/confetti = 15) + list_reagents = list(/datum/reagent/confetti = 15) volume = 15 amount_per_transfer_from_this = 5 can_toggle_range = FALSE diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index 2fc011246f79..2454416062a9 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -67,7 +67,7 @@ to_chat(user, span_warning("You cannot directly fill [target]!")) return ITEM_INTERACT_BLOCKING - if(target.reagents.total_volume >= target.reagents.maximum_volume) + if(target.reagents.holder_full()) to_chat(user, span_notice("[target] is full.")) return ITEM_INTERACT_BLOCKING @@ -82,7 +82,7 @@ return ITEM_INTERACT_BLOCKING if(!reagents.total_volume) return ITEM_INTERACT_BLOCKING - if(living_target.reagents.total_volume >= living_target.reagents.maximum_volume) + if(living_target.reagents.holder_full()) return ITEM_INTERACT_BLOCKING living_target.visible_message( span_danger("[user] injects [living_target] with the syringe!"), @@ -109,7 +109,7 @@ SEND_SIGNAL(target, COMSIG_LIVING_TRY_SYRINGE_WITHDRAW, user) - if(reagents.total_volume >= reagents.maximum_volume) + if(reagents.holder_full()) to_chat(user, span_notice("[src] is full.")) return ITEM_INTERACT_BLOCKING @@ -123,7 +123,7 @@ ) if(!do_after(user, CHEM_INTERACT_DELAY(3 SECONDS, user), target, extra_checks = CALLBACK(src, PROC_REF(try_syringe), living_target, user))) return ITEM_INTERACT_BLOCKING - if(reagents.total_volume >= reagents.maximum_volume) + if(reagents.holder_full()) return ITEM_INTERACT_BLOCKING if(living_target.transfer_blood_to(src, drawn_amount)) user.visible_message(span_notice("[user] takes a blood sample from [living_target].")) diff --git a/code/modules/religion/burdened/psyker.dm b/code/modules/religion/burdened/psyker.dm index 6a608059c495..2ffde313f6df 100644 --- a/code/modules/religion/burdened/psyker.dm +++ b/code/modules/religion/burdened/psyker.dm @@ -100,15 +100,16 @@ if(!burden || burden.burden_level < 9) to_chat(human_user, span_warning("You aren't burdened enough.")) return FALSE - for(var/obj/item/nullrod/null_rod in get_turf(religious_tool)) - transformation_target = null_rod - return ..() + for(var/obj/item/possible_rod in get_turf(religious_tool)) + if(HAS_TRAIT(possible_rod, TRAIT_NULLROD_ITEM)) + transformation_target = possible_rod + return ..() to_chat(human_user, span_warning("You need to place a null rod on [religious_tool] to do this!")) return FALSE /datum/religion_rites/nullrod_transformation/invoke_effect(mob/living/user, atom/movable/religious_tool) ..() - var/obj/item/nullrod/null_rod = transformation_target + var/obj/item/null_rod = transformation_target transformation_target = null if(QDELETED(null_rod) || null_rod.loc != get_turf(religious_tool)) to_chat(user, span_warning("Your target left the altar!")) diff --git a/code/modules/research/designs/comp_board_designs.dm b/code/modules/research/designs/comp_board_designs.dm index 50ed6e43f616..078e3aabcc0a 100644 --- a/code/modules/research/designs/comp_board_designs.dm +++ b/code/modules/research/designs/comp_board_designs.dm @@ -411,3 +411,13 @@ desc = "Allows for the construction of circuit boards used to build a console that enables the targetting of custom flight locations" id = "shuttle_docker" build_path = /obj/item/circuitboard/computer/shuttle/docker + +/datum/design/board/quantum_console + name = "Quantum Console Board" + desc = "Allows for the construction of circuit boards used to build a Quantum Console." + id = "quantum_console" + build_path = /obj/item/circuitboard/computer/quantum_console + category = list( + RND_CATEGORY_COMPUTER + RND_SUBCATEGORY_COMPUTER_CARGO + ) + departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING diff --git a/code/modules/research/designs/machine_designs.dm b/code/modules/research/designs/machine_designs.dm index fb7744459f46..086b4ca947b5 100644 --- a/code/modules/research/designs/machine_designs.dm +++ b/code/modules/research/designs/machine_designs.dm @@ -1395,3 +1395,23 @@ RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_ATMOS ) departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_ENGINEERING + +/datum/design/board/netpod + name = "Netpod Board" + desc = "The circuit board for a netpod." + id = "netpod" + build_path = /obj/item/circuitboard/machine/netpod + category = list( + RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_CARGO + ) + departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING + +/datum/design/board/byteforge + name = "Byteforge Board" + desc = "Allows for the construction of circuit boards used to build a Byteforge." + id = "byteforge" + build_path = /obj/item/circuitboard/machine/byteforge + category = list( + RND_CATEGORY_COMPUTER + RND_SUBCATEGORY_COMPUTER_CARGO + ) + departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm index 65421509c483..274f5f8b11d9 100644 --- a/code/modules/research/designs/mechfabricator_designs.dm +++ b/code/modules/research/designs/mechfabricator_designs.dm @@ -907,104 +907,6 @@ RND_CATEGORY_MECHFAB_SAVANNAH_IVANOV + RND_SUBCATEGORY_MECHFAB_CHASSIS ) -//Justice (emaged only) -/datum/design/justice_chassis - name = "Exosuit Chassis (\"Justice\")" - id = "justice_chassis" - build_type = MECHFAB - build_path = /obj/item/mecha_parts/chassis/justice - materials = list(/datum/material/iron=SHEET_MATERIAL_AMOUNT*20) - construction_time = 10 SECONDS - category = list( - RND_CATEGORY_MECHFAB_JUSTICE + RND_SUBCATEGORY_MECHFAB_CHASSIS - ) - -/datum/design/justice_torso - name = "Exosuit Torso (\"Justice\")" - id = "justice_torso" - build_type = MECHFAB - build_path = /obj/item/mecha_parts/part/justice_torso - materials = list( - /datum/material/iron = SHEET_MATERIAL_AMOUNT * 50, - /datum/material/silver = SHEET_MATERIAL_AMOUNT * 5, - ) - construction_time = 30 SECONDS - category = list( - RND_CATEGORY_MECHFAB_JUSTICE + RND_SUBCATEGORY_MECHFAB_CHASSIS - ) - -/datum/design/justice_left_arm - name = "Exosuit Left Arm (\"Justice\")" - id = "justice_left_arm" - build_type = MECHFAB - build_path = /obj/item/mecha_parts/part/justice_left_arm - materials = list( - /datum/material/iron = SHEET_MATERIAL_AMOUNT * 5, - /datum/material/silver = SHEET_MATERIAL_AMOUNT * 2, - ) - construction_time = 10 SECONDS - category = list( - RND_CATEGORY_MECHFAB_JUSTICE + RND_SUBCATEGORY_MECHFAB_CHASSIS - ) - -/datum/design/justice_right_arm - name = "Exosuit Right Arm (\"Justice\")" - id = "justice_right_arm" - build_type = MECHFAB - build_path = /obj/item/mecha_parts/part/justice_right_arm - materials = list( - /datum/material/iron=SHEET_MATERIAL_AMOUNT*5, - /datum/material/silver=SHEET_MATERIAL_AMOUNT*2, - ) - construction_time = 10 SECONDS - category = list( - RND_CATEGORY_MECHFAB_JUSTICE + RND_SUBCATEGORY_MECHFAB_CHASSIS - ) - -/datum/design/justice_left_leg - name = "Exosuit Left Leg (\"Justice\")" - id = "justice_left_leg" - build_type = MECHFAB - build_path = /obj/item/mecha_parts/part/justice_left_leg - materials = list( - /datum/material/iron=SHEET_MATERIAL_AMOUNT*5, - /datum/material/titanium=SHEET_MATERIAL_AMOUNT*2, - ) - construction_time = 10 SECONDS - category = list( - RND_CATEGORY_MECHFAB_JUSTICE + RND_SUBCATEGORY_MECHFAB_CHASSIS - ) - -/datum/design/justice_right_leg - name = "Exosuit Right Leg (\"Justice\")" - id = "justice_right_leg" - build_type = MECHFAB - build_path = /obj/item/mecha_parts/part/justice_right_leg - materials = list( - /datum/material/iron=SHEET_MATERIAL_AMOUNT*5, - /datum/material/titanium=SHEET_MATERIAL_AMOUNT*2, - ) - construction_time = 10 SECONDS - category = list( - RND_CATEGORY_MECHFAB_JUSTICE + RND_SUBCATEGORY_MECHFAB_CHASSIS - ) - -/datum/design/justice_armor - name = "Exosuit Armor (\"Justice\")" - id = "justice_armor" - build_type = MECHFAB - build_path = /obj/item/mecha_parts/part/justice_armor - materials = list( - /datum/material/silver=SHEET_MATERIAL_AMOUNT*10, - /datum/material/titanium=SHEET_MATERIAL_AMOUNT*10, - /datum/material/plastic=SHEET_MATERIAL_AMOUNT*5, - /datum/material/diamond=SHEET_MATERIAL_AMOUNT*1, - ) - construction_time = 20 SECONDS - category = list( - RND_CATEGORY_MECHFAB_JUSTICE + RND_SUBCATEGORY_MECHFAB_CHASSIS - ) - //Clarke /datum/design/clarke_chassis name = "Exosuit Chassis (\"Clarke\")" diff --git a/code/modules/research/designs/power_designs.dm b/code/modules/research/designs/power_designs.dm index eed1eb9a8b68..8b4d70749872 100644 --- a/code/modules/research/designs/power_designs.dm +++ b/code/modules/research/designs/power_designs.dm @@ -212,3 +212,68 @@ RND_CATEGORY_STOCK_PARTS + RND_SUBCATEGORY_STOCK_PARTS_TURBINE ) departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING + +/datum/design/diode_disk_stamina + name = "Electrodisruptive Diode Disk" + desc = "A stamina damaging and supermatter crystal healing Diode Disk." + id = "diode_disk_stamina" + build_type = PROTOLATHE | AWAY_LATHE + materials = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT * 0.5, /datum/material/glass =SMALL_MATERIAL_AMOUNT, /datum/material/gold =SMALL_MATERIAL_AMOUNT) + construction_time = 0.5 SECONDS + build_path = /obj/item/emitter_disk/stamina + category = list( + RND_CATEGORY_EQUIPMENT + ) + departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_ENGINEERING + +/datum/design/diode_disk_healing + name = "Bioregenerative Diode Disk" + desc = "A living creature healing Diode Disk." + id = "diode_disk_healing" + build_type = PROTOLATHE | AWAY_LATHE + materials = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT * 0.5, /datum/material/glass =SMALL_MATERIAL_AMOUNT, /datum/material/silver =SMALL_MATERIAL_AMOUNT) //silver is medical metal. Why? who knows. + construction_time = 0.5 SECONDS + build_path = /obj/item/emitter_disk/healing + category = list( + RND_CATEGORY_EQUIPMENT + ) + departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_ENGINEERING + +/datum/design/diode_disk_incendiary + name = "Conflagratory Diode Disk" + desc = "A high energy incendiary Diode Disk." + id = "diode_disk_incendiary" + build_type = PROTOLATHE | AWAY_LATHE + materials = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT * 0.5, /datum/material/glass =SMALL_MATERIAL_AMOUNT, /datum/material/diamond =SMALL_MATERIAL_AMOUNT * 0.5, /datum/material/plasma =SMALL_MATERIAL_AMOUNT * 2) + construction_time = 0.5 SECONDS + build_path = /obj/item/emitter_disk/incendiary + category = list( + RND_CATEGORY_EQUIPMENT + ) + departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_ENGINEERING + +/datum/design/diode_disk_sanity + name = "Psychosiphoning Diode Disk" + desc = "An supermatter comforting creature depressing Diode Disk." + id = "diode_disk_sanity" + build_type = PROTOLATHE | AWAY_LATHE + materials = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT * 0.5, /datum/material/glass =SMALL_MATERIAL_AMOUNT, /datum/material/uranium =SMALL_MATERIAL_AMOUNT * 0.5) //Uranium, the metal of love and warmth (from decay heat). + construction_time = 0.5 SECONDS + build_path = /obj/item/emitter_disk/sanity + category = list( + RND_CATEGORY_EQUIPMENT + ) + departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_ENGINEERING + +/datum/design/diode_disk_magnetic + name = "Magnetogenerative Diode Disk" + desc = "A mol absorbing item attracting Diode Disk." + id = "diode_disk_magnetic" + build_type = PROTOLATHE | AWAY_LATHE + materials = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT * 0.5, /datum/material/glass =SMALL_MATERIAL_AMOUNT, /datum/material/titanium =SMALL_MATERIAL_AMOUNT * 0.5) + construction_time = 0.5 SECONDS + build_path = /obj/item/emitter_disk/magnetic + category = list( + RND_CATEGORY_EQUIPMENT + ) + departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_ENGINEERING diff --git a/code/modules/research/designs/weapon_designs.dm b/code/modules/research/designs/weapon_designs.dm index 127e3cf5a317..d0a54cb7d4a6 100644 --- a/code/modules/research/designs/weapon_designs.dm +++ b/code/modules/research/designs/weapon_designs.dm @@ -78,7 +78,7 @@ /datum/material/iron = HALF_SHEET_MATERIAL_AMOUNT * 3, /datum/material/bluespace = HALF_SHEET_MATERIAL_AMOUNT * 1.5, ) - build_path = /obj/item/ammo_box/magazine/m38/true + build_path = /obj/item/ammo_box/c38/true category = list( RND_CATEGORY_WEAPONS + RND_SUBCATEGORY_WEAPONS_AMMO ) @@ -182,7 +182,7 @@ departmental_flags = DEPARTMENT_BITFLAG_SECURITY /datum/design/c38_true_mag - name = "Magazine (.38 Truee Strike) (Lethal)" + name = "Magazine (.38 True Strike) (Lethal)" desc = "Designed to tactically reload a NT BR-38 Battle Rifle. Bullets bounce towards new targets with surprising accuracy." id = "c38_true_strike_mag" build_type = PROTOLATHE | AWAY_LATHE @@ -198,7 +198,7 @@ departmental_flags = DEPARTMENT_BITFLAG_SECURITY /datum/design/c38_flare_mag - name = "Magazine (.38 Flae) (VERY Lethal)" + name = "Magazine (.38 Flare) (VERY Lethal)" desc = "Designed to tactically reload a NT BR-38 Battle Rifle. Flare casings launch a concentrated particle beam towards a target, lighting them up for everyone to see." id = "c38_flare_mag" build_type = PROTOLATHE | AWAY_LATHE diff --git a/code/modules/research/part_replacer.dm b/code/modules/research/part_replacer.dm index 538310264449..cb7c1819e58d 100644 --- a/code/modules/research/part_replacer.dm +++ b/code/modules/research/part_replacer.dm @@ -24,9 +24,10 @@ return attacked_machinery.exchange_parts(user, src) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_FAILURE -///Plays the sound for RPED exhanging or installing parts. -/obj/item/storage/part_replacer/proc/play_rped_sound() +///Plays the sound & flick animation for RPED exhanging or installing parts. +/obj/item/storage/part_replacer/proc/play_rped_effect() playsound(src, 'sound/items/tools/rped.ogg', 40, TRUE) + flick("[icon_state]_active", src) /** * Gets parts sorted in order of their tier @@ -53,6 +54,7 @@ /obj/item/storage/part_replacer/bluespace name = "bluespace rapid part exchange device" desc = "A version of the RPED that allows for replacement of parts and scanning from a distance, along with higher capacity for parts." + icon = 'icons/obj/storage/storage_wide.dmi' icon_state = "BS_RPED" inhand_icon_state = "BS_RPED" w_class = WEIGHT_CLASS_NORMAL @@ -72,11 +74,13 @@ /obj/item/storage/part_replacer/bluespace/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) return interact_with_atom(interacting_with, user, modifiers) -/obj/item/storage/part_replacer/bluespace/play_rped_sound() +/obj/item/storage/part_replacer/bluespace/play_rped_effect() if(prob(1)) playsound(src, 'sound/items/pshoom/pshoom_2.ogg', 40, TRUE) + flick("[icon_state]_old", src) return playsound(src, 'sound/items/pshoom/pshoom.ogg', 40, TRUE) + flick("[icon_state]_active", src) /** * Signal handler for when a part has been inserted into the BRPED. diff --git a/code/modules/research/techweb/nodes/atmos_nodes.dm b/code/modules/research/techweb/nodes/atmos_nodes.dm index e063629af97a..3da5b00ec400 100644 --- a/code/modules/research/techweb/nodes/atmos_nodes.dm +++ b/code/modules/research/techweb/nodes/atmos_nodes.dm @@ -63,6 +63,7 @@ "pacman", "mech_generator", "plasmacutter", + "diode_disk_incendiary", ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) discount_experiments = list(/datum/experiment/ordnance/gaseous/plasma = TECHWEB_TIER_2_POINTS) diff --git a/code/modules/research/techweb/nodes/engi_nodes.dm b/code/modules/research/techweb/nodes/engi_nodes.dm index 9a4d6cf6439f..19c925eb8c2c 100644 --- a/code/modules/research/techweb/nodes/engi_nodes.dm +++ b/code/modules/research/techweb/nodes/engi_nodes.dm @@ -179,6 +179,7 @@ "welding_goggles", "tray_goggles", "geigercounter", + "diode_disk_stamina" ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) announce_channels = list(RADIO_CHANNEL_ENGINEERING) @@ -227,6 +228,7 @@ "modular_shield_charger", "modular_shield_well", "modular_shield_console", + "diode_disk_magnetic", ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) diff --git a/code/modules/research/techweb/nodes/mech_nodes.dm b/code/modules/research/techweb/nodes/mech_nodes.dm index 4a7e589ac7ec..d4238e1b6f05 100644 --- a/code/modules/research/techweb/nodes/mech_nodes.dm +++ b/code/modules/research/techweb/nodes/mech_nodes.dm @@ -203,22 +203,6 @@ research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_4_POINTS) announce_channels = list(RADIO_CHANNEL_SCIENCE) -/datum/techweb_node/justice - id = "mecha_justice" - display_name = "EXOSUIT: Justice" - description = "Justice exosuit designs" - design_ids = list( - "justice_armor", - "justice_chassis", - "justice_left_arm", - "justice_left_leg", - "justice_right_arm", - "justice_right_leg", - "justice_torso", - ) - hidden = TRUE - illegal_mech_node = TRUE - /datum/techweb_node/mech_energy_guns id = TECHWEB_NODE_MECH_ENERGY_GUNS display_name = "Exosuit Energy Guns" diff --git a/code/modules/research/techweb/nodes/medbay_nodes.dm b/code/modules/research/techweb/nodes/medbay_nodes.dm index bd74b5b653c9..0e16f9cacbd5 100644 --- a/code/modules/research/techweb/nodes/medbay_nodes.dm +++ b/code/modules/research/techweb/nodes/medbay_nodes.dm @@ -81,6 +81,8 @@ "defibmount", "medicalbed_emergency", "piercesyringe", + "diode_disk_healing", + "diode_disk_sanity", ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) required_experiments = list(/datum/experiment/scanning/reagent/haloperidol) diff --git a/code/modules/research/xenobiology/vatgrowing/biopsy_tool.dm b/code/modules/research/xenobiology/vatgrowing/biopsy_tool.dm index d04a7f852da3..cfc3e56bc5b1 100644 --- a/code/modules/research/xenobiology/vatgrowing/biopsy_tool.dm +++ b/code/modules/research/xenobiology/vatgrowing/biopsy_tool.dm @@ -5,15 +5,26 @@ icon = 'icons/obj/science/vatgrowing.dmi' icon_state = "biopsy" worn_icon_state = "biopsy" + base_icon_state = "biopsy" + /// Whether or not we can swab objects + var/can_swap_objects = FALSE ///Adds the swabbing component to the biopsy tool /obj/item/biopsy_tool/Initialize(mapload) . = ..() - AddComponent(/datum/component/swabbing, FALSE, FALSE, TRUE, CALLBACK(src, PROC_REF(update_swab_icon)), max_items = 1) - + AddComponent(/datum/component/swabbing, can_swap_objects, FALSE, TRUE, CALLBACK(src, PROC_REF(update_swab_icon)), max_items = 1) /obj/item/biopsy_tool/proc/update_swab_icon(list/swabbed_items) if(LAZYLEN(swabbed_items)) - icon_state = "biopsy_full" + icon_state = base_icon_state + "_full" else - icon_state = "biopsy" + icon_state = base_icon_state + +/obj/item/biopsy_tool/organ + name = "tissue biopsy tool" + desc = "Used to retrieve cell lines from organ tissue and organisms. Don't worry, it won't sting." + icon_state = "biopsy_organ" + base_icon_state = "biopsy_organ" + + can_swap_objects = TRUE + diff --git a/code/modules/research/xenobiology/vatgrowing/microscope.dm b/code/modules/research/xenobiology/vatgrowing/microscope.dm index c3c7369981e1..d96f577db669 100644 --- a/code/modules/research/xenobiology/vatgrowing/microscope.dm +++ b/code/modules/research/xenobiology/vatgrowing/microscope.dm @@ -120,10 +120,13 @@ balloon_alert(user, "dish removed") return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN +/obj/structure/microscope/unanchored + anchored = FALSE + /datum/crafting_recipe/microscope name = "Microscope" result = /obj/structure/microscope - time = 30 + time = 3 SECONDS tool_behaviors = list(TOOL_SCREWDRIVER) reqs = list( /obj/item/stack/sheet/glass = 1, diff --git a/code/modules/research/xenobiology/vatgrowing/samples/_micro_organism.dm b/code/modules/research/xenobiology/vatgrowing/samples/_micro_organism.dm index 72cb3031841e..4a564b58b130 100644 --- a/code/modules/research/xenobiology/vatgrowing/samples/_micro_organism.dm +++ b/code/modules/research/xenobiology/vatgrowing/samples/_micro_organism.dm @@ -112,6 +112,7 @@ if(vat_creature.mutate()) return mutate_color(thing) + SEND_SIGNAL(vat.biological_sample, COMSIG_SAMPLE_DEPOSITED, thing) ///Overriden to show more info like needs, supplementary and supressive reagents and also growth. /datum/micro_organism/cell_line/get_details(show_details) @@ -137,23 +138,30 @@ var/hue_shift = 1 //This affix is added to the name of the atom, to help players understand and converse about the different rarity levels. var/rarity_affix = "glitched" + // for adding some unique effects for subtypes, should you wish to do so + var/strength_factor = 1 switch(rand(1, 100)) if(1 to 35) //35% chance : painted hue_shift = 0.15 rarity_affix = "painted" + strength_factor = 1.2 if(36 to 70) //35% chance : mutant hue_shift = 0.85 //this value is equivalent in distance as the painted tier, just in the other direction. rarity_affix = "mutant" + strength_factor = 1.4 if(71 to 83) //13% chance : rare hue_shift = 0.3 rarity_affix = "rare" + strength_factor = 1.6 if(84 to 95) //12% chance : shiny hue_shift = 0.7 rarity_affix = "shiny" + strength_factor = 2 if(96 to 100) //5% chance : mutant king hue_shift = 0.5 //Best in show, most extreme color change. rarity_affix = "mutant king" //The name is up to debate, since cyto is all about freaky creatures I thought it was good choice over something like "cosmic" or "regal". + strength_factor = 2.5 var/list/mutant_shift_matrix = list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, hue_shift,0,0,0) //matrix for our colour shifting. @@ -163,3 +171,5 @@ if(isliving(beautiful_mutant)) //update the real name var if it's actually a living mob var/mob/living/living_mutie = beautiful_mutant living_mutie.real_name = living_mutie.name + + return strength_factor diff --git a/code/modules/research/xenobiology/vatgrowing/samples/cell_lines/organs.dm b/code/modules/research/xenobiology/vatgrowing/samples/cell_lines/organs.dm new file mode 100644 index 000000000000..2685885644c7 --- /dev/null +++ b/code/modules/research/xenobiology/vatgrowing/samples/cell_lines/organs.dm @@ -0,0 +1,197 @@ +/// Cell lines for organ cytology, letting you duplicate or grow new mutant strains! +/datum/micro_organism/cell_line/organs + desc = "dense tissue" + growth_rate = 1 + consumption_rate = REAGENTS_METABOLISM + +/datum/micro_organism/cell_line/organs/mutate_color(atom/beautiful_mutant) + . = ..() + + if(isorgan(beautiful_mutant)) + var/obj/item/organ/organ = beautiful_mutant + // Rare affix organs get more health + organ.maxHealth *= . + +/datum/micro_organism/cell_line/organs/heart + desc = "dense heart tissue" + + required_reagents = list(/datum/reagent/consumable/nutriment/organ_tissue) + + supplementary_reagents = list( + /datum/reagent/love = 6, + /datum/reagent/blood = 3, + /datum/reagent/consumable/nutriment = 1, + ) + + suppressive_reagents = list( + /datum/reagent/toxin/mutagen = -2, + ) + + resulting_atom = /obj/item/organ/heart + +/datum/micro_organism/cell_line/organs/heart/evolved + desc = "dense evolved heart tissue" + + required_reagents = list(/datum/reagent/consumable/nutriment/organ_tissue) + + supplementary_reagents = list( + /datum/reagent/love = 6, + /datum/reagent/toxin/mutagen = 4, + /datum/reagent/blood = 3, + /datum/reagent/consumable/nutriment = 1, + ) + + resulting_atom = /obj/item/organ/heart/evolved + +/datum/micro_organism/cell_line/organs/heart/sacred + desc = "dense sacred heart tissue" + growth_rate = parent_type::growth_rate * 0.5 + + required_reagents = list(/datum/reagent/consumable/nutriment/organ_tissue, /datum/reagent/water/holywater) + + supplementary_reagents = list( + /datum/reagent/love = 6, + /datum/reagent/blood = 3, + /datum/reagent/consumable/nutriment = 1, + ) + + resulting_atom = /obj/item/organ/heart/evolved/sacred + +/datum/micro_organism/cell_line/organs/heart/corrupt + desc = "dense corrupted heart tissue" + + required_reagents = list(/datum/reagent/consumable/nutriment/organ_tissue) + + supplementary_reagents = list( + /datum/reagent/hellwater = 6, + /datum/reagent/blood = 3, + /datum/reagent/consumable/nutriment = 1, + ) + + suppressive_reagents = list( + /datum/reagent/water/holywater = -3, + ) + + resulting_atom = /obj/item/organ/heart/corrupt + +/datum/micro_organism/cell_line/organs/lungs + desc = "dense lung tissue" + + required_reagents = list(/datum/reagent/consumable/nutriment/organ_tissue) + + supplementary_reagents = list( + /datum/reagent/medicine/salbutamol = 6, + /datum/reagent/blood = 3, + /datum/reagent/consumable/nutriment = 1, + ) + + suppressive_reagents = list( + /datum/reagent/toxin/mutagen = -2, + ) + + resulting_atom = /obj/item/organ/lungs + +/datum/micro_organism/cell_line/organs/lungs/evolved + desc = "dense evolved lung tissue" + + required_reagents = list(/datum/reagent/consumable/nutriment/organ_tissue) + + supplementary_reagents = list( + /datum/reagent/medicine/salbutamol = 6, + /datum/reagent/toxin/mutagen = 4, + /datum/reagent/blood = 3, + /datum/reagent/consumable/nutriment = 1, + ) + + resulting_atom = /obj/item/organ/lungs/evolved + +/datum/micro_organism/cell_line/organs/liver + desc = "dense liver tissue" + + required_reagents = list(/datum/reagent/consumable/nutriment/organ_tissue) + + supplementary_reagents = list( + /datum/reagent/iron = 6, + /datum/reagent/blood = 3, + /datum/reagent/consumable/nutriment = 1, + ) + + suppressive_reagents = list( + /datum/reagent/toxin/mutagen = -2, + ) + + resulting_atom = /obj/item/organ/liver + +/datum/micro_organism/cell_line/organs/liver/evolved + desc = "dense evolved liver tissue" + + required_reagents = list(/datum/reagent/consumable/nutriment/organ_tissue) + + supplementary_reagents = list( + /datum/reagent/iron = 6, + /datum/reagent/toxin/mutagen = 4, + /datum/reagent/blood = 3, + /datum/reagent/consumable/nutriment = 1, + ) + + resulting_atom = /obj/item/organ/liver/evolved + +/datum/micro_organism/cell_line/organs/liver/bloody + desc = "spongy liver tissue" + + required_reagents = list(/datum/reagent/consumable/nutriment/organ_tissue, /datum/reagent/blood) + + supplementary_reagents = list( + /datum/reagent/iron = 6, + /datum/reagent/blood = 3, + /datum/reagent/consumable/nutriment = 1, + ) + + resulting_atom = /obj/item/organ/liver/bloody + +/datum/micro_organism/cell_line/organs/liver/distillery + desc = "alcoholic liver tissue" + required_reagents = list(/datum/reagent/consumable/nutriment/organ_tissue, /datum/reagent/consumable/ethanol) + + supplementary_reagents = list( + /datum/reagent/iron = 6, + /datum/reagent/blood = 3, + /datum/reagent/consumable/nutriment = 1, + ) + + suppressive_reagents = list( + /datum/reagent/water = -6, //are you trying to poison me or something? + ) + + resulting_atom = /obj/item/organ/liver/distillery + +/datum/micro_organism/cell_line/organs/stomach + desc = "dense stomach tissue" + + required_reagents = list(/datum/reagent/consumable/nutriment/organ_tissue/stomach_lining) + + supplementary_reagents = list( + /datum/reagent/consumable/nutriment/organ_tissue = 3, + /datum/reagent/blood = 3, + /datum/reagent/consumable/nutriment = 1, + ) + + suppressive_reagents = list( + /datum/reagent/toxin/mutagen = -2, + ) + + resulting_atom = /obj/item/organ/stomach + +/datum/micro_organism/cell_line/organs/stomach/evolved + desc = "dense evolved stomach tissue" + + required_reagents = list(/datum/reagent/consumable/nutriment/organ_tissue/stomach_lining) + + supplementary_reagents = list( + /datum/reagent/toxin/mutagen = 4, + /datum/reagent/consumable/nutriment/organ_tissue = 3, + /datum/reagent/consumable/nutriment = 3, + /datum/reagent/blood = 3, + ) + + resulting_atom = /obj/item/organ/stomach/evolved diff --git a/code/modules/research/xenobiology/vatgrowing/vatgrower.dm b/code/modules/research/xenobiology/vatgrowing/vatgrower.dm index 621f72f61f0c..4f65a3d9240f 100644 --- a/code/modules/research/xenobiology/vatgrowing/vatgrower.dm +++ b/code/modules/research/xenobiology/vatgrowing/vatgrower.dm @@ -15,13 +15,16 @@ var/datum/biological_sample/biological_sample ///If the vat will restart the sample upon completion var/resampler_active = FALSE + /// Whether or not to add the plumbing component and related stuff + var/use_plumbing = TRUE /obj/machinery/vatgrower/Initialize(mapload, bolt, layer) . = ..() create_reagents(reagent_volume, reagent_flags) - AddComponent(/datum/component/simple_rotation) - AddComponent(/datum/component/plumbing/simple_demand) + if(use_plumbing) + AddComponent(/datum/component/simple_rotation) + AddComponent(/datum/component/plumbing/simple_demand) var/static/list/hovering_item_typechecks = list( /obj/item/petri_dish = list( @@ -136,9 +139,9 @@ var/static/image/off_overlay var/static/image/emissive_overlay if(isnull(on_overlay)) - on_overlay = iconstate2appearance(icon, "growing_vat_on") - off_overlay = iconstate2appearance(icon, "growing_vat_off") - emissive_overlay = emissive_appearance(icon, "growing_vat_glow", src, alpha = src.alpha) + on_overlay = iconstate2appearance(icon, "[icon_state]_on") + off_overlay = iconstate2appearance(icon, "[icon_state]_off") + emissive_overlay = emissive_appearance(icon, "[icon_state]_glow", src, alpha = src.alpha) . += emissive_overlay if(is_operational) if(resampler_active) @@ -148,11 +151,11 @@ if(!reagents.total_volume) return var/reagentcolor = mix_color_from_reagents(reagents.reagent_list) - var/mutable_appearance/base_overlay = mutable_appearance(icon, "vat_reagent", appearance_flags = RESET_COLOR|KEEP_APART) + var/mutable_appearance/base_overlay = mutable_appearance(icon, "[icon_state]_reagent", appearance_flags = RESET_COLOR|KEEP_APART) base_overlay.color = reagentcolor . += base_overlay if(biological_sample && is_operational) - var/mutable_appearance/bubbles_overlay = mutable_appearance(icon, "vat_bubbles") + var/mutable_appearance/bubbles_overlay = mutable_appearance(icon, "[icon_state]_bubbles") . += bubbles_overlay /obj/machinery/vatgrower/emag_act(mob/user, obj/item/card/emag/emag_card) @@ -170,6 +173,43 @@ addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(playsound), get_turf(src), 'sound/effects/servostep.ogg', 100, 1), 1.5 SECONDS) biological_sample.reset_sample() else - UnregisterSignal(biological_sample, COMSIG_SAMPLE_GROWTH_COMPLETED) QDEL_NULL(biological_sample) update_appearance() + +/obj/machinery/vatgrower/small + name = "small growing vat" + desc = "Tastes just like the chef's soup. Fit for growing organ tissue samples." + icon_state = "growing_vat_small" + density = FALSE + pass_flags_self = PASSMACHINE | LETPASSTHROW + circuit = null + + anchored_tabletop_offset = 4 + pass_flags = PASSTABLE + use_plumbing = FALSE + + reagent_volume = 50 + +/obj/machinery/vatgrower/small/emag_act(mob/user, obj/item/card/emag/emag_card) + return + +/obj/machinery/vatgrower/small/deposit_sample(mob/user, obj/item/petri_dish/petri) + . = ..() + + if(. != ITEM_INTERACT_SUCCESS) + return + + RegisterSignal(biological_sample, COMSIG_SAMPLE_DEPOSITED, PROC_REF(on_sample_deposited)) + +/obj/machinery/vatgrower/small/proc/on_sample_deposited(datum/biological_sample/sample, atom/thing) + SIGNAL_HANDLER + + if(isliving(thing)) + var/mob/living/living_type = thing + if(living_type.mob_size > MOB_SIZE_SMALL) + explosion(src, light_impact_range = 2, explosion_cause = "growing vat too small") + qdel(src) + return + +/obj/machinery/vatgrower/small/unanchored + anchored = FALSE diff --git a/code/modules/shuttle/mobile_port/mobile_port.dm b/code/modules/shuttle/mobile_port/mobile_port.dm index 2d22cd28ccd6..a55cb09d6c72 100644 --- a/code/modules/shuttle/mobile_port/mobile_port.dm +++ b/code/modules/shuttle/mobile_port/mobile_port.dm @@ -23,13 +23,13 @@ ///current shuttle mode var/mode = SHUTTLE_IDLE ///time spent in transit (deciseconds). Should not be lower then 10 seconds without editing the animation of the hyperspace ripples. - var/callTime = 100 + var/callTime = 10 SECONDS /// time spent "starting the engines". Also rate limits how often we try to reserve transit space if its ever full of transiting shuttles. - var/ignitionTime = 55 + var/ignitionTime = 5.5 SECONDS /// time spent after arrival before being able to begin ignition - var/rechargeTime = 0 + var/rechargeTime = 0 SECONDS /// time spent after transit 'landing' before actually arriving - var/prearrivalTime = 0 + var/prearrivalTime = 0 SECONDS /// The direction the shuttle prefers to travel in, ie what direction the animation will cause it to appear to be traveling in var/preferred_direction = NORTH diff --git a/code/modules/shuttle/mobile_port/variants/arrivals.dm b/code/modules/shuttle/mobile_port/variants/arrivals.dm index df3126081b2b..4a1bc5744d85 100644 --- a/code/modules/shuttle/mobile_port/variants/arrivals.dm +++ b/code/modules/shuttle/mobile_port/variants/arrivals.dm @@ -6,7 +6,7 @@ port_direction = SOUTH callTime = INFINITY - ignitionTime = 50 + ignitionTime = 5 SECONDS movement_force = list("KNOCKDOWN" = 3, "THROW" = 0) diff --git a/code/modules/shuttle/mobile_port/variants/supply.dm b/code/modules/shuttle/mobile_port/variants/supply.dm index 2c4d14b62814..c48ab01178eb 100644 --- a/code/modules/shuttle/mobile_port/variants/supply.dm +++ b/code/modules/shuttle/mobile_port/variants/supply.dm @@ -44,7 +44,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( /obj/docking_port/mobile/supply name = "supply shuttle" shuttle_id = "cargo" - callTime = 600 + callTime = 60 SECONDS dir = WEST port_direction = EAST @@ -227,8 +227,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( var/obj/structure/closet/crate = spawning_order.generate(pick_n_take(empty_turfs)) crate.name += " - #[spawning_order.id]" - SSblackbox.record_feedback("nested tally", "cargo_imports", 1, list("[spawning_order.pack.get_cost()]", "[spawning_order.pack.name]")) - + SSblackbox.record_feedback("nested tally", "cargo_imports", 1, list("[spawning_order.pack.get_cost()]", "[spawning_order.pack.name]", "[spawning_order.orderer_rank]")) var/from_whom = paying_for_this?.account_holder || "nobody (department order)" investigate_log("Order #[spawning_order.id] ([spawning_order.pack.name], placed by [key_name(spawning_order.orderer_ckey)]), paid by [from_whom] has shipped.", INVESTIGATE_CARGO) diff --git a/code/modules/shuttle/stationary_port/stationary_port.dm b/code/modules/shuttle/stationary_port/stationary_port.dm index dfb40108ad2e..7c5d7d99aac5 100644 --- a/code/modules/shuttle/stationary_port/stationary_port.dm +++ b/code/modules/shuttle/stationary_port/stationary_port.dm @@ -10,8 +10,12 @@ var/shuttle_template_id /// Used to check if the shuttle template is enabled in the config file var/json_key - ///If true, the shuttle can always dock at this docking port, despite its area checks, or if something is already docked + /// If true, the shuttle can always dock at this docking port, despite its area checks, or if something is already docked var/override_can_dock_checks = FALSE + // Our initial roundstart coordinates + var/initial_x = -1 + var/initial_y = -1 + var/initial_z = -1 /obj/docking_port/stationary/get_save_vars() return ..() + NAMEOF(src, roundstart_template) @@ -27,6 +31,10 @@ for(var/turf/T in return_turfs()) T.turf_flags |= NO_RUINS + initial_x = x + initial_y = y + initial_z = z + if(SSshuttle.initialized) return INITIALIZE_HINT_LATELOAD diff --git a/code/modules/surgery/advanced/brainwashing.dm b/code/modules/surgery/advanced/brainwashing.dm index 34d4e065e133..fb12ecd6e359 100644 --- a/code/modules/surgery/advanced/brainwashing.dm +++ b/code/modules/surgery/advanced/brainwashing.dm @@ -48,7 +48,7 @@ TOOL_WIRECUTTER = 50, /obj/item/stack/package_wrap = 35, /obj/item/stack/cable_coil = 15) - time = 200 + time = 20 SECONDS preop_sound = 'sound/items/handling/surgery/hemostat1.ogg' success_sound = 'sound/items/handling/surgery/hemostat1.ogg' failure_sound = 'sound/items/handling/surgery/organ2.ogg' diff --git a/code/modules/surgery/advanced/lobotomy.dm b/code/modules/surgery/advanced/lobotomy.dm index c0206d59f372..e15228976f05 100644 --- a/code/modules/surgery/advanced/lobotomy.dm +++ b/code/modules/surgery/advanced/lobotomy.dm @@ -43,7 +43,7 @@ /obj/item/shard = 25, /obj/item = 20, ) - time = 100 + time = 10 SECONDS preop_sound = 'sound/items/handling/surgery/scalpel1.ogg' success_sound = 'sound/items/handling/surgery/scalpel2.ogg' failure_sound = 'sound/items/handling/surgery/organ2.ogg' diff --git a/code/modules/surgery/advanced/necrotic_revival.dm b/code/modules/surgery/advanced/necrotic_revival.dm index 9b537bf01553..a791a70494d5 100644 --- a/code/modules/surgery/advanced/necrotic_revival.dm +++ b/code/modules/surgery/advanced/necrotic_revival.dm @@ -23,7 +23,7 @@ implements = list( /obj/item/reagent_containers/syringe = 100, /obj/item/pen = 30) - time = 50 + time = 5 SECONDS chems_needed = list(/datum/reagent/toxin/zombiepowder, /datum/reagent/medicine/rezadone) require_all_chems = FALSE diff --git a/code/modules/surgery/advanced/pacification.dm b/code/modules/surgery/advanced/pacification.dm index 5f0c165ac5bb..0c4f0e7371da 100644 --- a/code/modules/surgery/advanced/pacification.dm +++ b/code/modules/surgery/advanced/pacification.dm @@ -38,7 +38,7 @@ TOOL_SCREWDRIVER = 35, /obj/item/pen = 15, ) - time = 40 + time = 4 SECONDS preop_sound = 'sound/items/handling/surgery/hemostat1.ogg' success_sound = 'sound/items/handling/surgery/hemostat1.ogg' failure_sound = 'sound/items/handling/surgery/organ2.ogg' diff --git a/code/modules/surgery/advanced/viral_bonding.dm b/code/modules/surgery/advanced/viral_bonding.dm index f57e49ec1bd8..be7e2969a0bf 100644 --- a/code/modules/surgery/advanced/viral_bonding.dm +++ b/code/modules/surgery/advanced/viral_bonding.dm @@ -26,7 +26,7 @@ TOOL_CAUTERY = 100, TOOL_WELDER = 50, /obj/item = 30) // 30% success with any hot item. - time = 100 + time = 10 SECONDS chems_needed = list(/datum/reagent/medicine/spaceacillin,/datum/reagent/consumable/virus_food,/datum/reagent/toxin/formaldehyde) /datum/surgery_step/viral_bond/tool_check(mob/user, obj/item/tool) diff --git a/code/modules/surgery/advanced/wingreconstruction.dm b/code/modules/surgery/advanced/wingreconstruction.dm index a3931dd4e5e9..3a27a19c391a 100644 --- a/code/modules/surgery/advanced/wingreconstruction.dm +++ b/code/modules/surgery/advanced/wingreconstruction.dm @@ -23,7 +23,7 @@ TOOL_HEMOSTAT = 85, TOOL_SCREWDRIVER = 35, /obj/item/pen = 15) - time = 200 + time = 20 SECONDS chems_needed = list(/datum/reagent/medicine/c2/synthflesh) require_all_chems = FALSE diff --git a/code/modules/surgery/amputation.dm b/code/modules/surgery/amputation.dm index 0bcf408b2a71..be4fbf7ea5f9 100644 --- a/code/modules/surgery/amputation.dm +++ b/code/modules/surgery/amputation.dm @@ -51,7 +51,7 @@ /obj/item/hatchet = 40, /obj/item/knife/butcher = 25, ) - time = 64 + time = 6.4 SECONDS preop_sound = 'sound/items/handling/surgery/scalpel1.ogg' success_sound = 'sound/items/handling/surgery/organ2.ogg' surgery_effects_mood = TRUE @@ -78,7 +78,7 @@ /obj/item/hatchet = 75, TOOL_SCALPEL = 25, ) - time = 30 + time = 3 SECONDS preop_sound = 'sound/items/handling/surgery/saw.ogg' success_sound = 'sound/items/handling/materials/wood_drop.ogg' diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index 78a20467bde2..0e25e1b981f8 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -244,6 +244,12 @@ pill.forceMove(src) name = "[owner.real_name]'s head" + + /// If our owner loses their head, update their name as their face ~cannot be seen~ does not exist anymore + if (ishuman(owner)) + var/mob/living/carbon/human/as_human = owner + as_human.update_visible_name() + return ..() ///Try to attach this bodypart to a mob, while replacing one if it exists, does nothing if it fails. @@ -351,6 +357,11 @@ new_head_owner.real_name = old_real_name real_name = new_head_owner.real_name + /// Update our owner's name with ours + if (ishuman(owner)) + var/mob/living/carbon/human/as_human = owner + as_human.update_visible_name() + //Handle dental implants for(var/obj/item/reagent_containers/applicator/pill/pill in src) for(var/datum/action/item_action/activate_pill/pill_action in pill.actions) diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index 2e70ebca694c..347eb6428d46 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -213,6 +213,16 @@ /obj/item/bodypart/head/GetVoice() return "The head of [real_name]" +/obj/item/bodypart/head/update_bodypart_damage_state() + if (!ishuman(owner)) + return ..() + var/old_states = brutestate + burnstate + . = ..() + var/new_states = brutestate + burnstate + var/mob/living/carbon/human/as_human = owner + if ((old_states >= HUMAN_DISFIGURATION_HEAD_DAMAGE_STATES && new_states < HUMAN_DISFIGURATION_HEAD_DAMAGE_STATES) || (old_states < HUMAN_DISFIGURATION_HEAD_DAMAGE_STATES && new_states >= HUMAN_DISFIGURATION_HEAD_DAMAGE_STATES)) + as_human.update_visible_name() + /obj/item/bodypart/head/monkey icon = 'icons/mob/human/species/monkey/bodyparts.dmi' icon_static = 'icons/mob/human/species/monkey/bodyparts.dmi' diff --git a/code/modules/surgery/bone_mending.dm b/code/modules/surgery/bone_mending.dm index 8afffb232fb9..24cea41ce302 100644 --- a/code/modules/surgery/bone_mending.dm +++ b/code/modules/surgery/bone_mending.dm @@ -53,7 +53,7 @@ /obj/item/stack/sticky_tape/surgical = 100, /obj/item/stack/sticky_tape/super = 50, /obj/item/stack/sticky_tape = 30) - time = 40 + time = 4 SECONDS /datum/surgery_step/repair_bone_hairline/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) if(surgery.operated_wound) @@ -102,7 +102,7 @@ /obj/item/stack/sticky_tape/surgical = 60, /obj/item/stack/sticky_tape/super = 40, /obj/item/stack/sticky_tape = 20) - time = 40 + time = 4 SECONDS /datum/surgery_step/reset_compound_fracture/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) if(surgery.operated_wound) @@ -152,7 +152,7 @@ /datum/surgery_step/repair_bone_compound name = "repair compound fracture (bone gel/tape)" implements = IMPLEMENTS_THAT_FIX_BONES - time = 40 + time = 4 SECONDS /datum/surgery_step/repair_bone_compound/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) if(surgery.operated_wound) diff --git a/code/modules/surgery/burn_dressing.dm b/code/modules/surgery/burn_dressing.dm index 54aa82f43b43..2e87d6b51b71 100644 --- a/code/modules/surgery/burn_dressing.dm +++ b/code/modules/surgery/burn_dressing.dm @@ -39,7 +39,7 @@ TOOL_SCALPEL = 85, TOOL_SAW = 60, TOOL_WIRECUTTER = 40) - time = 30 + time = 3 SECONDS repeatable = TRUE preop_sound = 'sound/items/handling/surgery/scalpel1.ogg' success_sound = 'sound/items/handling/surgery/retractor2.ogg' @@ -134,7 +134,7 @@ implements = list( /obj/item/stack/medical/gauze = 100, /obj/item/stack/sticky_tape/surgical = 100) - time = 40 + time = 4 SECONDS /// How much sanitization is added var/sanitization_added = 3 /// How much flesh healing is added diff --git a/code/modules/surgery/cavity_implant.dm b/code/modules/surgery/cavity_implant.dm index b07b562aa8db..cfab9cf74241 100644 --- a/code/modules/surgery/cavity_implant.dm +++ b/code/modules/surgery/cavity_implant.dm @@ -17,7 +17,7 @@ GLOBAL_LIST_INIT(heavy_cavity_implants, typecacheof(list(/obj/item/transfer_valv accept_hand = 1 implements = list(/obj/item = 100) repeatable = TRUE - time = 32 + time = 3.2 SECONDS preop_sound = 'sound/items/handling/surgery/organ1.ogg' success_sound = 'sound/items/handling/surgery/organ2.ogg' var/obj/item/item_for_cavity diff --git a/code/modules/surgery/core_removal.dm b/code/modules/surgery/core_removal.dm index 4c7382f3daee..890d62413f22 100644 --- a/code/modules/surgery/core_removal.dm +++ b/code/modules/surgery/core_removal.dm @@ -24,7 +24,7 @@ implements = list( TOOL_HEMOSTAT = 100, TOOL_CROWBAR = 100) - time = 16 + time = 1.6 SECONDS /datum/surgery_step/extract_core/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) display_results( diff --git a/code/modules/surgery/coronary_bypass.dm b/code/modules/surgery/coronary_bypass.dm index 7b0536367f13..75357ba4908b 100644 --- a/code/modules/surgery/coronary_bypass.dm +++ b/code/modules/surgery/coronary_bypass.dm @@ -40,7 +40,7 @@ /obj/item/melee/energy/sword = 45, /obj/item/knife = 45, /obj/item/shard = 25) - time = 16 + time = 1.6 SECONDS preop_sound = 'sound/items/handling/surgery/scalpel1.ogg' success_sound = 'sound/items/handling/surgery/scalpel2.ogg' failure_sound = 'sound/items/handling/surgery/organ2.ogg' @@ -108,7 +108,7 @@ TOOL_WIRECUTTER = 35, /obj/item/stack/package_wrap = 15, /obj/item/stack/cable_coil = 5) - time = 90 + time = 9 SECONDS preop_sound = 'sound/items/handling/surgery/hemostat1.ogg' success_sound = 'sound/items/handling/surgery/hemostat1.ogg' failure_sound = 'sound/items/handling/surgery/organ2.ogg' diff --git a/code/modules/surgery/dental_implant.dm b/code/modules/surgery/dental_implant.dm index 96208396b6e3..f12064a42c15 100644 --- a/code/modules/surgery/dental_implant.dm +++ b/code/modules/surgery/dental_implant.dm @@ -31,7 +31,7 @@ /datum/surgery_step/insert_pill name = "insert pill" implements = list(/obj/item/reagent_containers/applicator/pill = 100) - time = 16 + time = 1.6 SECONDS /datum/surgery_step/insert_pill/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) diff --git a/code/modules/surgery/ear_surgery.dm b/code/modules/surgery/ear_surgery.dm index 9e363e2ae9b2..9f41949f7638 100644 --- a/code/modules/surgery/ear_surgery.dm +++ b/code/modules/surgery/ear_surgery.dm @@ -20,7 +20,7 @@ TOOL_HEMOSTAT = 100, TOOL_SCREWDRIVER = 45, /obj/item/pen = 25) - time = 64 + time = 6.4 SECONDS /datum/surgery/ear_surgery/can_start(mob/user, mob/living/carbon/target) return target.get_organ_slot(ORGAN_SLOT_EARS) && ..() diff --git a/code/modules/surgery/eye_surgery.dm b/code/modules/surgery/eye_surgery.dm index 3a0f71400917..31a4fe261d44 100644 --- a/code/modules/surgery/eye_surgery.dm +++ b/code/modules/surgery/eye_surgery.dm @@ -18,7 +18,7 @@ TOOL_HEMOSTAT = 100, TOOL_SCREWDRIVER = 45, /obj/item/pen = 25) - time = 64 + time = 6.4 SECONDS /datum/surgery/eye_surgery/can_start(mob/user, mob/living/carbon/target) return target.get_organ_slot(ORGAN_SLOT_EYES) && ..() diff --git a/code/modules/surgery/gastrectomy.dm b/code/modules/surgery/gastrectomy.dm index d09933f303fe..caae23b25526 100644 --- a/code/modules/surgery/gastrectomy.dm +++ b/code/modules/surgery/gastrectomy.dm @@ -41,7 +41,7 @@ /obj/item/melee/energy/sword = 65, /obj/item/knife = 45, /obj/item/shard = 35) - time = 52 + time = 5.2 SECONDS preop_sound = 'sound/items/handling/surgery/scalpel1.ogg' success_sound = 'sound/items/handling/surgery/organ1.ogg' failure_sound = 'sound/items/handling/surgery/organ2.ogg' diff --git a/code/modules/surgery/healing.dm b/code/modules/surgery/healing.dm index 12540945a523..dfabe24234d0 100644 --- a/code/modules/surgery/healing.dm +++ b/code/modules/surgery/healing.dm @@ -41,7 +41,7 @@ TOOL_WIRECUTTER = 60, /obj/item/pen = 55) repeatable = TRUE - time = 25 + time = 2.5 SECONDS success_sound = 'sound/items/handling/surgery/retractor2.ogg' failure_sound = 'sound/items/handling/surgery/organ2.ogg' var/brutehealing = 0 @@ -330,7 +330,7 @@ burnhealing = 3 brute_multiplier = 0.07 burn_multiplier = 0.07 - time = 10 + time = 1 SECONDS /datum/surgery_step/heal/combo/upgraded brutehealing = 3 diff --git a/code/modules/surgery/hepatectomy.dm b/code/modules/surgery/hepatectomy.dm index 82921c3f2752..ebde95052142 100644 --- a/code/modules/surgery/hepatectomy.dm +++ b/code/modules/surgery/hepatectomy.dm @@ -40,7 +40,7 @@ /obj/item/melee/energy/sword = 65, /obj/item/knife = 45, /obj/item/shard = 35) - time = 52 + time = 5.2 SECONDS preop_sound = 'sound/items/handling/surgery/scalpel1.ogg' success_sound = 'sound/items/handling/surgery/organ1.ogg' failure_sound = 'sound/items/handling/surgery/organ2.ogg' diff --git a/code/modules/surgery/implant_removal.dm b/code/modules/surgery/implant_removal.dm index 51c279d32cd9..7893f33ec4d5 100644 --- a/code/modules/surgery/implant_removal.dm +++ b/code/modules/surgery/implant_removal.dm @@ -18,7 +18,7 @@ TOOL_HEMOSTAT = 100, TOOL_CROWBAR = 65, /obj/item/kitchen/fork = 35) - time = 64 + time = 6.4 SECONDS success_sound = 'sound/items/handling/surgery/hemostat1.ogg' var/obj/item/implant/implant diff --git a/code/modules/surgery/limb_augmentation.dm b/code/modules/surgery/limb_augmentation.dm index 5276111e5672..b9b1356db895 100644 --- a/code/modules/surgery/limb_augmentation.dm +++ b/code/modules/surgery/limb_augmentation.dm @@ -9,7 +9,7 @@ implements = list( /obj/item/bodypart = 100, /obj/item/borg/apparatus/organ_storage = 100) - time = 32 + time = 3.2 SECONDS var/obj/item/bodypart/target_limb diff --git a/code/modules/surgery/lipoplasty.dm b/code/modules/surgery/lipoplasty.dm index 975df4a8bdff..3183c968f701 100644 --- a/code/modules/surgery/lipoplasty.dm +++ b/code/modules/surgery/lipoplasty.dm @@ -37,7 +37,7 @@ /obj/item/hatchet = 35, /obj/item/knife/butcher = 25, ) - time = 64 + time = 6.4 SECONDS surgery_effects_mood = TRUE preop_sound = list( /obj/item/circular_saw = 'sound/items/handling/surgery/saw.ogg', @@ -87,7 +87,7 @@ TOOL_SCREWDRIVER = 45, TOOL_WIRECUTTER = 35, ) - time = 32 + time = 3.2 SECONDS preop_sound = 'sound/items/handling/surgery/retractor1.ogg' success_sound = 'sound/items/handling/surgery/retractor2.ogg' diff --git a/code/modules/surgery/lobectomy.dm b/code/modules/surgery/lobectomy.dm index e0988c8376c8..4f1c32873d8d 100644 --- a/code/modules/surgery/lobectomy.dm +++ b/code/modules/surgery/lobectomy.dm @@ -37,7 +37,7 @@ /obj/item/melee/energy/sword = 65, /obj/item/knife = 45, /obj/item/shard = 35) - time = 42 + time = 4.2 SECONDS preop_sound = 'sound/items/handling/surgery/scalpel1.ogg' success_sound = 'sound/items/handling/surgery/organ1.ogg' failure_sound = 'sound/items/handling/surgery/organ2.ogg' diff --git a/code/modules/surgery/mechanic_steps.dm b/code/modules/surgery/mechanic_steps.dm index 44be32bc858a..dab8730c2ed1 100644 --- a/code/modules/surgery/mechanic_steps.dm +++ b/code/modules/surgery/mechanic_steps.dm @@ -6,7 +6,7 @@ TOOL_SCALPEL = 75, // med borgs could try to unscrew shell with scalpel /obj/item/knife = 50, /obj/item = 10) // 10% success with any sharp item. - time = 24 + time = 2.4 SECONDS preop_sound = 'sound/items/tools/screwdriver.ogg' success_sound = 'sound/items/tools/screwdriver2.ogg' @@ -36,7 +36,7 @@ TOOL_SCALPEL = 75, /obj/item/knife = 50, /obj/item = 10) // 10% success with any sharp item. - time = 24 + time = 2.4 SECONDS preop_sound = 'sound/items/tools/screwdriver.ogg' success_sound = 'sound/items/tools/screwdriver2.ogg' @@ -64,7 +64,7 @@ implements = list( TOOL_MULTITOOL = 100, TOOL_HEMOSTAT = 75) - time = 24 + time = 2.4 SECONDS preop_sound = 'sound/items/taperecorder/tape_flip.ogg' success_sound = 'sound/items/taperecorder/taperecorder_close.ogg' @@ -84,7 +84,7 @@ implements = list( TOOL_WRENCH = 100, TOOL_RETRACTOR = 75) - time = 24 + time = 2.4 SECONDS preop_sound = 'sound/items/tools/ratchet.ogg' /datum/surgery_step/mechanic_unwrench/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) @@ -109,7 +109,7 @@ implements = list( TOOL_WRENCH = 100, TOOL_RETRACTOR = 75) - time = 24 + time = 2.4 SECONDS preop_sound = 'sound/items/tools/ratchet.ogg' /datum/surgery_step/mechanic_wrench/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) @@ -132,7 +132,7 @@ /datum/surgery_step/open_hatch name = "open the hatch (hand)" accept_hand = TRUE - time = 10 + time = 1 SECONDS preop_sound = 'sound/items/tools/ratchet.ogg' preop_sound = 'sound/machines/airlock/doorclick.ogg' diff --git a/code/modules/surgery/organic_steps.dm b/code/modules/surgery/organic_steps.dm index cdcb324c8670..30a06d70ff7d 100644 --- a/code/modules/surgery/organic_steps.dm +++ b/code/modules/surgery/organic_steps.dm @@ -8,7 +8,7 @@ /obj/item/knife = 65, /obj/item/shard = 45, /obj/item = 30) // 30% success with any sharp item. - time = 16 + time = 1.6 SECONDS preop_sound = 'sound/items/handling/surgery/scalpel1.ogg' success_sound = 'sound/items/handling/surgery/scalpel2.ogg' surgery_effects_mood = TRUE @@ -64,7 +64,7 @@ TOOL_WIRECUTTER = 60, /obj/item/stack/package_wrap = 35, /obj/item/stack/cable_coil = 15) - time = 24 + time = 2.4 SECONDS preop_sound = 'sound/items/handling/surgery/hemostat1.ogg' /datum/surgery_step/clamp_bleeders/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) @@ -95,7 +95,7 @@ TOOL_SCREWDRIVER = 45, TOOL_WIRECUTTER = 35, /obj/item/stack/rods = 35) - time = 24 + time = 2.4 SECONDS preop_sound = 'sound/items/handling/surgery/retractor1.ogg' success_sound = 'sound/items/handling/surgery/retractor2.ogg' @@ -117,7 +117,7 @@ /obj/item/gun/energy/laser = 90, TOOL_WELDER = 70, /obj/item = 30) // 30% success with any hot item. - time = 24 + time = 2.4 SECONDS preop_sound = 'sound/items/handling/surgery/cautery1.ogg' success_sound = 'sound/items/handling/surgery/cautery2.ogg' @@ -160,7 +160,7 @@ /obj/item/hatchet = 35, /obj/item/knife/butcher = 35, /obj/item = 25) //20% success (sort of) with any sharp item with a force >= 10 - time = 54 + time = 5.4 SECONDS preop_sound = list( /obj/item/circular_saw = 'sound/items/handling/surgery/saw.ogg', /obj/item/melee/arm_blade = 'sound/items/handling/surgery/scalpel1.ogg', @@ -208,7 +208,7 @@ /obj/item/pickaxe/drill = 60, TOOL_SCREWDRIVER = 25, /obj/item/kitchen/spoon = 20) - time = 30 + time = 3 SECONDS /datum/surgery_step/drill/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) display_results( diff --git a/code/modules/surgery/organs/_organ.dm b/code/modules/surgery/organs/_organ.dm index 534146d4d99f..ac602413eee1 100644 --- a/code/modules/surgery/organs/_organ.dm +++ b/code/modules/surgery/organs/_organ.dm @@ -68,6 +68,12 @@ var/failing_desc = "has decayed for too long, and has turned a sickly color. It probably won't work without repairs." /// Assoc list of alternate zones where this can organ be slotted to organ slot for that zone var/list/valid_zones = null + /// The cell line we can spawn on us + var/cell_line = null + /// The minimum cells we can spawn + var/cells_minimum = 0 + /// The maximum cells we can spawn + var/cells_maximum = 0 // Players can look at prefs before atoms SS init, and without this // they would not be able to see external organs, such as moth wings. @@ -90,6 +96,10 @@ INITIALIZE_IMMEDIATE(/obj/item/organ) if(bodypart_overlay) setup_bodypart_overlay() + + if(cell_line && (organ_flags & ORGAN_ORGANIC)) + AddElement(/datum/element/swabable, cell_line, cell_line_amount = rand(cells_minimum, cells_maximum)) + START_PROCESSING(SSobj, src) /obj/item/organ/Destroy() diff --git a/code/modules/surgery/organs/external/wings/functional_wings.dm b/code/modules/surgery/organs/external/wings/functional_wings.dm index 8161f618246a..86bad3a1b575 100644 --- a/code/modules/surgery/organs/external/wings/functional_wings.dm +++ b/code/modules/surgery/organs/external/wings/functional_wings.dm @@ -1,5 +1,5 @@ #define FUNCTIONAL_WING_FORCE 2.25 NEWTONS -#define FUNCTIONAL_WING_STABILIZATION 1.2 NEWTONS +#define FUNCTIONAL_WING_STABILIZATION 4.5 NEWTONS ///hud action for starting and stopping flight /datum/action/innate/flight diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm b/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm index 177a2ded6c8d..681d68e62820 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm @@ -578,13 +578,13 @@ bonus_deactivate_text = span_notice("You can no longer force open airlocks with your bare hands.") required_biotype = NONE -/datum/status_effect/organ_set_bonus/strongarm/enable_bonus() +/datum/status_effect/organ_set_bonus/strongarm/enable_bonus(obj/item/organ/inserted_organ) . = ..() if(!.) return owner.AddElement(/datum/element/door_pryer, pry_time = 6 SECONDS, interaction_key = DOAFTER_SOURCE_STRONGARM_INTERACTION) -/datum/status_effect/organ_set_bonus/strongarm/disable_bonus() +/datum/status_effect/organ_set_bonus/strongarm/disable_bonus(obj/item/organ/removed_organ) . = ..() owner.RemoveElement(/datum/element/door_pryer, pry_time = 6 SECONDS, interaction_key = DOAFTER_SOURCE_STRONGARM_INTERACTION) diff --git a/code/modules/surgery/organs/internal/eyes/_eyes.dm b/code/modules/surgery/organs/internal/eyes/_eyes.dm index ee9a72594431..98d32916c587 100644 --- a/code/modules/surgery/organs/internal/eyes/_eyes.dm +++ b/code/modules/surgery/organs/internal/eyes/_eyes.dm @@ -91,7 +91,7 @@ eye_color_left = as_human.eye_color_left if (!eye_color_right) eye_color_right = as_human.eye_color_right - refresh(receiver, call_update = !special) + refresh(receiver, call_update = TRUE) RegisterSignal(receiver, COMSIG_ATOM_BULLET_ACT, PROC_REF(on_bullet_act)) RegisterSignal(receiver, COMSIG_COMPONENT_CLEAN_FACE_ACT, PROC_REF(on_face_wash)) if (scarring) @@ -416,7 +416,6 @@ #define RAND_BLINKING_DELAY 1 SECONDS #define BLINK_DURATION 0.15 SECONDS #define BLINK_LOOPS 5 -#define ASYNC_BLINKING_BRAIN_DAMAGE 60 /// Modifies eye overlays to also act as eyelids, both for blinking and for when you're knocked out cold /obj/item/organ/eyes/proc/setup_eyelids(mutable_appearance/eye_left, mutable_appearance/eye_right, mob/living/carbon/human/parent) @@ -461,7 +460,6 @@ if (anim_times) if (sync_blinking) wait_time = anim_times[1] - anim_times.Cut(1, 2) else wait_time = rand(max(BASE_BLINKING_DELAY - RAND_BLINKING_DELAY, anim_times[1] - RAND_BLINKING_DELAY), anim_times[1]) @@ -472,17 +470,15 @@ for (var/i in 1 to cycles) if (anim_times) if (sync_blinking) - wait_time = anim_times[1] - anim_times.Cut(1, 2) + wait_time = anim_times[i + 1] else - wait_time = rand(max(BASE_BLINKING_DELAY - RAND_BLINKING_DELAY, anim_times[1] - RAND_BLINKING_DELAY), anim_times[1]) + wait_time = rand(max(BASE_BLINKING_DELAY - RAND_BLINKING_DELAY, anim_times[i + 1] - RAND_BLINKING_DELAY), anim_times[i + 1]) else wait_time = rand(BASE_BLINKING_DELAY - RAND_BLINKING_DELAY, BASE_BLINKING_DELAY + RAND_BLINKING_DELAY) . += wait_time if (anim_times && !sync_blinking) // Make sure that we're somewhat in sync with the other eye - animate(time = anim_times[1] - wait_time) - anim_times.Cut(1, 2) + animate(time = anim_times[i + 1] - wait_time) animate(alpha = 255, time = 0) animate(time = BLINK_DURATION) if (i != cycles) @@ -490,17 +486,18 @@ animate(time = wait_time) /obj/item/organ/eyes/proc/blink(duration = BLINK_DURATION, restart_animation = TRUE) - var/left_delayed = rand(50) + var/left_delayed = prob(50) // Storing blink delay so mistimed blinks of lizards don't get cut short - var/blink_delay = synchronized_blinking ? rand(0, RAND_BLINKING_DELAY) : 0 + var/sync_blinking = synchronized_blinking && (owner.get_organ_loss(ORGAN_SLOT_BRAIN) < BRAIN_DAMAGE_ASYNC_BLINKING) + var/blink_delay = sync_blinking ? 0 : rand(0, RAND_BLINKING_DELAY) animate(eyelid_left, alpha = 0, time = 0) - if (!synchronized_blinking && left_delayed) + if (!sync_blinking && left_delayed) animate(time = blink_delay) animate(alpha = 255, time = 0) animate(time = duration) animate(alpha = 0, time = 0) animate(eyelid_right, alpha = 0, time = 0) - if (!synchronized_blinking && !left_delayed) + if (!sync_blinking && !left_delayed) animate(time = blink_delay) animate(alpha = 255, time = 0) animate(time = duration) @@ -509,7 +506,7 @@ addtimer(CALLBACK(src, PROC_REF(animate_eyelids), owner), blink_delay + duration) /obj/item/organ/eyes/proc/animate_eyelids(mob/living/carbon/human/parent) - var/sync_blinking = synchronized_blinking && (parent.get_organ_loss(ORGAN_SLOT_BRAIN) < ASYNC_BLINKING_BRAIN_DAMAGE) + var/sync_blinking = synchronized_blinking && (parent.get_organ_loss(ORGAN_SLOT_BRAIN) < BRAIN_DAMAGE_ASYNC_BLINKING) // Randomize order for unsynched animations if (sync_blinking || prob(50)) var/list/anim_times = animate_eyelid(eyelid_left, parent, sync_blinking) @@ -532,7 +529,6 @@ #undef RAND_BLINKING_DELAY #undef BLINK_DURATION #undef BLINK_LOOPS -#undef ASYNC_BLINKING_BRAIN_DAMAGE /// by default, returns the eyes' penlight_message var as a notice span. May do other things when overridden, such as eldritch insanity, or eye damage, or whatnot. Whatever you want, really. /obj/item/organ/eyes/proc/penlight_examine(mob/living/viewer) diff --git a/code/modules/surgery/organs/internal/heart/_heart.dm b/code/modules/surgery/organs/internal/heart/_heart.dm index d0e386ac5a8f..0e00dce883af 100644 --- a/code/modules/surgery/organs/internal/heart/_heart.dm +++ b/code/modules/surgery/organs/internal/heart/_heart.dm @@ -21,6 +21,10 @@ // Love is stored in the heart. food_reagents = list(/datum/reagent/consumable/nutriment/organ_tissue = 5, /datum/reagent/love = 2.5) + cell_line = CELL_LINE_ORGAN_HEART + cells_minimum = 1 + cells_maximum = 2 + // Heart attack code is in code/modules/mob/living/carbon/human/life.dm /// Whether the heart is currently beating. @@ -291,6 +295,7 @@ maxHealth = 2 * STANDARD_ORGAN_THRESHOLD stabilization_available = TRUE toxification_probability = 0 + bleed_prevention = TRUE emp_vulnerability = 20 /obj/item/organ/heart/cybernetic/surplus @@ -334,3 +339,69 @@ beat_noise = "the power of the podperson" // makes sense foodtype_flags = PODPERSON_ORGAN_FOODTYPES color = COLOR_LIME + +/// An improved version of the organic heart, with more health and more "keeping you alive" potential +/obj/item/organ/heart/evolved + name = "evolved heart" + desc = "It beats ever strong." + icon_state = "heart-evolved-on" + base_icon_state = "heart-evolved" + + maxHealth = STANDARD_ORGAN_THRESHOLD * 1.2 + + /// Chance to heal per on_life + var/healing_probability = 10 + /// Base healing we receive per tick at 0 damage and for standard versions + var/base_healing = 1 + +/obj/item/organ/heart/evolved/on_life(seconds_per_tick, times_fired) + . = ..() + + if(prob(healing_probability * seconds_per_tick)) + var/damage_to_heal = base_healing * ((maxHealth - damage) / initial(maxHealth)) * seconds_per_tick + owner.heal_overall_damage(damage_to_heal, damage_to_heal, required_bodytype = BODYTYPE_ORGANIC) + + if(owner.stat == HARD_CRIT && !owner.has_reagent(/datum/reagent/medicine/atropine, 5)) + owner.reagents.add_reagent(/datum/reagent/medicine/atropine, 1 * seconds_per_tick) + +/// A weaker evolved heart, but can block magic in exchange for our organs health! +/obj/item/organ/heart/evolved/sacred + name = "sacred heart" + desc = "Your foul magics stand no chance against the power of LOVE!!!" + + icon_state = "heart-sacred-on" + base_icon_state = "heart-sacred" + + healing_probability = 5 + base_healing = 0.5 + + // How much damage each magic block deals to us + var/damage_per_block = 50 + +/obj/item/organ/heart/evolved/sacred/on_life(seconds_per_tick, times_fired) + . = ..() + + if(IS_CULTIST(owner)) + owner.reagents.add_reagent(/datum/reagent/water/holywater, 5 * seconds_per_tick) + +/obj/item/organ/heart/evolved/sacred/on_mob_insert(mob/living/carbon/receiver, special, movement_flags) + . = ..() + + receiver.AddComponent(/datum/component/anti_magic, block_magic = CALLBACK(src, PROC_REF(on_blocked)), check_blocking = CALLBACK(src, PROC_REF(check_block))) + +/obj/item/organ/heart/evolved/sacred/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags) + . = ..() + + qdel(organ_owner.GetComponent(/datum/component/anti_magic)) + +/// When we blocked damage, do PAIN on us +/obj/item/organ/heart/evolved/sacred/proc/on_blocked() + apply_organ_damage(damage_per_block) + owner.vomit(VOMIT_CATEGORY_BLOOD) + playsound(owner, 'sound/effects/health/slowbeat.ogg', 80) + +/// We don't block magic if it would kill our heart +/obj/item/organ/heart/evolved/sacred/proc/check_block() + if(maxHealth - damage <= damage_per_block) + return FALSE + return TRUE diff --git a/code/modules/surgery/organs/internal/liver/_liver.dm b/code/modules/surgery/organs/internal/liver/_liver.dm index 6e6444edfb7e..f6995237c694 100755 --- a/code/modules/surgery/organs/internal/liver/_liver.dm +++ b/code/modules/surgery/organs/internal/liver/_liver.dm @@ -18,6 +18,10 @@ food_reagents = list(/datum/reagent/consumable/nutriment/organ_tissue = 5, /datum/reagent/iron = 5) grind_results = list(/datum/reagent/consumable/nutriment/peptides = 5) + cell_line = CELL_LINE_ORGAN_LIVER + cells_minimum = 1 + cells_maximum = 2 + /// Affects how much damage the liver takes from alcohol var/alcohol_tolerance = ALCOHOL_RATE /// The maximum volume of toxins the liver will ignore @@ -328,6 +332,60 @@ organ_owner.reagents.remove_reagent(chem.type, REAGENTS_METABOLISM * seconds_per_tick) return COMSIG_MOB_STOP_REAGENT_TICK +/obj/item/organ/liver/evolved + name = "evolved liver" + desc = "A more robust liver, better at everything." + + icon_state = "evolved-liver" + + alcohol_tolerance = ALCOHOL_RATE * 0.5 + maxHealth = 1.2 * STANDARD_ORGAN_THRESHOLD + toxTolerance = 6 //can shrug off up to 6u of toxins + liver_resistance = 1.5 * LIVER_DEFAULT_TOX_RESISTANCE + +/obj/item/organ/liver/bloody + name = "leaky liver" + desc = "An extra spongy liver, only slightly better than a normal liver, but with an increased ability to replenish blood." + + icon_state = "leaky-liver" + + maxHealth = 1.1 * STANDARD_ORGAN_THRESHOLD + alcohol_tolerance = ALCOHOL_RATE * 0.8 + toxTolerance = LIVER_DEFAULT_TOX_TOLERANCE + 1 + liver_resistance = 1.1 * LIVER_DEFAULT_TOX_RESISTANCE + +/obj/item/organ/liver/bloody/on_life(seconds_per_tick, times_fired) + . = ..() + + if(owner.blood_volume < BLOOD_VOLUME_NORMAL) + owner.blood_volume += 4 * seconds_per_tick + +/// Convert all non-alcoholic drinks into alcohol +/obj/item/organ/liver/distillery + name = "alcoholics delight" + desc = "The perfect liver, distilling non-alcoholic reagents into alcohol whenever possible." + + icon_state = "liver-distillery" + + organ_traits = list(TRAIT_ALCOHOL_TOLERANCE) + + alcohol_tolerance = ALCOHOL_RATE * 0.1 + + /// Volume that is converted per second + var/ethanol_conversion = 0.2 + /// What to convert stuff into + var/convert_into = /datum/reagent/consumable/ethanol + +/obj/item/organ/liver/distillery/on_life(seconds_per_tick, times_fired) + . = ..() + + for(var/datum/reagent/reagent as anything in owner.reagents.reagent_list) + // Already alcohol + if(istype(reagent, convert_into)) + continue + + owner.reagents.convert_reagent(reagent.type, convert_into, ethanol_conversion) + #undef LIVER_DEFAULT_TOX_TOLERANCE #undef LIVER_DEFAULT_TOX_RESISTANCE #undef LIVER_FAILURE_STAGE_SECONDS diff --git a/code/modules/surgery/organs/internal/lungs/_lungs.dm b/code/modules/surgery/organs/internal/lungs/_lungs.dm index 91933262ac53..27a88a6d94e0 100644 --- a/code/modules/surgery/organs/internal/lungs/_lungs.dm +++ b/code/modules/surgery/organs/internal/lungs/_lungs.dm @@ -18,6 +18,10 @@ low_threshold_cleared = span_info("You can breathe normally again.") high_threshold_cleared = span_info("The constriction around your chest loosens as your breathing calms down.") + cell_line = CELL_LINE_ORGAN_LUNGS + cells_minimum = 1 + cells_maximum = 2 + var/failed = FALSE var/operated = FALSE //whether we can still have our damages fixed through surgery @@ -1077,6 +1081,17 @@ foodtype_flags = PODPERSON_ORGAN_FOODTYPES color = COLOR_LIME +/obj/item/organ/lungs/evolved + name = "evolved lungs" + desc = "A pair of lungs, with an organic filtering system and a stronger musculature." + + icon_state = "lungs-evolved" + + safe_plasma_max = 8 + safe_co2_max = 8 + maxHealth = 1.2 * STANDARD_ORGAN_THRESHOLD + safe_oxygen_min = 8 + #undef BREATH_RELATIONSHIP_INITIAL_GAS #undef BREATH_RELATIONSHIP_CONVERT #undef BREATH_RELATIONSHIP_MULTIPLIER diff --git a/code/modules/surgery/organs/internal/stomach/_stomach.dm b/code/modules/surgery/organs/internal/stomach/_stomach.dm index 12f76c6befd9..658598ee7d76 100644 --- a/code/modules/surgery/organs/internal/stomach/_stomach.dm +++ b/code/modules/surgery/organs/internal/stomach/_stomach.dm @@ -24,6 +24,10 @@ //This is a reagent user and needs more then the 10u from edible component reagent_vol = 1000 + cell_line = CELL_LINE_ORGAN_STOMACH + cells_minimum = 1 + cells_maximum = 2 + ///The rate that disgust decays var/disgust_metabolism = 1 @@ -565,4 +569,13 @@ movement_type = PHASING organ_flags = parent_type::organ_flags | ORGAN_GHOST +/obj/item/organ/stomach/evolved + name = "evolved stomach" + desc = "It can draw nutrients from your food even harder!" + icon_state = "stomach-evolved" + + maxHealth = 1.2 * STANDARD_ORGAN_THRESHOLD + disgust_metabolism = 2.5 + metabolism_efficiency = 0.08 + #undef STOMACH_METABOLISM_CONSTANT diff --git a/code/modules/surgery/organs/organ_movement.dm b/code/modules/surgery/organs/organ_movement.dm index d31c3e5e0b26..fb63d46eb26b 100644 --- a/code/modules/surgery/organs/organ_movement.dm +++ b/code/modules/surgery/organs/organ_movement.dm @@ -144,6 +144,8 @@ if(bodypart_overlay) limb.add_bodypart_overlay(bodypart_overlay) + SEND_SIGNAL(src, COMSIG_ORGAN_BODYPART_INSERTED, limb, movement_flags) + /* * Remove the organ from the select mob. * diff --git a/code/modules/surgery/plastic_surgery.dm b/code/modules/surgery/plastic_surgery.dm index a9905513e8c6..bedb2176d3db 100644 --- a/code/modules/surgery/plastic_surgery.dm +++ b/code/modules/surgery/plastic_surgery.dm @@ -59,7 +59,7 @@ TOOL_SCALPEL = 100, /obj/item/knife = 50, TOOL_WIRECUTTER = 35) - time = 64 + time = 6.4 SECONDS surgery_effects_mood = TRUE /datum/surgery_step/reshape_face/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) @@ -116,7 +116,7 @@ display_pain(target, "The pain fades, your face feels new and unfamiliar!") if(ishuman(target)) var/mob/living/carbon/human/human_target = target - human_target.sec_hud_set_ID() + human_target.update_ID_card() if(HAS_MIND_TRAIT(user, TRAIT_MORBID) && ishuman(user)) var/mob/living/carbon/human/morbid_weirdo = user morbid_weirdo.add_mood_event("morbid_abominable_surgery_success", /datum/mood_event/morbid_abominable_surgery_success) diff --git a/code/modules/surgery/stomachpump.dm b/code/modules/surgery/stomachpump.dm index 47f25074c3ac..be298cfd45cf 100644 --- a/code/modules/surgery/stomachpump.dm +++ b/code/modules/surgery/stomachpump.dm @@ -35,7 +35,7 @@ name = "pump stomach (hand)" accept_hand = TRUE repeatable = TRUE - time = 20 + time = 2 SECONDS success_sound = 'sound/items/handling/surgery/organ2.ogg' /datum/surgery_step/stomach_pump/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) diff --git a/code/modules/surgery/surgery_step.dm b/code/modules/surgery/surgery_step.dm index b34de84da99c..672d29ad8257 100644 --- a/code/modules/surgery/surgery_step.dm +++ b/code/modules/surgery/surgery_step.dm @@ -9,7 +9,7 @@ var/implement_type = null //the current type of implement used. This has to be stored, as the actual typepath of the tool may not match the list type. var/accept_hand = FALSE //does the surgery step require an open hand? If true, ignores implements. Compatible with accept_any_item. var/accept_any_item = FALSE //does the surgery step accept any item? If true, ignores implements. Compatible with require_hand. - var/time = 10 //how long does the step take? + var/time = 1 SECONDS //how long does the step take? var/repeatable = FALSE //can this step be repeated? Make shure it isn't last step, or else the surgeon will be stuck in the loop var/list/chems_needed = list() //list of chems needed to complete the step. Even on success, the step will have no effect if there aren't the chems required in the mob. var/require_all_chems = TRUE //any on the list or all on the list? diff --git a/code/modules/transport/tram/tram_doors.dm b/code/modules/transport/tram/tram_doors.dm index 5f9024978038..17173e79cd9a 100644 --- a/code/modules/transport/tram/tram_doors.dm +++ b/code/modules/transport/tram/tram_doors.dm @@ -159,19 +159,14 @@ for(var/turf/checked_turf in locs) for(var/mob/living/future_pancake in checked_turf) future_pancake.visible_message(span_warning("[src] beeps angrily and closes on [future_pancake]!"), span_userdanger("[src] beeps angrily and closes on you!")) - SEND_SIGNAL(future_pancake, COMSIG_LIVING_DOORCRUSHED, src) + var/sig_return = SEND_SIGNAL(future_pancake, COMSIG_LIVING_DOORCRUSHED, src) + future_pancake.add_splatter_floor(loc) + log_combat(src, future_pancake, "crushed") + var/door_wounding = (sig_return & DOORCRUSH_NO_WOUND) ? CANT_WOUND : 10 + future_pancake.apply_damage(DOOR_CRUSH_DAMAGE * 2, BRUTE, BODY_ZONE_CHEST, wound_bonus = door_wounding, attacking_item = src) + future_pancake.Paralyze(2 SECONDS) if(ishuman(future_pancake)) future_pancake.emote("scream") - future_pancake.adjustBruteLoss(DOOR_CRUSH_DAMAGE * 2) - future_pancake.Paralyze(2 SECONDS) - - else //for simple_animals & borgs - future_pancake.adjustBruteLoss(DOOR_CRUSH_DAMAGE * 2) - var/turf/location = get_turf(src) - //add_blood doesn't work for borgs/xenos, but add_blood_floor does. - future_pancake.add_splatter_floor(location) - - log_combat(src, future_pancake, "crushed") for(var/obj/vehicle/sealed/mecha/mech in checked_turf) // Your fancy metal won't save you here! mech.take_damage(DOOR_CRUSH_DAMAGE) diff --git a/code/modules/unit_tests/crafting.dm b/code/modules/unit_tests/crafting.dm index d76926e2749e..ed4ee4f631c8 100644 --- a/code/modules/unit_tests/crafting.dm +++ b/code/modules/unit_tests/crafting.dm @@ -1,11 +1,3 @@ -/** - * The accepted discrepancy between the amount of material between an item when crafted and the same item when spawned - * so we don't have to be obnoxious about small portion of mats being lost for items that are processed in multiple other - * results (eg. a slab of meat being cut in three cutlets, and each cutlet can be used to craft different things) - * right now it's around 3 points per 100 units of a material. - */ -#define ACCEPTABLE_MATERIAL_DEVIATION 0.033 - /** * Check if a generic atom (because both mobs and the crafter machinery can do it) can potentially craft all recipes, * with the exact same types required in the recipe, and also compare the materials of crafted result with one of the same type @@ -153,35 +145,17 @@ if(result.custom_materials == copycat.custom_materials) delete_components(spawned_components) return - var/comparison_failed = TRUE - if(length(result.custom_materials) == length(copycat.custom_materials)) - comparison_failed = FALSE - for(var/mat in result.custom_materials) - var/enemy_amount = copycat.custom_materials[mat] - if(!enemy_amount) //break the loop early, we cannot perform a division by zero anyway - comparison_failed = TRUE - break - var/ratio_difference = abs((result.custom_materials[mat] / enemy_amount) - 1) - if(ratio_difference > ACCEPTABLE_MATERIAL_DEVIATION) - comparison_failed = TRUE - if(comparison_failed) - var/warning = "custom_materials of [result.type] when crafted and spawned don't match" - var/what_it_should_be = "null" + if(!result.compare_materials(copycat)) + var/warning = "custom_materials of [result.type] when crafted compared to just spawned don't match" + var/what_it_should_be = result.get_materials_english_list() //compose a text string containing the syntax and paths to use for editing the custom_materials var if(result.custom_materials) - what_it_should_be = "\[list(" - var/index = 1 - var/mats_len = length(result.custom_materials) - for(var/datum/material/mat as anything in result.custom_materials) - what_it_should_be += "[mat.type] = [result.custom_materials[mat]]" - if(index < mats_len) - what_it_should_be += ", " - index++ - what_it_should_be += ")\] (you can round values a bit)" + what_it_should_be += " (you can round values a bit)" TEST_FAIL("[warning]. custom_materials should be [what_it_should_be]. \ Otherwise set the requirements_mats_blacklist variable for [recipe] \ or remove the CRAFT_ENFORCE_MATERIALS_PARITY crafting flag from it") + delete_components(spawned_components) /** @@ -195,5 +169,3 @@ /datum/component/personal_crafting/unit_test ignored_flags = CRAFT_MUST_BE_LEARNED|CRAFT_ONE_PER_TURF|CRAFT_CHECK_DIRECTION|CRAFT_CHECK_DENSITY|CRAFT_ON_SOLID_GROUND|CRAFT_IGNORE_DO_AFTER - -#undef ACCEPTABLE_MATERIAL_DEVIATION diff --git a/code/modules/unit_tests/fish_unit_tests.dm b/code/modules/unit_tests/fish_unit_tests.dm index e70ef1a7eb65..7d9df1df417e 100644 --- a/code/modules/unit_tests/fish_unit_tests.dm +++ b/code/modules/unit_tests/fish_unit_tests.dm @@ -472,11 +472,11 @@ REMOVE_TRAIT(gourmet, TRAIT_FISH_EATER, TRAIT_FISH_TESTING) fish.attack(gourmet, gourmet) - TEST_ASSERT(gourmet.has_reagent(/datum/reagent/consumable/nutriment/protein), "Human doesn't have ingested protein after eating fish") - TEST_ASSERT(gourmet.has_reagent(/datum/reagent/blood), "Human doesn't have ingested blood after eating fish") + TEST_ASSERT(gourmet.has_reagent(/datum/reagent/consumable/nutriment/protein), "Human hasn't ingested protein when eating fish") + TEST_ASSERT(gourmet.has_reagent(/datum/reagent/blood), "Human hasn't ingested blood when eating fish") TEST_ASSERT(gourmet.has_reagent(/datum/reagent/fishdummy), "Human doesn't have the reagent from /datum/fish_trait/dummy after eating fish") - TEST_ASSERT_EQUAL(fish.status, FISH_DEAD, "The fish is not dead, despite having sustained enough damage that it should. health: [fish.health]") + TEST_ASSERT_EQUAL(fish.status, FISH_DEAD, "The fish is not dead, despite having sustained enough damage that it should. health: [PERCENT(fish.get_health_percentage())]%") var/obj/item/organ/stomach/belly = gourmet.get_organ_slot(ORGAN_SLOT_STOMACH) belly.reagents.clear_reagents() diff --git a/code/modules/unit_tests/focus_only_tests.dm b/code/modules/unit_tests/focus_only_tests.dm index bd2596e16d61..28caadc58ef5 100644 --- a/code/modules/unit_tests/focus_only_tests.dm +++ b/code/modules/unit_tests/focus_only_tests.dm @@ -59,3 +59,6 @@ /// Checks that foodtypes are the same for food whether it's spawned or crafted (with the exact required types) /datum/unit_test/focus_only/check_foodtypes + +///Checks that items have roughly the same materials whenever spawned via processing/microwaving/baking etc. or any other mean. +/datum/unit_test/focus_only/check_materials_when_processed diff --git a/code/modules/unit_tests/mob_damage.dm b/code/modules/unit_tests/mob_damage.dm index 6c8a2a19141b..1cc63466bc99 100644 --- a/code/modules/unit_tests/mob_damage.dm +++ b/code/modules/unit_tests/mob_damage.dm @@ -93,16 +93,20 @@ * * amount - the amount of damage to verify that the mob has * * included_types - Bitflag of damage types to check. */ -/datum/unit_test/mob_damage/proc/verify_damage(mob/living/testing_mob, amount, included_types = ALL) +/datum/unit_test/mob_damage/proc/verify_damage(mob/living/carbon/testing_mob, amount, included_types = ALL) if(included_types & TOXLOSS) TEST_ASSERT_EQUAL(testing_mob.getToxLoss(), amount, \ "[testing_mob] should have [amount] toxin damage, instead they have [testing_mob.getToxLoss()]!") if(included_types & BRUTELOSS) TEST_ASSERT_EQUAL(round(testing_mob.getBruteLoss(), 1), amount, \ - "[testing_mob] should have [amount] brute damage, instead they have [testing_mob.getBruteLoss()]!") + "(Testing getBruteLoss()) [testing_mob] should have [amount] brute damage, instead they have [testing_mob.getBruteLoss()]!") + TEST_ASSERT_EQUAL(round(testing_mob.getBruteLossForType(BODYTYPE_ORGANIC), 1), amount, \ + "(Testing getBruteLossForType(BODYTYPE_ORGANIC)) [testing_mob] should have [amount] brute damage, instead they have [testing_mob.getBruteLossForType(BODYTYPE_ORGANIC)]!") if(included_types & FIRELOSS) TEST_ASSERT_EQUAL(round(testing_mob.getFireLoss(), 1), amount, \ - "[testing_mob] should have [amount] burn damage, instead they have [testing_mob.getFireLoss()]!") + "(Testing getFireLoss()) [testing_mob] should have [amount] burn damage, instead they have [testing_mob.getFireLoss()]!") + TEST_ASSERT_EQUAL(round(testing_mob.getFireLossForType(BODYTYPE_ORGANIC), 1), amount, \ + "(Testing getFireLossForType(BODYTYPE_ORGANIC)) [testing_mob] should have [amount] burn damage, instead they have [testing_mob.getFireLossForType(BODYTYPE_ORGANIC)]!") if(included_types & OXYLOSS) TEST_ASSERT_EQUAL(testing_mob.getOxyLoss(), amount, \ "[testing_mob] should have [amount] oxy damage, instead they have [testing_mob.getOxyLoss()]!") @@ -124,7 +128,7 @@ * * bodytypes - the bodytypes of damage to apply * * forced - whether or not this is forced damage */ -/datum/unit_test/mob_damage/proc/apply_damage(mob/living/testing_mob, amount, expected = -amount, included_types = ALL, biotypes = ALL, bodytypes = ALL, forced = FALSE) +/datum/unit_test/mob_damage/proc/apply_damage(mob/living/carbon/testing_mob, amount, expected = -amount, included_types = ALL, biotypes = ALL, bodytypes = ALL, forced = FALSE) var/damage_returned if(included_types & TOXLOSS) damage_returned = testing_mob.adjustToxLoss(amount, updating_health = FALSE, forced = forced, required_biotype = biotypes) @@ -161,7 +165,7 @@ * * bodytypes - the bodytypes of damage to apply * * forced - whether or not this is forced damage */ -/datum/unit_test/mob_damage/proc/set_damage(mob/living/testing_mob, amount, expected = -amount, included_types = ALL, biotypes = ALL, bodytypes = ALL, forced = FALSE) +/datum/unit_test/mob_damage/proc/set_damage(mob/living/carbon/testing_mob, amount, expected = -amount, included_types = ALL, biotypes = ALL, bodytypes = ALL, forced = FALSE) var/damage_returned if(included_types & TOXLOSS) damage_returned = testing_mob.setToxLoss(amount, updating_health = FALSE, forced = forced, required_biotype = biotypes) @@ -469,7 +473,7 @@ * * expected - the expected return value of the damage procs, if it differs from the default of (amount * 4) * * included_types - Bitflag of damage types to check. */ -/datum/unit_test/mob_damage/animal/verify_damage(mob/living/testing_mob, amount, expected, included_types = ALL) +/datum/unit_test/mob_damage/animal/verify_damage(mob/living/carbon/testing_mob, amount, expected, included_types = ALL) if(included_types & TOXLOSS) TEST_ASSERT_EQUAL(testing_mob.getToxLoss(), 0, \ "[testing_mob] should have [0] toxin damage, instead they have [testing_mob.getToxLoss()]!") @@ -487,7 +491,7 @@ "[testing_mob] should have [amount] stamina damage, instead they have [testing_mob.getStaminaLoss()]!") return TRUE -/datum/unit_test/mob_damage/animal/test_sanity_simple(mob/living/test_mob) +/datum/unit_test/mob_damage/animal/test_sanity_simple(mob/living/carbon/test_mob) // check to see if basic mob damage works // Simple damage and healing @@ -518,7 +522,7 @@ if(!test_apply_damage(test_mob, amount = -35, expected = 0)) TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! overhealing was not applied correctly") -/datum/unit_test/mob_damage/animal/test_sanity_complex(mob/living/test_mob) +/datum/unit_test/mob_damage/animal/test_sanity_complex(mob/living/carbon/test_mob) // Heal up, so that errors from the previous tests we won't cause this one to fail test_mob.fully_heal(HEAL_DAMAGE) var/damage_returned diff --git a/code/modules/unit_tests/organs.dm b/code/modules/unit_tests/organs.dm index 6162bd43e5b0..f7c0b38f453c 100644 --- a/code/modules/unit_tests/organs.dm +++ b/code/modules/unit_tests/organs.dm @@ -83,6 +83,9 @@ "Mob level \"apply organ damage\" returned the wrong value for [slot_to_use] organ with default arguments.") TEST_ASSERT_EQUAL(dummy.get_organ_loss(slot_to_use), test_organ.maxHealth, \ "Mob level \"apply organ damage\" can exceed the [slot_to_use] organ's damage cap with default arguments.") + TEST_ASSERT_EQUAL(dummy.get_organ_loss(slot_to_use, required_organ_flag = test_organ.organ_flags), test_organ.maxHealth, \ + "(Testing get_organ_loss() with required_organ_flag = [test_organ.organ_flags]) \ + Mob level \"apply organ damage\" can exceed the [slot_to_use] organ's damage cap with default arguments.") dummy.fully_heal(HEAL_ORGANS) // Tests [mob/living/proc/set_organ_damage] @@ -97,6 +100,9 @@ "Mob level \"apply organ damage\" returned the wrong value for [slot_to_use] organ with a large maximum supplied.") TEST_ASSERT_EQUAL(dummy.get_organ_loss(slot_to_use), test_organ.maxHealth, \ "Mob level \"apply organ damage\" can exceed the [slot_to_use] organ's damage cap with a large maximum supplied.") + TEST_ASSERT_EQUAL(dummy.get_organ_loss(slot_to_use, required_organ_flag = test_organ.organ_flags), test_organ.maxHealth, \ + "(Testing get_organ_loss() with required_organ_flag = [test_organ.organ_flags]) \ + Mob level \"apply organ damage\" can exceed the [slot_to_use] organ's damage cap with a large maximum supplied.") dummy.fully_heal(HEAL_ORGANS) ///Allocate a human mob, give 'em a skillchip and a generic trauma, then see if it throws any error when the brain is removed. diff --git a/code/modules/unit_tests/unit_test.dm b/code/modules/unit_tests/unit_test.dm index 1ed5c73ed480..49ee85862bee 100644 --- a/code/modules/unit_tests/unit_test.dm +++ b/code/modules/unit_tests/unit_test.dm @@ -276,8 +276,10 @@ GLOBAL_VAR_INIT(focused_tests, focused_tests()) /obj/effect/bug_moving, //The abstract grown item expects a seed, but doesn't have one /obj/item/food/grown, - ///Single use case holder atom requiring a user + //Single use case holder atom requiring a user /atom/movable/looking_holder, + //Should not exist outside of holders + /obj/effect/decal/cleanable/blood/trail, ) // Everything that follows is a typesof() check. diff --git a/code/modules/unit_tests/washing.dm b/code/modules/unit_tests/washing.dm index c593b7dfc3b6..795c66d018f1 100644 --- a/code/modules/unit_tests/washing.dm +++ b/code/modules/unit_tests/washing.dm @@ -10,7 +10,7 @@ VAR_PRIVATE/clean_sig_caught = 0 /datum/unit_test/washing/Run() - for(var/i in subtypesof(/obj/effect/decal/cleanable) + cleanable_bonus_list) + for(var/i in subtypesof(/obj/effect/decal/cleanable) + cleanable_bonus_list - uncreatables) var/atom/movable/to_clean = allocate(i) var/mopable = HAS_TRAIT(to_clean, TRAIT_MOPABLE) diff --git a/code/modules/uplink/uplink_items/job.dm b/code/modules/uplink/uplink_items/job.dm index bdcef67d046b..c2dbf1a675e9 100644 --- a/code/modules/uplink/uplink_items/job.dm +++ b/code/modules/uplink/uplink_items/job.dm @@ -397,3 +397,10 @@ progression_minimum = 30 MINUTES purchasable_from = parent_type::purchasable_from & ~UPLINK_SPY +/datum/uplink_item/role_restricted/concussivedisk + name = "Hyperconcussive Diode Disk" + desc = "A diode configuration disk that allows an emitter to shoot potent explosive lasers. \ + Please note that this will halve the fire-rate of the emitter." + item = /obj/item/emitter_disk/blast + cost = 5 + restricted_roles = list(JOB_STATION_ENGINEER, JOB_CHIEF_ENGINEER) diff --git a/code/modules/uplink/uplink_items/nukeops.dm b/code/modules/uplink/uplink_items/nukeops.dm index 289cec43f1ec..2e4b17717808 100644 --- a/code/modules/uplink/uplink_items/nukeops.dm +++ b/code/modules/uplink/uplink_items/nukeops.dm @@ -498,18 +498,7 @@ item = /obj/item/storage/backpack/duffelbag/syndie/x4 cost = 10 // 50% discount! -/datum/uplink_item/explosives/military_grade/emp - name = "Syndicate EMP Bomb" - desc = "A variation of the syndicate bomb designed to produce a large EMP effect." - item = /obj/item/sbeacondrop/emp - cost = 6 - -/datum/uplink_item/explosives/syndicate_bomb/emp/New() - ..() - if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) - cost *= 2 - -/datum/uplink_item/explosives/syndicate_bomb +/datum/uplink_item/explosives/military_grade/syndicate_bomb name = "Syndicate Bomb" desc = "The Syndicate bomb is a fearsome device capable of massive destruction. It has an adjustable timer, \ with a minimum of %MIN_BOMB_TIMER seconds, and can be bolted to the floor with a wrench to prevent \ @@ -520,10 +509,21 @@ item = /obj/item/sbeacondrop/bomb cost = 8 -/datum/uplink_item/explosives/syndicate_bomb/New() +/datum/uplink_item/explosives/military_grade/syndicate_bomb/New() . = ..() desc = replacetext(desc, "%MIN_BOMB_TIMER", SYNDIEBOMB_MIN_TIMER_SECONDS) +/datum/uplink_item/explosives/military_grade/syndicate_bomb/emp + name = "Syndicate EMP Bomb" + desc = "A variation of the syndicate bomb designed to produce a large EMP effect." + item = /obj/item/sbeacondrop/emp + cost = 6 + +/datum/uplink_item/explosives/military_grade/syndicate_bomb/emp/New() + . = ..() + if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) + cost *= 2 + // Support (Borgs and Reinforcements) /datum/uplink_category/reinforcements diff --git a/code/modules/vehicles/cars/clowncar.dm b/code/modules/vehicles/cars/clowncar.dm index 6bfbc1bbae19..eeacfbc17760 100644 --- a/code/modules/vehicles/cars/clowncar.dm +++ b/code/modules/vehicles/cars/clowncar.dm @@ -17,7 +17,7 @@ ///list of headlight colors we use to pick through when we have party mode due to emag var/headlight_colors = list(COLOR_RED, COLOR_ORANGE, COLOR_YELLOW, COLOR_LIME, COLOR_BRIGHT_BLUE, COLOR_CYAN, COLOR_PURPLE) ///Cooldown time inbetween [/obj/vehicle/sealed/car/clowncar/proc/roll_the_dice()] usages - var/dice_cooldown_time = 150 + var/dice_cooldown_time = 15 SECONDS ///How many times kidnappers in the clown car said thanks var/thankscount = 0 ///Current status of the cannon, alternates between CLOWN_CANNON_INACTIVE, CLOWN_CANNON_BUSY and CLOWN_CANNON_READY diff --git a/code/modules/vehicles/lavaboat.dm b/code/modules/vehicles/lavaboat.dm index 3c9046b399ed..3a8d86879bc8 100644 --- a/code/modules/vehicles/lavaboat.dm +++ b/code/modules/vehicles/lavaboat.dm @@ -33,14 +33,14 @@ name = "Goliath Bone Oar" result = /obj/item/oar reqs = list(/obj/item/stack/sheet/bone = 2) - time = 15 + time = 1.5 SECONDS category = CAT_TOOLS /datum/crafting_recipe/boat name = "Goliath Hide Boat" result = /obj/vehicle/ridden/lavaboat reqs = list(/obj/item/stack/sheet/animalhide/goliath_hide = 3) - time = 50 + time = 5 SECONDS category = CAT_TOOLS /obj/vehicle/ridden/lavaboat/plasma diff --git a/code/modules/vehicles/mecha/combat/justice.dm b/code/modules/vehicles/mecha/combat/justice.dm deleted file mode 100644 index bf428ff7ed21..000000000000 --- a/code/modules/vehicles/mecha/combat/justice.dm +++ /dev/null @@ -1,768 +0,0 @@ -#define DISMEMBER_CHANCE_HIGH 50 -#define DISMEMBER_CHANCE_LOW 25 - -#define MOVEDELAY_IDLE 3 -#define MOVEDELAY_INVISIBILITY 2 -#define MOVEDELAY_PRE_CHARGE 4 - -/obj/vehicle/sealed/mecha/justice - name = "\improper Justice" - desc = "Black and red syndicate mech designed for execution orders. \ - For safety reasons, the syndicate advises against standing too close." - icon_state = "justice" - base_icon_state = "justice" - movedelay = MOVEDELAY_IDLE - max_integrity = 300 - accesses = list(ACCESS_SYNDICATE) - armor_type = /datum/armor/mecha_justice - max_temperature = 40000 - force = 60 // dangerous in melee - damtype = BRUTE - destruction_sleep_duration = 10 - exit_delay = 10 - wreckage = /obj/structure/mecha_wreckage/justice - mech_type = EXOSUIT_MODULE_JUSTICE - resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF - mecha_flags = ID_LOCK_ON | QUIET_STEPS | QUIET_TURNS | CAN_STRAFE | HAS_LIGHTS | MMI_COMPATIBLE | IS_ENCLOSED | AI_COMPATIBLE - destroy_wall_sound = 'sound/vehicles/mecha/mech_blade_break_wall.ogg' - brute_attack_sound = 'sound/vehicles/mecha/mech_blade_attack.ogg' - attack_verbs = list("cut", "cuts", "cutting") - weapons_safety = TRUE - safety_sound_custom = TRUE - max_equip_by_category = list( - MECHA_L_ARM = null, - MECHA_R_ARM = null, - MECHA_UTILITY = 3, - MECHA_POWER = 1, - MECHA_ARMOR = 2, - ) - step_energy_drain = 2 - allow_diagonal_movement = TRUE - /// What actions does justice execute? - var/justice_state = JUSTICE_IDLE - /// Refs to our engines - var/list/obj/justice_engines = list() - /// UI arrow which directs justice mech during charge - var/atom/movable/screen/justice_charge_arrow/charge_arrow - /// Track turf to where justice wanna charge while drag right mouse button - var/turf/turf_to_charge - /// Maximum range of charge attack. - var/max_charge_range = 7 - /// Is charge used or can be used. - var/charge_on_cooldown = FALSE - /// Remember strafe mode when we press right click to make charge attack. We need it to return strafe mode that was before we pressed right click button. - var/remember_strafe = FALSE - /// Sound when mech do charge attack. - var/charge_attack_sound = 'sound/vehicles/mecha/mech_charge_attack.ogg' - /// Aoe pre attack sound. - var/stealth_pre_attack_sound = 'sound/vehicles/mecha/mech_stealth_pre_attack.ogg' - /// Aoe attack sound. - var/stealth_attack_sound = 'sound/vehicles/mecha/mech_stealth_attack.ogg' - /// Sound plays when one of justice engine being succesful attacked. - var/engine_attacked_sound = 'sound/vehicles/mecha/justice_shield_broken.ogg' - /// Sound plays when justice lose all engines. - var/shields_disabled_sound = 'sound/vehicles/mecha/justice_warning.ogg' - /// Sound plays when justice pilot press right mouse button to prepare charge attack. - var/pre_charge_sound = 'sound/vehicles/mecha/justice_pre_charge.ogg' - -/datum/armor/mecha_justice - melee = 50 - bullet = 30 - laser = 30 - energy = 30 - fire = 100 - acid = 100 - -/obj/vehicle/sealed/mecha/justice/Initialize(mapload, built_manually) - . = ..() - RegisterSignal(src, COMSIG_MECHA_MELEE_CLICK, PROC_REF(justice_attack)) //We do not hit those who are in crit or stun. We are finishing them. - RegisterSignal(src, COMSIG_ATOM_PRE_BULLET_ACT, PROC_REF(on_ranged_hit)) - RegisterSignal(src, COMSIG_JUSTICE_INVISIBILITY_ACTIVATE, PROC_REF(visibility_active)) - RegisterSignal(src, COMSIG_JUSTICE_INVISIBILITY_DEACTIVATE, PROC_REF(visibility_deactive)) - transform = transform.Scale(1.04, 1.04) - for(var/i in 1 to 3) - addtimer(CALLBACK(src, PROC_REF(create_engine)), i * 1 SECONDS) - -/obj/vehicle/sealed/mecha/justice/generate_actions() - . = ..() - initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/invisibility) - -/obj/vehicle/sealed/mecha/justice/update_icon_state() - . = ..() - if(!LAZYLEN(occupants)) - return - icon_state = weapons_safety ? "[base_icon_state]" : "[base_icon_state]-angry" - if(!has_gravity()) - icon_state = "[icon_state]-fly" - -/obj/vehicle/sealed/mecha/justice/set_safety(mob/user) - . = ..() - - playsound(src, 'sound/vehicles/mecha/mech_blade_safty.ogg', 75, FALSE) //everyone need to hear this sound - - update_appearance(UPDATE_ICON_STATE) - -/obj/vehicle/sealed/mecha/justice/Move(newloc, dir) - if(HAS_TRAIT(src, TRAIT_IMMOBILIZED)) - return - . = ..() - update_appearance(UPDATE_ICON_STATE) - -/obj/vehicle/sealed/mecha/justice/mob_enter(mob/he_drive, silent) - . = ..() - if(!.) - return - if(!isliving(he_drive)) - return - if(!is_driver(he_drive)) - return - RegisterSignal(he_drive.canon_client, COMSIG_CLIENT_MOUSEDOWN, PROC_REF(driver_mousedown)) - activate_engines() - var/datum/hud/user_hud = he_drive.hud_used - if(!user_hud) - return - charge_arrow = new /atom/movable/screen/justice_charge_arrow(null, user_hud) - charge_arrow.screen_loc = around_player - charge_arrow.icon_state = charge_arrow.inactive_icon - user_hud.infodisplay += charge_arrow - user_hud.show_hud(user_hud.hud_version) - -/obj/vehicle/sealed/mecha/justice/mob_exit(mob/exiter, silent, randomstep, forced) - . = ..() - null_arrow(exiter.hud_used) - deactivate_engines() - UnregisterSignal(exiter.canon_client, COMSIG_CLIENT_MOUSEDOWN) - -/obj/vehicle/sealed/mecha/justice/Destroy() - if(LAZYLEN(justice_engines) < 1) - return ..() - for(var/obj/effect/justice_engine/justice_engine as anything in justice_engines) - QDEL_NULL(justice_engine) - return ..() - -/obj/vehicle/sealed/mecha/justice/proc/null_arrow(datum/hud/user_hud) - if(isnull(user_hud)) - return - user_hud.infodisplay -= charge_arrow - user_hud.show_hud(user_hud.hud_version) - -/obj/vehicle/sealed/mecha/justice/proc/driver_mousedown(client/source, atom/target, turf/location, control, params) - SIGNAL_HANDLER - - var/list/modifiers = params2list(params) - - if(!LAZYACCESS(modifiers, RIGHT_CLICK)) - return - if(charge_on_cooldown) - for(var/mob/mob_occupant as anything in occupants) - balloon_alert(mob_occupant, "on cooldown!") - return - if(!weapons_safety) - for(var/mob/mob_occupant as anything in occupants) - balloon_alert(mob_occupant, "katana is out of the sheath!") - return - - turf_to_charge = get_turf(target) - if(!isnull(turf_to_charge)) - var/rotate_dir = get_dir(src, turf_to_charge) - animate(charge_arrow, transform = matrix(dir2angle(rotate_dir), MATRIX_ROTATE), 0.2 SECONDS) - dir = rotate_dir - else - set_charge_mouse_pointer(TRUE) - charge_arrow.icon_state = charge_arrow.active_icon - justice_state = JUSTICE_CHARGE - movedelay = MOVEDELAY_PRE_CHARGE - remember_strafe = strafe - strafe = TRUE - set_charge_mouse_pointer() - playsound(src, pre_charge_sound, 75, FALSE) - SEND_SIGNAL(src, COMSIG_JUSTICE_CHARGE_BUTTON_DOWN) - RegisterSignal(source, COMSIG_CLIENT_MOUSEUP, PROC_REF(driver_mouseup)) - RegisterSignal(source, COMSIG_CLIENT_MOUSEDRAG, PROC_REF(driver_mousedrag)) - -/obj/vehicle/sealed/mecha/justice/proc/driver_mousedrag(client/source, atom/src_object, atom/over_object, turf/src_location, turf/over_location, src_control, over_control, params) - SIGNAL_HANDLER - - var/list/modifiers = params2list(params) - - if(!LAZYACCESS(modifiers, RIGHT_CLICK)) - return - - if(justice_state != JUSTICE_CHARGE) - return - - turf_to_charge = get_turf(over_object) - if(isnull(turf_to_charge)) - set_charge_mouse_pointer(TRUE) - return - set_charge_mouse_pointer() - var/rotate_dir = get_dir(src, turf_to_charge) - animate(charge_arrow, transform = matrix(dir2angle(rotate_dir), MATRIX_ROTATE), 0.2 SECONDS) - dir = rotate_dir - -/obj/vehicle/sealed/mecha/justice/proc/driver_mouseup(client/source, atom/target, turf/location, control, params) - SIGNAL_HANDLER - - var/list/modifiers = params2list(params) - - if(!LAZYACCESS(modifiers, RIGHT_CLICK)) - return - - charge_attack(turf_to_charge) - - UnregisterSignal(source, COMSIG_CLIENT_MOUSEUP) - UnregisterSignal(source, COMSIG_CLIENT_MOUSEDRAG) - charge_arrow.icon_state = charge_arrow.inactive_icon - strafe = remember_strafe - justice_state = JUSTICE_IDLE - movedelay = MOVEDELAY_IDLE - charge_on_cooldown = TRUE - for(var/mob/mob_occupant as anything in occupants) - set_safety(mob_occupant) - break - addtimer(CALLBACK(src, PROC_REF(charge_recharge)), 5 SECONDS) - set_charge_mouse_pointer() - -/obj/vehicle/sealed/mecha/justice/proc/charge_recharge() - charge_on_cooldown = FALSE - set_charge_mouse_pointer() - -/obj/vehicle/sealed/mecha/justice/proc/create_engine() - var/obj/effect/justice_engine/justice_engine = new /obj/effect/justice_engine(get_turf(src)) - justice_engine.transform *= 0.6 - justice_engine.orbit(src, 25, FALSE, 30) - justice_engine.change_engine_state(JUSTICE_ENGINE_DEACTIVE) - justice_engines.Add(justice_engine) - -/obj/vehicle/sealed/mecha/justice/proc/activate_engines() - if(LAZYLEN(justice_engines) < 1) - return - for(var/obj/effect/justice_engine/justice_engine as anything in justice_engines) - if(justice_engine.engine_state != JUSTICE_ENGINE_DEACTIVE) - continue - justice_engine.change_engine_state(JUSTICE_ENGINE_ACTIVATING) - addtimer(CALLBACK(src, PROC_REF(after_engine_activated), justice_engine), 0.4 SECONDS) - return null - -/obj/vehicle/sealed/mecha/justice/proc/after_engine_activated(obj/effect/justice_engine/justice_engine) - justice_engine.change_engine_state(justice_engine.remember_engine_state_on_deactivate) - -/obj/vehicle/sealed/mecha/justice/proc/deactivate_engines() - if(LAZYLEN(justice_engines) < 1) - return - for(var/obj/effect/justice_engine/justice_engine as anything in justice_engines) - justice_engine.remember_engine_state_on_deactivate = justice_engine.engine_state - if(justice_engine.engine_state == JUSTICE_ENGINE_DEACTIVE) - continue - justice_engine.change_engine_state(JUSTICE_ENGINE_DEACTIVATING) - addtimer(CALLBACK(src, PROC_REF(after_engine_deactivated), justice_engine), 0.4 SECONDS) - return null - -/obj/vehicle/sealed/mecha/justice/proc/after_engine_deactivated(obj/effect/justice_engine/justice_engine) - justice_engine.change_engine_state(JUSTICE_ENGINE_DEACTIVE) - -/obj/vehicle/sealed/mecha/justice/proc/get_engine_by_state(state) - if(LAZYLEN(justice_engines) < 1) - return - for(var/obj/effect/justice_engine/justice_engine as anything in justice_engines) - if(justice_engine.engine_state != state) - continue - return justice_engine - return null - -/obj/vehicle/sealed/mecha/justice/proc/justice_attack(datum/source, mob/living/pilot, atom/target, on_cooldown, is_adjacent) - SIGNAL_HANDLER - - if(justice_state == JUSTICE_INVISIBILITY) - stealth_attack_aoe(source, pilot, target, on_cooldown, is_adjacent) - return COMPONENT_CANCEL_MELEE_CLICK - - if(justice_state == JUSTICE_CHARGE) - return COMPONENT_CANCEL_MELEE_CLICK - - if(fatality_attack(source, pilot, target, on_cooldown, is_adjacent)) - return COMPONENT_CANCEL_MELEE_CLICK - - if(!iscarbon(target)) - return - var/mob/living/carbon/carbon_target = target - if(carbon_target.stat >= UNCONSCIOUS) - return - var/obj/effect/justice_engine/cooldown_engine = get_engine_by_state(JUSTICE_ENGINE_ONCOOLDOWN) - if(isnull(cooldown_engine)) - return - cooldown_engine.change_engine_state(JUSTICE_ENGINE_ACTIVE) - return - -/obj/vehicle/sealed/mecha/justice/proc/set_charge_mouse_pointer(disabled = FALSE) - if(justice_state != JUSTICE_CHARGE) - return set_mouse_pointer() - if(disabled) - mouse_pointer = 'icons/effects/mouse_pointers/justice_mouse_charge-disabled.dmi' - else - mouse_pointer = 'icons/effects/mouse_pointers/justice_mouse_charge.dmi' - - for(var/mob/mob_occupant as anything in occupants) - mob_occupant.update_mouse_pointer() - -/obj/vehicle/sealed/mecha/justice/set_mouse_pointer() - if(weapons_safety) - mouse_pointer = "" - else if(charge_on_cooldown) - mouse_pointer = 'icons/effects/mouse_pointers/justice_mouse_charge-cooldown.dmi' - else - if(equipment_disabled) - mouse_pointer = 'icons/effects/mouse_pointers/justice_mouse_charge-disabled.dmi' - else - mouse_pointer = 'icons/effects/mouse_pointers/justice_mouse.dmi' - - for(var/mob/mob_occupant as anything in occupants) - mob_occupant.update_mouse_pointer() - -/obj/vehicle/sealed/mecha/justice/hitby(atom/movable/throwed_by, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) - . = ..() - if(isitem(throwed_by)) - var/obj/item/throwed_by_item = throwed_by - if(throwed_by_item.throwforce < 10) /// don't counts 0-9 damage for such moments like throwforce from severed limbs and other unpleasant little things for which you would not want to lose a charge. - block_effect() - return - - var/obj/effect/justice_engine/active_engine = get_engine_by_state(JUSTICE_ENGINE_ACTIVE) - if(isnull(active_engine)) - return ..() - - active_engine.change_engine_state(JUSTICE_ENGINE_ONCOOLDOWN) - playsound(src, engine_attacked_sound , 75, FALSE) - after_engine_attacked() - -/obj/vehicle/sealed/mecha/justice/attacked_by(obj/item/attacking_item, mob/living/user) - if(attacking_item.force < 10) /// don't counts 0-9 damage for such moments like throwforce from severed limbs and other unpleasant little things for which you would not want to lose a charge. - block_effect() - return - - var/obj/effect/justice_engine/active_engine = get_engine_by_state(JUSTICE_ENGINE_ACTIVE) - if(isnull(active_engine)) - return ..() - - active_engine.change_engine_state(JUSTICE_ENGINE_ONCOOLDOWN) - playsound(src, engine_attacked_sound , 75, FALSE) - after_engine_attacked() - -/obj/vehicle/sealed/mecha/justice/emp_act(severity) - var/obj/effect/justice_engine/active_engine = get_engine_by_state(JUSTICE_ENGINE_ACTIVE) - if(isnull(active_engine)) - return ..() - - active_engine.change_engine_state(JUSTICE_ENGINE_ONCOOLDOWN) - playsound(src, engine_attacked_sound , 75, FALSE) - after_engine_attacked() - - return EMP_PROTECT_SELF - -/obj/vehicle/sealed/mecha/justice/proc/on_ranged_hit(obj/vehicle/sealed/mecha/source, obj/projectile/hitting_projectile) - SIGNAL_HANDLER - - var/obj/effect/justice_engine/active_engine = get_engine_by_state(JUSTICE_ENGINE_ACTIVE) - if(isnull(active_engine)) - return NONE - - var/deflect_angel = dir2angle(get_dir(src, hitting_projectile.firer)) - hitting_projectile.firer = src - hitting_projectile.set_angle(deflect_angel) - playsound(src, 'sound/vehicles/mecha/mech_blade_break_wall.ogg' , 75, FALSE) - return COMPONENT_BULLET_PIERCED - -/obj/vehicle/sealed/mecha/justice/proc/block_effect() - new /obj/effect/temp_visual/mech_sparks(get_turf(src)) - playsound(src, 'sound/vehicles/mecha/mech_stealth_effect.ogg' , 75, FALSE) - -/obj/vehicle/sealed/mecha/justice/proc/after_engine_attacked() - if(!isnull(get_engine_by_state(JUSTICE_ENGINE_ACTIVE))) - return - deactivate_engines() - for(var/mob/mob_occupant as anything in occupants) - balloon_alert(mob_occupant, "shields disabled! recharge after 10 seconds!") - addtimer(CALLBACK(src, PROC_REF(reactivate_engines)), 10 SECONDS) - playsound(src, shields_disabled_sound , 75, FALSE) - -/obj/vehicle/sealed/mecha/justice/proc/reactivate_engines() - for(var/obj/effect/justice_engine/justice_engine as anything in justice_engines) - justice_engine.remember_engine_state_on_deactivate = JUSTICE_ENGINE_ACTIVE - if(isnull(occupants)) - return - activate_engines() - -/obj/vehicle/sealed/mecha/justice/melee_attack_effect(mob/living/victim, heavy) - if(!heavy) - victim.Knockdown(4 SECONDS) - return - if(!prob(DISMEMBER_CHANCE_HIGH)) - return - var/obj/item/bodypart/cut_bodypart = victim.get_bodypart(pick(BODY_ZONE_R_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_ARM, BODY_ZONE_L_LEG)) - cut_bodypart?.dismember(BRUTE) - -/obj/vehicle/sealed/mecha/justice/proc/state_change(new_state) - if(new_state == justice_state) - return - if(new_state != JUSTICE_INVISIBILITY && LAZYLEN(justice_engines) > 0) - for(var/obj/effect/justice_engine/justice_engine as anything in justice_engines) - if(!justice_engine.is_in_invis) - continue - justice_engine.is_in_invis = FALSE - justice_engine.alpha = 255 - - if(new_state == JUSTICE_INVISIBILITY && LAZYLEN(justice_engines) > 0) - for(var/obj/effect/justice_engine/justice_engine as anything in justice_engines) - if(justice_engine.is_in_invis) - continue - justice_engine.is_in_invis = TRUE - justice_engine.alpha = 0 - - justice_state = new_state - -/obj/vehicle/sealed/mecha/justice/proc/visibility_active(obj/vehicle/sealed/mecha/source, datum/action/vehicle/sealed/mecha/invisibility/status_caller) - SIGNAL_HANDLER - - if(justice_state == JUSTICE_INVISIBILITY) - return COMPONENT_CANCEL_JUSTICE_INVISIBILITY_ACTIVATE - state_change(JUSTICE_INVISIBILITY) - movedelay = MOVEDELAY_INVISIBILITY - -/obj/vehicle/sealed/mecha/justice/proc/visibility_deactive(obj/vehicle/sealed/mecha/source, datum/action/vehicle/sealed/mecha/invisibility/status_caller) - SIGNAL_HANDLER - - if(justice_state == JUSTICE_IDLE) - return COMPONENT_CANCEL_JUSTICE_INVISIBILITY_DEACTIVATE - state_change(JUSTICE_IDLE) - movedelay = MOVEDELAY_IDLE - -/// Says 1 of 3 epic phrases before attacking and make a finishing blow to targets in stun or crit after 1 SECOND. -/obj/vehicle/sealed/mecha/justice/proc/fatality_attack(datum/source, mob/living/pilot, atom/target, on_cooldown, is_adjacent) - if(!ishuman(target)) - return FALSE - var/mob/living/carbon/human/live_or_dead = target - if(live_or_dead.stat < UNCONSCIOUS && live_or_dead.getStaminaLoss() < 100) - return FALSE - var/obj/item/bodypart/check_head = live_or_dead.get_bodypart(BODY_ZONE_HEAD) - if(!check_head) - return FALSE - INVOKE_ASYNC(src, PROC_REF(finish_him), src, pilot, live_or_dead) - return TRUE - -/** - * ## finish_him - * - * Target's head is cut off (if it has one) - * Attack from invisibility and charged attack have higher priority. - * Arguments: - * * finisher - Mech pilot who makes an attack. - * * him - Target at which the mech makes an attack. - */ -/obj/vehicle/sealed/mecha/justice/proc/finish_him(obj/vehicle/sealed/mecha/my_mech, mob/finisher, mob/living/him) - if(justice_state == JUSTICE_FATALITY) - return - justice_state = JUSTICE_FATALITY - say(pick("Take my Justice-Slash!", "A falling leaf...", "Justice is quite a lonely path"), forced = "Justice Mech") - playsound(src, 'sound/vehicles/mecha/mech_stealth_pre_attack.ogg', 75, FALSE) - if(!do_after(finisher, 1 SECONDS, him)) - justice_state = JUSTICE_IDLE - return - if(QDELETED(finisher) \ - || QDELETED(him) \ - || !LAZYLEN(my_mech?.occupants)) - justice_state = JUSTICE_IDLE - return - var/turf/finish_turf = get_step(him, get_dir(my_mech, him)) - var/turf/for_line_turf = get_turf(my_mech) - var/obj/item/bodypart/in_your_head = him.get_bodypart(BODY_ZONE_HEAD) - in_your_head?.dismember(BRUTE) - playsound(src, brute_attack_sound, 75, FALSE) - for_line_turf.Beam(src, icon_state = "mech_charge", time = 4) - forceMove(finish_turf) - justice_state = JUSTICE_IDLE - -/** - * Proc makes an AOE attack after 0.5 SECOND. - * Called by the mech pilot when he is in stealth mode and wants to attack. - * During this, mech cannot move. -*/ -/obj/vehicle/sealed/mecha/justice/proc/stealth_attack_aoe(datum/source, mob/living/pilot, atom/target, on_cooldown, is_adjacent) - if(justice_state == JUSTICE_INVISIBILITY_ATTACK) - return - justice_state = JUSTICE_INVISIBILITY_ATTACK - new /obj/effect/temp_visual/mech_attack_aoe_charge(get_turf(src)) - ADD_TRAIT(src, TRAIT_IMMOBILIZED, REF(src)) - playsound(src, stealth_pre_attack_sound, 75, FALSE) - addtimer(CALLBACK(src, PROC_REF(attack_in_aoe), pilot), 0.5 SECONDS) - return TRUE - -/** - * ## attack_in_aoe - * - * Brings mech out of invisibility. - * Deal everyone in range 3x3 35 damage and 25 chanse to cut off limb. - * Arguments: - * * pilot - occupant inside mech. - */ -/obj/vehicle/sealed/mecha/justice/proc/attack_in_aoe(mob/living/pilot) - new /obj/effect/temp_visual/mech_attack_aoe_attack(get_turf(src)) - for(var/mob/living/something_living in range(1, get_turf(src))) - if(something_living.stat >= UNCONSCIOUS \ - || something_living.getStaminaLoss() >= 100 \ - || something_living == pilot) - continue - if(prob(DISMEMBER_CHANCE_LOW)) - var/obj/item/bodypart/cut_bodypart = something_living.get_bodypart(pick(BODY_ZONE_R_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_ARM, BODY_ZONE_L_LEG)) - cut_bodypart?.dismember(BRUTE) - something_living.apply_damage(35, BRUTE) - playsound(src, stealth_attack_sound, 75, FALSE) - REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, REF(src)) - SEND_SIGNAL(src, COMSIG_JUSTICE_ATTACK_AOE) - justice_state = JUSTICE_IDLE - -/** - * ## charge_attack - * - * Deal everyone in line for mech location to mouse location 35 damage and 25 chanse to cut off limb. - * Teleport mech to the end of line. - * Arguments: - * * target - occupant inside mech. - */ -/obj/vehicle/sealed/mecha/justice/proc/charge_attack(atom/target) - var/turf/start_charge_here = get_turf(src) - var/turf/target_pos = get_turf(target) - var/turf/here_we_go = start_charge_here - for(var/turf/line_turf in get_line(start_charge_here, target_pos)) - if(floor(get_dist_euclidean(start_charge_here, line_turf)) > max_charge_range) - break - if(get_turf(src) == get_turf(line_turf)) - continue - if(isclosedturf(line_turf)) - break - var/obj/machinery/power/supermatter_crystal/funny_crystal = locate() in line_turf - if(funny_crystal) - funny_crystal.Bumped(src) - break - var/obj/machinery/door/airlock/like_a_wall = locate() in line_turf - if(like_a_wall?.density) - break - if(locate(/obj/structure/window) in line_turf) - break - for(var/mob/living/something_living in line_turf.contents) - if(something_living.stat >= UNCONSCIOUS \ - || something_living.getStaminaLoss() >= 100 \ - || is_driver(something_living) \ - || is_occupant(something_living)) - continue - if(prob(DISMEMBER_CHANCE_LOW)) - var/obj/item/bodypart/cut_bodypart = something_living.get_bodypart(pick(BODY_ZONE_R_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_ARM, BODY_ZONE_L_LEG, BODY_ZONE_HEAD)) - cut_bodypart?.dismember(BRUTE) - something_living.apply_damage(35, BRUTE) - here_we_go = line_turf - - // If the mech didn't move, it didn't charge - if(here_we_go == start_charge_here) - for(var/mob/occupant in occupants) - if(is_driver(occupant)) - balloon_alert(occupant, "invalid direction!") - return FALSE - - forceMove(here_we_go) - start_charge_here.Beam(src, icon_state = "mech_charge", time = 8) - playsound(src, charge_attack_sound, 75, FALSE) - use_energy(200) - return TRUE - -/datum/action/vehicle/sealed/mecha/invisibility - name = "Invisibility" - button_icon_state = "mech_stealth_off" - /// Is invisibility activated. - var/on = FALSE - /// Recharge check. - var/charge = TRUE - /// Energy cost to become invisibile - var/energy_cost = 200 - - -/datum/action/vehicle/sealed/mecha/invisibility/set_chassis(passed_chassis) - . = ..() - RegisterSignals(chassis, list(COMSIG_MECH_SAFETIES_TOGGLE, COMSIG_MECHA_MOB_EXIT, COMSIG_JUSTICE_ATTACK_AOE, COMSIG_JUSTICE_CHARGE_BUTTON_DOWN), PROC_REF(diactivate_invisibility_by_signal)) - -/datum/action/vehicle/sealed/mecha/invisibility/proc/diactivate_invisibility_by_signal() - SIGNAL_HANDLER - - make_visible() - build_all_button_icons(UPDATE_BUTTON_STATUS) - -/datum/action/vehicle/sealed/mecha/invisibility/Trigger(trigger_flags) - . = ..() - if(!.) - return - on = !on - if(on) - invisibility_on() - else - invisibility_off() - -/datum/action/vehicle/sealed/mecha/invisibility/IsAvailable(feedback) - . = ..() - if(!.) - return FALSE - if(!chassis.has_charge(energy_cost)) - if(feedback) - owner.balloon_alert(owner, "not enough energy!") - return FALSE - if(chassis.weapons_safety) - if(feedback) - owner.balloon_alert(owner, "safety is on!") - return FALSE - if(!charge) - if(feedback) - owner.balloon_alert(owner, "recharging!") - return FALSE - - return TRUE - -///Called when invisibility activated. -/datum/action/vehicle/sealed/mecha/invisibility/proc/invisibility_on() - if(SEND_SIGNAL(chassis, COMSIG_JUSTICE_INVISIBILITY_ACTIVATE, src) & COMPONENT_CANCEL_JUSTICE_INVISIBILITY_ACTIVATE) - return - new /obj/effect/temp_visual/mech_sparks(get_turf(chassis)) - playsound(chassis, 'sound/vehicles/mecha/mech_stealth_effect.ogg' , 75, FALSE) - animate(chassis, alpha = 0, time = 0.5 SECONDS) - button_icon_state = "mech_stealth_on" - RegisterSignal(chassis, COMSIG_MOVABLE_BUMP, PROC_REF(bumb_on)) - RegisterSignal(chassis, COMSIG_ATOM_BUMPED, PROC_REF(bumbed_on)) - RegisterSignal(chassis, COMSIG_ATOM_TAKE_DAMAGE, PROC_REF(take_damage)) - chassis.use_energy(energy_cost) - build_all_button_icons() - -///Called when invisibility deactivated. -/datum/action/vehicle/sealed/mecha/invisibility/proc/invisibility_off() - if(SEND_SIGNAL(chassis, COMSIG_JUSTICE_INVISIBILITY_DEACTIVATE, src) & COMPONENT_CANCEL_JUSTICE_INVISIBILITY_DEACTIVATE) - return - new /obj/effect/temp_visual/mech_sparks(get_turf(chassis)) - playsound(chassis, 'sound/vehicles/mecha/mech_stealth_effect.ogg' , 75, FALSE) - charge = FALSE - addtimer(CALLBACK(src, PROC_REF(charge)), 5 SECONDS) - button_icon_state = "mech_stealth_cooldown" - animate(chassis, alpha = 255, time = 0.5 SECONDS) - UnregisterSignal(chassis, list( - COMSIG_MOVABLE_BUMP, - COMSIG_ATOM_BUMPED, - COMSIG_ATOM_TAKE_DAMAGE - )) - build_all_button_icons() - -/** - * ## bumb_on - * - * Called when mech bumb on somthing. If is living somthing shutdown mech invisibility. - */ -/datum/action/vehicle/sealed/mecha/invisibility/proc/bumb_on(obj/vehicle/sealed/mecha/our_mech, atom/obstacle) - SIGNAL_HANDLER - - if(!iscarbon(obstacle)) - return - make_visible() - -/** - * ## bumbed_on - * - * Called when somthing bumbed on mech. If is living somthing shutdown mech invisibility. - */ -/datum/action/vehicle/sealed/mecha/invisibility/proc/bumbed_on(obj/vehicle/sealed/mecha/our_mech, atom/movable/bumped_atom) - SIGNAL_HANDLER - - if(!iscarbon(bumped_atom)) - return - make_visible() - -/** - * ## take_damage - * - * Called when mech take damage. Shutdown mech invisibility. - */ -/datum/action/vehicle/sealed/mecha/invisibility/proc/take_damage(obj/vehicle/sealed/mecha/our_mech) - SIGNAL_HANDLER - - make_visible() - -/** - * ## make_visible - * - * Called when somthing force invisibility shutdown. - */ -/datum/action/vehicle/sealed/mecha/invisibility/proc/make_visible() - if(!on) - return - on = !on - invisibility_off() - -/** - * ## charge - * - * Recharge invisibility action after 5 SECONDS. - */ -/datum/action/vehicle/sealed/mecha/invisibility/proc/charge() - button_icon_state = "mech_stealth_off" - charge = TRUE - build_all_button_icons() - -/obj/vehicle/sealed/mecha/justice/loaded - equip_by_category = list( - MECHA_L_ARM = null, - MECHA_R_ARM = null, - MECHA_UTILITY = list(/obj/item/mecha_parts/mecha_equipment/radio, /obj/item/mecha_parts/mecha_equipment/air_tank/full, /obj/item/mecha_parts/mecha_equipment/thrusters/ion), - MECHA_POWER = list(), - MECHA_ARMOR = list(), - ) - -/obj/vehicle/sealed/mecha/justice/loaded/populate_parts() - cell = new /obj/item/stock_parts/power_store/cell/bluespace(src) - scanmod = new /obj/item/stock_parts/scanning_module/triphasic(src) - capacitor = new /obj/item/stock_parts/capacitor/quadratic(src) - servo = new /obj/item/stock_parts/servo/femto(src) - update_part_values() - -/obj/effect/justice_engine - name = "engine core" - icon = 'icons/effects/effects.dmi' - icon_state = "justice_engine_deactive" - base_icon_state = "justice_engine" - layer = ABOVE_ALL_MOB_LAYER - plane = ABOVE_GAME_PLANE - /// We need to orbit around someone. - var/datum/weakref/owner - /// Switch engine state for future justice checks. - var/engine_state = JUSTICE_ENGINE_DEACTIVE - /// Remember if engine is on cooldown when we exit justice mech - var/remember_engine_state_on_deactivate = JUSTICE_ENGINE_ACTIVE - /// Check if engine in invis - var/is_in_invis = FALSE; - -/obj/effect/justice_engine/update_icon_state() - . = ..() - icon_state = "[base_icon_state]_[engine_state]" - -/obj/effect/justice_engine/proc/change_engine_state(new_state) - engine_state = new_state - update_appearance(UPDATE_ICON_STATE) - -/atom/movable/screen/justice_charge_arrow - icon = 'icons/effects/96x96.dmi' - name = "justice charge arrow" - icon_state = "justice_charge_arrow" - pixel_x = -32 - pixel_y = -32 - /// Icon when we drag right mouse button to choice turf to charge - var/active_icon = "justice_charge_arrow" - /// Idle charge arrow icon - var/inactive_icon = "" - -#undef DISMEMBER_CHANCE_HIGH -#undef DISMEMBER_CHANCE_LOW - -#undef MOVEDELAY_IDLE -#undef MOVEDELAY_INVISIBILITY -#undef MOVEDELAY_PRE_CHARGE diff --git a/code/modules/vehicles/mecha/combat/marauder.dm b/code/modules/vehicles/mecha/combat/marauder.dm index 4d7aca910dae..93d8fb2e2c50 100644 --- a/code/modules/vehicles/mecha/combat/marauder.dm +++ b/code/modules/vehicles/mecha/combat/marauder.dm @@ -58,7 +58,7 @@ name = "Smoke" button_icon_state = "mech_smoke" -/datum/action/vehicle/sealed/mecha/mech_smoke/Trigger(trigger_flags) +/datum/action/vehicle/sealed/mecha/mech_smoke/Trigger(mob/clicker, trigger_flags) if(!..()) return if(!chassis || !(owner in chassis.occupants)) @@ -72,7 +72,7 @@ name = "Zoom" button_icon_state = "mech_zoom_off" -/datum/action/vehicle/sealed/mecha/mech_zoom/Trigger(trigger_flags) +/datum/action/vehicle/sealed/mecha/mech_zoom/Trigger(mob/clicker, trigger_flags) if(!..()) return if(!owner.client || !chassis || !(owner in chassis.occupants)) diff --git a/code/modules/vehicles/mecha/combat/phazon.dm b/code/modules/vehicles/mecha/combat/phazon.dm index 1ff67996e792..30d15edfe179 100644 --- a/code/modules/vehicles/mecha/combat/phazon.dm +++ b/code/modules/vehicles/mecha/combat/phazon.dm @@ -41,7 +41,7 @@ name = "Reconfigure arm microtool arrays" button_icon_state = "mech_damtype_brute" -/datum/action/vehicle/sealed/mecha/mech_switch_damtype/Trigger(trigger_flags) +/datum/action/vehicle/sealed/mecha/mech_switch_damtype/Trigger(mob/clicker, trigger_flags) if(!..()) return if(!chassis || !(owner in chassis.occupants)) @@ -66,7 +66,7 @@ name = "Toggle Phasing" button_icon_state = "mech_phasing_off" -/datum/action/vehicle/sealed/mecha/mech_toggle_phasing/Trigger(trigger_flags) +/datum/action/vehicle/sealed/mecha/mech_toggle_phasing/Trigger(mob/clicker, trigger_flags) if(!..()) return if(!chassis || !(owner in chassis.occupants)) diff --git a/code/modules/vehicles/mecha/combat/savannah_ivanov.dm b/code/modules/vehicles/mecha/combat/savannah_ivanov.dm index a5496c77a069..15585e9caa5a 100644 --- a/code/modules/vehicles/mecha/combat/savannah_ivanov.dm +++ b/code/modules/vehicles/mecha/combat/savannah_ivanov.dm @@ -80,7 +80,7 @@ ///skyfall builds up in charges every 2 seconds, when it reaches 5 charges the ability actually starts var/skyfall_charge_level = 0 -/datum/action/vehicle/sealed/mecha/skyfall/Trigger(trigger_flags) +/datum/action/vehicle/sealed/mecha/skyfall/Trigger(mob/clicker, trigger_flags) if(!..()) return if(!owner || !chassis || !(owner in chassis.occupants)) @@ -252,7 +252,7 @@ end_missile_targeting() return ..() -/datum/action/vehicle/sealed/mecha/ivanov_strike/Trigger(trigger_flags) +/datum/action/vehicle/sealed/mecha/ivanov_strike/Trigger(mob/clicker, trigger_flags) if(!..()) return if(!chassis || !(owner in chassis.occupants)) diff --git a/code/modules/vehicles/mecha/equipment/tools/work_tools.dm b/code/modules/vehicles/mecha/equipment/tools/work_tools.dm index 8f1a1e704bd2..21831931296e 100644 --- a/code/modules/vehicles/mecha/equipment/tools/work_tools.dm +++ b/code/modules/vehicles/mecha/equipment/tools/work_tools.dm @@ -391,7 +391,7 @@ newmech.name = markone.name markone.wreckage = FALSE if(HAS_TRAIT(markone, TRAIT_MECHA_CREATED_NORMALLY)) - ADD_TRAIT(newmech, TRAIT_MECHA_CREATED_NORMALLY, newmech) + ADD_TRAIT(newmech, TRAIT_MECHA_CREATED_NORMALLY, REF(newmech)) qdel(markone) playsound(get_turf(newmech),'sound/items/tools/ratchet.ogg',50,TRUE) diff --git a/code/modules/vehicles/mecha/mech_fabricator.dm b/code/modules/vehicles/mecha/mech_fabricator.dm index 6292fed5e39f..c5318bc3cd64 100644 --- a/code/modules/vehicles/mecha/mech_fabricator.dm +++ b/code/modules/vehicles/mecha/mech_fabricator.dm @@ -53,9 +53,6 @@ /// Looping sound for printing items var/datum/looping_sound/lathe_print/print_sound - /// Local designs that only this mechfab have(using when mechfab emaged so it's illegal designs). - var/list/datum/design/illegal_local_designs - /// Direction the produced items will drop (0 means on top of us) var/drop_direction = SOUTH @@ -63,7 +60,6 @@ print_sound = new(src, FALSE) rmat = AddComponent(/datum/component/remote_materials, mapload && link_on_init) cached_designs = list() - illegal_local_designs = list() return ..() /obj/machinery/mecha_part_fabricator/Destroy() @@ -153,27 +149,6 @@ drop_direction = direction balloon_alert(user, "dropping [dir2text(drop_direction)]") -/obj/machinery/mecha_part_fabricator/emag_act(mob/user, obj/item/card/emag/emag_card) - if(obj_flags & EMAGGED) - return FALSE - if(!HAS_TRAIT(user, TRAIT_KNOW_ROBO_WIRES)) - to_chat(user, span_warning("You're unsure about [emag_card ? "where to swipe [emag_card] over" : "how to override"] [src] for any effect. Maybe if you had more knowledge of robotics...")) - - return FALSE - obj_flags |= EMAGGED - for(var/found_illegal_mech_nods in SSresearch.techweb_nodes) - var/datum/techweb_node/illegal_mech_node = SSresearch.techweb_nodes[found_illegal_mech_nods] - if(!illegal_mech_node?.illegal_mech_node) - continue - for(var/id in illegal_mech_node.design_ids) - var/datum/design/illegal_mech_design = SSresearch.techweb_design_by_id(id) - illegal_local_designs |= illegal_mech_design - cached_designs |= illegal_mech_design - say("R$c!i&ed ERROR de#i$ns. C@n%ec$%ng to ~NULL~ se%ve$s.") - playsound(src, 'sound/machines/uplink/uplinkerror.ogg', 50, TRUE) - update_static_data_for_all_viewers() - return TRUE - /** * Updates the `final_sets` and `buildable_parts` for the current mecha fabricator. */ @@ -187,9 +162,6 @@ if(design.build_type & MECHFAB) cached_designs |= design - for(var/datum/design/illegal_disign in illegal_local_designs) - cached_designs |= illegal_disign - var/design_delta = cached_designs.len - previous_design_count if(design_delta > 0) @@ -458,7 +430,7 @@ if(!istext(design_id)) continue - if(!(stored_research.researched_designs.Find(design_id) || is_type_in_list(SSresearch.techweb_design_by_id(design_id), illegal_local_designs))) + if(!stored_research.researched_designs.Find(design_id)) continue var/datum/design/design = SSresearch.techweb_design_by_id(design_id) diff --git a/code/modules/vehicles/mecha/mecha_actions.dm b/code/modules/vehicles/mecha/mecha_actions.dm index 7c85d047996a..47d4bc033367 100644 --- a/code/modules/vehicles/mecha/mecha_actions.dm +++ b/code/modules/vehicles/mecha/mecha_actions.dm @@ -23,7 +23,7 @@ name = "Eject From Mech" button_icon_state = "mech_eject" -/datum/action/vehicle/sealed/mecha/mech_eject/Trigger(trigger_flags) +/datum/action/vehicle/sealed/mecha/mech_eject/Trigger(mob/clicker, trigger_flags) if(!..()) return if(!chassis || !(owner in chassis.occupants)) @@ -35,7 +35,7 @@ button_icon_state = "mech_cabin_open" desc = "Airtight cabin preserves internal air and can be pressurized with a mounted air tank." -/datum/action/vehicle/sealed/mecha/mech_toggle_cabin_seal/Trigger(trigger_flags) +/datum/action/vehicle/sealed/mecha/mech_toggle_cabin_seal/Trigger(mob/clicker, trigger_flags) if(!..()) return if(!chassis || !(owner in chassis.occupants)) @@ -46,7 +46,7 @@ name = "Toggle Lights" button_icon_state = "mech_lights_off" -/datum/action/vehicle/sealed/mecha/mech_toggle_lights/Trigger(trigger_flags) +/datum/action/vehicle/sealed/mecha/mech_toggle_lights/Trigger(mob/clicker, trigger_flags) if(!..()) return if(!chassis || !(owner in chassis.occupants)) @@ -57,7 +57,7 @@ name = "View Stats" button_icon_state = "mech_view_stats" -/datum/action/vehicle/sealed/mecha/mech_view_stats/Trigger(trigger_flags) +/datum/action/vehicle/sealed/mecha/mech_view_stats/Trigger(mob/clicker, trigger_flags) if(!..()) return if(!chassis || !(owner in chassis.occupants)) @@ -73,7 +73,7 @@ . = ..() RegisterSignal(chassis, COMSIG_MECH_SAFETIES_TOGGLE, PROC_REF(update_action_icon)) -/datum/action/vehicle/sealed/mecha/mech_toggle_safeties/Trigger(trigger_flags) +/datum/action/vehicle/sealed/mecha/mech_toggle_safeties/Trigger(mob/clicker, trigger_flags) if(!..()) return if(!chassis || !(owner in chassis.occupants)) @@ -93,7 +93,7 @@ name = "Toggle Strafing. Disabled when Alt is held." button_icon_state = "strafe" -/datum/action/vehicle/sealed/mecha/strafe/Trigger(trigger_flags) +/datum/action/vehicle/sealed/mecha/strafe/Trigger(mob/clicker, trigger_flags) if(!..()) return if(!chassis || !(owner in chassis.occupants)) @@ -123,7 +123,7 @@ name = "Switch Seats" button_icon_state = "mech_seat_swap" -/datum/action/vehicle/sealed/mecha/swap_seat/Trigger(trigger_flags) +/datum/action/vehicle/sealed/mecha/swap_seat/Trigger(mob/clicker, trigger_flags) if(!..()) return if(!chassis || !(owner in chassis.occupants)) diff --git a/code/modules/vehicles/mecha/mecha_construction_paths.dm b/code/modules/vehicles/mecha/mecha_construction_paths.dm index 226b3e2107a4..35e394f5062a 100644 --- a/code/modules/vehicles/mecha/mecha_construction_paths.dm +++ b/code/modules/vehicles/mecha/mecha_construction_paths.dm @@ -35,7 +35,7 @@ content.forceMove(mech) mech.locate_parts() SSblackbox.record_feedback("tally", "mechas_created", 1, mech.name) - ADD_TRAIT(mech, TRAIT_MECHA_CREATED_NORMALLY, mech) + ADD_TRAIT(mech, TRAIT_MECHA_CREATED_NORMALLY, REF(mech)) QDEL_NULL(parent) // Default proc to generate mech steps. @@ -821,39 +821,3 @@ outer_plating = /obj/item/stack/sheet/plasteel outer_plating_amount = 5 - -//Justice -/datum/component/construction/unordered/mecha_chassis/justice - result = /datum/component/construction/mecha/justice - steps = list( - /obj/item/mecha_parts/part/justice_torso, - /obj/item/mecha_parts/part/justice_left_arm, - /obj/item/mecha_parts/part/justice_right_arm, - /obj/item/mecha_parts/part/justice_left_leg, - /obj/item/mecha_parts/part/justice_right_leg - ) - -/datum/component/construction/mecha/justice - result = /obj/vehicle/sealed/mecha/justice - base_icon = "justice" - - inner_plating = /obj/item/stack/telecrystal - inner_plating_amount = 8 - - outer_plating = /obj/item/mecha_parts/part/justice_armor - outer_plating_amount = 1 - -/datum/component/construction/mecha/justice/get_circuit_steps() - return list() - -/datum/component/construction/mecha/justice/get_inner_plating_steps() - return list( - list( - "key" = inner_plating, - "amount" = inner_plating_amount, - "back_key" = TOOL_SCREWDRIVER, - "desc" = "The power cell is secured, and [inner_plating_amount] telecrystals can be added.", - "forward_message" = "added telecrystal", - "backward_message" = "unsecured power cell" - ) - ) diff --git a/code/modules/vehicles/mecha/mecha_parts.dm b/code/modules/vehicles/mecha/mecha_parts.dm index 427347bff513..57a3f6c04133 100644 --- a/code/modules/vehicles/mecha/mecha_parts.dm +++ b/code/modules/vehicles/mecha/mecha_parts.dm @@ -333,42 +333,6 @@ desc="Savannah-Ivanov armor plates. They are uniquely shaped and reinforced to deal with the stresses of two pilots, grandiose leaps, and missiles." icon_state = "savannah_ivanov_armor" -// Justice - -/obj/item/mecha_parts/chassis/justice - name = "\improper Justice chassis" - construct_type = /datum/component/construction/unordered/mecha_chassis/justice - -/obj/item/mecha_parts/part/justice_torso - name="\improper Justice torso" - desc="A Justice torso part." - icon_state = "justice_torso" - -/obj/item/mecha_parts/part/justice_left_arm - name="\improper Justice left arm" - desc="A Justice left arm." - icon_state = "justice_l_arm" - -/obj/item/mecha_parts/part/justice_right_arm - name="\improper Justice right arm" - desc="A Justice left arm." - icon_state = "justice_r_arm" - -/obj/item/mecha_parts/part/justice_left_leg - name="\improper Justice left leg" - desc="A Justice left leg." - icon_state = "justice_l_leg" - -/obj/item/mecha_parts/part/justice_right_leg - name="\improper Justice right leg" - desc="A Justice left leg." - icon_state = "justice_r_leg" - -/obj/item/mecha_parts/part/justice_armor - name="Justice armor" - desc="Justice armor plates." - icon_state = "justice_armor" - ///////// Circuitboards /obj/item/circuitboard/mecha diff --git a/code/modules/vehicles/mecha/mecha_wreckage.dm b/code/modules/vehicles/mecha/mecha_wreckage.dm index 8f972ef47815..dc0414e86063 100644 --- a/code/modules/vehicles/mecha/mecha_wreckage.dm +++ b/code/modules/vehicles/mecha/mecha_wreckage.dm @@ -245,8 +245,3 @@ /obj/item/mecha_parts/part/odysseus_right_arm, /obj/item/mecha_parts/part/odysseus_left_leg, /obj/item/mecha_parts/part/odysseus_right_leg) - -/obj/structure/mecha_wreckage/justice - name = "\improper Justice wreckage" - icon_state = "justice-broken" - welder_salvage = list(/obj/item/stack/sheet/iron, /obj/item/stack/rods) diff --git a/code/modules/vehicles/mecha/working/clarke.dm b/code/modules/vehicles/mecha/working/clarke.dm index 834ac17b5cf6..95b920aa047e 100644 --- a/code/modules/vehicles/mecha/working/clarke.dm +++ b/code/modules/vehicles/mecha/working/clarke.dm @@ -120,7 +120,7 @@ button_icon = 'icons/obj/devices/mecha_equipment.dmi' button_icon_state = "mecha_sleeper_miner" -/datum/action/vehicle/sealed/mecha/clarke_scoop_body/Trigger(trigger_flags) +/datum/action/vehicle/sealed/mecha/clarke_scoop_body/Trigger(mob/clicker, trigger_flags) if(!..()) return var/obj/item/mecha_parts/mecha_equipment/sleeper/clarke/sleeper = locate() in chassis @@ -139,7 +139,7 @@ button_icon_state = "mech_search_ruins" COOLDOWN_DECLARE(search_cooldown) -/datum/action/vehicle/sealed/mecha/mech_search_ruins/Trigger(trigger_flags) +/datum/action/vehicle/sealed/mecha/mech_search_ruins/Trigger(mob/clicker, trigger_flags) if(!..()) return if(!chassis || !(owner in chassis.occupants)) diff --git a/code/modules/vehicles/vehicle_actions.dm b/code/modules/vehicles/vehicle_actions.dm index 63d9dff013fe..0463ac7bfa75 100644 --- a/code/modules/vehicles/vehicle_actions.dm +++ b/code/modules/vehicles/vehicle_actions.dm @@ -209,7 +209,7 @@ desc = "Climb out of your vehicle!" button_icon_state = "car_eject" -/datum/action/vehicle/sealed/climb_out/Trigger(trigger_flags) +/datum/action/vehicle/sealed/climb_out/Trigger(mob/clicker, trigger_flags) if(..() && istype(vehicle_entered_target)) vehicle_entered_target.mob_try_exit(owner, owner) @@ -221,7 +221,7 @@ desc = "Take your key out of the vehicle's ignition." button_icon_state = "car_removekey" -/datum/action/vehicle/sealed/remove_key/Trigger(trigger_flags) +/datum/action/vehicle/sealed/remove_key/Trigger(mob/clicker, trigger_flags) vehicle_entered_target.remove_key(owner) //CLOWN CAR ACTION DATUMS @@ -231,7 +231,7 @@ button_icon_state = "car_horn" var/hornsound = 'sound/items/carhorn.ogg' -/datum/action/vehicle/sealed/horn/Trigger(trigger_flags) +/datum/action/vehicle/sealed/horn/Trigger(mob/clicker, trigger_flags) if(TIMER_COOLDOWN_RUNNING(src, COOLDOWN_CAR_HONK)) return TIMER_COOLDOWN_START(src, COOLDOWN_CAR_HONK, 2 SECONDS) @@ -247,7 +247,7 @@ desc = "Turn on your brights!" button_icon_state = "car_headlights" -/datum/action/vehicle/sealed/headlights/Trigger(trigger_flags) +/datum/action/vehicle/sealed/headlights/Trigger(mob/clicker, trigger_flags) to_chat(owner, span_notice("You flip the switch for the vehicle's headlights.")) vehicle_entered_target.headlights_toggle = !vehicle_entered_target.headlights_toggle vehicle_entered_target.set_light_on(vehicle_entered_target.headlights_toggle) @@ -259,7 +259,7 @@ desc = "Dump all objects and people in your car on the floor." button_icon_state = "car_dump" -/datum/action/vehicle/sealed/dump_kidnapped_mobs/Trigger(trigger_flags) +/datum/action/vehicle/sealed/dump_kidnapped_mobs/Trigger(mob/clicker, trigger_flags) vehicle_entered_target.visible_message(span_danger("[vehicle_entered_target] starts dumping the people inside of it.")) vehicle_entered_target.dump_specific_mobs(VEHICLE_CONTROL_KIDNAPPED) @@ -269,7 +269,7 @@ desc = "Press one of those colorful buttons on your display panel!" button_icon_state = "car_rtd" -/datum/action/vehicle/sealed/roll_the_dice/Trigger(trigger_flags) +/datum/action/vehicle/sealed/roll_the_dice/Trigger(mob/clicker, trigger_flags) if(!istype(vehicle_entered_target, /obj/vehicle/sealed/car/clowncar)) return var/obj/vehicle/sealed/car/clowncar/C = vehicle_entered_target @@ -280,7 +280,7 @@ desc = "Destroy them with their own fodder!" button_icon_state = "car_cannon" -/datum/action/vehicle/sealed/cannon/Trigger(trigger_flags) +/datum/action/vehicle/sealed/cannon/Trigger(mob/clicker, trigger_flags) if(!istype(vehicle_entered_target, /obj/vehicle/sealed/car/clowncar)) return var/obj/vehicle/sealed/car/clowncar/C = vehicle_entered_target @@ -294,7 +294,7 @@ COOLDOWN_DECLARE(thank_time_cooldown) -/datum/action/vehicle/sealed/thank/Trigger(trigger_flags) +/datum/action/vehicle/sealed/thank/Trigger(mob/clicker, trigger_flags) if(!istype(vehicle_entered_target, /obj/vehicle/sealed/car/clowncar)) return if(!COOLDOWN_FINISHED(src, thank_time_cooldown)) @@ -317,7 +317,7 @@ check_flags = AB_CHECK_CONSCIOUS|AB_CHECK_INCAPACITATED var/bell_cooldown -/datum/action/vehicle/ridden/wheelchair/bell/Trigger(trigger_flags) +/datum/action/vehicle/ridden/wheelchair/bell/Trigger(mob/clicker, trigger_flags) if(TIMER_COOLDOWN_RUNNING(src, bell_cooldown)) return TIMER_COOLDOWN_START(src, bell_cooldown, 0.5 SECONDS) @@ -330,7 +330,7 @@ button_icon_state = "skateboard_ollie" check_flags = AB_CHECK_CONSCIOUS -/datum/action/vehicle/ridden/scooter/skateboard/ollie/Trigger(trigger_flags) +/datum/action/vehicle/ridden/scooter/skateboard/ollie/Trigger(mob/clicker, trigger_flags) . = ..() if(!.) return @@ -375,7 +375,7 @@ button_icon_state = "skateboard_ollie" check_flags = AB_CHECK_CONSCIOUS -/datum/action/vehicle/ridden/scooter/skateboard/kickflip/Trigger(trigger_flags) +/datum/action/vehicle/ridden/scooter/skateboard/kickflip/Trigger(mob/clicker, trigger_flags) var/obj/vehicle/ridden/scooter/skateboard/board = vehicle_target var/mob/living/rider = owner @@ -424,7 +424,7 @@ var/sound_path = 'sound/items/carhorn.ogg' var/sound_message = "makes a sound." -/datum/action/vehicle/sealed/noise/Trigger(trigger_flags) +/datum/action/vehicle/sealed/noise/Trigger(mob/clicker, trigger_flags) var/obj/vehicle/sealed/car/vim/vim_mecha = vehicle_entered_target if(!COOLDOWN_FINISHED(vim_mecha, sound_cooldown)) vim_mecha.balloon_alert(owner, "on cooldown!") @@ -441,7 +441,7 @@ sound_path = 'sound/machines/chime.ogg' sound_message = "chimes!" -/datum/action/vehicle/sealed/noise/chime/Trigger(trigger_flags) +/datum/action/vehicle/sealed/noise/chime/Trigger(mob/clicker, trigger_flags) if(..()) SEND_SIGNAL(vehicle_entered_target, COMSIG_VIM_CHIME_USED) @@ -452,13 +452,13 @@ sound_path = 'sound/machines/buzz/buzz-sigh.ogg' sound_message = "buzzes." -/datum/action/vehicle/sealed/noise/buzz/Trigger(trigger_flags) +/datum/action/vehicle/sealed/noise/buzz/Trigger(mob/clicker, trigger_flags) if(..()) SEND_SIGNAL(vehicle_entered_target, COMSIG_VIM_BUZZ_USED) /datum/action/vehicle/sealed/headlights/vim button_icon_state = "vim_headlights" -/datum/action/vehicle/sealed/headlights/vim/Trigger(trigger_flags) +/datum/action/vehicle/sealed/headlights/vim/Trigger(mob/clicker, trigger_flags) . = ..() SEND_SIGNAL(vehicle_entered_target, COMSIG_VIM_HEADLIGHTS_TOGGLED, vehicle_entered_target.headlights_toggle) diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm deleted file mode 100644 index d0ca0642d5f9..000000000000 --- a/code/modules/vending/_vending.dm +++ /dev/null @@ -1,1922 +0,0 @@ -/* - * Vending machine types - Can be found under /code/modules/vending/ - */ - -/* - -/obj/machinery/vending/[vendors name here] // --vending machine template :) - name = "" - desc = "" - icon = '' - icon_state = "" - products = list() - contraband = list() - premium = list() -*/ - -/// List of vending machines that players can restock, so only vending machines that are on station or don't have a unique condition. -GLOBAL_LIST_EMPTY(vending_machines_to_restock) - -/// Maximum amount of items in a storage bag that we're transferring items to the vendor from. -#define MAX_VENDING_INPUT_AMOUNT 30 -#define CREDITS_DUMP_THRESHOLD 50 -/** - * # vending record datum - * - * A datum that represents a product that is vendable - */ -/datum/data/vending_product - name = "generic" - ///Typepath of the product that is created when this record "sells" - var/product_path = null - ///How many of this product we currently have - var/amount = 0 - ///How many we can store at maximum - var/max_amount = 0 - ///The price of the item - var/price - ///Whether spessmen with an ID with an age below AGE_MINOR (20 by default) can buy this item - var/age_restricted = FALSE - ///Whether the product can be recolored by the GAGS system - var/colorable - /// The category the product was in, if any. - /// Sourced directly from product_categories. - var/category - ///List of items that have been returned to the vending machine. - var/list/returned_products - -/** - * # vending machines - * - * Captalism in the year 2525, everything in a vending machine, even love - */ -/obj/machinery/vending - name = "\improper Vendomat" - desc = "A generic vending machine." - icon = 'icons/obj/machines/vending.dmi' - icon_state = "generic" - layer = BELOW_OBJ_LAYER - density = TRUE - verb_say = "beeps" - verb_ask = "beeps" - verb_exclaim = "beeps" - max_integrity = 300 - integrity_failure = 0.33 - armor_type = /datum/armor/machinery_vending - circuit = /obj/item/circuitboard/machine/vendor - payment_department = ACCOUNT_SRV - light_power = 0.7 - light_range = MINIMUM_USEFUL_LIGHT_RANGE - voice_filter = "alimiter=0.9,acompressor=threshold=0.2:ratio=20:attack=10:release=50:makeup=2,highpass=f=1000" - - /// Is the machine active (No sales pitches if off)! - var/active = 1 - ///Are we ready to vend?? Is it time?? - var/vend_ready = TRUE - ///Next world time to send a purchase message - var/purchase_message_cooldown - ///The ref of the last mob to shop with us - var/last_shopper - ///Whether the vendor is tilted or not - var/tilted = FALSE - /// If tilted, this variable should always be the rotation that was applied when we were tilted. Stored for the purposes of unapplying it. - var/tilted_rotation = 0 - ///Whether this vendor can be tilted over or not - var/tiltable = TRUE - ///Damage this vendor does when tilting onto an atom - var/squish_damage = 75 - /// The chance, in percent, of this vendor performing a critical hit on anything it crushes via [tilt]. - var/crit_chance = 15 - /// If set to a critical define in crushing.dm, anything this vendor crushes will always be hit with that effect. - var/forcecrit = null - ///Number of glass shards the vendor creates and tries to embed into an atom it tilted onto - var/num_shards = 7 - ///List of mobs stuck under the vendor - var/list/pinned_mobs = list() - ///Icon for the maintenance panel overlay - var/panel_type = "panel1" - - /** - * List of products this machine sells - * - * form should be list(/type/path = amount, /type/path2 = amount2) - */ - var/list/products = list() - - /** - * List of products this machine sells, categorized. - * Can only be used as an alternative to `products`, not alongside it. - * - * Form should be list( - * "name" = "Category Name", - * "icon" = "UI Icon (Font Awesome or tgfont)", - * "products" = list(/type/path = amount, ...), - * ) - */ - var/list/product_categories = null - - /** - * List of products this machine sells when you hack it - * - * form should be list(/type/path = amount, /type/path2 = amount2) - */ - var/list/contraband = list() - - /** - * List of premium products this machine sells - * - * form should be list(/type/path = amount, /type/path2 = amount2) - */ - var/list/premium = list() - - ///String of slogans separated by semicolons, optional - var/product_slogans = "" - ///String of small ad messages in the vending screen - random chance - var/product_ads = "" - - ///List of standard product records - var/list/product_records = list() - ///List of contraband product records - var/list/hidden_records = list() - ///List of premium product records - var/list/coin_records = list() - ///List of slogans to scream at potential customers; built upon Iniitialize() of the vendor from product_slogans - var/list/slogan_list = list() - ///Message sent post vend (Thank you for shopping!) - var/vend_reply - ///Last world tick we sent a vent reply - var/last_reply = 0 - ///Last world tick we sent a slogan message out - var/last_slogan = 0 - ///How many ticks until we can send another - var/slogan_delay = 10 MINUTES - ///Icon when vending an item to the user - var/icon_vend - ///Icon to flash when user is denied a vend - var/icon_deny - ///World ticks the machine is electified for - var/seconds_electrified = MACHINE_NOT_ELECTRIFIED - ///When this is TRUE, we fire items at customers! We're broken! - var/shoot_inventory = FALSE - ///How likely this is to happen (prob 100) per second - var/shoot_inventory_chance = 1 - //Stop spouting those godawful pitches! - var/shut_up = FALSE - ///can we access the hidden inventory? - var/extended_inventory = FALSE - ///Are we checking the users ID - var/scan_id = TRUE - ///Coins that we accept? - var/obj/item/coin/coin - ///Bills we accept? - var/obj/item/stack/spacecash/bill - ///Default price of items if not overridden - var/default_price = 25 - ///Default price of premium items if not overridden - var/extra_price = 50 - ///fontawesome icon name to use in to display the user's balance in the vendor UI - var/displayed_currency_icon = "coins" - ///String of the used currency to display in the vendor UI - var/displayed_currency_name = " cr" - ///Whether our age check is currently functional - var/age_restrictions = TRUE - /// How many credits does this vending machine have? 20% of all sales go to this pool, and are given freely when the machine is restocked, or successfully tilted. Lost on deconstruction. - var/credits_contained = 0 - /** - * Is this item on station or not - * - * if it doesn't originate from off-station during mapload, all_products_free gets automatically set to TRUE if it was unset previously. - * if it's off-station during mapload, it's also safe from the brand intelligence event - */ - var/onstation = TRUE - /** - * DO NOT APPLY THIS GLOBALLY. For mapping var edits only. - * A variable to change on a per instance basis that allows the instance to avoid having onstation set for them during mapload. - * Setting this to TRUE means that the vending machine is treated as if it were still onstation if it spawns off-station during mapload. - * Useful to specify an off-station machine that will be affected by machine-brand intelligence for whatever reason. - */ - var/onstation_override = FALSE - /** - * If this is set to TRUE, all products sold by the vending machine are free (cost nothing). - * If unset, this will get automatically set to TRUE during init if the machine originates from off-station during mapload. - * Defaults to null, set it to TRUE or FALSE explicitly on a per-machine basis if you want to force it to be a certain value. - */ - var/all_products_free - - ///Items that the players have loaded into the vendor - var/list/vending_machine_input = list() - - //The type of refill canisters used by this machine. - var/obj/item/vending_refill/refill_canister = null - - /// how many items have been inserted in a vendor - var/loaded_items = 0 - - ///Name of lighting mask for the vending machine - var/light_mask - - //the path of the fish_source datum to use for the fishing_spot component - var/fish_source_path = /datum/fish_source/vending - -/datum/armor/machinery_vending - melee = 20 - fire = 50 - acid = 70 - -/** - * Initialize the vending machine - * - * Builds the vending machine inventory, sets up slogans and other such misc work - * - * This also sets the onstation var to: - * * FALSE - if the machine was maploaded on a zlevel that doesn't pass the is_station_level check - * * TRUE - all other cases - */ -/obj/machinery/vending/Initialize(mapload) - var/build_inv = FALSE - if(!refill_canister) - circuit = null - build_inv = TRUE - . = ..() - set_wires(new /datum/wires/vending(src)) - - if(SStts.tts_enabled) - var/static/vendor_voice_by_type = list() - if(!vendor_voice_by_type[type]) - vendor_voice_by_type[type] = pick(SStts.available_speakers) - voice = vendor_voice_by_type[type] - - if(build_inv) //non-constructable vending machine - ///Non-constructible vending machines do not have a refill canister to populate its products list from, - ///Which apparently is still needed in the case we use product categories instead. - if(product_categories) - for(var/list/category as anything in product_categories) - products |= category["products"] - build_inventories() - - slogan_list = splittext(product_slogans, ";") - // So not all machines speak at the exact same time. - // The first time this machine says something will be at slogantime + this random value, - // so if slogantime is 10 minutes, it will say it at somewhere between 10 and 20 minutes after the machine is crated. - last_slogan = world.time + rand(0, slogan_delay) - power_change() - - if(mapload) //check if it was initially created off station during mapload. - if(!is_station_level(z)) - if(!onstation_override) - onstation = FALSE - if(isnull(all_products_free)) // Only auto-set the free products var if we haven't explicitly assigned a value to it yet. - all_products_free = TRUE - if(circuit) - circuit.all_products_free = all_products_free //sync up the circuit so the pricing schema is carried over if it's reconstructed. - - else if(circuit) - all_products_free = circuit.all_products_free //if it was constructed outside mapload, sync the vendor up with the circuit's var so you can't bypass price requirements by moving / reconstructing it off station. - if(!all_products_free) - AddComponent(/datum/component/payment, 0, SSeconomy.get_dep_account(payment_department), PAYMENT_VENDING) - GLOB.vending_machines_to_restock += src //We need to keep track of the final onstation vending machines so we can keep them restocked. - register_context() - - if(fish_source_path) - AddComponent(/datum/component/fishing_spot, fish_source_path) - -/obj/machinery/vending/Destroy() - QDEL_NULL(coin) - QDEL_NULL(bill) - GLOB.vending_machines_to_restock -= src - return ..() - -/obj/machinery/vending/vv_edit_var(vname, vval) - . = ..() - if (vname == NAMEOF(src, all_products_free)) - if (all_products_free) - qdel(GetComponent(/datum/component/payment)) - GLOB.vending_machines_to_restock -= src - else - AddComponent(/datum/component/payment, 0, SSeconomy.get_dep_account(payment_department), PAYMENT_VENDING) - GLOB.vending_machines_to_restock += src - -/obj/machinery/vending/can_speak(allow_mimes) - return is_operational && !shut_up && ..() - -/obj/machinery/vending/emp_act(severity) - . = ..() - var/datum/language_holder/vending_languages = get_language_holder() - var/datum/wires/vending/vending_wires = wires - // if the language wire got pulsed during an EMP, this will make sure the language_iterator is synched correctly - vending_languages.selected_language = vending_languages.spoken_languages[vending_wires.language_iterator] - -//Better would be to make constructable child -/obj/machinery/vending/RefreshParts() - SHOULD_CALL_PARENT(FALSE) - if(!component_parts) - return - - build_products_from_categories() - - product_records = list() - hidden_records = list() - coin_records = list() - - build_inventories(start_empty = TRUE) - - for(var/obj/item/vending_refill/installed_refill in component_parts) - restock(installed_refill) - -/obj/machinery/vending/on_deconstruction(disassembled) - if(refill_canister) - return ..() - new /obj/item/stack/sheet/iron(loc, 3) - -/obj/machinery/vending/update_appearance(updates=ALL) - . = ..() - if(machine_stat & BROKEN) - set_light(0) - return - set_light(powered() ? MINIMUM_USEFUL_LIGHT_RANGE : 0) - -/obj/machinery/vending/update_icon_state() - if(machine_stat & BROKEN) - icon_state = "[initial(icon_state)]-broken" - return ..() - icon_state = "[initial(icon_state)][powered() ? null : "-off"]" - return ..() - -/obj/machinery/vending/update_overlays() - . = ..() - if(panel_open) - . += panel_type - if(light_mask && !(machine_stat & BROKEN) && powered()) - . += emissive_appearance(icon, light_mask, src) - -/obj/machinery/vending/examine(mob/user) - . = ..() - if(isnull(refill_canister)) - return // you can add the comment here instead - if(total_max_stock()) - if(total_loaded_stock() < total_max_stock()) - . += span_notice("\The [src] can be restocked with [span_boldnotice("\a [initial(refill_canister.machine_name)] [initial(refill_canister.name)]")] with the panel open.") - else - . += span_notice("\The [src] is fully stocked.") - if(credits_contained < CREDITS_DUMP_THRESHOLD && credits_contained > 0) - . += span_notice("It should have a handfull of credits stored based on the missing items.") - else if (credits_contained > PAYCHECK_CREW) - . += span_notice("It should have at least a full paycheck worth of credits inside!") - /** - * Intentionally leaving out a case for zero credits as it should be covered by the vending machine's stock being full, - * or covered by first case if items were returned. - */ - - -/obj/machinery/vending/atom_break(damage_flag) - . = ..() - if(!.) - return - - var/dump_amount = 0 - var/found_anything = TRUE - while (found_anything) - found_anything = FALSE - for(var/datum/data/vending_product/record as anything in shuffle(product_records)) - //first dump any of the items that have been returned, in case they contain the nuke disk or something - for(var/i in 1 to LAZYLEN(record.returned_products)) - var/obj/item/returned_obj_to_dump = dispense(record, get_turf(src), dispense_returned = TRUE) - step(returned_obj_to_dump, pick(GLOB.alldirs)) - - if(record.amount <= 0) //Try to use a record that actually has something to dump. - continue - var/dump_path = record.product_path - if(!dump_path) - continue - // busting open a vendor will destroy some of the contents - if(found_anything && prob(80)) - record.amount-- - continue - - var/obj/obj_to_dump = dispense(record, loc) - step(obj_to_dump, pick(GLOB.alldirs)) - found_anything = TRUE - dump_amount++ - if (dump_amount >= 16) - return - -/** - * Build the inventory of the vending machine from its product and record lists - * - * This builds up a full set of /datum/data/vending_products from the product list of the vending machine type - * Arguments: - * * productlist - the list of products that need to be converted - * * recordlist - the list containing /datum/data/vending_product datums - * * categories - A list in the format of product_categories to source category from - * * startempty - should we set vending_product record amount from the product list (so it's prefilled at roundstart) - * * premium - Whether the ending products shall have premium or default prices - */ -/obj/machinery/vending/proc/build_inventory(list/productlist, list/recordlist, list/categories, start_empty = FALSE, premium = FALSE) - var/inflation_value = HAS_TRAIT(SSeconomy, TRAIT_MARKET_CRASHING) ? SSeconomy.inflation_value() : 1 - default_price = round(initial(default_price) * inflation_value) - extra_price = round(initial(extra_price) * inflation_value) - - var/list/product_to_category = list() - for (var/list/category as anything in categories) - var/list/products = category["products"] - for (var/product_key in products) - product_to_category[product_key] = category - - for(var/typepath in productlist) - var/amount = productlist[typepath] - if(isnull(amount)) - amount = 0 - - var/obj/item/temp = typepath - var/datum/data/vending_product/new_record = new /datum/data/vending_product() - new_record.name = initial(temp.name) - new_record.product_path = typepath - if(!start_empty) - new_record.amount = amount - new_record.max_amount = amount - - ///Prices of vending machines are all increased uniformly. - var/custom_price = round(initial(temp.custom_price) * inflation_value) - if(!premium) - new_record.price = custom_price || default_price - else - var/premium_custom_price = round(initial(temp.custom_premium_price) * inflation_value) - if(!premium_custom_price && custom_price) //For some ungodly reason, some premium only items only have a custom_price - new_record.price = extra_price + custom_price - else - new_record.price = premium_custom_price || extra_price - - new_record.age_restricted = initial(temp.age_restricted) - new_record.colorable = !!(initial(temp.greyscale_config) && initial(temp.greyscale_colors) && (initial(temp.flags_1) & IS_PLAYER_COLORABLE_1)) - new_record.category = product_to_category[typepath] - recordlist += new_record - -/**Builds all available inventories for the vendor - standard, contraband and premium - * Arguments: - * start_empty - bool to pass into build_inventory that determines whether a product entry starts with available stock or not -*/ -/obj/machinery/vending/proc/build_inventories(start_empty) - build_inventory(products, product_records, product_categories, start_empty) - build_inventory(contraband, hidden_records, create_categories_from("Contraband", "mask", contraband), start_empty, premium = TRUE) - build_inventory(premium, coin_records, create_categories_from("Premium", "coins", premium), start_empty, premium = TRUE) - -/** - * Returns a list of data about the category - * Arguments: - * name - string for the name of the category - * icon - string for the fontawesome icon to use in the UI for the category - * products - list of products available in the category -*/ -/obj/machinery/vending/proc/create_categories_from(name, icon, products) - return list(list( - "name" = name, - "icon" = icon, - "products" = products, - )) - -///Populates list of products with categorized products -/obj/machinery/vending/proc/build_products_from_categories() - if (isnull(product_categories)) - return - - products = list() - - for (var/list/category in product_categories) - var/list/category_products = category["products"] - for (var/product_key in category_products) - products[product_key] += category_products[product_key] - -/** - * Reassign the prices of the vending machine as a result of the inflation value, as provided by SSeconomy - * - * This rebuilds both /datum/data/vending_products lists for premium and standard products based on their most relevant pricing values. - * Arguments: - * * recordlist - the list of standard product datums in the vendor to refresh their prices. - * * premiumlist - the list of premium product datums in the vendor to refresh their prices. - */ -/obj/machinery/vending/proc/reset_prices(list/recordlist, list/premiumlist) - var/inflation_value = HAS_TRAIT(SSeconomy, TRAIT_MARKET_CRASHING) ? SSeconomy.inflation_value() : 1 - default_price = round(initial(default_price) * inflation_value) - extra_price = round(initial(extra_price) * inflation_value) - - for(var/datum/data/vending_product/record as anything in recordlist) - var/obj/item/potential_product = record.product_path - var/custom_price = round(initial(potential_product.custom_price) * inflation_value) - record.price = custom_price | default_price - for(var/datum/data/vending_product/premium_record as anything in premiumlist) - var/obj/item/potential_product = premium_record.product_path - var/premium_custom_price = round(initial(potential_product.custom_premium_price) * inflation_value) - var/custom_price = initial(potential_product.custom_price) - if(!premium_custom_price && custom_price) //For some ungodly reason, some premium only items only have a custom_price - premium_record.price = extra_price + round(custom_price * inflation_value) - else - premium_record.price = premium_custom_price || extra_price - -/** - * Refill a vending machine from a refill canister - * - * This takes the products from the refill canister and then fills the products, contraband and premium product categories - * - * Arguments: - * * canister - the vending canister we are refilling from - */ -/obj/machinery/vending/proc/restock(obj/item/vending_refill/canister) - if (!canister.products) - canister.products = products.Copy() - if (!canister.contraband) - canister.contraband = contraband.Copy() - if (!canister.premium) - canister.premium = premium.Copy() - - . = 0 - - if (isnull(canister.product_categories) && !isnull(product_categories)) - canister.product_categories = product_categories.Copy() - - if (!isnull(canister.product_categories)) - var/list/products_unwrapped = list() - for (var/list/category as anything in canister.product_categories) - var/list/products = category["products"] - for (var/product_key in products) - products_unwrapped[product_key] += products[product_key] - - . += refill_inventory(products_unwrapped, product_records) - else - . += refill_inventory(canister.products, product_records) - - . += refill_inventory(canister.contraband, hidden_records) - . += refill_inventory(canister.premium, coin_records) - - return . - -/** - * After-effects of refilling a vending machine from a refill canister - * - * This takes the amount of products restocked and gives the user our contained credits if needed, - * sending the user a fitting message. - * - * Arguments: - * * user - the user restocking us - * * restocked - the amount of items we've been refilled with - */ -/obj/machinery/vending/proc/post_restock(mob/living/user, restocked) - if(!restocked) - to_chat(user, span_warning("There's nothing to restock!")) - return - - to_chat(user, span_notice("You loaded [restocked] items in [src][credits_contained > 0 ? ", and are rewarded [credits_contained] credits." : "."]")) - var/datum/bank_account/cargo_account = SSeconomy.get_dep_account(ACCOUNT_CAR) - cargo_account.adjust_money(round(credits_contained * 0.5), "Vending: Restock") - var/obj/item/holochip/payday = new(src, credits_contained) - try_put_in_hand(payday, user) - credits_contained = 0 - -/** - * Refill our inventory from the passed in product list into the record list - * - * Arguments: - * * productlist - list of types -> amount - * * recordlist - existing record datums - */ -/obj/machinery/vending/proc/refill_inventory(list/productlist, list/recordlist) - . = 0 - for(var/datum/data/vending_product/record as anything in recordlist) - var/diff = min(record.max_amount - record.amount, productlist[record.product_path]) - if (diff) - productlist[record.product_path] -= diff - record.amount += diff - . += diff - -/** - * Set up a refill canister that matches this machine's products - * - * This is used when the machine is deconstructed, so the items aren't "lost" - */ -/obj/machinery/vending/proc/update_canister() - if (!component_parts) - return - - var/obj/item/vending_refill/installed_refill = locate() in component_parts - if (!installed_refill) - CRASH("Constructible vending machine did not have a refill canister") - - unbuild_inventory_into(product_records, installed_refill.products, installed_refill.product_categories) - - installed_refill.contraband = unbuild_inventory(hidden_records) - installed_refill.premium = unbuild_inventory(coin_records) - -/** - * Given a record list, go through and return a list of products in format of type -> amount - * Arguments: - * recordlist - list of records to unbuild products from - */ -/obj/machinery/vending/proc/unbuild_inventory(list/recordlist) - . = list() - for(var/datum/data/vending_product/record as anything in recordlist) - .[record.product_path] += record.amount - -/** - * Unbuild product_records into categorized product lists to the machine's refill canister. - * Does not handle contraband/premium products, only standard stock and any other categories used by the vendor(see: ClothesMate). - * If a product has no category, puts it into standard stock category. - * Arguments: - * product_records - list of products of the vendor - * products - list of products of the refill canister - * product_categories - list of product categories of the refill canister -*/ -/obj/machinery/vending/proc/unbuild_inventory_into(list/product_records, list/products, list/product_categories) - products?.Cut() - product_categories?.Cut() - - var/others_have_category = null - - var/list/categories_to_index = list() - - for (var/datum/data/vending_product/record as anything in product_records) - var/list/category = record.category - var/has_category = !isnull(category) - //check if there're any uncategorized products - if (isnull(others_have_category)) - others_have_category = has_category - else if (others_have_category != has_category) - if (has_category) - WARNING("[record.product_path] in [type] has a category, but other products don't") - else - WARNING("[record.product_path] in [type] does not have a category, but other products do") - - continue - - if (has_category) - var/index = categories_to_index.Find(category) - - if (index) //if we've already established a category, add the product there - var/list/category_in_list = product_categories[index] - var/list/products_in_category = category_in_list["products"] - products_in_category[record.product_path] += record.amount - else //create a category that the product is supposed to have and put it there - categories_to_index += list(category) - index = categories_to_index.len - - var/list/category_clone = category.Copy() - - var/list/initial_product_list = list() - initial_product_list[record.product_path] = record.amount - category_clone["products"] = initial_product_list - - product_categories += list(category_clone) - else //no category found - dump it into standard stock - products[record.product_path] = record.amount - -/** - * Returns the total amount of items in the vending machine based on the product records and premium records, but not contraband - */ -/obj/machinery/vending/proc/total_loaded_stock() - var/total = 0 - for(var/datum/data/vending_product/record as anything in product_records + coin_records) - total += record.amount - return total - -/** - * Returns the total amount of items in the vending machine based on the product records and premium records, but not contraband - */ -/obj/machinery/vending/proc/total_max_stock() - var/total_max = 0 - for(var/datum/data/vending_product/record as anything in product_records + coin_records) - total_max += record.max_amount - return total_max - -/obj/machinery/vending/crowbar_act(mob/living/user, obj/item/attack_item) - if(!component_parts) - return FALSE - default_deconstruction_crowbar(attack_item) - return TRUE - -/obj/machinery/vending/wrench_act(mob/living/user, obj/item/tool) - . = ..() - if(!panel_open) - return FALSE - if(default_unfasten_wrench(user, tool, time = 6 SECONDS)) - unbuckle_all_mobs(TRUE) - return ITEM_INTERACT_SUCCESS - return FALSE - -/obj/machinery/vending/screwdriver_act(mob/living/user, obj/item/attack_item) - if(..()) - return TRUE - if(anchored) - default_deconstruction_screwdriver(user, icon_state, icon_state, attack_item) - update_appearance() - else - to_chat(user, span_warning("You must first secure [src].")) - return TRUE - -/obj/machinery/vending/attackby(obj/item/attack_item, mob/living/user, list/modifiers, list/attack_modifiers) - if(panel_open && is_wire_tool(attack_item)) - wires.interact(user) - return - - if(refill_canister && istype(attack_item, refill_canister)) - if (!panel_open) - to_chat(user, span_warning("You should probably unscrew the service panel first!")) - else if (machine_stat & (BROKEN|NOPOWER)) - to_chat(user, span_notice("[src] does not respond.")) - else - //if the panel is open we attempt to refill the machine - var/obj/item/vending_refill/canister = attack_item - if(canister.get_part_rating() == 0) - to_chat(user, span_warning("[canister] is empty!")) - else - // instantiate canister if needed - var/restocked = restock(canister) - post_restock(user, restocked) - return - - if(compartmentLoadAccessCheck(user) && !user.combat_mode) - if(canLoadItem(attack_item)) - loadingAttempt(attack_item, user) - - if(istype(attack_item, /obj/item/storage/bag)) //trays USUALLY - var/obj/item/storage/storage_item = attack_item - var/loaded = 0 - var/denied_items = 0 - for(var/obj/item/the_item in storage_item.contents) - if(contents.len >= MAX_VENDING_INPUT_AMOUNT) // no more than 30 item can fit inside, legacy from snack vending although not sure why it exists - to_chat(user, span_warning("[src]'s compartment is full.")) - break - if(canLoadItem(the_item) && loadingAttempt(the_item, user)) - storage_item.atom_storage?.attempt_remove(the_item, src) - loaded++ - else - denied_items++ - if(denied_items) - to_chat(user, span_warning("[src] refuses some items!")) - if(loaded) - to_chat(user, span_notice("You insert [loaded] dishes into [src]'s compartment.")) - else - . = ..() - if(tiltable && !tilted && attack_item.force) - if(isclosedturf(get_turf(user))) //If the attacker is inside of a wall, immediately fall in the other direction, with no chance for goodies. - var/opposite_direction = REVERSE_DIR(get_dir(src, user)) - var/target = get_step(src, opposite_direction) - tilt(get_turf(target)) - return - switch(rand(1, 100)) - if(1 to 5) - freebie(3) - if(6 to 15) - freebie(2) - if(16 to 25) - freebie(1) - if(26 to 75) - return - if(76 to 100) - tilt(user) - -/** - * Dispenses free items from the standard stock. - * Arguments: - * freebies - number of free items to vend - */ -/obj/machinery/vending/proc/freebie(freebies) - visible_message(span_notice("[src] yields [freebies > 1 ? "several free goodies" : "a free goody"][credits_contained > 0 ? " and some credits" : ""]!")) - - for(var/i in 1 to freebies) - playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3) - for(var/datum/data/vending_product/record in shuffle(product_records)) - - if(record.amount <= 0) //Try to use a record that actually has something to dump. - continue - // Always give out new stuff that costs before free returned stuff, because of the risk getting gibbed involved - var/only_returned_left = (record.amount <= LAZYLEN(record.returned_products)) - dispense(record, get_turf(src), silent = TRUE, dispense_returned = only_returned_left) - break - deploy_credits() - -/** - * Tilts ontop of the atom supplied, if crit is true some extra shit can happen. See [fall_and_crush] for return values. - * Arguments: - * fatty - atom to tilt the vendor onto - * local_crit_chance - percent chance of a critical hit - * forced_crit - specific critical hit case to use, if any - * range - the range of the machine when thrown if not adjacent -*/ -/obj/machinery/vending/proc/tilt(atom/fatty, local_crit_chance = crit_chance, forced_crit = forcecrit, range = 1) - if(QDELETED(src) || !has_gravity(src)) - return - - . = NONE - - var/picked_rotation = pick(90, 270) - if(Adjacent(fatty)) - . = fall_and_crush(get_turf(fatty), squish_damage, local_crit_chance, forced_crit, 6 SECONDS, rotation = picked_rotation) - - if (. & SUCCESSFULLY_FELL_OVER) - visible_message(span_danger("[src] tips over!")) - tilted = TRUE - tilted_rotation = picked_rotation - layer = ABOVE_MOB_LAYER - - if(get_turf(fatty) != get_turf(src)) - throw_at(get_turf(fatty), range, 1, spin = FALSE, quickstart = FALSE) - -/** - * Causes src to fall onto [target], crushing everything on it (including itself) with [damage] - * and a small chance to do a spectacular effect per entity (if a chance above 0 is provided). - * - * Args: - * * turf/target: The turf to fall onto. Cannot be null. - * * damage: The raw numerical damage to do by default. - * * chance_to_crit: The percent chance of a critical hit occurring. Default: 0 - * * forced_crit_case: If given a value from crushing.dm, [target] and its contents will always be hit with that specific critical hit. Default: null - * * paralyze_time: The time, in deciseconds, a given mob/living will be paralyzed for if crushed. - * * crush_dir: The direction the crush is coming from. Default: dir of src to [target]. - * * damage_type: The type of damage to do. Default: BRUTE - * * damage_flag: The attack flag for armor purposes. Default: MELEE - * * rotation: The angle of which to rotate src's transform by on a successful tilt. Default: 90. - * - * Returns: A collection of bitflags defined in crushing.dm. Read that file's documentation for info. - */ -/atom/movable/proc/fall_and_crush(turf/target, damage, chance_to_crit = 0, forced_crit_case = null, paralyze_time, crush_dir = get_dir(get_turf(src), target), damage_type = BRUTE, damage_flag = MELEE, rotation = 90) - - ASSERT(!isnull(target)) - - var/flags_to_return = NONE - - if (!target.is_blocked_turf(TRUE, src, list(src))) - for(var/atom/atom_target in (target.contents) + target) - if (isarea(atom_target)) - continue - - if (SEND_SIGNAL(atom_target, COMSIG_PRE_TILT_AND_CRUSH, src) & COMPONENT_IMMUNE_TO_TILT_AND_CRUSH) - continue - - var/crit_case = forced_crit_case - if (isnull(crit_case) && chance_to_crit > 0) - if (prob(chance_to_crit)) - crit_case = pick_weight(get_crit_crush_chances()) - var/crit_rebate_mult = 1 // lessen the normal damage we deal for some of the crits - - if (!isnull(crit_case)) - crit_rebate_mult = fall_and_crush_crit_rebate_table(crit_case) - apply_crit_crush(crit_case, atom_target) - - var/adjusted_damage = damage * crit_rebate_mult - var/crushed - if (isliving(atom_target)) - crushed = TRUE - var/mob/living/carbon/living_target = atom_target - var/was_alive = (living_target.stat != DEAD) - var/blocked = living_target.run_armor_check(attack_flag = damage_flag) - if (iscarbon(living_target)) - var/mob/living/carbon/carbon_target = living_target - if(prob(30)) - carbon_target.apply_damage(max(0, adjusted_damage), damage_type, blocked = blocked, forced = TRUE, spread_damage = TRUE, attack_direction = crush_dir) // the 30% chance to spread the damage means you escape breaking any bones - else - var/brute = (damage_type == BRUTE ? damage : 0) * 0.5 - var/burn = (damage_type == BURN ? damage : 0) * 0.5 - carbon_target.take_bodypart_damage(brute, burn, check_armor = TRUE, wound_bonus = 5) // otherwise, deal it to 2 random limbs (or the same one) which will likely shatter something - carbon_target.take_bodypart_damage(brute, burn, check_armor = TRUE, wound_bonus = 5) - carbon_target.AddElement(/datum/element/squish, 80 SECONDS) - else - living_target.apply_damage(adjusted_damage, damage_type, blocked = blocked, forced = TRUE, attack_direction = crush_dir) - - living_target.Paralyze(paralyze_time) - living_target.emote("scream") - playsound(living_target, 'sound/effects/blob/blobattack.ogg', 40, TRUE) - playsound(living_target, 'sound/effects/splat.ogg', 50, TRUE) - post_crush_living(living_target, was_alive) - flags_to_return |= (SUCCESSFULLY_CRUSHED_MOB|SUCCESSFULLY_CRUSHED_ATOM) - - else if(check_atom_crushable(atom_target)) - atom_target.take_damage(adjusted_damage, damage_type, damage_flag, FALSE, crush_dir) - crushed = TRUE - flags_to_return |= SUCCESSFULLY_CRUSHED_ATOM - - if (crushed) - atom_target.visible_message(span_danger("[atom_target] is crushed by [src]!"), span_userdanger("You are crushed by [src]!")) - SEND_SIGNAL(atom_target, COMSIG_POST_TILT_AND_CRUSH, src) - - var/matrix/to_turn = turn(transform, rotation) - animate(src, transform = to_turn, 0.2 SECONDS) - playsound(src, 'sound/effects/bang.ogg', 40) - - visible_message(span_danger("[src] tips over, slamming hard onto [target]!")) - flags_to_return |= SUCCESSFULLY_FELL_OVER - post_tilt() - else - visible_message(span_danger("[src] rebounds comically as it fails to slam onto [target]!")) - - Move(target, crush_dir) // we still TRY to move onto it for shit like teleporters - return flags_to_return - -/** - * Exists for the purposes of custom behavior. - * Called directly after [crushed] is crushed. - * - * Args: - * * mob/living/crushed: The mob that was crushed. - * * was_alive: Boolean. True if the mob was alive before the crushing. - */ -/atom/movable/proc/post_crush_living(mob/living/crushed, was_alive) - return - -/** - * Exists for the purposes of custom behavior. - * Called directly after src actually rotates and falls over. - */ -/atom/movable/proc/post_tilt() - return - -/proc/check_atom_crushable(atom/atom_target) - /// Contains structures and items that vendors shouldn't crush when we land on them. - var/static/list/vendor_uncrushable_objects = list( - /obj/structure/chair, - /obj/machinery/conveyor, - ) + GLOB.WALLITEMS_INTERIOR + GLOB.WALLITEMS_EXTERIOR - - if(is_type_in_list(atom_target, vendor_uncrushable_objects)) //make sure its not in the list of "uncrushable" stuff - return FALSE - - if (atom_target.uses_integrity && !(atom_target.invisibility > SEE_INVISIBLE_LIVING)) //check if it has integrity + allow ninjas, etc to be crushed in cloak - return TRUE //SMUSH IT - - return FALSE - -/obj/machinery/vending/post_crush_living(mob/living/crushed, was_alive) - - if(was_alive && crushed.stat == DEAD && crushed.client) - crushed.client.give_award(/datum/award/achievement/misc/vendor_squish, crushed) // good job losing a fight with an inanimate object idiot - - add_memory_in_range(crushed, 7, /datum/memory/witness_vendor_crush, protagonist = crushed, antagonist = src) - - return ..() - -/** - * Allows damage to be reduced on certain crit cases. - * Args: - * * crit_case: The critical case chosen. - */ -/atom/movable/proc/fall_and_crush_crit_rebate_table(crit_case) - - ASSERT(!isnull(crit_case)) - - switch(crit_case) - if (CRUSH_CRIT_SHATTER_LEGS) - return 0.2 - else - return 1 - -/obj/machinery/vending/fall_and_crush_crit_rebate_table(crit_case) - - if (crit_case == VENDOR_CRUSH_CRIT_GLASSCANDY) - return 0.33 - - return ..() - -/** - * Returns a assoc list of (critcase -> num), where critcase is a critical define in crushing.dm and num is a weight. - * Use with pickweight to acquire a random critcase. - */ -/atom/movable/proc/get_crit_crush_chances() - RETURN_TYPE(/list) - - var/list/weighted_crits = list() - - weighted_crits[CRUSH_CRIT_SHATTER_LEGS] = 100 - weighted_crits[CRUSH_CRIT_PARAPLEGIC] = 80 - weighted_crits[CRUSH_CRIT_HEADGIB] = 20 - weighted_crits[CRUSH_CRIT_SQUISH_LIMB] = 100 - - return weighted_crits - -/obj/machinery/vending/get_crit_crush_chances() - var/list/weighted_crits = ..() - - weighted_crits[VENDOR_CRUSH_CRIT_GLASSCANDY] = 100 - weighted_crits[VENDOR_CRUSH_CRIT_PIN] = 100 - - return weighted_crits - -/** - * Should be where critcase effects are actually implemented. Use this to apply critcases. - * Args: - * * crit_case: The chosen critcase, defined in crushing.dm. - * * atom/atom_target: The target to apply the critical hit to. Cannot be null. Can be anything except /area. - * - * Returns: - * TRUE if a crit case is successfully applied, FALSE otherwise. - */ -/atom/movable/proc/apply_crit_crush(crit_case, atom/atom_target) - switch (crit_case) - if(CRUSH_CRIT_SHATTER_LEGS) // shatter their legs and bleed 'em - if (!iscarbon(atom_target)) - return FALSE - var/mob/living/carbon/carbon_target = atom_target - carbon_target.bleed(150) - var/obj/item/bodypart/leg/left/left_leg = carbon_target.get_bodypart(BODY_ZONE_L_LEG) - if(left_leg) - left_leg.receive_damage(brute = 200) - var/obj/item/bodypart/leg/right/right_leg = carbon_target.get_bodypart(BODY_ZONE_R_LEG) - if(right_leg) - right_leg.receive_damage(brute = 200) - if(left_leg || right_leg) - carbon_target.visible_message(span_danger("[carbon_target]'s legs shatter with a sickening crunch!"), span_userdanger("Your legs shatter with a sickening crunch!")) - return TRUE - if(CRUSH_CRIT_PARAPLEGIC) // paralyze this binch - // the new paraplegic gets like 4 lines of losing their legs so skip them - if (!iscarbon(atom_target)) - return FALSE - var/mob/living/carbon/carbon_target = atom_target - visible_message(span_danger("[carbon_target]'s spinal cord is obliterated with a sickening crunch!"), ignored_mobs = list(carbon_target)) - carbon_target.gain_trauma(/datum/brain_trauma/severe/paralysis/paraplegic) - return TRUE - if(CRUSH_CRIT_SQUISH_LIMB) // limb squish! - if (!iscarbon(atom_target)) - return FALSE - var/mob/living/carbon/carbon_target = atom_target - for(var/obj/item/bodypart/squish_part in carbon_target.bodyparts) - var/severity = pick(WOUND_SEVERITY_MODERATE, WOUND_SEVERITY_SEVERE, WOUND_SEVERITY_CRITICAL) - if (!carbon_target.cause_wound_of_type_and_severity(WOUND_BLUNT, squish_part, severity, wound_source = "crushed by [src]")) - squish_part.receive_damage(brute = 30) - carbon_target.visible_message(span_danger("[carbon_target]'s body is maimed underneath the mass of [src]!"), span_userdanger("Your body is maimed underneath the mass of [src]!")) - return TRUE - if(CRUSH_CRIT_HEADGIB) // skull squish! - if (!iscarbon(atom_target)) - return FALSE - var/mob/living/carbon/carbon_target = atom_target - var/obj/item/bodypart/head/carbon_head = carbon_target.get_bodypart(BODY_ZONE_HEAD) - if(carbon_head) - if(carbon_head.dismember()) - carbon_target.visible_message(span_danger("[carbon_head] explodes in a shower of gore beneath [src]!"), span_userdanger("Oh f-")) - carbon_head.drop_organs() - qdel(carbon_head) - new /obj/effect/gibspawner/human/bodypartless(get_turf(carbon_target), carbon_target) - return TRUE - - return FALSE - -/obj/machinery/vending/apply_crit_crush(crit_case, atom_target) - . = ..() - - if (.) - return TRUE - - switch (crit_case) - if (VENDOR_CRUSH_CRIT_GLASSCANDY) - if (!iscarbon(atom_target)) - return FALSE - var/mob/living/carbon/carbon_target = atom_target - for(var/i in 1 to num_shards) - var/obj/item/shard/shard = new /obj/item/shard(get_turf(carbon_target)) - var/datum/embedding/embed = shard.get_embed() - embed.embed_chance = 100 - embed.ignore_throwspeed_threshold = TRUE - embed.impact_pain_mult = 1 - carbon_target.hitby(shard, skipcatch = TRUE, hitpush = FALSE) - embed.embed_chance = initial(embed.embed_chance) - embed.ignore_throwspeed_threshold = initial(embed.ignore_throwspeed_threshold) - embed.impact_pain_mult = initial(embed.impact_pain_mult) - return TRUE - if (VENDOR_CRUSH_CRIT_PIN) // pin them beneath the machine until someone untilts it - if (!isliving(atom_target)) - return FALSE - var/mob/living/living_target = atom_target - forceMove(get_turf(living_target)) - buckle_mob(living_target, force=TRUE) - living_target.visible_message(span_danger("[living_target] is pinned underneath [src]!"), span_userdanger("You are pinned down by [src]!")) - return TRUE - - return FALSE - -/** - * Rights the vendor up, unpinning mobs under it, if any. - * Arguments: - * user - mob that has untilted the vendor - */ -/obj/machinery/vending/proc/untilt(mob/user) - if(user) - user.visible_message(span_notice("[user] rights [src]."), \ - span_notice("You right [src].")) - - unbuckle_all_mobs(TRUE) - - tilted = FALSE - layer = initial(layer) - - var/matrix/to_turn = turn(transform, -tilted_rotation) - animate(src, transform = to_turn, 0.2 SECONDS) - tilted_rotation = 0 - -/** - * Tries to insert the item into the vendor, and depending on whether the product is a part of the vendor's - * stock or not, increments an already present product entry's available amount or creates a new entry. - * arguments: - * inserted_item - the item we're trying to insert - * user - mob who's trying to insert the item - */ -/obj/machinery/vending/proc/loadingAttempt(obj/item/inserted_item, mob/user) - . = TRUE - if(!user.transferItemToLoc(inserted_item, src)) - return FALSE - to_chat(user, span_notice("You insert [inserted_item] into [src]'s input compartment.")) - - for(var/datum/data/vending_product/product_datum in product_records + coin_records + hidden_records) - if(inserted_item.type == product_datum.product_path) - product_datum.amount++ - LAZYADD(product_datum.returned_products, inserted_item) - return - - if(vending_machine_input[inserted_item.type]) - vending_machine_input[inserted_item.type]++ - else - vending_machine_input[inserted_item.type] = 1 - loaded_items++ - - -/obj/machinery/vending/unbuckle_mob(mob/living/buckled_mob, force = FALSE, can_fall = TRUE) - if(!force) - return - . = ..() - -/** - * Is the passed in user allowed to load this vending machines compartments? This only is ran if we are using a /obj/item/storage/bag to load the vending machine, and not a dedicated restocker. - * - * Arguments: - * * user - mob that is doing the loading of the vending machine - */ -/obj/machinery/vending/proc/compartmentLoadAccessCheck(mob/user) - if(!req_access || allowed(user) || (obj_flags & EMAGGED) || !scan_id) - return TRUE - - to_chat(user, span_warning("[src]'s input compartment blinks red: Access denied.")) - return FALSE - -/obj/machinery/vending/exchange_parts(mob/user, obj/item/storage/part_replacer/replacer) - if(!istype(replacer) || !component_parts || !refill_canister) - return FALSE - - var/works_from_distance = istype(replacer, /obj/item/storage/part_replacer/bluespace) - - if(!panel_open || works_from_distance) - to_chat(user, display_parts(user)) - - if(!panel_open && !works_from_distance) - return FALSE - - var/restocked = 0 - for(var/replacer_item in replacer) - if(istype(replacer_item, refill_canister)) - restocked += restock(replacer_item) - post_restock(user, restocked) - if(restocked > 0) - replacer.play_rped_sound() - return TRUE - -/obj/machinery/vending/on_deconstruction(disassembled) - update_canister() - . = ..() - -/obj/machinery/vending/emag_act(mob/user, obj/item/card/emag/emag_card) - if(obj_flags & EMAGGED) - return FALSE - obj_flags |= EMAGGED - balloon_alert(user, "product lock disabled") - return TRUE - -/obj/machinery/vending/interact(mob/user) - if (HAS_AI_ACCESS(user)) - return ..() - - if(seconds_electrified && !(machine_stat & NOPOWER)) - if(shock(user, 100)) - return - - if(tilted && !user.buckled) - to_chat(user, span_notice("You begin righting [src].")) - if(do_after(user, 5 SECONDS, target=src)) - untilt(user) - return - - return ..() - -/obj/machinery/vending/attack_robot_secondary(mob/user, list/modifiers) - . = ..() - if (!Adjacent(user, src)) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - -/obj/machinery/vending/ui_assets(mob/user) - return list( - get_asset_datum(/datum/asset/spritesheet_batched/vending), - ) - -/obj/machinery/vending/ui_interact(mob/user, datum/tgui/ui) - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "Vending", name) - ui.open() - -/obj/machinery/vending/ui_static_data(mob/user) - var/list/data = list() - data["onstation"] = onstation - data["all_products_free"] = all_products_free - data["department"] = payment_department - data["jobDiscount"] = DEPARTMENT_DISCOUNT - data["product_records"] = list() - data["displayed_currency_icon"] = displayed_currency_icon - data["displayed_currency_name"] = displayed_currency_name - - var/list/categories = list() - - data["product_records"] = collect_records_for_static_data(product_records, categories) - data["coin_records"] = collect_records_for_static_data(coin_records, categories, premium = TRUE) - data["hidden_records"] = collect_records_for_static_data(hidden_records, categories, premium = TRUE) - - data["categories"] = categories - - return data - -/** - * Returns a list of given product records of the vendor to be used in UI. - * arguments: - * records - list of records available - * categories - list of categories available - * premium - bool of whether a record should be priced by a custom/premium price or not - */ -/obj/machinery/vending/proc/collect_records_for_static_data(list/records, list/categories, premium) - var/static/list/default_category = list( - "name" = "Products", - "icon" = "cart-shopping", - ) - - var/list/out_records = list() - - for (var/datum/data/vending_product/record as anything in records) - var/list/static_record = list( - path = replacetext(replacetext("[record.product_path]", "/obj/item/", ""), "/", "-"), - name = record.name, - price = record.price, - max_amount = record.max_amount, - ref = REF(record), - ) - - var/atom/printed = record.product_path - // If it's not GAGS and has no innate colors we have to care about, we use DMIcon - if(ispath(printed, /atom) \ - && (!initial(printed.greyscale_config) || !initial(printed.greyscale_colors)) \ - && !initial(printed.color) \ - ) - static_record["icon"] = initial(printed.icon) - static_record["icon_state"] = initial(printed.icon_state) - - var/list/category = record.category || default_category - if (!isnull(category)) - if (!(category["name"] in categories)) - categories[category["name"]] = list( - "icon" = category["icon"], - ) - - static_record["category"] = category["name"] - - if (premium) - static_record["premium"] = TRUE - - out_records += list(static_record) - - return out_records - -/obj/machinery/vending/ui_data(mob/user) - . = list() - var/obj/item/card/id/card_used - var/held_cash = 0 - if(isliving(user)) - var/mob/living/living_user = user - card_used = living_user.get_idcard(TRUE) - held_cash = living_user.tally_physical_credits() - - var/list/user_data = null - if(card_used?.registered_account) - user_data = list() - user_data["name"] = card_used.registered_account.account_holder - user_data["cash"] = fetch_balance_to_use(card_used) + held_cash - if(card_used.registered_account.account_job) - user_data["job"] = card_used.registered_account.account_job.title - user_data["department"] = card_used.registered_account.account_job.paycheck_department - else - user_data["job"] = "No Job" - user_data["department"] = DEPARTMENT_UNASSIGNED - .["user"] = user_data - - .["stock"] = list() - - for (var/datum/data/vending_product/product_record as anything in product_records + coin_records + hidden_records) - var/list/product_data = list( - name = product_record.name, - path = replacetext(replacetext("[product_record.product_path]", "/obj/item/", ""), "/", "-"), - amount = product_record.amount, - colorable = product_record.colorable, - ) - - .["stock"][product_data["path"]] = product_data - - .["extended_inventory"] = extended_inventory - -/obj/machinery/vending/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) - . = ..() - if(.) - return - switch(action) - if("vend") - . = vend(params) - if("select_colors") - . = select_colors(params) - -/** - * Whether this vendor can vend items or not. - * arguments: - * user - current customer - */ -/obj/machinery/vending/proc/can_vend(user) - . = FALSE - if(!vend_ready) - return - if(panel_open) - to_chat(user, span_warning("The vending machine cannot dispense products while its service panel is open!")) - return - return TRUE - -/** - * Brings up a color config menu for the picked greyscaled item - */ -/obj/machinery/vending/proc/select_colors(list/params) - . = TRUE - if(!can_vend(usr)) - return - var/datum/data/vending_product/product = locate(params["ref"]) - var/atom/fake_atom = product.product_path - - var/list/allowed_configs = list() - var/config = initial(fake_atom.greyscale_config) - if(!config) - return - allowed_configs += "[config]" - if(ispath(fake_atom, /obj/item)) - var/obj/item/item = fake_atom - if(initial(item.greyscale_config_worn)) - allowed_configs += "[initial(item.greyscale_config_worn)]" - if(initial(item.greyscale_config_inhand_left)) - allowed_configs += "[initial(item.greyscale_config_inhand_left)]" - if(initial(item.greyscale_config_inhand_right)) - allowed_configs += "[initial(item.greyscale_config_inhand_right)]" - - var/datum/greyscale_modify_menu/menu = new( - src, usr, allowed_configs, CALLBACK(src, PROC_REF(vend_greyscale), params), - starting_icon_state=initial(fake_atom.icon_state), - starting_config=initial(fake_atom.greyscale_config), - starting_colors=initial(fake_atom.greyscale_colors) - ) - menu.ui_interact(usr) - -/** - * Vends a greyscale modified item. - * arguments: - * menu - greyscale config menu that has been used to vend the item - */ -/obj/machinery/vending/proc/vend_greyscale(list/params, datum/greyscale_modify_menu/menu) - if(usr != menu.user) - return - vend(params, menu.split_colors) - -/** - * The entire shebang of vending the picked item. Processes the vending and initiates the payment for the item. - * arguments: - * greyscale_colors - greyscale config for the item we're about to vend, if any - */ -/obj/machinery/vending/proc/vend(list/params, list/greyscale_colors) - . = TRUE - if(!can_vend(usr)) - return - vend_ready = FALSE //One thing at a time!! - var/datum/data/vending_product/item_record = locate(params["ref"]) - var/list/record_to_check = product_records + coin_records - if(extended_inventory) - record_to_check = product_records + coin_records + hidden_records - if(!item_record || !istype(item_record) || !item_record.product_path) - vend_ready = TRUE - return - var/price_to_use = item_record.price - if(item_record in hidden_records) - if(!extended_inventory) - vend_ready = TRUE - return - else if (!(item_record in record_to_check)) - vend_ready = TRUE - message_admins("Vending machine exploit attempted by [ADMIN_LOOKUPFLW(usr)]!") - return - if (item_record.amount <= 0) - speak("Sold out of [item_record.name].") - flick(icon_deny,src) - vend_ready = TRUE - return - if(onstation) - // Here we do additional handing ahead of the payment component's logic, such as age restrictions and additional logging - var/obj/item/card/id/card_used - var/mob/living/living_user - if(isliving(usr)) - living_user = usr - card_used = living_user.get_idcard(TRUE) - if(age_restrictions && item_record.age_restricted && (!card_used.registered_age || card_used.registered_age < AGE_MINOR)) - speak("You are not of legal age to purchase [item_record.name].") - if(!(usr in GLOB.narcd_underages)) - aas_config_announce(/datum/aas_config_entry/vendomat_age_control, list( - "PERSON" = usr.name, - "LOCATION" = get_area_name(src), - "VENDOR" = name, - "PRODUCT" = item_record.name - ), src, list(RADIO_CHANNEL_SECURITY)) - GLOB.narcd_underages += usr - flick(icon_deny,src) - vend_ready = TRUE - return - - if(!proceed_payment(card_used, living_user, item_record, price_to_use, params["discountless"])) - vend_ready = TRUE - return - - if(last_shopper != REF(usr) || purchase_message_cooldown < world.time) - var/vend_response = vend_reply || "Thank you for shopping with [src]!" - speak(vend_response) - purchase_message_cooldown = world.time + 5 SECONDS - //This is not the best practice, but it's safe enough here since the chances of two people using a machine with the same ref in 5 seconds is fuck low - last_shopper = REF(usr) - use_energy(active_power_usage) - if(icon_vend) //Show the vending animation if needed - flick(icon_vend,src) - - // Always give out free returned stuff first, e.g. to avoid walling a traitor objective in a bag behind paid items - var/returned_available = LAZYLEN(item_record.returned_products) - var/obj/item/vended_item = dispense(item_record, get_turf(src), dispense_returned = returned_available) - - if(greyscale_colors) - vended_item.set_greyscale(colors=greyscale_colors) - if(usr.CanReach(src) && usr.put_in_hands(vended_item)) - to_chat(usr, span_notice("You take [item_record.name] out of the slot.")) - vended_item.do_pickup_animation(usr, src) - else - to_chat(usr, span_warning("[capitalize(format_text(item_record.name))] falls onto the floor!")) - SSblackbox.record_feedback("nested tally", "vending_machine_usage", 1, list("[type]", "[item_record.product_path]")) - vend_ready = TRUE - -///Common proc that dispenses an item. Called when the item is vended, or gotten some other way. -/obj/machinery/vending/proc/dispense(datum/data/vending_product/item_record, atom/spawn_location, silent = FALSE, dispense_returned = FALSE) - SHOULD_CALL_PARENT(TRUE) - if(!silent) - playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3) - - var/obj/item/vended_item - if(dispense_returned) - vended_item = LAZYACCESS(item_record.returned_products, LAZYLEN(item_record.returned_products)) //first in, last out - LAZYREMOVE(item_record.returned_products, vended_item) - vended_item.forceMove(spawn_location) - else - vended_item = new item_record.product_path(spawn_location) - if(vended_item.type in contraband) - ADD_TRAIT(vended_item, TRAIT_CONTRABAND, INNATE_TRAIT) - - on_dispense(vended_item, dispense_returned) - item_record.amount-- - return vended_item - -///A proc meant to perform custom behavior on newly dispensed items. -/obj/machinery/vending/proc/on_dispense(obj/item/vended_item, dispense_returned = FALSE) - return - -/** - * Returns the balance that the vendor will use for proceeding payment. Most vendors would want to use the user's - * card's account credits balance. - * arguments: - * passed_id - the id card that will be billed for the product - */ -/obj/machinery/vending/proc/fetch_balance_to_use(obj/item/card/id/passed_id) - return passed_id.registered_account.account_balance - -/** - * Handles payment processing: discounts, logging, balance change etc. - * arguments: - * paying_id_card - the id card that will be billed for the product. - * mob_paying - the mob that is trying to purchase the item. - * product_to_vend - the product record of the item we're trying to vend. - * price_to_use - price of the item we're trying to vend. - * discountless - whether or not to apply discounts - */ -/obj/machinery/vending/proc/proceed_payment(obj/item/card/id/paying_id_card, mob/living/mob_paying, datum/data/vending_product/product_to_vend, price_to_use, discountless) - if(QDELETED(paying_id_card)) //not available(null) or somehow is getting destroyed - speak("You do not possess an ID to purchase [product_to_vend.name].") - return FALSE - var/datum/bank_account/account = paying_id_card.registered_account - if(account.account_job && account.account_job.paycheck_department == payment_department && !discountless) - price_to_use = max(round(price_to_use * DEPARTMENT_DISCOUNT), 1) //No longer free, but signifigantly cheaper. - if(LAZYLEN(product_to_vend.returned_products)) - price_to_use = 0 //returned items are free - if(price_to_use && (attempt_charge(src, mob_paying, price_to_use) & COMPONENT_OBJ_CANCEL_CHARGE)) - speak("You do not possess the funds to purchase [product_to_vend.name].") - flick(icon_deny,src) - vend_ready = TRUE - return FALSE - //actual payment here - var/datum/bank_account/paying_id_account = SSeconomy.get_dep_account(payment_department) - if(paying_id_account) - SSblackbox.record_feedback("amount", "vending_spent", price_to_use) - SSeconomy.track_purchase(account, price_to_use, name) - log_econ("[price_to_use] credits were inserted into [src] by [account.account_holder] to buy [product_to_vend].") - credits_contained += round(price_to_use * VENDING_CREDITS_COLLECTION_AMOUNT) - return TRUE - -/obj/machinery/vending/process(seconds_per_tick) - if(machine_stat & (BROKEN|NOPOWER)) - return PROCESS_KILL - if(!active) - return - - if(seconds_electrified > MACHINE_NOT_ELECTRIFIED) - seconds_electrified-- - - //Pitch to the people! Really sell it! - if(last_slogan + slogan_delay <= world.time && slogan_list.len > 0 && !shut_up && SPT_PROB(2.5, seconds_per_tick)) - var/slogan = pick(slogan_list) - speak(slogan) - last_slogan = world.time - - if(shoot_inventory && SPT_PROB(shoot_inventory_chance, seconds_per_tick)) - throw_item() - -/** - * Speak the given message verbally - * - * Checks if the machine is powered and the message exists - * - * Arguments: - * * message - the message to speak - */ -/obj/machinery/vending/proc/speak(message) - if(machine_stat & (BROKEN|NOPOWER)) - return - if(!message) - return - - say(message) - -/obj/machinery/vending/power_change() - . = ..() - if(powered()) - START_PROCESSING(SSmachines, src) - -//Somebody cut an important wire and now we're following a new definition of "pitch." -/** - * Throw an item from our internal inventory out in front of us - * - * This is called when we are hacked, it selects a random product from the records that has an amount > 0 - * This item is then created and tossed out in front of us with a visible message - */ -/obj/machinery/vending/proc/throw_item() - var/mob/living/target = locate() in view(7,src) - if(!target) - return FALSE - - var/obj/thrown_item - for(var/datum/data/vending_product/record in shuffle(product_records)) - if(record.amount <= 0) //Try to use a record that actually has something to dump. - continue - var/dump_path = record.product_path - if(!dump_path) - continue - // Always throw new stuff that costs before free returned stuff, because of the hacking effort and time between throws involved - var/only_returned_left = (record.amount <= LAZYLEN(record.returned_products)) - thrown_item = dispense(record, get_turf(src), silent = TRUE, dispense_returned = only_returned_left) - break - if(isnull(thrown_item)) - return FALSE - - pre_throw(thrown_item) - - thrown_item.throw_at(target, 16, 3) - visible_message(span_danger("[src] launches [thrown_item] at [target]!")) - return TRUE - -/** - * A callback called before an item is tossed out - * - * Override this if you need to do any special case handling - * - * Arguments: - * * thrown_item - obj/item being thrown - */ -/obj/machinery/vending/proc/pre_throw(obj/item/thrown_item) - return - -/** - * Shock the passed in user - * - * This checks we have power and that the passed in prob is passed, then generates some sparks - * and calls electrocute_mob on the user - * - * Arguments: - * * user - the user to shock - * * shock_chance - probability the shock happens - */ -/obj/machinery/vending/proc/shock(mob/living/user, shock_chance) - if(!istype(user) || machine_stat & (BROKEN|NOPOWER)) // unpowered, no shock - return FALSE - if(!prob(shock_chance)) - return FALSE - do_sparks(5, TRUE, src) - if(electrocute_mob(user, get_area(src), src, 0.7, dist_check = TRUE)) - return TRUE - else - return FALSE -/** - * Are we able to load the item passed in - * - * Arguments: - * * loaded_item - the item being loaded - * * user - the user doing the loading - * * send_message - should we send a message to the user if the item can't be loaded? Either a to_chat or a speak depending on vending type. - */ -/obj/machinery/vending/proc/canLoadItem(obj/item/loaded_item, mob/user, send_message = TRUE) - if(!length(loaded_item.contents) && ((loaded_item.type in products) || (loaded_item.type in premium) || (loaded_item.type in contraband))) - return TRUE - if(send_message) - to_chat(user, span_warning("[src] does not accept [loaded_item]!")) - return FALSE - -/obj/machinery/vending/hitby(atom/movable/hitting_atom, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) - . = ..() - var/mob/living/living_mob = hitting_atom - if(tilted || !istype(living_mob) || !prob(20 * (throwingdatum.speed - living_mob.throw_speed))) // hulk throw = +20%, neckgrab throw = +20% - return - - tilt(living_mob) - -/obj/machinery/vending/attack_tk_grab(mob/user) - to_chat(user, span_warning("[src] seems to resist your mental grasp!")) - -///Crush the mob that the vending machine got thrown at -/obj/machinery/vending/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) - if(isliving(hit_atom)) - tilt(fatty=hit_atom) - return ..() - -/** Drop credits when the vendor is attacked.*/ -/obj/machinery/vending/proc/deploy_credits() - if(credits_contained <= 0) - return - var/credits_to_remove = min(CREDITS_DUMP_THRESHOLD, round(credits_contained)) - var/obj/item/holochip/holochip = new(loc, credits_to_remove) - playsound(src, 'sound/effects/cashregister.ogg', 40, TRUE) - credits_contained = max(0, credits_contained - credits_to_remove) - SSblackbox.record_feedback("amount", "vending machine looted", holochip.credits) - -/obj/machinery/vending/add_context(atom/source, list/context, obj/item/held_item, mob/user) - if(tilted && !held_item) - context[SCREENTIP_CONTEXT_LMB] = "Right machine" - return CONTEXTUAL_SCREENTIP_SET - - if(held_item?.tool_behaviour == TOOL_SCREWDRIVER) - context[SCREENTIP_CONTEXT_LMB] = panel_open ? "Close panel" : "Open panel" - return CONTEXTUAL_SCREENTIP_SET - - if(panel_open && held_item?.tool_behaviour == TOOL_WRENCH) - context[SCREENTIP_CONTEXT_LMB] = anchored ? "Unsecure" : "Secure" - return CONTEXTUAL_SCREENTIP_SET - - if(panel_open && held_item?.tool_behaviour == TOOL_CROWBAR) - context[SCREENTIP_CONTEXT_LMB] = "Deconstruct" - return CONTEXTUAL_SCREENTIP_SET - - if(!isnull(held_item) && (vending_machine_input[held_item.type] || canLoadItem(held_item, user, send_message = FALSE))) - context[SCREENTIP_CONTEXT_LMB] = "Load item" - return CONTEXTUAL_SCREENTIP_SET - - if(panel_open && istype(held_item, refill_canister)) - context[SCREENTIP_CONTEXT_LMB] = "Restock vending machine[credits_contained ? " and collect credits" : null]" - return TRUE - return NONE - -/obj/machinery/vending/custom - name = "Custom Vendor" - icon_state = "custom" - icon_deny = "custom-deny" - max_integrity = 400 - payment_department = NO_FREEBIES - light_mask = "custom-light-mask" - refill_canister = /obj/item/vending_refill/custom - fish_source_path = /datum/fish_source/vending/custom - /// where the money is sent - var/datum/bank_account/linked_account - /// max number of items that the custom vendor can hold - var/max_loaded_items = 20 - /// Base64 cache of custom icons. - var/list/base64_cache = list() - panel_type = "panel20" - -/obj/machinery/vending/custom/compartmentLoadAccessCheck(mob/user) - . = FALSE - if(!isliving(user)) - return FALSE - var/mob/living/living_user = user - var/obj/item/card/id/id_card = living_user.get_idcard(FALSE) - if(id_card?.registered_account && id_card.registered_account == linked_account) - return TRUE - -/obj/machinery/vending/custom/canLoadItem(obj/item/loaded_item, mob/user, send_message = TRUE) - . = FALSE - if(loaded_item.flags_1 & HOLOGRAM_1) - if(send_message) - speak("This vendor cannot accept nonexistent items.") - return - if(loaded_items >= max_loaded_items) - if(send_message) - speak("There are too many items in stock.") - return - if(isstack(loaded_item)) - if(send_message) - speak("Loose items may cause problems, try to use it inside wrapping paper.") - return - if(loaded_item.custom_price) - return TRUE - -/obj/machinery/vending/custom/ui_interact(mob/user, datum/tgui/ui) - if(!linked_account) - balloon_alert(user, "no registered owner!") - return FALSE - return ..() - -/obj/machinery/vending/custom/ui_data(mob/user) - . = ..() - .["access"] = compartmentLoadAccessCheck(user) - .["vending_machine_input"] = list() - for (var/obj/item/stocked_item as anything in vending_machine_input) - if(vending_machine_input[stocked_item] > 0) - var/base64 - var/price = 0 - var/itemname = initial(stocked_item.name) - for(var/obj/item/stored_item in contents) - if(stored_item.type == stocked_item) - price = stored_item.custom_price - itemname = stored_item.name - if(!base64) //generate an icon of the item to use in UI - if(base64_cache[stored_item.type]) - base64 = base64_cache[stored_item.type] - else - base64 = icon2base64(getFlatIcon(stored_item, no_anim=TRUE)) - base64_cache[stored_item.type] = base64 - break - var/list/data = list( - path = stocked_item, - name = itemname, - price = price, - img = base64, - amount = vending_machine_input[stocked_item], - colorable = FALSE - ) - .["vending_machine_input"] += list(data) - -/obj/machinery/vending/custom/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) - . = ..() - if(.) - return - switch(action) - if("dispense") - if(isliving(usr)) - vend_act(usr, params) - vend_ready = TRUE - return TRUE - -/obj/machinery/vending/custom/attackby(obj/item/attack_item, mob/user, list/modifiers, list/attack_modifiers) - if(!linked_account && isliving(user)) - var/mob/living/living_user = user - var/obj/item/card/id/card_used = living_user.get_idcard(TRUE) - if(card_used?.registered_account) - linked_account = card_used.registered_account - speak("\The [src] has been linked to [card_used].") - - if(!compartmentLoadAccessCheck(user) || !IS_WRITING_UTENSIL(attack_item)) - return ..() - - var/new_name = reject_bad_name(tgui_input_text(user, "Set name", "Name", name, max_length = 20), allow_numbers = TRUE, strict = TRUE, cap_after_symbols = FALSE) - if (new_name) - name = new_name - var/new_desc = reject_bad_text(tgui_input_text(user, "Set description", "Description", desc, max_length = 60)) - if (new_desc) - desc = new_desc - var/new_slogan = reject_bad_text(tgui_input_text(user, "Set slogan", "Slogan", "Epic", max_length = 60)) - if (new_slogan) - slogan_list += new_slogan - last_slogan = world.time + rand(0, slogan_delay) - -/obj/machinery/vending/custom/crowbar_act(mob/living/user, obj/item/attack_item) - return FALSE - -/obj/machinery/vending/custom/on_deconstruction(disassembled) - unbuckle_all_mobs(TRUE) - var/turf/current_turf = get_turf(src) - if(current_turf) - for(var/obj/item/stored_item in contents) - stored_item.forceMove(current_turf) - explosion(src, devastation_range = -1, light_impact_range = 3) - -/** - * Vends an item to the user. Handles all the logic: - * Updating stock, account transactions, alerting users. - * @return -- TRUE if a valid condition was met, FALSE otherwise. - */ -/obj/machinery/vending/custom/proc/vend_act(mob/living/user, list/params) - if(!vend_ready) - return - var/obj/item/choice = text2path(params["item"]) // typepath is a string coming from javascript, we need to convert it back - var/obj/item/dispensed_item - var/obj/item/card/id/id_card = user.get_idcard(TRUE) - vend_ready = FALSE - if(!id_card || !id_card.registered_account || !id_card.registered_account.account_job) - balloon_alert(usr, "no card found!") - flick(icon_deny, src) - return TRUE - var/datum/bank_account/payee = id_card.registered_account - for(var/obj/item/stock in contents) - if(istype(stock, choice)) - dispensed_item = stock - break - if(!dispensed_item) - return FALSE - /// Charges the user if its not the owner - if(!compartmentLoadAccessCheck(user)) - if(!payee.has_money(dispensed_item.custom_price)) - balloon_alert(user, "insufficient funds!") - return TRUE - /// Make the transaction - payee.adjust_money(-dispensed_item.custom_price, , "Vending: [dispensed_item]") - linked_account.adjust_money(dispensed_item.custom_price, "Vending: [dispensed_item] Bought") - linked_account.bank_card_talk("[payee.account_holder] made a [dispensed_item.custom_price] \ - cr purchase at your custom vendor.") - /// Log the transaction - SSblackbox.record_feedback("amount", "vending_spent", dispensed_item.custom_price) - log_econ("[dispensed_item.custom_price] credits were spent on [src] buying a \ - [dispensed_item] by [payee.account_holder], owned by [linked_account.account_holder].") - /// Make an alert - if(last_shopper != REF(usr) || purchase_message_cooldown < world.time) - speak("Thank you for your patronage [user]!") - purchase_message_cooldown = world.time + 5 SECONDS - last_shopper = REF(usr) - /// Remove the item - loaded_items-- - use_energy(active_power_usage) - vending_machine_input[choice] = max(vending_machine_input[choice] - 1, 0) - if(user.CanReach(src) && user.put_in_hands(dispensed_item)) - to_chat(user, span_notice("You take [dispensed_item.name] out of the slot.")) - else - to_chat(user, span_warning("[capitalize(format_text(dispensed_item.name))] falls onto the floor!")) - return TRUE - -/obj/machinery/vending/custom/unbreakable - name = "Indestructible Vendor" - resistance_flags = INDESTRUCTIBLE - -/obj/item/vending_refill/custom - machine_name = "Custom Vendor" - icon_state = "refill_custom" - custom_premium_price = PAYCHECK_CREW - -/obj/machinery/vending/custom/greed //name and like decided by the spawn - icon_state = "greed" - icon_deny = "greed-deny" - panel_type = "panel4" - max_integrity = 700 - max_loaded_items = 40 - light_mask = "greed-light-mask" - custom_materials = list(/datum/material/gold = SHEET_MATERIAL_AMOUNT * 5) - -/obj/machinery/vending/custom/greed/Initialize(mapload) - . = ..() - //starts in a state where you can move it - set_panel_open(TRUE) - set_anchored(FALSE) - add_overlay(panel_type) - //and references the deity - name = "[GLOB.deity]'s Consecrated Vendor" - desc = "A vending machine created by [GLOB.deity]." - slogan_list = list("[GLOB.deity] says: It's your divine right to buy!") - add_filter("vending_outline", 9, list("type" = "outline", "color" = COLOR_VERY_SOFT_YELLOW)) - add_filter("vending_rays", 10, list("type" = "rays", "size" = 35, "color" = COLOR_VIVID_YELLOW)) - -/datum/aas_config_entry/vendomat_age_control - name = "Security Alert: Underaged Substance Abuse" - announcement_lines_map = list( - "Message" = "SECURITY ALERT: Underaged crewmember %PERSON recorded attempting to purchase %PRODUCT in %LOCATION by %VENDOR. Please watch for substance abuse." - ) - vars_and_tooltips_map = list( - "PERSON" = "will be replaced with the name of the crewmember", - "PRODUCT" = "with the product, he attempted to purchase", - "LOCATION" = "with place of purchase", - "VENDOR" = "with the vending machine" - ) - -#undef MAX_VENDING_INPUT_AMOUNT diff --git a/code/modules/vending/assist.dm b/code/modules/vending/assist.dm index 9e5a3c4d8ec4..aff6ed1958ce 100644 --- a/code/modules/vending/assist.dm +++ b/code/modules/vending/assist.dm @@ -34,6 +34,7 @@ /obj/item/universal_scanner = 3, /obj/item/vending_refill/custom = 3, ) + allow_custom = TRUE refill_canister = /obj/item/vending_refill/assist product_ads = "Only the finest!;Have some tools.;The most robust equipment.;The finest gear in space!" diff --git a/code/modules/vending/autodrobe.dm b/code/modules/vending/autodrobe.dm index ffdf0bd5aa0d..8ed868b0391d 100644 --- a/code/modules/vending/autodrobe.dm +++ b/code/modules/vending/autodrobe.dm @@ -234,6 +234,7 @@ GLOBAL_VAR_INIT(all_autodrobe_items, (autodrobe_costumes_items +\ extra_price = PAYCHECK_COMMAND payment_department = ACCOUNT_SRV light_mask = "theater-light-mask" + allow_custom = TRUE /obj/machinery/vending/autodrobe/Initialize(mapload) product_categories = list( diff --git a/code/modules/vending/boozeomat.dm b/code/modules/vending/boozeomat.dm index f05dcb3e9f17..9f867f9f97b8 100644 --- a/code/modules/vending/boozeomat.dm +++ b/code/modules/vending/boozeomat.dm @@ -90,10 +90,12 @@ extra_price = PAYCHECK_COMMAND payment_department = ACCOUNT_SRV light_mask = "boozeomat-light-mask" + allow_custom = TRUE /obj/machinery/vending/boozeomat/syndicate age_restrictions = FALSE initial_language_holder = /datum/language_holder/syndicate + allow_custom = FALSE /obj/item/vending_refill/boozeomat machine_name = "Booze-O-Mat" diff --git a/code/modules/vending/cartridge.dm b/code/modules/vending/cartridge.dm index ccc13b7de720..852c88452ad5 100644 --- a/code/modules/vending/cartridge.dm +++ b/code/modules/vending/cartridge.dm @@ -20,6 +20,7 @@ extra_price = PAYCHECK_COMMAND * 2.5 payment_department = ACCOUNT_SRV light_mask = "cart-light-mask" + allow_custom = TRUE /obj/item/vending_refill/cart machine_name = "PTech" diff --git a/code/modules/vending/cigarette.dm b/code/modules/vending/cigarette.dm index 05c939bbcb87..8925d7ecd2ad 100644 --- a/code/modules/vending/cigarette.dm +++ b/code/modules/vending/cigarette.dm @@ -35,6 +35,7 @@ extra_price = PAYCHECK_COMMAND payment_department = ACCOUNT_SRV light_mask = "cigs-light-mask" + allow_custom = TRUE /obj/machinery/vending/cigarette/syndicate products = list( @@ -50,6 +51,7 @@ /obj/item/storage/fancy/rollingpapers = 5, ) initial_language_holder = /datum/language_holder/syndicate + allow_custom = FALSE /obj/machinery/vending/cigarette/beach //Used in the lavaland_biodome_beach.dmm ruin name = "\improper ShadyCigs Ultra" @@ -73,6 +75,7 @@ /obj/item/lighter = 3, ) initial_language_holder = /datum/language_holder/beachbum + allow_custom = FALSE /obj/item/vending_refill/cigarette machine_name = "ShadyCigs Deluxe" diff --git a/code/modules/vending/clothesmate.dm b/code/modules/vending/clothesmate.dm index 9ad6ff54dfd3..b9acfe563e9d 100644 --- a/code/modules/vending/clothesmate.dm +++ b/code/modules/vending/clothesmate.dm @@ -232,6 +232,7 @@ payment_department = NO_FREEBIES light_mask = "wardrobe-light-mask" light_color = LIGHT_COLOR_ELECTRIC_GREEN + allow_custom = TRUE /obj/item/vending_refill/clothing machine_name = "ClothesMate" diff --git a/code/modules/vending/coffee.dm b/code/modules/vending/coffee.dm index 10b895d1367f..e75cc4f47ceb 100644 --- a/code/modules/vending/coffee.dm +++ b/code/modules/vending/coffee.dm @@ -19,6 +19,7 @@ payment_department = ACCOUNT_SRV light_mask = "coffee-light-mask" light_color = COLOR_DARK_MODERATE_ORANGE + allow_custom = TRUE /obj/item/vending_refill/coffee machine_name = "Solar's Best Hot Drinks" diff --git a/code/modules/vending/cola.dm b/code/modules/vending/cola.dm index 9352c0c8b100..53aa82f8e12a 100644 --- a/code/modules/vending/cola.dm +++ b/code/modules/vending/cola.dm @@ -35,6 +35,7 @@ default_price = PAYCHECK_CREW * 0.7 extra_price = PAYCHECK_CREW payment_department = ACCOUNT_SRV + allow_custom = TRUE var/static/list/spiking_booze = list( // Your "common" spiking booze @@ -81,10 +82,12 @@ icon_state = "Cola_Machine" light_mask = "cola-light-mask" light_color = COLOR_MODERATE_BLUE + allow_custom = FALSE /obj/machinery/vending/cola/black icon_state = "cola_black" light_mask = "cola-light-mask" + allow_custom = FALSE /obj/machinery/vending/cola/red icon_state = "red_cola" @@ -93,6 +96,7 @@ product_slogans = "Cola in space!" light_mask = "red_cola-light-mask" light_color = COLOR_DARK_RED + allow_custom = FALSE /obj/machinery/vending/cola/space_up icon_state = "space_up" @@ -101,6 +105,7 @@ product_slogans = "Space-up! Like a hull breach in your mouth." light_mask = "space_up-light-mask" light_color = COLOR_DARK_MODERATE_LIME_GREEN + allow_custom = FALSE /obj/machinery/vending/cola/starkist icon_state = "starkist" @@ -110,12 +115,14 @@ panel_type = "panel7" light_mask = "starkist-light-mask" light_color = COLOR_LIGHT_ORANGE + allow_custom = FALSE /obj/machinery/vending/cola/sodie icon_state = "soda" panel_type = "panel7" light_mask = "soda-light-mask" light_color = COLOR_WHITE + allow_custom = FALSE /obj/machinery/vending/cola/pwr_game icon_state = "pwr_game" @@ -124,6 +131,7 @@ product_slogans = "The POWER that gamers crave! PWR GAME!" light_mask = "pwr_game-light-mask" light_color = COLOR_STRONG_VIOLET + allow_custom = FALSE /obj/machinery/vending/cola/shamblers name = "\improper Shambler's Vendor" @@ -145,6 +153,7 @@ product_ads = "Refreshing!;Thirsty for DNA? Satiate your craving!;Over 1 trillion souls drank!;Made with real DNA!;The hivemind demands your thirst!;Drink up!;Absorb your thirst." light_mask = "shamblers-light-mask" light_color = COLOR_MOSTLY_PURE_PINK + allow_custom = FALSE /obj/machinery/vending/cola/shamblers/Initialize(mapload) . = ..() diff --git a/code/modules/vending/custom.dm b/code/modules/vending/custom.dm new file mode 100644 index 000000000000..90456c8fba4a --- /dev/null +++ b/code/modules/vending/custom.dm @@ -0,0 +1,359 @@ +///This unique key decides how items are stacked on the UI. We separate them based on name,price & type +#define ITEM_HASH(item)("[item.name][item.custom_price][item.type]") + +/obj/machinery/vending/custom + name = "Custom Vendor" + icon_state = "custom" + icon_deny = "custom-deny" + max_integrity = 400 + payment_department = NO_FREEBIES + light_mask = "custom-light-mask" + panel_type = "panel20" + allow_custom = TRUE + refill_canister = /obj/item/vending_refill/custom + fish_source_path = /datum/fish_source/vending/custom + + /// max number of items that the custom vendor can hold + var/max_loaded_items = 20 + /// where the money is sent + VAR_PRIVATE/datum/bank_account/linked_account + /// Base64 cache of custom icons. + VAR_PRIVATE/static/list/base64_cache = list() + +/obj/machinery/vending/custom/on_deconstruction(disassembled) + var/obj/item/vending_refill/custom/installed_refill = locate() in component_parts + + if(linked_account) + //we delete the canister so players don't resell our products as their own + component_parts -= installed_refill + qdel(installed_refill) + + //self destruct protocol for unauthorized destruction + explosion(get_turf(src), devastation_range = -1, light_impact_range = 3) + + return + + //copy product hash keys + installed_refill.products.Cut() + installed_refill.products += products + + //move products to canister + for(var/obj/item/stored_item in contents - component_parts) + stored_item.forceMove(installed_refill) + +/obj/machinery/vending/custom/add_context(atom/source, list/context, obj/item/held_item, mob/user) + if(panel_open && istype(held_item, refill_canister)) + context[SCREENTIP_CONTEXT_LMB] = "Restock vending machine" + return CONTEXTUAL_SCREENTIP_SET + + if(isliving(user) && istype(held_item, /obj/item/card/id)) + var/obj/item/card/id/card_used = held_item + if(card_used?.registered_account) + if(!linked_account) + context[SCREENTIP_CONTEXT_LMB] = "Link account" + return ITEM_INTERACT_SUCCESS + else if(linked_account == card_used.registered_account) + context[SCREENTIP_CONTEXT_LMB] = "Unlink account" + return ITEM_INTERACT_SUCCESS + + return ..() + +/obj/machinery/vending/custom/examine(mob/user) + . = ..() + if(linked_account) + . += span_warning("Machine is ID locked. Be sure to unlink before deconstructing the machine.") + +/obj/machinery/vending/custom/Exited(obj/item/gone, direction) + . = ..() + + var/hash_key = ITEM_HASH(gone) + if(products[hash_key]) + var/new_amount = products[hash_key] - 1 + if(!new_amount) + products -= hash_key + update_static_data_for_all_viewers() + else + products[hash_key] = new_amount + +///Returns the number of products loaded in this machine +/obj/machinery/vending/custom/proc/loaded_items() + PRIVATE_PROC(TRUE) + SHOULD_BE_PURE(TRUE) + + . = 0 + for(var/product_hash in products) + . += products[product_hash] + +/obj/machinery/vending/custom/canLoadItem(obj/item/loaded_item, mob/user, send_message = TRUE) + if(loaded_item.flags_1 & HOLOGRAM_1) + if(send_message) + speak("This vendor cannot accept nonexistent items.") + return FALSE + if(isstack(loaded_item)) + if(send_message) + speak("Loose items may cause problems, try to use it inside wrapping paper.") + return FALSE + if(!loaded_item.custom_price) + if(send_message) + speak("Item needs to have a custom price set.") + return FALSE + return TRUE + +/obj/machinery/vending/custom/loadingAttempt(obj/item/inserted_item, mob/user) + if(!canLoadItem(inserted_item, user)) + return FALSE + + if(loaded_items() == max_loaded_items) + speak("There are too many items in stock.") + return FALSE + + if(!user.transferItemToLoc(inserted_item, src)) + to_chat(user, span_warning("[inserted_item] is stuck in your hand!")) + return FALSE + + //the hash key decides how items stack in the UI. We diffrentiate them based on name & price + var/hash_key = ITEM_HASH(inserted_item) + if(products[hash_key]) + products[hash_key]++ + else + products[hash_key] = 1 + update_static_data_for_all_viewers() + return TRUE + +/obj/machinery/vending/custom/RefreshParts() + SHOULD_CALL_PARENT(FALSE) + + restock(locate(refill_canister) in component_parts) + +/obj/machinery/vending/custom/restock(obj/item/vending_refill/canister) + . = 0 + if(!canister.products?.len) + return + + var/update_static_data = FALSE + var/available_load = max_loaded_items - loaded_items() + for(var/product_hash in canister.products) + //get available space + var/load_count = min(canister.products[product_hash], available_load) + if(!load_count) + break + //update canister record + canister.products[product_hash] -= load_count + if(!canister.products[product_hash]) + canister.products -= product_hash + //update vendor record + products[product_hash] += load_count + //reduce from available space + available_load -= load_count + + //update product + for(var/obj/item/product in canister) + if(!load_count) + break + if(ITEM_HASH(product) == product_hash) + . += 1 + product.forceMove(src) + load_count-- + + if(update_static_data) + update_static_data_for_all_viewers() + + +/obj/machinery/vending/custom/post_restock(mob/living/user, restocked) + if(!restocked) + to_chat(user, span_warning("There's nothing to restock!")) + return + + to_chat(user, span_notice("You loaded [restocked] items in [src]")) + +/obj/machinery/vending/custom/crowbar_act(mob/living/user, obj/item/attack_item) + if(linked_account) + visible_message( + span_warning("Security warning"), + span_warning("Unauthorized deconstruction of vending machine is prohibited. Please read the warning alert") + ) + if(tgui_alert(user, "Vending machine is ID locked.\ + Deconstruction will result in an catrostrophic self destruct.\ + If you are the owner of this machine please unlink your account with an ID swipe before proceeding.\ + Still proceed?", + "Vandalism protection protocol", + list("Yes", "No")) == "No") + return ITEM_INTERACT_FAILURE + + return ..() + +/obj/machinery/vending/custom/compartmentLoadAccessCheck(mob/user) + . = FALSE + if(!isliving(user)) + return FALSE + var/mob/living/living_user = user + var/obj/item/card/id/id_card = living_user.get_idcard(FALSE) + if(id_card?.registered_account && id_card.registered_account == linked_account) + return TRUE + +/obj/machinery/vending/custom/item_interaction(mob/living/user, obj/item/attack_item, list/modifiers) + if(isliving(user) && istype(attack_item, /obj/item/card/id)) + var/obj/item/card/id/card_used = attack_item + if(card_used?.registered_account) + if(!linked_account) + linked_account = card_used.registered_account + speak("\The [src] has been linked to [card_used].") + else if(linked_account == card_used.registered_account) + linked_account = null + speak("account unlinked.") + else + to_chat(user, "verification failed. unlinking process has been cancelled.") + return ITEM_INTERACT_SUCCESS + + if(!compartmentLoadAccessCheck(user) || !IS_WRITING_UTENSIL(attack_item)) + return ..() + + . ITEM_INTERACT_FAILURE + var/new_name = reject_bad_name(tgui_input_text(user, "Set name", "Name", name, max_length = 20), allow_numbers = TRUE, strict = TRUE, cap_after_symbols = FALSE) + if(!user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) + return + if (new_name) + name = new_name + var/new_desc = reject_bad_text(tgui_input_text(user, "Set description", "Description", desc, max_length = 60)) + if(!user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) + return + if (new_desc) + desc = new_desc + var/new_slogan = reject_bad_text(tgui_input_text(user, "Set slogan", "Slogan", "Epic", max_length = 60)) + if(!user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) + return + if (new_slogan) + slogan_list += new_slogan + last_slogan = world.time + rand(0, slogan_delay) + return ITEM_INTERACT_SUCCESS + +/obj/machinery/vending/custom/collect_records_for_static_data(list/records, list/categories, premium) + . = list() + if(records != product_records) //no coin or hidden stuff only product records + return + + categories["Products"] = list("icon" = "cart-shopping") + for(var/stocked_hash in products) + var/base64 = "" + var/obj/item/target = null + for(var/obj/item/stored_item in contents - component_parts) + if(ITEM_HASH(stored_item) == stocked_hash) + base64 = base64_cache[stocked_hash] + if(!base64) //generate an icon of the item to use in UI + base64 = icon2base64(getFlatIcon(stored_item, no_anim = TRUE)) + base64_cache[stocked_hash] = base64 + target = stored_item + break + + . += list(list( + path = stocked_hash, + name = target.name, + price = target.custom_price, + category = "Products", + ref = stocked_hash, + colorable = FALSE, + image = base64 + )) + + +/obj/machinery/vending/custom/ui_interact(mob/user, datum/tgui/ui) + if(!linked_account) + balloon_alert(user, "no registered owner!") + return FALSE + return ..() + +/obj/machinery/vending/custom/ui_data(mob/user) + . = ..() + + var/is_owner = compartmentLoadAccessCheck(user) + + .["stock"] = list() + for(var/stocked_hash in products) + .["stock"][stocked_hash] = list( + amount = products[stocked_hash], + free = is_owner + ) + +/obj/machinery/vending/custom/vend(list/params, mob/living/user, list/greyscale_colors) + . = FALSE + if(!isliving(user)) + return + var/obj/item/dispensed_item = params["ref"] + for(var/obj/item/product in contents - component_parts) + if(ITEM_HASH(product) == dispensed_item) + dispensed_item = product + break + if(QDELETED(dispensed_item)) + return + + var/obj/item/card/id/id_card = user.get_idcard(TRUE) + if(!id_card || !id_card.registered_account || !id_card.registered_account.account_job) + balloon_alert(user, "no card found!") + flick(icon_deny, src) + return + + /// Charges the user if its not the owner + var/datum/bank_account/payee = id_card.registered_account + if(!compartmentLoadAccessCheck(user)) + if(!payee.has_money(dispensed_item.custom_price)) + balloon_alert(user, "insufficient funds!") + return + /// Make the transaction + payee.adjust_money(-dispensed_item.custom_price, , "Vending: [dispensed_item]") + linked_account.adjust_money(dispensed_item.custom_price, "Vending: [dispensed_item] Bought") + linked_account.bank_card_talk("[payee.account_holder] made a [dispensed_item.custom_price] \ + cr purchase at your custom vendor.") + /// Log the transaction + SSblackbox.record_feedback("amount", "vending_spent", dispensed_item.custom_price) + log_econ("[dispensed_item.custom_price] credits were spent on [src] buying a \ + [dispensed_item] by [payee.account_holder], owned by [linked_account.account_holder].") + /// Make an alert + var/ref = REF(user) + if(last_shopper != ref || purchase_message_cooldown < world.time) + speak("Thank you for your patronage [user]!") + purchase_message_cooldown = world.time + 5 SECONDS + last_shopper = ref + + /// Remove the item + use_energy(active_power_usage) + try_put_in_hand(dispensed_item, user) + return TRUE + +/obj/item/vending_refill/custom + machine_name = "Custom Vendor" + icon_state = "refill_custom" + custom_premium_price = PAYCHECK_CREW + +/obj/item/vending_refill/custom/get_part_rating() + . = 0 + for(var/key in products) + . += products[key] + +/obj/machinery/vending/custom/unbreakable + name = "Indestructible Vendor" + resistance_flags = INDESTRUCTIBLE + allow_custom = FALSE + +/obj/machinery/vending/custom/greed //name and like decided by the spawn + icon_state = "greed" + icon_deny = "greed-deny" + panel_type = "panel4" + max_integrity = 700 + max_loaded_items = 40 + light_mask = "greed-light-mask" + allow_custom = FALSE + custom_materials = list(/datum/material/gold = SHEET_MATERIAL_AMOUNT * 5) + +/obj/machinery/vending/custom/greed/Initialize(mapload) + . = ..() + //starts in a state where you can move it + set_anchored(FALSE) + set_panel_open(TRUE) + //and references the deity + name = "[GLOB.deity]'s Consecrated Vendor" + desc = "A vending machine created by [GLOB.deity]." + slogan_list = list("[GLOB.deity] says: It's your divine right to buy!") + add_filter("vending_outline", 9, list("type" = "outline", "color" = COLOR_VERY_SOFT_YELLOW)) + add_filter("vending_rays", 10, list("type" = "rays", "size" = 35, "color" = COLOR_VIVID_YELLOW)) + +#undef ITEM_HASH diff --git a/code/modules/vending/cytopro.dm b/code/modules/vending/cytopro.dm index ce351be7769d..c27b9e537b21 100644 --- a/code/modules/vending/cytopro.dm +++ b/code/modules/vending/cytopro.dm @@ -29,6 +29,7 @@ default_price = PAYCHECK_CREW * 1 extra_price = PAYCHECK_COMMAND * 0.5 payment_department = ACCOUNT_SCI + allow_custom = TRUE /obj/item/vending_refill/cytopro machine_name = "CytoPro" diff --git a/code/modules/vending/drinnerware.dm b/code/modules/vending/drinnerware.dm index c37750a2d3d8..648d5762f9ea 100644 --- a/code/modules/vending/drinnerware.dm +++ b/code/modules/vending/drinnerware.dm @@ -69,6 +69,7 @@ extra_price = PAYCHECK_CREW * 2.4 payment_department = ACCOUNT_SRV light_mask = "dinnerware-light-mask" + allow_custom = TRUE /obj/item/vending_refill/dinnerware machine_name = "Plasteel Chef's Dinnerware Vendor" diff --git a/code/modules/vending/engineering.dm b/code/modules/vending/engineering.dm index f360b89a07fa..9b4999161df2 100644 --- a/code/modules/vending/engineering.dm +++ b/code/modules/vending/engineering.dm @@ -35,6 +35,7 @@ extra_price = PAYCHECK_COMMAND * 1.5 payment_department = ACCOUNT_ENG light_mask = "engi-light-mask" + allow_custom = TRUE /obj/item/vending_refill/engineering machine_name = "Robco Tool Maker" diff --git a/code/modules/vending/engivend.dm b/code/modules/vending/engivend.dm index 13e30e1783f9..256ea76870f9 100644 --- a/code/modules/vending/engivend.dm +++ b/code/modules/vending/engivend.dm @@ -32,6 +32,7 @@ extra_price = PAYCHECK_COMMAND * 1.5 payment_department = ACCOUNT_ENG light_mask = "engivend-light-mask" + allow_custom = TRUE /obj/item/vending_refill/engivend machine_name = "Engi-Vend" diff --git a/code/modules/vending/games.dm b/code/modules/vending/games.dm index 1b5722dbc126..a5b38b8fa0df 100644 --- a/code/modules/vending/games.dm +++ b/code/modules/vending/games.dm @@ -115,6 +115,7 @@ extra_price = PAYCHECK_COMMAND * 1.25 payment_department = ACCOUNT_SRV light_mask = "games-light-mask" + allow_custom = TRUE /obj/item/vending_refill/games machine_name = "\improper Good Clean Fun" diff --git a/code/modules/vending/medical.dm b/code/modules/vending/medical.dm index 78e260431155..d8fadb9130f3 100644 --- a/code/modules/vending/medical.dm +++ b/code/modules/vending/medical.dm @@ -39,6 +39,7 @@ extra_price = PAYCHECK_COMMAND payment_department = ACCOUNT_MED light_mask = "med-light-mask" + allow_custom = TRUE /obj/item/vending_refill/medical machine_name = "NanoMed Plus" @@ -47,6 +48,7 @@ /obj/machinery/vending/medical/syndicate name = "\improper SyndiMed Plus" initial_language_holder = /datum/language_holder/syndicate + allow_custom = FALSE /obj/machinery/vending/medical/infested_frigate products = list( @@ -64,6 +66,8 @@ /obj/item/cane/white = 2, /obj/item/clothing/glasses/eyepatch/medical = 2, ) + allow_custom = FALSE + //Created out of a necessity to get these dumb chems out of the medical tools vendor. /obj/machinery/vending/drugs name = "\improper NanoDrug Plus" @@ -102,6 +106,7 @@ extra_price = 100 payment_department = ACCOUNT_MED refill_canister = /obj/item/vending_refill/drugs + allow_custom = TRUE /obj/item/vending_refill/drugs machine_name = "NanoDrug Plus" diff --git a/code/modules/vending/medical_wall.dm b/code/modules/vending/medical_wall.dm index d853010d15be..53027e5b7df5 100644 --- a/code/modules/vending/medical_wall.dm +++ b/code/modules/vending/medical_wall.dm @@ -26,6 +26,10 @@ payment_department = ACCOUNT_MED tiltable = FALSE light_mask = "wallmed-light-mask" + allow_custom = TRUE + +/obj/machinery/vending/wallmed/directional + allow_custom = FALSE MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/vending/wallmed, 32) diff --git a/code/modules/vending/megaseed.dm b/code/modules/vending/megaseed.dm index 130a0921a43a..1be33c56ca2c 100644 --- a/code/modules/vending/megaseed.dm +++ b/code/modules/vending/megaseed.dm @@ -105,6 +105,7 @@ default_price = PAYCHECK_LOWER extra_price = PAYCHECK_CREW payment_department = ACCOUNT_SRV + allow_custom = TRUE /obj/item/vending_refill/hydroseeds machine_name = "MegaSeed Servitor" diff --git a/code/modules/vending/modularpc.dm b/code/modules/vending/modularpc.dm index 415329366c7d..0e894147e220 100644 --- a/code/modules/vending/modularpc.dm +++ b/code/modules/vending/modularpc.dm @@ -19,6 +19,7 @@ default_price = PAYCHECK_CREW extra_price = PAYCHECK_COMMAND payment_department = ACCOUNT_SCI + allow_custom = TRUE /obj/item/vending_refill/modularpc machine_name = "Deluxe Silicate Selections" diff --git a/code/modules/vending/nutrimax.dm b/code/modules/vending/nutrimax.dm index d7b3a0aaa5cd..7438dedcfc3b 100644 --- a/code/modules/vending/nutrimax.dm +++ b/code/modules/vending/nutrimax.dm @@ -28,6 +28,7 @@ default_price = PAYCHECK_CREW * 0.8 extra_price = PAYCHECK_COMMAND * 0.8 payment_department = ACCOUNT_SRV + allow_custom = TRUE /obj/item/vending_refill/hydronutrients machine_name = "NutriMax" diff --git a/code/modules/vending/robotics.dm b/code/modules/vending/robotics.dm index 849640419538..7e813d78e08b 100644 --- a/code/modules/vending/robotics.dm +++ b/code/modules/vending/robotics.dm @@ -26,6 +26,7 @@ refill_canister = /obj/item/vending_refill/robotics default_price = PAYCHECK_COMMAND payment_department = ACCOUNT_SCI + allow_custom = TRUE /obj/item/vending_refill/robotics machine_name = "Robotech Deluxe" diff --git a/code/modules/vending/security.dm b/code/modules/vending/security.dm index bf0b9dbee386..5004a8749d58 100644 --- a/code/modules/vending/security.dm +++ b/code/modules/vending/security.dm @@ -37,6 +37,7 @@ default_price = PAYCHECK_CREW extra_price = PAYCHECK_COMMAND * 1.5 payment_department = ACCOUNT_SEC + allow_custom = TRUE /obj/machinery/vending/security/pre_throw(obj/item/thrown_item) if(isgrenade(thrown_item)) diff --git a/code/modules/vending/snack.dm b/code/modules/vending/snack.dm index 1e81679135b3..95c932b89999 100644 --- a/code/modules/vending/snack.dm +++ b/code/modules/vending/snack.dm @@ -45,18 +45,23 @@ default_price = PAYCHECK_CREW * 0.6 extra_price = PAYCHECK_CREW payment_department = ACCOUNT_SRV + allow_custom = TRUE /obj/item/vending_refill/snack machine_name = "Getmore Chocolate Corp" /obj/machinery/vending/snack/blue icon_state = "snackblue" + allow_custom = FALSE /obj/machinery/vending/snack/orange icon_state = "snackorange" + allow_custom = FALSE /obj/machinery/vending/snack/green icon_state = "snackgreen" + allow_custom = FALSE /obj/machinery/vending/snack/teal icon_state = "snackteal" + allow_custom = FALSE diff --git a/code/modules/vending/sovietsoda.dm b/code/modules/vending/sovietsoda.dm index aaf631c10555..5031a68ad64a 100644 --- a/code/modules/vending/sovietsoda.dm +++ b/code/modules/vending/sovietsoda.dm @@ -18,6 +18,7 @@ payment_department = NO_FREEBIES light_color = COLOR_PALE_ORANGE initial_language_holder = /datum/language_holder/spinwarder + allow_custom = TRUE /obj/item/vending_refill/sovietsoda machine_name = "BODA" diff --git a/code/modules/vending/subtype.dm b/code/modules/vending/subtype.dm index 360eb46defd3..e9633c56cb93 100644 --- a/code/modules/vending/subtype.dm +++ b/code/modules/vending/subtype.dm @@ -15,19 +15,18 @@ var/type_to_vend = /obj/item/food/grown/citrus /obj/machinery/vending/subtype_vendor/Initialize(mapload, type_to_vend) - . = ..() if(type_to_vend) src.type_to_vend = type_to_vend - load_subtypes() - -/obj/machinery/vending/subtype_vendor/proc/load_subtypes() - products = list() - product_records = list() + return ..() +///Adds the subtype to the product list +/obj/machinery/vending/subtype_vendor/RefreshParts() + products.Cut() for(var/type in typesof(type_to_vend)) LAZYADDASSOC(products, type, 50) - build_inventories() + //no refill canister so we fill the records with their max amounts directly + build_inventories(start_empty = FALSE) /obj/machinery/vending/subtype_vendor/attack_hand_secondary(mob/user, list/modifiers) . = ..() @@ -48,5 +47,5 @@ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN type_to_vend = type_to_vend_now - load_subtypes() + RefreshParts() return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN diff --git a/code/modules/vending/sustenance.dm b/code/modules/vending/sustenance.dm index 8667e5d978f9..0ad7eadc3549 100644 --- a/code/modules/vending/sustenance.dm +++ b/code/modules/vending/sustenance.dm @@ -25,6 +25,19 @@ default_price = PAYCHECK_LOWER extra_price = PAYCHECK_LOWER * 0.6 payment_department = NO_FREEBIES + allow_custom = TRUE + +/obj/machinery/vending/sustenance/interact(mob/living/living_user) + if(!isliving(living_user)) + return + if(!istype(living_user.get_idcard(TRUE), /obj/item/card/id/advanced/prisoner)) + if(!req_access) + speak("No valid prisoner account found. Vending is not permitted.") + return + if(!allowed(living_user)) + speak("No valid permissions. Vending is not permitted.") + return + return ..() /obj/item/vending_refill/sustenance machine_name = "Sustenance Vendor" @@ -39,34 +52,17 @@ all_products_free = FALSE displayed_currency_icon = "digging" displayed_currency_name = " LP" + allow_custom = FALSE -/obj/machinery/vending/sustenance/interact(mob/user) - if(!isliving(user)) - return ..() - var/mob/living/living_user = user - if(!is_operational) - to_chat(user, span_warning("Machine does not respond to your ID swipe")) - return - if(!istype(living_user.get_idcard(TRUE), /obj/item/card/id/advanced/prisoner)) - if(!req_access) - speak("No valid prisoner account found. Vending is not permitted.") - return - if(!allowed(user)) - speak("No valid permissions. Vending is not permitted.") - return - return ..() - -/obj/machinery/vending/sustenance/labor_camp/proceed_payment(obj/item/card/id/paying_id_card, mob/living/mob_paying, datum/data/vending_product/product_to_vend, price_to_use) - if(!istype(paying_id_card, /obj/item/card/id/advanced/prisoner)) +/obj/machinery/vending/sustenance/labor_camp/proceed_payment(obj/item/card/id/advanced/prisoner/paying_scum_id, mob/living/mob_paying, datum/data/vending_product/product_to_vend, price_to_use) + if(!istype(paying_scum_id)) speak("I don't take bribes! Pay with labor points!") return FALSE - var/obj/item/card/id/advanced/prisoner/paying_scum_id = paying_id_card if(LAZYLEN(product_to_vend.returned_products)) price_to_use = 0 //returned items are free if(price_to_use && !(paying_scum_id.points >= price_to_use)) //not enough good prisoner points speak("You do not possess enough points to purchase [product_to_vend.name].") flick(icon_deny, src) - vend_ready = TRUE return FALSE paying_scum_id.points -= price_to_use diff --git a/code/modules/vending/syndichem.dm b/code/modules/vending/syndichem.dm new file mode 100644 index 000000000000..896198f65a65 --- /dev/null +++ b/code/modules/vending/syndichem.dm @@ -0,0 +1,21 @@ +/obj/machinery/vending/syndichem + name = "\improper SyndiChem" + desc = "A vending machine full of grenades and grenade accessories. Sponsored by Donk Co." + products = list( + /obj/item/stack/cable_coil = 5, + /obj/item/assembly/igniter = 20, + /obj/item/assembly/prox_sensor = 5, + /obj/item/assembly/signaler = 5, + /obj/item/assembly/timer = 5, + /obj/item/assembly/voice = 5, + /obj/item/assembly/health = 5, + /obj/item/assembly/infra = 5, + /obj/item/grenade/chem_grenade = 5, + /obj/item/grenade/chem_grenade/large = 5, + /obj/item/grenade/chem_grenade/pyro = 5, + /obj/item/grenade/chem_grenade/cryo = 5, + /obj/item/grenade/chem_grenade/adv_release = 5, + /obj/item/reagent_containers/cup/glass/bottle/holywater = 1 + ) + product_slogans = "It's not pyromania if you're getting paid!;You smell that? Plasma, son. Nothing else in the world smells like that.;I love the smell of Plasma in the morning." + resistance_flags = FIRE_PROOF diff --git a/code/modules/vending/vendor/_vending.dm b/code/modules/vending/vendor/_vending.dm new file mode 100644 index 000000000000..0c4fba16efb1 --- /dev/null +++ b/code/modules/vending/vendor/_vending.dm @@ -0,0 +1,477 @@ +///Maximum credits dump threshold +#define CREDITS_DUMP_THRESHOLD 50 +/** + * # vending record datum + * A datum that represents a product that is vendable + */ +/datum/data/vending_product + name = "generic" + ///Typepath of the product that is created when this record "sells" + var/product_path = null + ///How many of this product we currently have + var/amount = 0 + ///How many we can store at maximum + var/max_amount = 0 + ///The price of the item + var/price + ///Whether spessmen with an ID with an age below AGE_MINOR (20 by default) can buy this item + var/age_restricted = FALSE + ///Whether the product can be recolored by the GAGS system + var/colorable + /// The category the product was in, if any. + /// Sourced directly from product_categories. + var/category + ///List of items that have been returned to the vending machine. + var/list/returned_products + +/datum/data/vending_product/Destroy(force) + returned_products = null + return ..() + +/** + * # vending machines + * + * Captalism in the year 2525, everything in a vending machine, even love + */ +/obj/machinery/vending + name = "\improper Vendomat" + desc = "A generic vending machine." + icon = 'icons/obj/machines/vending.dmi' + icon_state = "generic" + layer = BELOW_OBJ_LAYER + density = TRUE + verb_say = "beeps" + verb_ask = "beeps" + verb_exclaim = "beeps" + max_integrity = 300 + integrity_failure = 0.33 + armor_type = /datum/armor/machinery_vending + circuit = /obj/item/circuitboard/machine/vendor + payment_department = ACCOUNT_SRV + light_power = 0.7 + light_range = MINIMUM_USEFUL_LIGHT_RANGE + voice_filter = "alimiter=0.9,acompressor=threshold=0.2:ratio=20:attack=10:release=50:makeup=2,highpass=f=1000" + + ///Next world time to send a purchase message + var/purchase_message_cooldown + ///The ref of the last mob to shop with us + var/last_shopper + ///Whether the vendor is tilted or not + var/tilted = FALSE + /// If tilted, this variable should always be the rotation that was applied when we were tilted. Stored for the purposes of unapplying it. + var/tilted_rotation = 0 + ///Whether this vendor can be tilted over or not + var/tiltable = TRUE + ///Damage this vendor does when tilting onto an atom + var/squish_damage = 75 + /// The chance, in percent, of this vendor performing a critical hit on anything it crushes via [tilt]. + var/crit_chance = 15 + ///List of mobs stuck under the vendor + var/list/pinned_mobs = list() + ///Icon for the maintenance panel overlay + var/panel_type = "panel1" + ///Whether this vendor can be selected when building a custom vending machine + var/allow_custom = FALSE + + /** + * List of products this machine sells + * + * form should be list(/type/path = amount, /type/path2 = amount2) + */ + var/list/products = list() + + /** + * List of products this machine sells, categorized. + * Can only be used as an alternative to `products`, not alongside it. + * + * Form should be list( + * "name" = "Category Name", + * "icon" = "UI Icon (Font Awesome or tgfont)", + * "products" = list(/type/path = amount, ...), + * ) + */ + var/list/product_categories = null + + /** + * List of products this machine sells when you hack it + * + * form should be list(/type/path = amount, /type/path2 = amount2) + */ + var/list/contraband = list() + + /** + * List of premium products this machine sells + * + * form should be list(/type/path = amount, /type/path2 = amount2) + */ + var/list/premium = list() + + ///String of slogans separated by semicolons, optional + var/product_slogans = "" + ///String of small ad messages in the vending screen - random chance + var/product_ads = "" + + ///List of standard product records + var/list/datum/data/vending_product/product_records = list() + ///List of contraband product records + var/list/datum/data/vending_product/hidden_records = list() + ///List of premium product records + var/list/datum/data/vending_product/coin_records = list() + ///List of slogans to scream at potential customers; built upon Iniitialize() of the vendor from product_slogans + var/list/slogan_list = list() + ///List of ads built from product_ads upon Iniitialize() + var/list/ad_list = list() + ///Message sent post vend (Thank you for shopping!) + var/vend_reply + ///Last world tick we sent a vent reply + var/last_reply = 0 + ///Last world tick we sent a slogan message out + var/last_slogan = 0 + ///How many ticks until we can send another + var/slogan_delay = 10 MINUTES + ///Icon when vending an item to the user + var/icon_vend + ///Icon to flash when user is denied a vend + var/icon_deny + ///World ticks the machine is electified for + var/seconds_electrified = MACHINE_NOT_ELECTRIFIED + ///When this is TRUE, we fire items at customers! We're broken! + var/shoot_inventory = FALSE + ///How likely this is to happen (prob 100) per second + var/shoot_inventory_chance = 1 + //Stop spouting those godawful pitches! + var/shut_up = FALSE + ///can we access the hidden inventory? + var/extended_inventory = FALSE + ///Are we checking the users ID + var/scan_id = TRUE + ///Default price of items if not overridden + var/default_price = 25 + ///Default price of premium items if not overridden + var/extra_price = 50 + ///fontawesome icon name to use in to display the user's balance in the vendor UI + var/displayed_currency_icon = "coins" + ///String of the used currency to display in the vendor UI + var/displayed_currency_name = " cr" + ///Whether our age check is currently functional + var/age_restrictions = TRUE + /// How many credits does this vending machine have? 20% of all sales go to this pool, and are given freely when the machine is restocked, or successfully tilted. Lost on deconstruction. + var/credits_contained = 0 + /** + * Is this item on station or not + * + * if it doesn't originate from off-station during mapload, all_products_free gets automatically set to TRUE if it was unset previously. + * if it's off-station during mapload, it's also safe from the brand intelligence event + */ + var/onstation = TRUE + /** + * DO NOT APPLY THIS GLOBALLY. For mapping var edits only. + * A variable to change on a per instance basis that allows the instance to avoid having onstation set for them during mapload. + * Setting this to TRUE means that the vending machine is treated as if it were still onstation if it spawns off-station during mapload. + * Useful to specify an off-station machine that will be affected by machine-brand intelligence for whatever reason. + */ + var/onstation_override = FALSE + /** + * If this is set to TRUE, all products sold by the vending machine are free (cost nothing). + * If unset, this will get automatically set to TRUE during init if the machine originates from off-station during mapload. + * Defaults to null, set it to TRUE or FALSE explicitly on a per-machine basis if you want to force it to be a certain value. + */ + var/all_products_free + + //The type of refill canisters used by this machine. + var/obj/item/vending_refill/refill_canister = null + + ///Name of lighting mask for the vending machine + var/light_mask + + //the path of the fish_source datum to use for the fishing_spot component + var/fish_source_path = /datum/fish_source/vending + +/datum/armor/machinery_vending + melee = 20 + fire = 50 + acid = 70 + +/** + * Initialize the vending machine + * + * Builds the vending machine inventory, sets up slogans and other such misc work + * + * This also sets the onstation var to: + * * FALSE - if the machine was maploaded on a zlevel that doesn't pass the is_station_level check + * * TRUE - all other cases + */ +/obj/machinery/vending/Initialize(mapload) + //means we produce products with fixed amounts + if(!refill_canister) + circuit = null + RefreshParts() + + . = ..() + + set_wires(new /datum/wires/vending(src)) + + if(SStts.tts_enabled) + var/static/vendor_voice_by_type = list() + if(!vendor_voice_by_type[type]) + vendor_voice_by_type[type] = pick(SStts.available_speakers) + voice = vendor_voice_by_type[type] + + slogan_list = splittext(product_slogans, ";") + ad_list = splittext(product_ads, ";") + // So not all machines speak at the exact same time. + // The first time this machine says something will be at slogantime + this random value, + // so if slogantime is 10 minutes, it will say it at somewhere between 10 and 20 minutes after the machine is crated. + last_slogan = world.time + rand(0, slogan_delay) + power_change() + + if(mapload) //check if it was initially created off station during mapload. + if(!is_station_level(z)) + if(!onstation_override) + onstation = FALSE + if(isnull(all_products_free)) // Only auto-set the free products var if we haven't explicitly assigned a value to it yet. + all_products_free = TRUE + if(circuit) + circuit.all_products_free = all_products_free //sync up the circuit so the pricing schema is carried over if it's reconstructed. + + else if(circuit) + all_products_free = circuit.all_products_free //if it was constructed outside mapload, sync the vendor up with the circuit's var so you can't bypass price requirements by moving / reconstructing it off station. + if(!all_products_free) + AddComponent(/datum/component/payment, 0, SSeconomy.get_dep_account(payment_department), PAYMENT_VENDING) + register_context() + + if(fish_source_path) + AddComponent(/datum/component/fishing_spot, fish_source_path) + +/obj/machinery/vending/atom_break(damage_flag) + . = ..() + if(!.) + return + + var/dump_amount = 0 + var/found_anything = TRUE + while (found_anything) + found_anything = FALSE + for(var/datum/data/vending_product/record as anything in shuffle(product_records)) + //first dump any of the items that have been returned, in case they contain the nuke disk or something + for(var/i in 1 to LAZYLEN(record.returned_products)) + var/obj/item/returned_obj_to_dump = dispense(record, get_turf(src), dispense_returned = TRUE) + step(returned_obj_to_dump, pick(GLOB.alldirs)) + + if(record.amount <= 0) //Try to use a record that actually has something to dump. + continue + var/dump_path = record.product_path + if(!dump_path) + continue + // busting open a vendor will destroy some of the contents + if(found_anything && prob(80)) + record.amount-- + continue + + var/obj/obj_to_dump = dispense(record, loc) + step(obj_to_dump, pick(GLOB.alldirs)) + found_anything = TRUE + dump_amount++ + if (dump_amount >= 16) + return + +/obj/machinery/vending/on_deconstruction(disassembled) + var/obj/item/vending_refill/installed_refill = locate() in component_parts + if(!installed_refill) + return + + var/list/datum/data/vending_product/record_list + var/list/canister_list + for(var/i in 1 to 3) + switch(i) + if (1) + record_list = product_records + canister_list = installed_refill.products + if (2) + record_list = hidden_records + canister_list = installed_refill.contraband + else + record_list = coin_records + canister_list = installed_refill.premium + + canister_list.Cut() + for(var/datum/data/vending_product/record as anything in record_list) + var/stock = record.amount - LAZYLEN(record.returned_products) + if(stock) + canister_list[record.product_path] = stock + +/obj/machinery/vending/Destroy() + QDEL_LIST(product_records) + QDEL_LIST(hidden_records) + QDEL_LIST(coin_records) + return ..() + +/obj/machinery/vending/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = NONE + if(tilted && !held_item) + context[SCREENTIP_CONTEXT_LMB] = "Right machine" + return CONTEXTUAL_SCREENTIP_SET + + if(held_item?.tool_behaviour == TOOL_SCREWDRIVER) + context[SCREENTIP_CONTEXT_LMB] = "[panel_open ? "Close" : "Open"] Panel" + return CONTEXTUAL_SCREENTIP_SET + + if(panel_open && held_item?.tool_behaviour == TOOL_WRENCH) + context[SCREENTIP_CONTEXT_LMB] = anchored ? "Unsecure" : "Secure" + return CONTEXTUAL_SCREENTIP_SET + + if(panel_open && held_item?.tool_behaviour == TOOL_CROWBAR) + context[SCREENTIP_CONTEXT_LMB] = "Deconstruct" + return CONTEXTUAL_SCREENTIP_SET + + if(!isnull(held_item) && canLoadItem(held_item, user, send_message = FALSE)) + context[SCREENTIP_CONTEXT_LMB] = "Load item" + return CONTEXTUAL_SCREENTIP_SET + + if(panel_open && istype(held_item, refill_canister)) + context[SCREENTIP_CONTEXT_LMB] = "Restock vending machine[credits_contained ? " and collect credits" : null]" + return CONTEXTUAL_SCREENTIP_SET + +/** + * Returns the total loaded & max amount of items i.e list(total_loaded, total_maximum) in the vending machine based on the product records and premium records + * + * Arguments + * * contraband - should we count contrabrand as well +*/ +/obj/machinery/vending/proc/total_stock(contrabrand = TRUE) + SHOULD_BE_PURE(TRUE) + SHOULD_NOT_OVERRIDE(TRUE) + RETURN_TYPE(/list) + + var/total_loaded = 0 + var/total_max = 0 + var/list/stock = product_records + coin_records + if(contrabrand) + stock += hidden_records + for(var/datum/data/vending_product/record as anything in stock) + total_loaded += record.amount + total_max += record.max_amount + return list(total_loaded, total_max) + +/obj/machinery/vending/examine(mob/user) + . = ..() + if(isnull(refill_canister)) + return // you can add the comment here instead + + . += span_notice("Its maintainence panel can be [EXAMINE_HINT("screwed")] [panel_open ? "closed" : "open"]") + if(panel_open) + . += span_notice("The machine may be [EXAMINE_HINT("pried")] apart.") + + var/list/total_stock = total_stock() + if(total_stock[2]) + if(total_stock[1] < total_stock[2]) + . += span_notice("\The [src] can be restocked with [span_boldnotice("\a [initial(refill_canister.machine_name)] [initial(refill_canister.name)]")] with the panel open.") + else + . += span_notice("\The [src] is fully stocked.") + if(credits_contained < CREDITS_DUMP_THRESHOLD && credits_contained > 0) + . += span_notice("It should have a handfull of credits stored based on the missing items.") + else if (credits_contained > PAYCHECK_CREW) + . += span_notice("It should have at least a full paycheck worth of credits inside!") + +/obj/machinery/vending/update_appearance(updates = ALL) + . = ..() + if(machine_stat & BROKEN) + set_light(0) + return + set_light(powered() ? MINIMUM_USEFUL_LIGHT_RANGE : 0) + +/obj/machinery/vending/update_icon_state() + if(machine_stat & BROKEN) + icon_state = "[initial(icon_state)]-broken" + return ..() + icon_state = "[initial(icon_state)][powered() ? null : "-off"]" + return ..() + +/obj/machinery/vending/update_overlays() + . = ..() + if(panel_open) + . += panel_type + if(light_mask && !(machine_stat & BROKEN) && powered()) + . += emissive_appearance(icon, light_mask, src) + +/obj/machinery/vending/vv_edit_var(vname, vval) + . = ..() + if (vname == NAMEOF(src, all_products_free)) + if (all_products_free) + RemoveComponentSource(src, /datum/component/payment) + else + AddComponent(/datum/component/payment, 0, SSeconomy.get_dep_account(payment_department), PAYMENT_VENDING) + +/obj/machinery/vending/emp_act(severity) + . = ..() + var/datum/language_holder/vending_languages = get_language_holder() + var/datum/wires/vending/vending_wires = wires + // if the language wire got pulsed during an EMP, this will make sure the language_iterator is synched correctly + vending_languages.selected_language = vending_languages.spoken_languages[vending_wires.language_iterator] + +/obj/machinery/vending/unbuckle_mob(mob/living/buckled_mob, force = FALSE, can_fall = TRUE) + if(!force) + return + . = ..() + +/obj/machinery/vending/emag_act(mob/user, obj/item/card/emag/emag_card) + if(obj_flags & EMAGGED) + return FALSE + obj_flags |= EMAGGED + balloon_alert(user, "product lock disabled") + return TRUE + + +/obj/machinery/vending/power_change() + . = ..() + if(powered()) + START_PROCESSING(SSmachines, src) + +/obj/machinery/vending/process(seconds_per_tick) + if(!is_operational) + return PROCESS_KILL + + if(seconds_electrified > MACHINE_NOT_ELECTRIFIED) + seconds_electrified-- + + //Pitch to the people! Really sell it! + if(last_slogan + slogan_delay <= world.time && slogan_list.len && !shut_up && SPT_PROB(2.5, seconds_per_tick)) + say(pick(slogan_list)) + last_slogan = world.time + + if(shoot_inventory && SPT_PROB(shoot_inventory_chance, seconds_per_tick)) + throw_item() + + +//===============================SPEACH=================================================== +/obj/machinery/vending/can_speak(allow_mimes) + return is_operational && !shut_up && ..() + + +/** + * Speak the given message verbally + * Checks if the machine is powered and the message exists + * + * Arguments: + * * message - the message to speak + */ +/obj/machinery/vending/proc/speak(message) + if(!is_operational) + return + if(!message) + return + + say(message) + +/datum/aas_config_entry/vendomat_age_control + name = "Security Alert: Underaged Substance Abuse" + announcement_lines_map = list( + "Message" = "SECURITY ALERT: Underaged crewmember %PERSON recorded attempting to purchase %PRODUCT in %LOCATION by %VENDOR. Please watch for substance abuse." + ) + vars_and_tooltips_map = list( + "PERSON" = "will be replaced with the name of the crewmember", + "PRODUCT" = "with the product, he attempted to purchase", + "LOCATION" = "with place of purchase", + "VENDOR" = "with the vending machine" + ) +//============================================================================= diff --git a/code/modules/vending/vendor/interaction.dm b/code/modules/vending/vendor/interaction.dm new file mode 100644 index 000000000000..bd250db4022e --- /dev/null +++ b/code/modules/vending/vendor/interaction.dm @@ -0,0 +1,235 @@ +/// Maximum amount of items in a storage bag that we're transferring items to the vendor from. +#define MAX_VENDING_INPUT_AMOUNT 30 + +//================================TOOL ACTS============================================== +/obj/machinery/vending/crowbar_act(mob/living/user, obj/item/attack_item) + if(!component_parts) + return ITEM_INTERACT_FAILURE + default_deconstruction_crowbar(attack_item) + return ITEM_INTERACT_SUCCESS + +/obj/machinery/vending/wrench_act(mob/living/user, obj/item/tool) + . = NONE + if(!panel_open) + return ITEM_INTERACT_FAILURE + if(default_unfasten_wrench(user, tool, time = 6 SECONDS)) + unbuckle_all_mobs(TRUE) + return ITEM_INTERACT_SUCCESS + +/obj/machinery/vending/screwdriver_act(mob/living/user, obj/item/attack_item) + if(anchored) + default_deconstruction_screwdriver(user, icon_state, icon_state, attack_item) + return ITEM_INTERACT_SUCCESS + else + to_chat(user, span_warning("You must first secure [src].")) + return ITEM_INTERACT_FAILURE + +/obj/machinery/vending/on_set_panel_open(old_value) + update_appearance(UPDATE_OVERLAYS) + +//=======================================RESTOCKING========================================== +/** + * Is the passed in user allowed to load this vending machines compartments? This only is ran if we are using a /obj/item/storage/bag to load the vending machine, and not a dedicated restocker. + * + * Arguments: + * * user - mob that is doing the loading of the vending machine + */ +/obj/machinery/vending/proc/compartmentLoadAccessCheck(mob/user) + PROTECTED_PROC(TRUE) + + return !req_access || allowed(user) || (obj_flags & EMAGGED) || !scan_id + +/** + * Are we able to load the item passed in + * + * Arguments: + * * loaded_item - the item being loaded + * * user - the user doing the loading + */ +/obj/machinery/vending/proc/canLoadItem(obj/item/loaded_item, mob/user, send_message = TRUE) + PROTECTED_PROC(TRUE) + + if(!length(loaded_item.contents) && (products[loaded_item.type] || premium[loaded_item.type] || contraband[loaded_item.type])) + return TRUE + if(send_message) + to_chat(user, span_warning("[src] does not accept [loaded_item]!")) + return FALSE + + +/** + * Tries to insert the item into the vendor, and depending on whether the product is a part of the vendor's + * stock or not, increments an already present product entry's available amount or creates a new entry. + * arguments: + * inserted_item - the item we're trying to insert + * user - mob who's trying to insert the item + */ +/obj/machinery/vending/proc/loadingAttempt(obj/item/inserted_item, mob/user) + PROTECTED_PROC(TRUE) + + . = TRUE + if(!canLoadItem(inserted_item, user)) + to_chat(user, span_warning("[src] does not accept [inserted_item]!")) + return FALSE + + to_chat(user, span_notice("You insert [inserted_item] into [src]'s input compartment.")) + for(var/datum/data/vending_product/product_datum in product_records + coin_records + hidden_records) + if(inserted_item.type == product_datum.product_path) + if(product_datum.amount == product_datum.max_amount) + to_chat(user, span_warning("no space for any more [product_datum.category || "Products"]!")) + return FALSE + + if(!user.transferItemToLoc(inserted_item, src)) + to_chat(user, span_warning("[inserted_item] is stuck in your hand!")) + return FALSE + + product_datum.amount++ + LAZYADD(product_datum.returned_products, inserted_item) + break + +/obj/machinery/vending/item_interaction(mob/living/user, obj/item/attack_item, list/modifiers) + . = NONE + if(panel_open && is_wire_tool(attack_item)) + wires.interact(user) + return ITEM_INTERACT_SUCCESS + + if(refill_canister && istype(attack_item, refill_canister)) + . = ITEM_INTERACT_FAILURE + if (!panel_open) + to_chat(user, span_warning("You should probably unscrew the service panel first!")) + else if (!is_operational) + to_chat(user, span_warning("[src] does not respond.")) + else + var/obj/item/vending_refill/canister = attack_item + if(canister.get_part_rating() == 0) + to_chat(user, span_warning("[canister] is empty!")) + else + post_restock(user, restock(canister)) + return ITEM_INTERACT_SUCCESS + + if(compartmentLoadAccessCheck(user) && !user.combat_mode) + . = ITEM_INTERACT_FAILURE + if (!is_operational) + to_chat(user, span_warning("[src] does not respond.")) + else if(istype(attack_item, /obj/item/storage/bag)) //trays USUALLY + var/obj/item/storage/storage_item = attack_item + var/loaded = 0 + var/denied_items = 0 + for(var/obj/item/the_item in storage_item.contents) + if(contents.len >= MAX_VENDING_INPUT_AMOUNT) // no more than 30 item can fit inside, legacy from snack vending although not sure why it exists + to_chat(user, span_warning("[src]'s compartment is full.")) + break + if(loadingAttempt(the_item, user)) + loaded++ + else + denied_items++ + if(denied_items) + to_chat(user, span_warning("[src] refuses some items!")) + if(loaded) + to_chat(user, span_notice("You insert [loaded] dishes into [src]'s compartment.")) + return ITEM_INTERACT_SUCCESS + else + return loadingAttempt(attack_item, user) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_FAILURE + +/** + * After-effects of refilling a vending machine from a refill canister + * + * This takes the amount of products restocked and gives the user our contained credits if needed, + * sending the user a fitting message. + * + * Arguments: + * * user - the user restocking us + * * restocked - the amount of items we've been refilled with + */ +/obj/machinery/vending/proc/post_restock(mob/living/user, restocked) + PROTECTED_PROC(TRUE) + + if(!restocked) + to_chat(user, span_warning("There's nothing to restock!")) + return + + to_chat(user, span_notice("You loaded [restocked] items in [src][credits_contained > 0 ? ", and are rewarded [credits_contained] credits." : "."]")) + var/datum/bank_account/cargo_account = SSeconomy.get_dep_account(ACCOUNT_CAR) + cargo_account.adjust_money(round(credits_contained * 0.5), "Vending: Restock") + var/obj/item/holochip/payday = new(src, credits_contained) + try_put_in_hand(payday, user) + credits_contained = 0 + +/obj/machinery/vending/exchange_parts(mob/user, obj/item/storage/part_replacer/replacer) + if(!istype(replacer) || !component_parts || !refill_canister) + return FALSE + + var/works_from_distance = istype(replacer, /obj/item/storage/part_replacer/bluespace) + + if(!panel_open || works_from_distance) + to_chat(user, display_parts(user)) + + if(!panel_open && !works_from_distance) + return FALSE + + var/restocked = 0 + for(var/replacer_item in replacer) + if(istype(replacer_item, refill_canister)) + restocked += restock(replacer_item) + post_restock(user, restocked) + if(restocked > 0) + replacer.play_rped_effect() + return TRUE + +//=======================================ATTACKS================================================ +/** + * Dispenses free items from the standard stock. + * + * Arguments: + * freebies - number of free items to vend + */ +/obj/machinery/vending/proc/freebie(freebies) + PRIVATE_PROC(TRUE) + + visible_message(span_notice("[src] yields [freebies > 1 ? "several free goodies" : "a free goody"][credits_contained > 0 ? " and some credits" : ""]!")) + + for(var/i in 1 to freebies) + playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3) + for(var/datum/data/vending_product/record in shuffle(product_records)) + if(record.amount <= 0) //Try to use a record that actually has something to dump. + continue + // Always give out new stuff that costs before free returned stuff, because of the risk getting gibbed involved + var/only_returned_left = (record.amount <= LAZYLEN(record.returned_products)) + dispense(record, get_turf(src), silent = TRUE, dispense_returned = only_returned_left) + break + + if(credits_contained > 0) + var/credits_to_remove = min(CREDITS_DUMP_THRESHOLD, round(credits_contained)) + var/obj/item/holochip/holochip = new(loc, credits_to_remove) + playsound(src, 'sound/effects/cashregister.ogg', 40, TRUE) + credits_contained = max(0, credits_contained - credits_to_remove) + SSblackbox.record_feedback("amount", "vending machine looted", holochip.credits) + +/obj/machinery/vending/attacked_by(obj/item/attacking_item, mob/living/user, list/modifiers, list/attack_modifiers) + . = ..() + if(!tiltable || tilted || . <= 0) + return + if(isclosedturf(get_turf(user))) //If the attacker is inside of a wall, immediately fall in the other direction, with no chance for goodies. + tilt(get_turf(get_step(src, REVERSE_DIR(get_dir(src, user))))) + return + + switch(rand(1, 100)) + if(1 to 5) + freebie(3) + if(6 to 15) + freebie(2) + if(16 to 25) + freebie(1) + if(26 to 75) + pass() + if(76 to 100) + tilt(user) + +/obj/machinery/vending/attack_tk_grab(mob/user) + to_chat(user, span_warning("[src] seems to resist your mental grasp!")) + +/obj/machinery/vending/attack_robot_secondary(mob/user, list/modifiers) + . = ..() + if (!Adjacent(user, src)) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + +#undef MAX_VENDING_INPUT_AMOUNT diff --git a/code/modules/vending/vendor/inventory.dm b/code/modules/vending/vendor/inventory.dm new file mode 100644 index 000000000000..5073f5017aeb --- /dev/null +++ b/code/modules/vending/vendor/inventory.dm @@ -0,0 +1,284 @@ +//================================STOCKING IN ITEMS================================= + +/** + * Build the inventory of the vending machine from its product and record lists + * + * This builds up a full set of /datum/data/vending_products from the product list of the vending machine type + * Arguments: + * * productlist - the list of products that need to be converted + * * recordlist - the list containing /datum/data/vending_product datums + * * categories - A list in the format of product_categories to source category from + * * startempty - should we set vending_product record amount from the product list (so it's prefilled at roundstart) + * * premium - Whether the ending products shall have premium or default prices + */ +/obj/machinery/vending/proc/build_inventory(list/productlist, list/recordlist, list/categories, start_empty = FALSE, premium = FALSE) + PRIVATE_PROC(TRUE) + + var/inflation_value = HAS_TRAIT(SSeconomy, TRAIT_MARKET_CRASHING) ? SSeconomy.inflation_value() : 1 + default_price = round(initial(default_price) * inflation_value) + extra_price = round(initial(extra_price) * inflation_value) + + QDEL_LIST(recordlist) + + var/list/product_to_category = list() + for (var/list/category as anything in categories) + for (var/product_key in category["products"]) + product_to_category[product_key] = category + + for(var/typepath in productlist) + var/amount = productlist[typepath] + + var/obj/item/temp = typepath + var/datum/data/vending_product/new_record = new + new_record.name = initial(temp.name) + new_record.product_path = typepath + if(!start_empty) + new_record.amount = amount + new_record.max_amount = amount + + ///Prices of vending machines are all increased uniformly. + var/custom_price = round(initial(temp.custom_price) * inflation_value) + if(!premium) + new_record.price = custom_price || default_price + else + var/premium_custom_price = round(initial(temp.custom_premium_price) * inflation_value) + if(!premium_custom_price && custom_price) //For some ungodly reason, some premium only items only have a custom_price + new_record.price = extra_price + custom_price + else + new_record.price = premium_custom_price || extra_price + + new_record.age_restricted = initial(temp.age_restricted) + new_record.colorable = !!(initial(temp.greyscale_config) && initial(temp.greyscale_colors) && (initial(temp.flags_1) & IS_PLAYER_COLORABLE_1)) + new_record.category = product_to_category[typepath] + recordlist += new_record + +/** + * Builds all available inventories for the vendor - standard, contraband and premium + * + * Arguments + * start_empty - bool to pass into build_inventory that determines whether a product entry starts with available stock or not +*/ +/obj/machinery/vending/proc/build_inventories(start_empty = FALSE) + build_inventory(products, product_records, product_categories, start_empty) + build_inventory(contraband, hidden_records, list(list("name" = "Contraband", "icon" = "mask", "products" = contraband)), start_empty, premium = TRUE) + build_inventory(premium, coin_records, list(list("name" = "Premium", "icon" = "coins", "products" = premium)), start_empty, premium = TRUE) + +//Better would be to make constructable child +/obj/machinery/vending/RefreshParts() + SHOULD_CALL_PARENT(FALSE) + + //compress all product categories into an linear list + if(product_categories) + products.Cut() + for(var/list/category as anything in product_categories) + products |= category["products"] + + //locate canister + var/obj/item/vending_refill/canister = refill_canister ? locate(refill_canister) in component_parts : null + + //build the records, if we have a canister make the records empty so we can refill it from the canister else make it max amount + build_inventories(start_empty = !isnull(canister)) + + //fill the records if we have an canister + if(canister) + restock(canister) + +/** + * Refill a vending machine from a refill canister + * + * This takes the products from the refill canister and then fills the products, contraband and premium product categories + * + * Arguments: + * * canister - the vending canister we are refilling from + */ +/obj/machinery/vending/proc/restock(obj/item/vending_refill/canister) + . = 0 + + //to initialize product category & cargo ordered canisters for the 1st time + if(!canister.products) + canister.products = products.Copy() + canister.contraband = contraband.Copy() + canister.premium = premium.Copy() + + var/list/datum/data/vending_product/record_list + var/list/canister_list + + for(var/i in 1 to 3) + switch(i) + if (1) + record_list = product_records + canister_list = canister.products + if (2) + record_list = hidden_records + canister_list = canister.contraband + else + record_list = coin_records + canister_list = canister.premium + if(!record_list.len || !canister_list.len) + continue + + for(var/datum/data/vending_product/record as anything in record_list) + var/diff = min(record.max_amount - record.amount, canister_list[record.product_path] || 0) + if (diff) + canister_list[record.product_path] -= diff + if(!canister_list[record.product_path]) + canister_list -= record.product_path + record.amount += diff + . += diff + +//===========================VENDING OUT ITEMS================================ +/obj/machinery/vending/Exited(atom/movable/gone, direction) + . = ..() + for(var/datum/data/vending_product/record in product_records + coin_records + hidden_records) + if(gone in record.returned_products) + record.returned_products -= gone + record.amount -= 1 + break + +/** + * The entire shebang of vending the picked item. Processes the vending and initiates the payment for the item. + * arguments: + * greyscale_colors - greyscale config for the item we're about to vend, if any + */ +/obj/machinery/vending/proc/vend(list/params, mob/user, list/greyscale_colors) + PROTECTED_PROC(TRUE) + + . = TRUE + var/datum/data/vending_product/item_record = locate(params["ref"]) + var/list/record_to_check = product_records + coin_records + if(extended_inventory) + record_to_check = product_records + coin_records + hidden_records + if(!item_record || !istype(item_record) || !item_record.product_path) + return + var/price_to_use = item_record.price + if(item_record in hidden_records) + if(!extended_inventory) + return + else if (!(item_record in record_to_check)) + message_admins("Vending machine exploit attempted by [ADMIN_LOOKUPFLW(user)]!") + return + if (item_record.amount <= 0) + speak("Sold out of [item_record.name].") + flick(icon_deny, src) + return + if(onstation) + // Here we do additional handing ahead of the payment component's logic, such as age restrictions and additional logging + var/obj/item/card/id/card_used + var/mob/living/living_user + if(isliving(user)) + living_user = user + card_used = living_user.get_idcard(TRUE) + if(age_restrictions && item_record.age_restricted && (!card_used.registered_age || card_used.registered_age < AGE_MINOR)) + speak("You are not of legal age to purchase [item_record.name].") + if(!(user in GLOB.narcd_underages)) + aas_config_announce(/datum/aas_config_entry/vendomat_age_control, list( + "PERSON" = usr.name, + "LOCATION" = get_area_name(src), + "VENDOR" = name, + "PRODUCT" = item_record.name + ), src, list(RADIO_CHANNEL_SECURITY)) + GLOB.narcd_underages += user + flick(icon_deny, src) + return + + if(!proceed_payment(card_used, living_user, item_record, price_to_use, params["discountless"])) + return + + if(last_shopper != REF(user) || purchase_message_cooldown < world.time) + var/vend_response = vend_reply || "Thank you for shopping with [src]!" + speak(vend_response) + purchase_message_cooldown = world.time + 5 SECONDS + //This is not the best practice, but it's safe enough here since the chances of two people using a machine with the same ref in 5 seconds is fuck low + last_shopper = REF(user) + use_energy(active_power_usage) + if(icon_vend) //Show the vending animation if needed + flick(icon_vend, src) + + // Always give out free returned stuff first, e.g. to avoid walling a traitor objective in a bag behind paid items + var/obj/item/vended_item = dispense(item_record, get_turf(src), dispense_returned = LAZYLEN(item_record.returned_products)) + if(!vended_item) + return + + if(greyscale_colors) + vended_item.set_greyscale(colors=greyscale_colors) + if(user.CanReach(src) && user.put_in_hands(vended_item)) + to_chat(user, span_notice("You take [item_record.name] out of the slot.")) + vended_item.do_pickup_animation(user, src) + else + to_chat(user, span_warning("[capitalize(format_text(item_record.name))] falls onto the floor!")) + SSblackbox.record_feedback("nested tally", "vending_machine_usage", 1, list("[type]", "[item_record.product_path]")) + +/** + * Common proc that dispenses an item. Called when the item is vended, or gotten some other way. + * + * Arguments + * * datum/data/vending_product/item_record - the vending record which contains the information of the item to dispense + * * atom/spawn_location - location to dispense the item to + * * silent - should we play the vending sound + * * dispense_returned - are we vending out an returned item +*/ +/obj/machinery/vending/proc/dispense(datum/data/vending_product/item_record, atom/spawn_location, silent = FALSE, dispense_returned = FALSE) + SHOULD_NOT_OVERRIDE(TRUE) + + if(!silent) + playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3) + + var/obj/item/vended_item = null + if(dispense_returned) + vended_item = LAZYACCESS(item_record.returned_products, LAZYLEN(item_record.returned_products)) //first in, last out + if(!QDELETED(vended_item)) + vended_item.forceMove(spawn_location) + else if(item_record.amount) + vended_item = new item_record.product_path(spawn_location) + if(vended_item.type in contraband) + ADD_TRAIT(vended_item, TRAIT_CONTRABAND, INNATE_TRAIT) + item_record.amount-- + + if(!QDELETED(vended_item)) + on_dispense(vended_item, dispense_returned) + return vended_item + +/** + * A proc meant to perform custom behavior on newly dispensed items. + * + * Arguments + * * obj/item/vended_item - the item that has just been dispensed + * * dispense_returned - is this item an returned product +*/ +/obj/machinery/vending/proc/on_dispense(obj/item/vended_item, dispense_returned = FALSE) + PROTECTED_PROC(TRUE) + + return + +/** + * Handles payment processing: discounts, logging, balance change etc. + * arguments: + * paying_id_card - the id card that will be billed for the product. + * mob_paying - the mob that is trying to purchase the item. + * product_to_vend - the product record of the item we're trying to vend. + * price_to_use - price of the item we're trying to vend. + * discountless - whether or not to apply discounts + */ +/obj/machinery/vending/proc/proceed_payment(obj/item/card/id/paying_id_card, mob/living/mob_paying, datum/data/vending_product/product_to_vend, price_to_use, discountless) + PROTECTED_PROC(TRUE) + + if(QDELETED(paying_id_card)) //not available(null) or somehow is getting destroyed + speak("You do not possess an ID to purchase [product_to_vend.name].") + return FALSE + var/datum/bank_account/account = paying_id_card.registered_account + if(account.account_job && account.account_job.paycheck_department == payment_department && !discountless) + price_to_use = max(round(price_to_use * DEPARTMENT_DISCOUNT), 1) //No longer free, but signifigantly cheaper. + if(LAZYLEN(product_to_vend.returned_products)) + price_to_use = 0 //returned items are free + if(price_to_use && (attempt_charge(src, mob_paying, price_to_use) & COMPONENT_OBJ_CANCEL_CHARGE)) + speak("You do not possess the funds to purchase [product_to_vend.name].") + flick(icon_deny,src) + return FALSE + //actual payment here + var/datum/bank_account/paying_id_account = SSeconomy.get_dep_account(payment_department) + if(paying_id_account) + SSblackbox.record_feedback("amount", "vending_spent", price_to_use) + SSeconomy.track_purchase(account, price_to_use, name) + log_econ("[price_to_use] credits were inserted into [src] by [account.account_holder] to buy [product_to_vend].") + credits_contained += round(price_to_use * VENDING_CREDITS_COLLECTION_AMOUNT) + return TRUE diff --git a/code/modules/vending/vendor/throwing.dm b/code/modules/vending/vendor/throwing.dm new file mode 100644 index 000000000000..0b1cbbd0a178 --- /dev/null +++ b/code/modules/vending/vendor/throwing.dm @@ -0,0 +1,57 @@ + +/** + * Throw an item from our internal inventory out in front of us + * + * This is called when we are hacked, it selects a random product from the records that has an amount > 0 + * This item is then created and tossed out in front of us with a visible message + */ +/obj/machinery/vending/proc/throw_item() + var/mob/living/target = locate() in view(7,src) + if(!target) + return FALSE + + var/obj/thrown_item + for(var/datum/data/vending_product/record in shuffle(product_records)) + if(record.amount <= 0) //Try to use a record that actually has something to dump. + continue + var/dump_path = record.product_path + if(!dump_path) + continue + // Always throw new stuff that costs before free returned stuff, because of the hacking effort and time between throws involved + var/only_returned_left = (record.amount <= LAZYLEN(record.returned_products)) + thrown_item = dispense(record, get_turf(src), silent = TRUE, dispense_returned = only_returned_left) + break + if(isnull(thrown_item)) + return FALSE + + pre_throw(thrown_item) + + thrown_item.throw_at(target, 16, 3) + visible_message(span_danger("[src] launches [thrown_item] at [target]!")) + return TRUE + +/** + * A callback called before an item is tossed out + * + * Override this if you need to do any special case handling + * + * Arguments: + * * thrown_item - obj/item being thrown + */ +/obj/machinery/vending/proc/pre_throw(obj/item/thrown_item) + return + + +///Crush the mob that the vending machine got thrown at +/obj/machinery/vending/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) + if(isliving(hit_atom)) + tilt(fatty=hit_atom) + return ..() + +/obj/machinery/vending/hitby(atom/movable/hitting_atom, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) + . = ..() + var/mob/living/living_mob = hitting_atom + if(tilted || !istype(living_mob) || !prob(20 * (throwingdatum.speed - living_mob.throw_speed))) // hulk throw = +20%, neckgrab throw = +20% + return + + tilt(living_mob) diff --git a/code/modules/vending/vendor/tilting.dm b/code/modules/vending/vendor/tilting.dm new file mode 100644 index 000000000000..1d7d899c0ea7 --- /dev/null +++ b/code/modules/vending/vendor/tilting.dm @@ -0,0 +1,312 @@ +/** + * Can this atom be curshed by the vending machine + * Arguments + * + * * atom/atom_target - the atom we are checking for +*/ +/proc/check_atom_crushable(atom/atom_target) + /// Contains structures and items that vendors shouldn't crush when we land on them. + var/static/list/vendor_uncrushable_objects = list( + /obj/structure/chair, + /obj/machinery/conveyor, + ) + GLOB.WALLITEMS_INTERIOR + GLOB.WALLITEMS_EXTERIOR + + //make sure its not in the list of "uncrushable" stuff + if(is_type_in_list(atom_target, vendor_uncrushable_objects)) + return FALSE + + //check if it has integrity + allow ninjas, etc to be crushed in cloak + if (atom_target.uses_integrity && !(atom_target.invisibility > SEE_INVISIBLE_LIVING)) + return TRUE //SMUSH IT + + return FALSE + +/** + * Causes src to fall onto [target], crushing everything on it (including itself) with [damage] + * and a small chance to do a spectacular effect per entity (if a chance above 0 is provided). + * + * Args: + * * turf/target: The turf to fall onto. Cannot be null. + * * damage: The raw numerical damage to do by default. + * * chance_to_crit: The percent chance of a critical hit occurring. Default: 0 + * * forced_crit_case: If given a value from crushing.dm, [target] and its contents will always be hit with that specific critical hit. Default: null + * * paralyze_time: The time, in deciseconds, a given mob/living will be paralyzed for if crushed. + * * crush_dir: The direction the crush is coming from. Default: dir of src to [target]. + * * damage_type: The type of damage to do. Default: BRUTE + * * damage_flag: The attack flag for armor purposes. Default: MELEE + * * rotation: The angle of which to rotate src's transform by on a successful tilt. Default: 90. + * + * Returns: A collection of bitflags defined in crushing.dm. Read that file's documentation for info. + */ +/atom/movable/proc/fall_and_crush(turf/target, damage, chance_to_crit = 0, forced_crit_case = null, paralyze_time, crush_dir = get_dir(get_turf(src), target), damage_type = BRUTE, damage_flag = MELEE, rotation = 90) + + ASSERT(!isnull(target)) + + var/flags_to_return = NONE + + if (!target.is_blocked_turf(TRUE, src, list(src))) + for(var/atom/atom_target in (target.contents) + target) + if (isarea(atom_target)) + continue + + if (SEND_SIGNAL(atom_target, COMSIG_PRE_TILT_AND_CRUSH, src) & COMPONENT_IMMUNE_TO_TILT_AND_CRUSH) + continue + + var/crit_case = forced_crit_case + if (isnull(crit_case) && chance_to_crit > 0) + if (prob(chance_to_crit)) + crit_case = pick_weight(get_crit_crush_chances()) + var/crit_rebate_mult = 1 // lessen the normal damage we deal for some of the crits + + if (!isnull(crit_case)) + crit_rebate_mult = fall_and_crush_crit_rebate_table(crit_case) + apply_crit_crush(crit_case, atom_target) + + var/adjusted_damage = damage * crit_rebate_mult + var/crushed + if (isliving(atom_target)) + crushed = TRUE + var/mob/living/carbon/living_target = atom_target + var/was_alive = living_target.stat != DEAD + var/blocked = living_target.run_armor_check(attack_flag = damage_flag) + if (iscarbon(living_target)) + var/mob/living/carbon/carbon_target = living_target + if(prob(30)) + carbon_target.apply_damage(max(0, adjusted_damage), damage_type, blocked = blocked, forced = TRUE, spread_damage = TRUE, attack_direction = crush_dir) // the 30% chance to spread the damage means you escape breaking any bones + else + var/brute = (damage_type == BRUTE ? damage : 0) * 0.5 + var/burn = (damage_type == BURN ? damage : 0) * 0.5 + carbon_target.take_bodypart_damage(brute, burn, check_armor = TRUE, wound_bonus = 5) // otherwise, deal it to 2 random limbs (or the same one) which will likely shatter something + carbon_target.take_bodypart_damage(brute, burn, check_armor = TRUE, wound_bonus = 5) + carbon_target.AddElement(/datum/element/squish, 80 SECONDS) + else + living_target.apply_damage(adjusted_damage, damage_type, blocked = blocked, forced = TRUE, attack_direction = crush_dir) + + living_target.Paralyze(paralyze_time) + living_target.emote("scream") + playsound(living_target, 'sound/effects/blob/blobattack.ogg', 40, TRUE) + playsound(living_target, 'sound/effects/splat.ogg', 50, TRUE) + post_crush_living(living_target, was_alive) + flags_to_return |= (SUCCESSFULLY_CRUSHED_MOB|SUCCESSFULLY_CRUSHED_ATOM) + + else if(check_atom_crushable(atom_target)) + atom_target.take_damage(adjusted_damage, damage_type, damage_flag, FALSE, crush_dir) + crushed = TRUE + flags_to_return |= SUCCESSFULLY_CRUSHED_ATOM + + if (crushed) + atom_target.visible_message(span_danger("[atom_target] is crushed by [src]!"), span_userdanger("You are crushed by [src]!")) + SEND_SIGNAL(atom_target, COMSIG_POST_TILT_AND_CRUSH, src) + + var/matrix/to_turn = turn(transform, rotation) + animate(src, transform = to_turn, 0.2 SECONDS) + playsound(src, 'sound/effects/bang.ogg', 40) + + visible_message(span_danger("[src] tips over, slamming hard onto [target]!")) + flags_to_return |= SUCCESSFULLY_FELL_OVER + post_tilt() + else + visible_message(span_danger("[src] rebounds comically as it fails to slam onto [target]!")) + + Move(target, crush_dir) // we still TRY to move onto it for shit like teleporters + return flags_to_return + +/** + * Returns a assoc list of (critcase -> num), where critcase is a critical define in crushing.dm and num is a weight. + * Use with pickweight to acquire a random critcase. + */ +/atom/movable/proc/get_crit_crush_chances() + RETURN_TYPE(/list) + + return list( + CRUSH_CRIT_SHATTER_LEGS = 100, + CRUSH_CRIT_PARAPLEGIC = 80, + CRUSH_CRIT_HEADGIB = 20, + CRUSH_CRIT_SQUISH_LIMB = 100 + ) + +/** + * Exists for the purposes of custom behavior. + * Called directly after [crushed] is crushed. + * + * Args: + * * mob/living/crushed: The mob that was crushed. + * * was_alive: Boolean. True if the mob was alive before the crushing. + */ +/atom/movable/proc/post_crush_living(mob/living/crushed, was_alive) + return + +/** + * Exists for the purposes of custom behavior. + * Called directly after src actually rotates and falls over. + */ +/atom/movable/proc/post_tilt() + return + +/** + * Should be where critcase effects are actually implemented. Use this to apply critcases. + * Args: + * * crit_case: The chosen critcase, defined in crushing.dm. + * * atom/atom_target: The target to apply the critical hit to. Cannot be null. Can be anything except /area. + * + * Returns: + * TRUE if a crit case is successfully applied, FALSE otherwise. + */ +/atom/movable/proc/apply_crit_crush(crit_case, atom/atom_target) + switch (crit_case) + if(CRUSH_CRIT_SHATTER_LEGS) // shatter their legs and bleed 'em + if (!iscarbon(atom_target)) + return FALSE + var/mob/living/carbon/carbon_target = atom_target + carbon_target.bleed(150) + var/obj/item/bodypart/leg/left/left_leg = carbon_target.get_bodypart(BODY_ZONE_L_LEG) + if(left_leg) + left_leg.receive_damage(brute = 200) + var/obj/item/bodypart/leg/right/right_leg = carbon_target.get_bodypart(BODY_ZONE_R_LEG) + if(right_leg) + right_leg.receive_damage(brute = 200) + if(left_leg || right_leg) + carbon_target.visible_message(span_danger("[carbon_target]'s legs shatter with a sickening crunch!"), span_userdanger("Your legs shatter with a sickening crunch!")) + return TRUE + if(CRUSH_CRIT_PARAPLEGIC) // paralyze this binch + // the new paraplegic gets like 4 lines of losing their legs so skip them + if (!iscarbon(atom_target)) + return FALSE + var/mob/living/carbon/carbon_target = atom_target + visible_message(span_danger("[carbon_target]'s spinal cord is obliterated with a sickening crunch!"), ignored_mobs = list(carbon_target)) + carbon_target.gain_trauma(/datum/brain_trauma/severe/paralysis/paraplegic) + return TRUE + if(CRUSH_CRIT_SQUISH_LIMB) // limb squish! + if (!iscarbon(atom_target)) + return FALSE + var/mob/living/carbon/carbon_target = atom_target + for(var/obj/item/bodypart/squish_part in carbon_target.bodyparts) + var/severity = pick(WOUND_SEVERITY_MODERATE, WOUND_SEVERITY_SEVERE, WOUND_SEVERITY_CRITICAL) + if (!carbon_target.cause_wound_of_type_and_severity(WOUND_BLUNT, squish_part, severity, wound_source = "crushed by [src]")) + squish_part.receive_damage(brute = 30) + carbon_target.visible_message(span_danger("[carbon_target]'s body is maimed underneath the mass of [src]!"), span_userdanger("Your body is maimed underneath the mass of [src]!")) + return TRUE + if(CRUSH_CRIT_HEADGIB) // skull squish! + if (!iscarbon(atom_target)) + return FALSE + var/mob/living/carbon/carbon_target = atom_target + var/obj/item/bodypart/head/carbon_head = carbon_target.get_bodypart(BODY_ZONE_HEAD) + if(carbon_head) + if(carbon_head.dismember()) + carbon_target.visible_message(span_danger("[carbon_head] explodes in a shower of gore beneath [src]!"), span_userdanger("Oh f-")) + carbon_head.drop_organs() + qdel(carbon_head) + new /obj/effect/gibspawner/human/bodypartless(get_turf(carbon_target), carbon_target) + return TRUE + + return FALSE + +/** + * Tilts ontop of the atom supplied, if crit is true some extra shit can happen. See [fall_and_crush] for return values. + * Arguments: + * fatty - atom to tilt the vendor onto + * local_crit_chance - percent chance of a critical hit + * forced_crit - specific critical hit case to use, if any + * range - the range of the machine when thrown if not adjacent +*/ +/obj/machinery/vending/proc/tilt(atom/fatty, local_crit_chance = crit_chance, forced_crit, range = 1) + if(QDELETED(src) || !has_gravity(src)) + return + + . = NONE + + var/picked_rotation = pick(90, 270) + if(Adjacent(fatty)) + . = fall_and_crush(get_turf(fatty), squish_damage, local_crit_chance, forced_crit, 6 SECONDS, rotation = picked_rotation) + + if (. & SUCCESSFULLY_FELL_OVER) + visible_message(span_danger("[src] tips over!")) + tilted = TRUE + tilted_rotation = picked_rotation + layer = ABOVE_MOB_LAYER + + if(get_turf(fatty) != get_turf(src)) + throw_at(get_turf(fatty), range, 1, spin = FALSE, quickstart = FALSE) + +/obj/machinery/vending/post_crush_living(mob/living/crushed, was_alive) + + if(was_alive && crushed.stat == DEAD && crushed.client) + crushed.client.give_award(/datum/award/achievement/misc/vendor_squish, crushed) // good job losing a fight with an inanimate object idiot + + add_memory_in_range(crushed, 7, /datum/memory/witness_vendor_crush, protagonist = crushed, antagonist = src) + + return ..() + +/** + * Allows damage to be reduced on certain crit cases. + * Args: + * * crit_case: The critical case chosen. + */ +/atom/movable/proc/fall_and_crush_crit_rebate_table(crit_case) + ASSERT(!isnull(crit_case)) + + switch(crit_case) + if (CRUSH_CRIT_SHATTER_LEGS) + return 0.2 + else + return 1 + +/obj/machinery/vending/fall_and_crush_crit_rebate_table(crit_case) + return crit_case == VENDOR_CRUSH_CRIT_GLASSCANDY ? 0.33 : ..() + +/obj/machinery/vending/get_crit_crush_chances() + return list( + VENDOR_CRUSH_CRIT_GLASSCANDY = 100, + VENDOR_CRUSH_CRIT_PIN = 100 + ) + +/obj/machinery/vending/apply_crit_crush(crit_case, atom_target) + . = ..() + if (.) + return TRUE + + switch (crit_case) + if (VENDOR_CRUSH_CRIT_GLASSCANDY) + if (!iscarbon(atom_target)) + return FALSE + var/mob/living/carbon/carbon_target = atom_target + for(var/i in 1 to 7) + var/obj/item/shard/shard = new /obj/item/shard(get_turf(carbon_target)) + var/datum/embedding/embed = shard.get_embed() + embed.embed_chance = 100 + embed.ignore_throwspeed_threshold = TRUE + embed.impact_pain_mult = 1 + carbon_target.hitby(shard, skipcatch = TRUE, hitpush = FALSE) + embed.embed_chance = initial(embed.embed_chance) + embed.ignore_throwspeed_threshold = initial(embed.ignore_throwspeed_threshold) + embed.impact_pain_mult = initial(embed.impact_pain_mult) + return TRUE + if (VENDOR_CRUSH_CRIT_PIN) // pin them beneath the machine until someone untilts it + if (!isliving(atom_target)) + return FALSE + var/mob/living/living_target = atom_target + forceMove(get_turf(living_target)) + buckle_mob(living_target, force=TRUE) + living_target.visible_message(span_danger("[living_target] is pinned underneath [src]!"), span_userdanger("You are pinned down by [src]!")) + return TRUE + + return FALSE + +/** + * Rights the vendor up, unpinning mobs under it, if any. + * Arguments: + * user - mob that has untilted the vendor + */ +/obj/machinery/vending/proc/untilt(mob/user) + if(user) + user.visible_message(span_notice("[user] rights [src]."), \ + span_notice("You right [src].")) + + unbuckle_all_mobs(TRUE) + + tilted = FALSE + layer = initial(layer) + + var/matrix/to_turn = turn(transform, -tilted_rotation) + animate(src, transform = to_turn, 0.2 SECONDS) + tilted_rotation = 0 diff --git a/code/modules/vending/vendor/ui_data.dm b/code/modules/vending/vendor/ui_data.dm new file mode 100644 index 000000000000..e5508c3cd356 --- /dev/null +++ b/code/modules/vending/vendor/ui_data.dm @@ -0,0 +1,181 @@ +///Helper to create a typepath to be used in the UI +#define SANITIZED_PATH(path)(replacetext(replacetext("[path]", "/obj/item/", ""), "/", "-")) + +/obj/machinery/vending/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet_batched/vending), + ) + +/obj/machinery/vending/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Vending", name) + ui.open() + + +/** + * Returns a list of given product records of the vendor to be used in UI. + * arguments: + * records - list of records available + * categories - list of categories available + * premium - bool of whether a record should be priced by a custom/premium price or not + */ +/obj/machinery/vending/proc/collect_records_for_static_data(list/records, list/categories, premium) + PROTECTED_PROC(TRUE) + + var/static/list/default_category = list( + "name" = "Products", + "icon" = "cart-shopping", + ) + + var/list/out_records = list() + + for (var/datum/data/vending_product/record as anything in records) + var/list/static_record = list( + path = SANITIZED_PATH(record.product_path), + name = record.name, + price = record.price, + ref = REF(record), + colorable = record.colorable, + ) + + var/atom/printed = record.product_path + // If it's not GAGS and has no innate colors we have to care about, we use DMIcon + if(ispath(printed, /atom) \ + && (!initial(printed.greyscale_config) || !initial(printed.greyscale_colors)) \ + && !initial(printed.color) \ + ) + static_record["icon"] = initial(printed.icon) + static_record["icon_state"] = initial(printed.icon_state) + + var/list/category = record.category || default_category + if (!isnull(category)) + if (!(category["name"] in categories)) + categories[category["name"]] = list("icon" = category["icon"]) + + static_record["category"] = category["name"] + + if (premium) + static_record["premium"] = TRUE + + out_records += list(static_record) + + return out_records + +/obj/machinery/vending/ui_static_data(mob/user) + var/list/data = list() + data["onstation"] = onstation + if(ad_list.len) + data["ad"] = ad_list[rand(1, ad_list.len)] + data["all_products_free"] = all_products_free + data["department"] = payment_department + data["jobDiscount"] = DEPARTMENT_DISCOUNT + data["product_records"] = list() + data["displayed_currency_icon"] = displayed_currency_icon + data["displayed_currency_name"] = displayed_currency_name + + var/list/categories = list() + + data["product_records"] = collect_records_for_static_data(product_records, categories) + data["coin_records"] = collect_records_for_static_data(coin_records, categories, premium = TRUE) + data["hidden_records"] = collect_records_for_static_data(hidden_records, categories, premium = TRUE) + + data["categories"] = categories + + return data + + +/** + * Returns the balance that the vendor will use for proceeding payment. Most vendors would want to use the user's + * card's account credits balance. + * arguments: + * passed_id - the id card that will be billed for the product + */ +/obj/machinery/vending/proc/fetch_balance_to_use(obj/item/card/id/passed_id) + PROTECTED_PROC(TRUE) + + return passed_id.registered_account.account_balance + +/obj/machinery/vending/ui_data(mob/user) + . = list() + + var/obj/item/card/id/card_used + var/held_cash = 0 + if(isliving(user)) + var/mob/living/living_user = user + card_used = living_user.get_idcard(TRUE) + held_cash = living_user.tally_physical_credits() + + var/list/user_data = null + if(card_used?.registered_account) + user_data = list() + user_data["name"] = card_used.registered_account.account_holder + user_data["cash"] = fetch_balance_to_use(card_used) + held_cash + if(card_used.registered_account.account_job) + user_data["job"] = card_used.registered_account.account_job.title + user_data["department"] = card_used.registered_account.account_job.paycheck_department + else + user_data["job"] = "No Job" + user_data["department"] = DEPARTMENT_UNASSIGNED + .["user"] = user_data + + .["stock"] = list() + for (var/datum/data/vending_product/product_record as anything in product_records + coin_records + hidden_records) + .["stock"][SANITIZED_PATH(product_record.product_path)] = list( + amount = product_record.amount, + free = length(product_record.returned_products) + ) + + if(prob(10) && ad_list.len) + .["ad"] = ad_list[rand(1, ad_list.len)] + + .["extended_inventory"] = extended_inventory + +/obj/machinery/vending/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if(.) + return + + switch(action) + if("vend") + . = vend(params, ui.user) + if("select_colors") + var/datum/data/vending_product/product = locate(params["ref"]) + if(!istype(product)) + return FALSE + var/atom/fake_atom = product.product_path + var/config = initial(fake_atom.greyscale_config) + if(!config) + return FALSE + + var/list/allowed_configs = list("[config]") + if(ispath(fake_atom, /obj/item)) + var/obj/item/item = fake_atom + if(initial(item.greyscale_config_worn)) + allowed_configs += "[initial(item.greyscale_config_worn)]" + if(initial(item.greyscale_config_inhand_left)) + allowed_configs += "[initial(item.greyscale_config_inhand_left)]" + if(initial(item.greyscale_config_inhand_right)) + allowed_configs += "[initial(item.greyscale_config_inhand_right)]" + var/datum/greyscale_modify_menu/menu = new( + src, ui.user, allowed_configs, CALLBACK(src, PROC_REF(_vend_greyscale), params, ui.user), + starting_icon_state=initial(fake_atom.icon_state), + starting_config = initial(fake_atom.greyscale_config), + starting_colors = initial(fake_atom.greyscale_colors) + ) + menu.ui_interact(ui.user) + return TRUE + +/** + * Vends a greyscale modified item. + * arguments: + * menu - greyscale config menu that has been used to vend the item + */ +/obj/machinery/vending/proc/_vend_greyscale(list/params, mob/user, datum/greyscale_modify_menu/menu) + PRIVATE_PROC(TRUE) + + if(user != menu.user) + return + vend(params, user, menu.split_colors) + +#undef SANITIZED_PATH diff --git a/code/modules/vending/wardrobes.dm b/code/modules/vending/wardrobes.dm index 2aa696505e2a..e00c74523bfb 100644 --- a/code/modules/vending/wardrobes.dm +++ b/code/modules/vending/wardrobes.dm @@ -71,6 +71,7 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) refill_canister = /obj/item/vending_refill/wardrobe/sec_wardrobe payment_department = ACCOUNT_SEC light_color = COLOR_MOSTLY_PURE_RED + allow_custom = TRUE /obj/item/vending_refill/wardrobe/sec_wardrobe machine_name = "SecDrobe" @@ -117,6 +118,7 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) ) refill_canister = /obj/item/vending_refill/wardrobe/medi_wardrobe payment_department = ACCOUNT_MED + allow_custom = TRUE /obj/item/vending_refill/wardrobe/medi_wardrobe machine_name = "MediDrobe" @@ -147,6 +149,7 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) refill_canister = /obj/item/vending_refill/wardrobe/engi_wardrobe payment_department = ACCOUNT_ENG light_color = COLOR_VIVID_YELLOW + allow_custom = TRUE /obj/item/vending_refill/wardrobe/engi_wardrobe machine_name = "EngiDrobe" @@ -155,7 +158,7 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) name = "AtmosDrobe" desc = "This relatively unknown vending machine delivers clothing for Atmospherics Technicians, an equally unknown job." icon_state = "atmosdrobe" - product_ads = "Get your inflammable clothing right here!!!" + product_slogans = "Get your inflammable clothing right here!!!" vend_reply = "Thank you for using the AtmosDrobe!" products = list( /obj/item/clothing/accessory/pocketprotector = 3, @@ -172,6 +175,7 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) refill_canister = /obj/item/vending_refill/wardrobe/atmos_wardrobe payment_department = ACCOUNT_ENG light_color = COLOR_VIVID_YELLOW + allow_custom = TRUE /obj/item/vending_refill/wardrobe/atmos_wardrobe machine_name = "AtmosDrobe" @@ -215,6 +219,7 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) ) refill_canister = /obj/item/vending_refill/wardrobe/cargo_wardrobe payment_department = ACCOUNT_CAR + allow_custom = TRUE /obj/item/vending_refill/wardrobe/cargo_wardrobe machine_name = "CargoDrobe" @@ -249,6 +254,7 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) refill_canister = /obj/item/vending_refill/wardrobe/robo_wardrobe extra_price = PAYCHECK_COMMAND * 1.2 payment_department = ACCOUNT_SCI + allow_custom = TRUE /obj/item/vending_refill/wardrobe/robo_wardrobe machine_name = "RoboDrobe" @@ -278,6 +284,7 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) ) refill_canister = /obj/item/vending_refill/wardrobe/science_wardrobe payment_department = ACCOUNT_SCI + allow_custom = TRUE /obj/item/vending_refill/wardrobe/science_wardrobe machine_name = "SciDrobe" @@ -306,6 +313,7 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) refill_canister = /obj/item/vending_refill/wardrobe/hydro_wardrobe payment_department = ACCOUNT_SRV light_color = LIGHT_COLOR_ELECTRIC_GREEN + allow_custom = TRUE /obj/item/vending_refill/wardrobe/hydro_wardrobe machine_name = "HyDrobe" @@ -314,7 +322,7 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) name = "CuraDrobe" desc = "A low-stock vendor only capable of vending clothing for curators and librarians." icon_state = "curadrobe" - product_ads = "Glasses for your eyes and literature for your soul, Curadrobe has it all!; Impress & enthrall your library guests with Curadrobe's extended line of pens!" + product_slogans = "Glasses for your eyes and literature for your soul, Curadrobe has it all!; Impress & enthrall your library guests with Curadrobe's extended line of pens!" vend_reply = "Thank you for using the CuraDrobe!" products = list( /obj/item/clothing/accessory/pocketprotector = 2, @@ -339,6 +347,7 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) ) refill_canister = /obj/item/vending_refill/wardrobe/curator_wardrobe payment_department = ACCOUNT_SRV + allow_custom = TRUE /obj/item/vending_refill/wardrobe/curator_wardrobe machine_name = "CuraDrobe" @@ -388,6 +397,7 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) ) refill_canister = /obj/item/vending_refill/wardrobe/coroner_wardrobe payment_department = ACCOUNT_MED + allow_custom = TRUE /obj/item/vending_refill/wardrobe/coroner_wardrobe machine_name = "MortiDrobe" @@ -425,6 +435,8 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) refill_canister = /obj/item/vending_refill/wardrobe/bar_wardrobe payment_department = ACCOUNT_MED extra_price = PAYCHECK_COMMAND + allow_custom = TRUE + /obj/item/vending_refill/wardrobe/bar_wardrobe machine_name = "BarDrobe" @@ -454,6 +466,7 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) ) refill_canister = /obj/item/vending_refill/wardrobe/chef_wardrobe payment_department = ACCOUNT_SRV + allow_custom = TRUE /obj/item/vending_refill/wardrobe/chef_wardrobe machine_name = "ChefDrobe" @@ -493,6 +506,7 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) extra_price = PAYCHECK_COMMAND * 0.8 payment_department = ACCOUNT_SRV light_color = COLOR_STRONG_MAGENTA + allow_custom = TRUE /obj/item/vending_refill/wardrobe/jani_wardrobe machine_name = "JaniDrobe" @@ -535,6 +549,7 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) ) refill_canister = /obj/item/vending_refill/wardrobe/law_wardrobe payment_department = ACCOUNT_SRV + allow_custom = TRUE /obj/item/vending_refill/wardrobe/law_wardrobe machine_name = "LawDrobe" @@ -581,6 +596,7 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) ) refill_canister = /obj/item/vending_refill/wardrobe/chap_wardrobe payment_department = ACCOUNT_SRV + allow_custom = TRUE /obj/item/vending_refill/wardrobe/chap_wardrobe machine_name = "DeusVend" @@ -612,6 +628,7 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) ) refill_canister = /obj/item/vending_refill/wardrobe/chem_wardrobe payment_department = ACCOUNT_MED + allow_custom = TRUE /obj/item/vending_refill/wardrobe/chem_wardrobe machine_name = "ChemDrobe" @@ -637,6 +654,7 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) ) refill_canister = /obj/item/vending_refill/wardrobe/gene_wardrobe payment_department = ACCOUNT_SCI + allow_custom = TRUE /obj/item/vending_refill/wardrobe/gene_wardrobe machine_name = "GeneDrobe" @@ -645,7 +663,7 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) name = "ViroDrobe" desc = "An unsterilized machine for dispensing virology related clothing." icon_state = "virodrobe" - product_ads = " Viruses getting you down? Then upgrade to sterilized clothing today!" + product_slogans = " Viruses getting you down? Then upgrade to sterilized clothing today!" vend_reply = "Thank you for using the ViroDrobe" products = list( /obj/item/clothing/mask/surgical = 2, @@ -664,6 +682,7 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) ) refill_canister = /obj/item/vending_refill/wardrobe/viro_wardrobe payment_department = ACCOUNT_MED + allow_custom = TRUE /obj/item/vending_refill/wardrobe/viro_wardrobe machine_name = "ViroDrobe" @@ -710,6 +729,7 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) refill_canister = /obj/item/vending_refill/wardrobe/det_wardrobe extra_price = PAYCHECK_COMMAND * 1.75 payment_department = ACCOUNT_SEC + allow_custom = TRUE /obj/item/vending_refill/wardrobe/det_wardrobe machine_name = "DetDrobe" diff --git a/code/modules/vending/youtool.dm b/code/modules/vending/youtool.dm index 819ddbe22089..b73b183fad24 100644 --- a/code/modules/vending/youtool.dm +++ b/code/modules/vending/youtool.dm @@ -33,6 +33,7 @@ default_price = PAYCHECK_CREW extra_price = PAYCHECK_COMMAND * 1.5 payment_department = ACCOUNT_ENG + allow_custom = TRUE /obj/item/vending_refill/youtool machine_name = "YouTool" diff --git a/code/modules/wiremod/core/component_printer.dm b/code/modules/wiremod/core/component_printer.dm index 7797d6c8b62a..343f0db5e6f4 100644 --- a/code/modules/wiremod/core/component_printer.dm +++ b/code/modules/wiremod/core/component_printer.dm @@ -139,6 +139,7 @@ . = ..() if (.) return + var/alist/user_data = ID_DATA(usr) switch (action) if ("print") @@ -150,7 +151,7 @@ if (!(design.build_type & COMPONENT_PRINTER)) return TRUE - if (!materials.can_use_resource(user_data = ID_DATA(usr))) + if (!materials.can_use_resource(user_data = user_data)) return TRUE if (!materials.mat_container.has_materials(design.materials, efficiency_coeff)) @@ -159,7 +160,7 @@ balloon_alert_to_viewers("printed [design.name]") - materials.use_materials(design.materials, efficiency_coeff, 1, "printed", "[design.name]") + materials.use_materials(design.materials, efficiency_coeff, 1, "printed", "[design.name]", user_data) var/atom/printed_design = new design.build_path(drop_location()) printed_design.pixel_x = printed_design.base_pixel_x + rand(-5, 5) printed_design.pixel_y = printed_design.base_pixel_y + rand(-5, 5) @@ -167,7 +168,7 @@ var/datum/material/material = locate(params["ref"]) var/amount = text2num(params["amount"]) // SAFETY: eject_sheets checks for valid mats - materials.eject_sheets(material, amount) + materials.eject_sheets(material_ref = material, eject_amount = amount, user_data = user_data) return TRUE diff --git a/code/modules/wiremod/shell/brain_computer_interface.dm b/code/modules/wiremod/shell/brain_computer_interface.dm index 72d6ca751805..0b61abe7eefd 100644 --- a/code/modules/wiremod/shell/brain_computer_interface.dm +++ b/code/modules/wiremod/shell/brain_computer_interface.dm @@ -250,7 +250,7 @@ return ..() -/datum/action/innate/bci_charge_action/Trigger(trigger_flags) +/datum/action/innate/bci_charge_action/Trigger(mob/clicker, trigger_flags) var/obj/item/stock_parts/power_store/cell/cell = circuit_component.parent.cell if (isnull(cell)) diff --git a/code/modules/wiremod/shell/gun.dm b/code/modules/wiremod/shell/gun.dm index 9bfa8764f41d..6e9043a146a7 100644 --- a/code/modules/wiremod/shell/gun.dm +++ b/code/modules/wiremod/shell/gun.dm @@ -34,10 +34,12 @@ /obj/item/gun/energy/wiremod_gun/Initialize(mapload) . = ..() - AddComponent(/datum/component/shell, list( + var/datum/component/shell/shell = AddComponent(/datum/component/shell, list( new /obj/item/circuit_component/wiremod_gun() ), SHELL_CAPACITY_MEDIUM) + RegisterSignal(shell, COMSIG_SHELL_CIRCUIT_ATTACHED, PROC_REF(on_circuit_attached)) + /obj/item/circuit_component/wiremod_gun display_name = "Gun" desc = "Used to receive entities hit by projectiles from a gun." @@ -62,6 +64,18 @@ /obj/item/circuit_component/wiremod_gun/unregister_shell(atom/movable/shell) UnregisterSignal(shell, list(COMSIG_PROJECTILE_ON_HIT, COMSIG_GUN_CHAMBER_PROCESSED)) +/obj/item/gun/energy/wiremod_gun/proc/on_circuit_attached(datum/component/shell/source) + SIGNAL_HANDLER + + if (istype(source, /datum/component/shell)) + var/datum/component/shell/comp = source + var/obj/item/integrated_circuit/circuit = comp.attached_circuit + if (!circuit.cell) + return + var/transferred = src.cell.give(min(0.1 * STANDARD_CELL_CHARGE, circuit.cell.charge)) + if (transferred) + circuit.cell.use(transferred, force=TRUE) + /** * Called when the shell item shoots something */ diff --git a/code/modules/zombie/organs.dm b/code/modules/zombie/organs.dm index 5a70881851e0..10f1b5cf1c8d 100644 --- a/code/modules/zombie/organs.dm +++ b/code/modules/zombie/organs.dm @@ -6,11 +6,11 @@ icon_state = "blacktumor" var/causes_damage = TRUE var/datum/species/old_species = /datum/species/human - var/living_transformation_time = 30 + var/living_transformation_time = 3 SECONDS var/converts_living = FALSE - var/revive_time_min = 450 - var/revive_time_max = 700 + var/revive_time_min = 45 SECONDS + var/revive_time_max = 70 SECONDS var/timer_id /obj/item/organ/zombie_infection/Initialize(mapload) diff --git a/config/config.txt b/config/config.txt index 1059bfe277a0..f4391f83bcc0 100644 --- a/config/config.txt +++ b/config/config.txt @@ -459,10 +459,15 @@ MINUTE_CLICK_LIMIT 400 BASE_MC_TICK_RATE 1 ##High population MC tick rate -## Byond rounds timer values UP, but the tick rate is modified with heuristics during lag spites so setting this to something like 2 +## Byond rounds timer values DOWN, but the tick rate is modified with heuristics during lag spites so setting this to something like 2 ## will make it run every 2 byond ticks, but will also double the effect of anti-lag heuristics. You can instead set it to something like -## 1.1 to make it run every 2 byond ticks, but only increase the effect of anti-lag heuristics by 10%. or 1.5 for 50%. +## 1.1 to make it run every 1 byond ticks, but will increase the effect of anti-lag heuristics by 10%. or 1.5 for 50%. ## (As an aside, you could in theory also reduce the effect of anti-lag heuristics in the base tick rate by setting it to something like 0.5) +## +## Note: The reason to set this at/above 2 would be to carve out more time for sleeping procs and muck with scheduling the mc. +## Basically if set to 2 one tick will be dominated by sleeping procs, and the other has... a chance of being dominated by the mc (a low chance but yaknow) +## This is largely deprecated behavior, we have systems that do this automatically and more effectively. I'm keeping this here because of the heuristics stuff +## since I have a weaker grasp on that, but it should basically never be set above 2 (guarantees skipped ticks and horrible gameplay) HIGH_POP_MC_TICK_RATE 1.1 ##Engage high pop mode if player count raises above this (Player in this context means any connected user. Lobby, ghost or in-game all count) diff --git a/cutter_templates/bitmask/cardinal_32x32.toml b/cutter_templates/bitmask/cardinal_32x32.toml index 987e9126b2d8..f06fb8264771 100644 --- a/cutter_templates/bitmask/cardinal_32x32.toml +++ b/cutter_templates/bitmask/cardinal_32x32.toml @@ -1,9 +1,18 @@ mode = "BitmaskSlice" -# Don't try and put directions in our icon states -produce_dirs = false +# Dictates what sort of directions this dmi will have. +# There are currently 4 possible values: +# Standard (Default, used if none is specified) -> only 1 direction per frame +# Cardinals -> 4 directions per frame, arranged as duplicates of the full input set out to the right +# ... in order SOUTH, NORTH, EAST, WEST +# All -> 8 directions per frame, arranged in the same pattern as cardinals +# ... in order SOUTH, NORTH, EAST, WEST, SOUTHEAST, SOUTHWEST, NORTHEAST, NORTHWEST +# CardinalsRotated -> 1 direction per frame, will be expanded in the dmi to be Cardinals, with each +# ... direction being that base junction, rotated in whatever way. Exists mostly so client.dir supporting states +# ... can be created. Creates a lot of duplicate blocks otherwise. +directional_strategy = "Standard" # We smooth only with our cardinal neighbors, not the ones on the diagonal -smooth_diagonally = false +output_type = "Cardinal" # Take as input a set of 32x32 blocks [icon_size] diff --git a/cutter_templates/bitmask/diagonal_32x32.toml b/cutter_templates/bitmask/diagonal_32x32.toml index 1e80e3627e92..0da4d2a10c40 100644 --- a/cutter_templates/bitmask/diagonal_32x32.toml +++ b/cutter_templates/bitmask/diagonal_32x32.toml @@ -1,7 +1,7 @@ template = "bitmask/cardinal_32x32" # We're diagonal -smooth_diagonally = true +output_type = "StandardDiagonal" # And because of that we need a state for all directions [positions] diff --git a/cutter_templates/bitmask/diagonal_corner_32x32.toml b/cutter_templates/bitmask/diagonal_corner_32x32.toml new file mode 100644 index 000000000000..a895df5b0b25 --- /dev/null +++ b/cutter_templates/bitmask/diagonal_corner_32x32.toml @@ -0,0 +1,20 @@ +template = "bitmask/diagonal_32x32" + +# We're a corner diagonal +output_type = "CornerDiagonal" + +# And because of that we need a state for all directions and all our asshole corner bits +[positions] +convex = 0 +vertical = 1 +horizontal = 2 +concave = 3 +flat = 4 +bottom_right_inner = 5 +bottom_left_inner = 6 +top_right_inner = 7 +top_left_inner = 8 +bottom_right_outer = 9 +bottom_left_outer = 10 +top_right_outer = 11 +top_left_outer = 12 diff --git a/cutter_templates/bitmask/restore_corners.toml b/cutter_templates/bitmask/restore_corners.toml new file mode 100644 index 000000000000..fbbcdc086284 --- /dev/null +++ b/cutter_templates/bitmask/restore_corners.toml @@ -0,0 +1,25 @@ +# Bitmask restoration! (Corners) +# Allows for easy mass extraction of template pngs and their configs from a dmi +# Use this if you have a dmi and you want a cutter config you can edit easily +# Of note, while it tries its best it is nowhere near perfect. We don't parity check against the existing dmi +# And we also do not account for overrided states very well +# Always double check (and be aware that dmi is weird so you may get diffs of 1 rgb value when doin this) +mode = "BitmaskSliceReconstruct" +# List of icon states to pull out, expanded to get the standard ordering for diagonals +extract = [ + "0", "3", "12", "15", "255", + "6-diagonal", "10-diagonal", "5-diagonal", "9-diagonal", + "38-diagonal", "74-diagonal", "21-diagonal", "137-diagonal" +] + +# Map of name -> state that will be encoded into a positions list later +# Lets you extract particular states and use them to fill in for states later +# Useful to carry over odd snowflake states +#[bespoke] + +# Map of key -> value to set on the created config +# Lets you set arbitrary values on the created config, mostly useful for batch processing +# IMPORTANT NOTE: We sort of assume you'll setup a default template here (since this is for batch processing), +# so if things work odd that's likely why +#[set] +#template = "\"bitmask/diagonal_corner_32x32\"" diff --git a/dependencies.sh b/dependencies.sh index c89c1d8597a7..910fc9d0281f 100644 --- a/dependencies.sh +++ b/dependencies.sh @@ -8,7 +8,7 @@ export BYOND_MAJOR=516 export BYOND_MINOR=1659 #rust_g git tag -export RUST_G_VERSION=3.9.0 +export RUST_G_VERSION=4.0.0 # node version export NODE_VERSION_LTS=22.11.0 @@ -32,5 +32,5 @@ export DREAMLUAU_VERSION=0.1.2 export CUTTER_REPO=spacestation13/hypnagogic #hypnagogic git tag -export CUTTER_VERSION=v4.0.0 +export CUTTER_VERSION=v5.0.0 diff --git a/html/changelogs/AutoChangeLog-pr-92146.yml b/html/changelogs/AutoChangeLog-pr-92146.yml deleted file mode 100644 index 9a96e3013fe5..000000000000 --- a/html/changelogs/AutoChangeLog-pr-92146.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: "Rhials" -delete-after: True -changes: - - balance: "Nightmares/Shadowpeople are no longer stunned by intense flashes like flashbangs or handheld flashes." - - balance: "Nightmares/Shadowpeople are now harmed and confused by ALL flash sources, including welding or other sources of flash-like flashing." - - sound: "Nightmares now have a wretched hiss as their default scream sound. Spooky!" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-92329.yml b/html/changelogs/AutoChangeLog-pr-92329.yml deleted file mode 100644 index d56bbbda78e7..000000000000 --- a/html/changelogs/AutoChangeLog-pr-92329.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: "Bisar" -delete-after: True -changes: - - qol: "Power cells and megacells now take much less time to print." - - balance: "Power cells now take the base-item time-to-print ( 10 seconds -> 3.2 seconds ), WITHOUT the stock-item print speed increase." - - balance: "Megacells now take 5 seconds to print ( 10 seconds -> 5 seconds), WITHOUT the stock-item print speed increase." \ No newline at end of file diff --git a/html/changelogs/archive/2025-07.yml b/html/changelogs/archive/2025-07.yml index 17b4ac79232c..7ade717b2ea1 100644 --- a/html/changelogs/archive/2025-07.yml +++ b/html/changelogs/archive/2025-07.yml @@ -723,3 +723,54 @@ - balance: Sphere MODule bombs no longer hit NODE drones and minebots - balance: Ice demon/ice demon cube afterimages can now be walked through by players - bugfix: Sphere MODule bombs now aggro basicmobs hit by their explosions +2025-07-30: + Bisar: + - qol: Power cells and megacells now take much less time to print. + - balance: Power cells now take the base-item time-to-print ( 10 seconds -> 3.2 + seconds ), WITHOUT the stock-item print speed increase. + - balance: Megacells now take 5 seconds to print ( 10 seconds -> 5 seconds), WITHOUT + the stock-item print speed increase. + Rhials: + - balance: Nightmares/Shadowpeople are no longer stunned by intense flashes like + flashbangs or handheld flashes. + - balance: Nightmares/Shadowpeople are now harmed and confused by ALL flash sources, + including welding or other sources of flash-like flashing. + - sound: Nightmares now have a wretched hiss as their default scream sound. Spooky! + TealSeer: + - refactor: refactored custom vending machine brand code, a new var on /obj/machinery/vending + called allow_custom now determines whether the machine can be chosen when screwdrivering + the circuit board +2025-07-31: + Aliceee2ch: + - bugfix: Tier 3 cyber heart now prevents bleeding as intended + Bisar: + - bugfix: Fixed a couple of missing entries for user_data + - code_imp: Ore silo logs will now generate an entry for a failed ID_DATA entry + instead of not generating anything if the initial provided user_data wasn't + valid. + - bugfix: The calculation for discharged energy when committing suicide with a power + storage part should now be correctly evaluated. + Ghommie: + - bugfix: Fixes a few dishes getting a bit too, uh, meaty when cut. + - bugfix: Fixes being able to turn different types of cooked spaghetti into generic + cooked spaghetti with an oven. + JohnFulpWillard: + - rscadd: Added a new role to Mafia; the Coroner, which takes the Chaplain's ability + to see dead people's roles. + - rscadd: Mafia Chaplains now speak with the dead at night instead, and the dead + are corpselocked to prevent cheating. + - bugfix: Mafia's HoS doesn't kill himself when executing non-townies. + - qol: You can now update your notes & send them in chat while dead, as well as + look up the descriptions of other roles. + LemonInTheDark: + - bugfix: Distortion/fov effects now properly impact the full game world + Melbert: + - qol: Adds some wardrobes and backpacks to Catwalk laundry + dorms + MelokG and KREKS: + - image: resprited all RPEDs + - image: RPEDs now play an animation when replacing parts + SmArtKar: + - bugfix: Fixed fly infusion deleting the last infused organ upon activation + Thunder12345: + - map: Tramstation's xenobiology now receives xeno eggs in the middle of the chamber + instead of tucked away at the back. diff --git a/html/changelogs/archive/2025-08.yml b/html/changelogs/archive/2025-08.yml new file mode 100644 index 000000000000..1fbbd4964b94 --- /dev/null +++ b/html/changelogs/archive/2025-08.yml @@ -0,0 +1,369 @@ +2025-08-01: + 00-Steven: + - bugfix: Newspapers can be scrolled through again. + Glamyr: + - image: update old sprites of general minerals in hands + Maximal08: + - qol: Right-clicking with a sheet of metal on a tile puts a computer or machine + if you have a board of the appropriate type in your other hand. + SmArtKar: + - rscdel: Removes forced tint from NVGs + - bugfix: Fixed eyes not being affected by human height + - rscdel: Hitting objects at high speed in zero-g no longer makes you crash into + them. + SyncIt21: + - bugfix: reagent intercept operations use correct volumes e.g. ph buffers + - bugfix: impure cryostylane now has inverse cryogeldia effects when applied on + mods + - bugfix: exposing reagents now uses correct volumes i.e. injecting blood into mobs + don't increase it exponentially and stops when max levels are reached. Exposure + affects of all reagents are lessened upon continuous exposure + - refactor: refactors how reagent affects are applied on mobs. Report bugs on github + itsmeow: + - code_imp: Improved performance of several icon metadata operations. + - rscadd: IconForge GAGS now fully supports the OR blend mode and color matrices. + necromanceranne: + - bugfix: Operatives once again can purchase syndicate bombs. + - balance: Athletics experience gain from non-workout sources, such as climbing + ladders, hopping tables and rope climbing, experience diminishing returns as + you gain athletics levels. To reach legendary fitness, you really should hit + the gym. + projectkepler-ru: + - bugfix: .38 Truestrike speedloader not being printable + - spellcheck: .38 Truestrike Magazine no longer have the extra E and Flareshot now + no longer lose the R + trazodont: + - bugfix: honey sweetrolls can now be eaten + zxaber: + - bugfix: Cyborgs correctly take brute damage from lasers again. + - bugfix: Cyborgs correctly take burn damage from EMP again. + - bugfix: EMP Flashlights work on cyborgs for non-combat mode as well as combat + mode +2025-08-02: + Aliceee2ch: + - bugfix: Fixed the nukies outpost chemical locker not having beakers inside of + a beaker box + SmArtKar: + - bugfix: Fixed fire arrow ritual not being accessible + - bugfix: Fixed certain nullrod types not being usable for certain holy and unholy + interactions + - bugfix: Fixed emissive bloom being all white + - bugfix: Fixed M90 underbarrel having its separate inaccessible firing pin + SyncIt21: + - bugfix: reagent transfer amounts with multiplier applied(e.g. cryotubes) have + been corrected + ZeWaka: + - bugfix: tgui windows should now stop flashing for a single frame elsewhere when + opening + necromanceranne: + - bugfix: Swimming now no longer punishes you with less gains for swimming in heavy + gravity, but also weirdly easier to swim in. + subject217: + - spellcheck: fixed a typo in the operative bomb implant manual +2025-08-03: + SmArtKar: + - qol: Monster cores now display above corpses when dropped + Thunder12345: + - rscadd: Glitter can now be made from plastic polymers and aluminium. + - rscadd: Plastic polymer can be made at any temperature, and then heated to produce + sheets. + - rscadd: Glitter can now be made any colour, mix 10 units each of glitter and acetone + to change its colour to that of the other reagents in the beaker. + - rscadd: Mixing different colours of glitter will cause a random selection of those + colours to appear on the floor when released. + - rscadd: Being exposed to glitter in reagent form causes you to cough up more glitter + onto the floor + - rscadd: Dragging glittery crates will now spread a trail of glitter and angry + janitors behind them. + - image: Added new glitter sprites (that don't look like gasses) +2025-08-04: + carpotoxin: + - qol: Mobs entangled within spacevines are layered above the spacevines for as + long as they stay buckled +2025-08-05: + FalloutFalcon: + - code_imp: debug proc for painting the world based on spatial grid. + IgiariValkyr: + - bugfix: Fixes the void eater's right-hand sprite + OnlineGirlfriend: + - image: update barnyard spellbook + Pickle-Coding: + - bugfix: Fixes BZ formation not actually creating the nitrogen and oxygen when + it decomposes nitrous oxide. + SmArtKar: + - bugfix: Fixed style meter text going out of bounds + - bugfix: Fixed recovered crew bodybags being foldable while there's a "corpse" + inside + - bugfix: Knocking someone out cold now properly stops their panic attack + - bugfix: Fixed portable atmospheric machines trying to add themselves to SSair + queue when destroyed + TheEmber: + - bugfix: Fixed bitrunning psyker +2025-08-06: + Bisar: + - bugfix: Correct a few banners on Catwalk Station to be mundane banners, and not + the magic barriers that heal you and remove your stuns. + Ghommie: + - bugfix: Shooting a fish with a laser gun or otherwise damaging it like any other + item or object will reduce its health. + Rhials: + - balance: Dragon rifts no longer take damage from telekinesis-ed objects. Get in + there and fight like a man! + SmArtKar: + - bugfix: Fixed All-in-One tcomms servers not translating radio frequencies + - bugfix: Fixed RPD causing runtimes when placing atmos components for the first + time. + SyncIt21: + - code_imp: moved designs & circuitboards for bitrunning into their correct files + - qol: adds examines & screentips for bitrunning netpod, bitforge & server on how + to deconstruct them + - bugfix: bitforge can be deconstructed with a screwdriver & crowbar + - refactor: code for copying reagents has been refactored. Please report bugs on + github + - bugfix: You can no longer see parallel universes when 2 or more people gets shoved + into closets. + - code_imp: cleaned up closet see through code. It's documented & slightly faster + performance wise +2025-08-07: + Arturlang: + - code_imp: action's now pass down the clicker via the first arg of Trigger() + - code_imp: antagonist ui_act now ensures that the owners of the antag datum thesmelves + can only do stuff in the UI + - bugfix: admins giving out heretic antag no longer opens it for them. + - bugfix: Action button binding works again + Exester509: + - qol: Made angel wings more maneuverable + - spellcheck: The cytology crate no longer references the non-existent research + plumbing constructor. + FalloutFalcon: + - map: converts all non-basic space turfs to space/basic + Majkl-J: + - rscadd: Redesigned the Icebox, Tram, and Wawa gardens, adding fishing pools to + them + Rhials: + - balance: The Chain of Command will give a speed bonus to other players when right-clicking + them. + SmArtKar: + - rscadd: Added specular overlays - some items like hazard vests or firefighter + suits no longer outright glow in the dark, but instead amplify existing light + to shine brighter than their surroundings. + - rscadd: Redid unrestricted access airlock overlays to look less bad + - bugfix: Fixed unrestricted access overlays not showing up on windoors. + - bugfix: Fixed blood/glass floor glow going over objects +2025-08-08: + Arturlang: + - bugfix: ghosts can't buy heretic powers + Melbert: + - balance: Airlock crushing now does 20 damage, up from 15. Also may uncommonly + cause wounds. Also is properly affected by damage reduction or modifiers. + - balance: Mood threshold to become "crazy" changed from -7 (one moderately bad + event) to -15 (two moderately bad events). + SmArtKar: + - balance: Fluoride Stare quirk now takes much longer to start damaging your eyes, + and deals less eye damage per second + - bugfix: Fixed lizard blinking constantly freezing one of their eyes + - bugfix: Fixed brain damage not updating your blinking to be async when you get + stupid enough + - bugfix: Fixed species changing breaking passive blinking + lelandkemble: + - qol: informs changelings they can't absorb people they've already taken the DNA + of + - spellcheck: changelings refer to themselves in second-person less + necromanceranne: + - balance: Gravity anomalies can be properly clicked. Rather than chain stunning + you, the anomaly will knock you down. You can avoid the negatives of gravity + anomalies by wearing magboots. (Yes, it did not really protect you until now) + - balance: Flux anomalies detonate in a much smaller explosion, but release a wide + EMP as well. + - balance: Long range gas analyzers can now scan anomalies. + panvxv: + - rscadd: Bone bracers to Divine Adept kit + - qol: Adept robes doesn't cover arms, hands and feet as to match the sprite + - qol: Ancient armour doesn't cover hands as to match the sprite + - qol: Divine Archer coat doesn't cover arms, hands and feet as to match the sprite + - qol: Divine Archer bracers now have the same armor as Divine Archer coat + - balance: Divine Archer boots have their own unique armor +2025-08-09: + Cirrial: + - balance: You will no longer be allergic to saline-glucose solution. + LemonInTheDark: + - admin: MC tab renders without jumping around constantly now, some labels are more + readable + Melbert: + - rscadd: Adds Black Workboots to Loadout + SmArtKar: + - refactor: Refactored how human names are updated, yell at us on our github if + you spot any bugs! + - bugfix: Fixed slimepeople regenerating blood while dead + - bugfix: Rescued the station from a time-space bubble + Thunder12345: + - bugfix: CRAB-17 machines will now hold onto funds internally if they cannot find + the original user's bank account to transfer them to. +2025-08-10: + Mickyan: + - rscdel: Reduces mood penalty from Empaths examining people with the Fundamentally + Evil quirk + vinylspiders: + - code_imp: adds support to check for a required_bodytype or required_organ_flag + for the damage getter procs +2025-08-11: + Axidyuwu: + - bugfix: after lizard raid on the popular chef show "Kotra Wellington" was renamed + to "Korta Wellington" + Melbert: + - qol: Grand Pianos can be climbed on + SyncIt21: + - bugfix: deconstructing material platforms drops the correct sheet types + - bugfix: certain material platforms now have the correct amount of custom materials + in them +2025-08-12: + Absolucy: + - code_imp: Item weapon description elements are now initialized when first examined, + instead of immediately upon initialization. + Aliceee2ch: + - bugfix: Removed floating posters in DeltaStation science + Cameron-The-Raven: + - bugfix: Nar'Sie can no longer be spam-clicked as a ghost and destroy ears via + infinite shell creation. + - bugfix: Cult-banned players can no longer interact with Nar'Sie + - qol: Interacting with Nar'Sie as a ghost no longer creates a ghost query and instead + allows you to immediately become a harvester after confirming you wish to become + a harvester. + Exester509: + - rscdel: The Justice mech has been removed. + Ghommie: + - bugfix: burned mess made with a microwave, oven or griddle once again toxins. + Hatterhat: + - code_imp: Ammo boxes' multiload variable is now a bitflag that determines if a + magazine can be multiloaded into or out of. Ammo boxes can multiload in or out, + while magazines can only multiload in. + - image: .223 ammo now has a distinct casing icon. + - bugfix: Foam force magazines now have a proper description. + L0pz: + - image: Resprited the whip, chain, cat o' nine tails and liz o' nine tails + LemonInTheDark: + - bugfix: Using fake space tiles on icebox will no longer summon the endless void + Maximal08: + - bugfix: manufacturing lathe now prints items according to their quantity in the + autolathe + - bugfix: night vision module can now be activated and turned off again. + Melbert: + - qol: The access changing software (the HoP console) now has ID two slots again + (one for the HoP's id and one for the ID being changed). You can insert IDs + in the secondary slot via the UI or right click, and remove them via the UI + or alt-right click. + - qol: If your PDA is destroyed via acid or bombs, your ID (and similar contents + such as disks) are spit out instead of being deleted + - rscdel: Deletes the "New IDs and you" memo in the HoP's office. They haven't been + new for 4 years. + - bugfix: Engineering sub-tab in the access changing software no longer looks messed + up + - bugfix: Fix reversed alt-click logic for mod pcs + SSensum13: + - bugfix: fixed incorrect use of bit flags in some components. + SmArtKar: + - bugfix: Shuttle catastrophe should no longer cause random unintended crashlandings + - bugfix: Fixed light flickering potentially causing lag + - bugfix: Fixed fishes not dying on dry land + SyncIt21: + - code_imp: cleaned up vending machine code + - qol: vending machines now have more product slogans you never heard before + - qol: custom & normal vending machines now have more feedback on why an item could + not be loaded + - qol: vending machines now display random ads on the UI + - qol: custom vending machines can be deconstructed via crowbar safely only after + unlinking your account from the machine. + - qol: upon deconstructing a custom vendor all its products are moved into its refill + canister & it will be restored when reconstructing the machine elsewhere + - bugfix: Returned items to the vending machine now show up as free in the UI and + won't be greyed out if you don't have credits to get them back + - bugfix: items that leave the vending machine by any means will update the UI in + all cases + - bugfix: loading items by hand to the vending machine now respects the max_amount + for that category + - bugfix: custom vendors can now actually be used by players who are not the owner + thus enabling them to transfer credits to the owner during purchases & basically + they do their job again + - bugfix: custom vendors now show the correct icon for inserted items + - bugfix: Items with different names & custom prices now show up in unique rows + in custom vendors + - refactor: separated custom & normal vending machine code. Reduced UI code & improved + attack chain + Thunder12345: + - bugfix: Chaplain helmets and clockwork armour now have the same wound protection + as the other chaplain body armours. + Time-Green: + - rscadd: Adds an organ growing kit to medical cargo orders. Grow your very own + evolved hearts at home! + - bugfix: Mutagen can now mutate fish + tonyhawq: + - bugfix: fixes circuit gun not recharging it's internal cell when an integrated + circuit is inserted + trazodont: + - bugfix: added the CRAFT_CLEARS_REAGENTS flag to the rootdough recipes, bananas + + water will no longer doom lizard food ever again +2025-08-13: + 00-Steven: + - refactor: Refactored say modes (i.e. robotic talk, drone chat, hivemind speak), + custom say verbs (i.e. `says in a custom way*The spoken thing.`), and quoted + messages. Please report any issues. + - rscadd: You can now use custom say verbs with robotic talk, drone chat, alien + hivemind talk, AI holograms, holopad calls, modlink/scryer calls, imaginary + friends, and blob telepathy. + - rscadd: Message spans like from say modifiers carry over through robotic talk, + drone chat, alien hivemind talk, AI holograms, holopad calls, and modlink/scryer + calls. + - bugfix: Languages and say verbs carry over through holopad calls and modlink/scryer + calls. + - bugfix: You can use custom say verbs when using the department radio key. + - bugfix: Drone chat now counts as a radio message for chat settings, parallel to + binary chat. + - bugfix: No longer highlight messages you sent yourself over drone chat, blob telepathy, + and speaking as revenant. + - admin: Removed a redundant emote log entry for custom say verbs/'radio emotes' + accompanying a message. Instead it's only logged as part of the message it accompanied + in the say logs. + - admin: Pure custom say verbs without accompanying messages are now similarly tagged + with their type (i.e. robotic talk, drone chat, imaginary friend) in the emote + logs. + - admin: Pure custom say verbs without accompanying messages are properly logged + if somehow forced. + - admin: Alien hivemind talk logs are properly tagged as alien hivemind talk. + - admin: Drone chat is properly logged. + - refactor: Refactored how the newscaster network keeps track of channels. Please + report any issues. + - bugfix: Newscaster channels no longer have an increasing random chance of breaking + whenever a new channel is made. + Aliceee2ch: + - balance: Paramedic now has extra access to pharmacy on skeleton crew station. + Krysonism: + - image: The tesla cannon has new sprites. + - image: The tesla parts kit has new sprites. + - image: The tesla cannon has a new shocking beam effect when firing. + - sound: The tesla cannon has new sounds. + - balance: The tesla cannon must now be unfolded to fire. + - bugfix: looping sounds now stop playing sounds when commaned to do so. + Melbert: + - bugfix: Bashing vendors works good again + SyncIt21: + - bugfix: product category vendors start out correctly filled & can be refilled + with cargo ordered vending canisters again + TealSeer: + - bugfix: fixed firelocks spawning with no area name or ID + Thunder12345: + - code_imp: Reduced the number of files named misc.dm or similar by 14%. + - code_imp: Converted a lot of time-based variables to be expressed with time defines. + kuricityy: + - balance: Buffs godslayer armor values to be worth the effort you have to put in + to getting it. + lelandkemble: + - spellcheck: whispering now spelled correctly + - bugfix: prevents inputting letters into the abandoned crate puzzle + throwawayuseless: + - rscadd: New Diode Disks which allow you to configurate emitters with special functions. + - rscadd: New Engi & CE exclusive traitor item, a diode disk that causes an emitter + to create low radius explosions when it hits things. Note that this will reduce + the fire-rate of your emitter. + uaioy: + - qol: All coroner's offices that lacked a cabinet will now have one, coroner's + organ fridge is now more accessible diff --git a/html/statbrowser.css b/html/statbrowser.css index f7b09a2cde60..da470bc4ae13 100644 --- a/html/statbrowser.css +++ b/html/statbrowser.css @@ -99,6 +99,21 @@ img { border-bottom-color: #000000; } +.statcontent { + flex: 1; + padding: 0.75em 0.5em; + overflow-y: auto; + overflow-x: hidden; +} + +.mcstatcontent { + flex: 1; + padding: 0.75em 0.5em; + overflow-y: auto; + overflow-x: auto; + white-space: pre; +} + #under-menu { height: 0.5em; background-color: #eeeeee; @@ -109,13 +124,6 @@ img { background-color: #eeeeee; } -#statcontent { - flex: 1; - padding: 0.75em 0.5em; - overflow-y: auto; - overflow-x: hidden; -} - .grid-container { margin: -0.25em; } diff --git a/html/statbrowser.html b/html/statbrowser.html index 9b1862912502..bbbd8fa53ab9 100644 --- a/html/statbrowser.html +++ b/html/statbrowser.html @@ -1,6 +1,6 @@
-
+
diff --git a/html/statbrowser.js b/html/statbrowser.js index 3bc8336012b1..f9b889cd9f83 100644 --- a/html/statbrowser.js +++ b/html/statbrowser.js @@ -236,6 +236,7 @@ function tab_change(tab) { document.getElementById(tab).className = "button active"; // make current button active var spell_tabs_thingy = spell_tabs.includes(tab); var verb_tabs_thingy = verb_tabs.includes(tab); + statcontentdiv.className = "statcontent" if (tab == "Status") { draw_status(); } else if (tab == "MC") { @@ -389,6 +390,7 @@ function draw_status() { function draw_mc() { statcontentdiv.textContent = ""; + statcontentdiv.className = "mcstatcontent" var table = document.createElement("table"); for (var i = 0; i < mc_tab_parts.length; i++) { var part = mc_tab_parts[i]; diff --git a/icons/effects/beam.dmi b/icons/effects/beam.dmi index 12bbd4788f0f..9915bcf238dc 100644 Binary files a/icons/effects/beam.dmi and b/icons/effects/beam.dmi differ diff --git a/icons/effects/glitter.dmi b/icons/effects/glitter.dmi new file mode 100644 index 000000000000..6beb6c9821b6 Binary files /dev/null and b/icons/effects/glitter.dmi differ diff --git a/icons/hud/screen_alert.dmi b/icons/hud/screen_alert.dmi index d7a288212b67..1d1f3ff79c0b 100644 Binary files a/icons/hud/screen_alert.dmi and b/icons/hud/screen_alert.dmi differ diff --git a/icons/hud/style_meter.dmi b/icons/hud/style_meter.dmi index 5da5f72c3eef..8e8c61ba8523 100644 Binary files a/icons/hud/style_meter.dmi and b/icons/hud/style_meter.dmi differ diff --git a/icons/map_icons/clothing/accessory.dmi b/icons/map_icons/clothing/accessory.dmi index 1f048116d9ad..1719b8a73bbd 100644 Binary files a/icons/map_icons/clothing/accessory.dmi and b/icons/map_icons/clothing/accessory.dmi differ diff --git a/icons/map_icons/clothing/head/_head.dmi b/icons/map_icons/clothing/head/_head.dmi index 4032ed9f1028..b05d7b9b050d 100644 Binary files a/icons/map_icons/clothing/head/_head.dmi and b/icons/map_icons/clothing/head/_head.dmi differ diff --git a/icons/map_icons/clothing/head/beret.dmi b/icons/map_icons/clothing/head/beret.dmi index 9fb1cf8fa9e1..975bbf80cf2c 100644 Binary files a/icons/map_icons/clothing/head/beret.dmi and b/icons/map_icons/clothing/head/beret.dmi differ diff --git a/icons/map_icons/clothing/mask.dmi b/icons/map_icons/clothing/mask.dmi index 2651067be636..e8fa3c8594ca 100644 Binary files a/icons/map_icons/clothing/mask.dmi and b/icons/map_icons/clothing/mask.dmi differ diff --git a/icons/map_icons/clothing/neck.dmi b/icons/map_icons/clothing/neck.dmi index 10a1bd2ddfed..a477d15da68c 100644 Binary files a/icons/map_icons/clothing/neck.dmi and b/icons/map_icons/clothing/neck.dmi differ diff --git a/icons/map_icons/clothing/shoes.dmi b/icons/map_icons/clothing/shoes.dmi index b73fd466d3f1..1381efbf904f 100644 Binary files a/icons/map_icons/clothing/shoes.dmi and b/icons/map_icons/clothing/shoes.dmi differ diff --git a/icons/map_icons/clothing/suit/_suit.dmi b/icons/map_icons/clothing/suit/_suit.dmi index 43b0400ab55d..484ecf793177 100644 Binary files a/icons/map_icons/clothing/suit/_suit.dmi and b/icons/map_icons/clothing/suit/_suit.dmi differ diff --git a/icons/map_icons/clothing/suit/costume.dmi b/icons/map_icons/clothing/suit/costume.dmi index 7dbba8d3e16b..3db984062306 100644 Binary files a/icons/map_icons/clothing/suit/costume.dmi and b/icons/map_icons/clothing/suit/costume.dmi differ diff --git a/icons/map_icons/clothing/under/_under.dmi b/icons/map_icons/clothing/under/_under.dmi index 7549dc9baa5a..82a09867c533 100644 Binary files a/icons/map_icons/clothing/under/_under.dmi and b/icons/map_icons/clothing/under/_under.dmi differ diff --git a/icons/map_icons/clothing/under/color.dmi b/icons/map_icons/clothing/under/color.dmi index c091de182d64..aa09a947f9dc 100644 Binary files a/icons/map_icons/clothing/under/color.dmi and b/icons/map_icons/clothing/under/color.dmi differ diff --git a/icons/map_icons/clothing/under/costume.dmi b/icons/map_icons/clothing/under/costume.dmi index 4402789a4c54..bd69a61ff4dc 100644 Binary files a/icons/map_icons/clothing/under/costume.dmi and b/icons/map_icons/clothing/under/costume.dmi differ diff --git a/icons/map_icons/clothing/under/dress.dmi b/icons/map_icons/clothing/under/dress.dmi index 6e6a9883a126..fde8dfbebaaa 100644 Binary files a/icons/map_icons/clothing/under/dress.dmi and b/icons/map_icons/clothing/under/dress.dmi differ diff --git a/icons/map_icons/items/_item.dmi b/icons/map_icons/items/_item.dmi index 9e3ce568af03..c81bfa7d4f4c 100644 Binary files a/icons/map_icons/items/_item.dmi and b/icons/map_icons/items/_item.dmi differ diff --git a/icons/map_icons/items/encryptionkey.dmi b/icons/map_icons/items/encryptionkey.dmi index c44fac3a26e7..be7514ad789c 100644 Binary files a/icons/map_icons/items/encryptionkey.dmi and b/icons/map_icons/items/encryptionkey.dmi differ diff --git a/icons/map_icons/items/pda.dmi b/icons/map_icons/items/pda.dmi index 6ba874d57fba..488e0ea2e7ac 100644 Binary files a/icons/map_icons/items/pda.dmi and b/icons/map_icons/items/pda.dmi differ diff --git a/icons/map_icons/objects.dmi b/icons/map_icons/objects.dmi index 8fc20d26983f..faefc9cb0d61 100644 Binary files a/icons/map_icons/objects.dmi and b/icons/map_icons/objects.dmi differ diff --git a/icons/mob/inhands/antag/voidwalker_righthand.dmi b/icons/mob/inhands/antag/voidwalker_righthand.dmi index f227c6105ad1..17dc25516335 100644 Binary files a/icons/mob/inhands/antag/voidwalker_righthand.dmi and b/icons/mob/inhands/antag/voidwalker_righthand.dmi differ diff --git a/icons/mob/inhands/items/sheets_lefthand.dmi b/icons/mob/inhands/items/sheets_lefthand.dmi index aed1d5eddca1..6bfb4fbfdeb5 100644 Binary files a/icons/mob/inhands/items/sheets_lefthand.dmi and b/icons/mob/inhands/items/sheets_lefthand.dmi differ diff --git a/icons/mob/inhands/items/sheets_righthand.dmi b/icons/mob/inhands/items/sheets_righthand.dmi index e669afcae7db..c49274871318 100644 Binary files a/icons/mob/inhands/items/sheets_righthand.dmi and b/icons/mob/inhands/items/sheets_righthand.dmi differ diff --git a/icons/mob/inhands/weapons/64x_guns_left.dmi b/icons/mob/inhands/weapons/64x_guns_left.dmi index faeae6f2eea5..ac78bda58263 100644 Binary files a/icons/mob/inhands/weapons/64x_guns_left.dmi and b/icons/mob/inhands/weapons/64x_guns_left.dmi differ diff --git a/icons/mob/inhands/weapons/64x_guns_right.dmi b/icons/mob/inhands/weapons/64x_guns_right.dmi index 2ccdeb577fed..575a60967159 100644 Binary files a/icons/mob/inhands/weapons/64x_guns_right.dmi and b/icons/mob/inhands/weapons/64x_guns_right.dmi differ diff --git a/icons/mob/rideables/mech_construct.dmi b/icons/mob/rideables/mech_construct.dmi index 656322b8187a..c25eb971f2e3 100644 Binary files a/icons/mob/rideables/mech_construct.dmi and b/icons/mob/rideables/mech_construct.dmi differ diff --git a/icons/mob/rideables/mech_construction.dmi b/icons/mob/rideables/mech_construction.dmi index 6e1cdbc3a2d4..f26dbe17fd03 100644 Binary files a/icons/mob/rideables/mech_construction.dmi and b/icons/mob/rideables/mech_construction.dmi differ diff --git a/icons/mob/rideables/mecha.dmi b/icons/mob/rideables/mecha.dmi index a52a3ff5d4be..d21037c49ab0 100644 Binary files a/icons/mob/rideables/mecha.dmi and b/icons/mob/rideables/mecha.dmi differ diff --git a/icons/obj/machines/bitrunning.dmi b/icons/obj/machines/bitrunning.dmi index d61e910d195b..626ab4ff4f39 100644 Binary files a/icons/obj/machines/bitrunning.dmi and b/icons/obj/machines/bitrunning.dmi differ diff --git a/icons/obj/mafia.dmi b/icons/obj/mafia.dmi index 7c3b525c0055..49e3e5767480 100644 Binary files a/icons/obj/mafia.dmi and b/icons/obj/mafia.dmi differ diff --git a/icons/obj/medical/organs/organs.dmi b/icons/obj/medical/organs/organs.dmi index 5f045ac4f9b5..cadfac4b9928 100644 Binary files a/icons/obj/medical/organs/organs.dmi and b/icons/obj/medical/organs/organs.dmi differ diff --git a/icons/obj/science/vatgrowing.dmi b/icons/obj/science/vatgrowing.dmi index ec8b5dcb6acd..4d25046ea764 100644 Binary files a/icons/obj/science/vatgrowing.dmi and b/icons/obj/science/vatgrowing.dmi differ diff --git a/icons/obj/service/library.dmi b/icons/obj/service/library.dmi index 7a37ac0e8cc3..bf1c1c659ac6 100644 Binary files a/icons/obj/service/library.dmi and b/icons/obj/service/library.dmi differ diff --git a/icons/obj/smooth_structures/platform/frame_faces/window_frame_bamboo.png.toml b/icons/obj/smooth_structures/platform/frame_faces/window_frame_bamboo.png.toml index ca6044375c0c..29fa4cca0ff4 100644 --- a/icons/obj/smooth_structures/platform/frame_faces/window_frame_bamboo.png.toml +++ b/icons/obj/smooth_structures/platform/frame_faces/window_frame_bamboo.png.toml @@ -8,7 +8,3 @@ y = 33 [output_icon_size] x = 32 y = 33 - -[cut_pos] -x = 16 -y = 16 \ No newline at end of file diff --git a/icons/obj/smooth_structures/platform/frame_faces/window_frame_bronze.png.toml b/icons/obj/smooth_structures/platform/frame_faces/window_frame_bronze.png.toml index ef568da6ab27..9a8326a93bcc 100644 --- a/icons/obj/smooth_structures/platform/frame_faces/window_frame_bronze.png.toml +++ b/icons/obj/smooth_structures/platform/frame_faces/window_frame_bronze.png.toml @@ -1,14 +1,2 @@ output_name = "window_frame_bronze" template = "bitmask/diagonal_32x32.toml" - -[icon_size] -x = 32 -y = 32 - -[output_icon_size] -x = 32 -y = 32 - -[cut_pos] -x = 16 -y = 16 \ No newline at end of file diff --git a/icons/obj/smooth_structures/platform/frame_faces/window_frame_cult.png.toml b/icons/obj/smooth_structures/platform/frame_faces/window_frame_cult.png.toml index 12914b352a14..eb9c06599673 100644 --- a/icons/obj/smooth_structures/platform/frame_faces/window_frame_cult.png.toml +++ b/icons/obj/smooth_structures/platform/frame_faces/window_frame_cult.png.toml @@ -1,14 +1,2 @@ output_name = "window_frame_cult" template = "bitmask/diagonal_32x32.toml" - -[icon_size] -x = 32 -y = 32 - -[output_icon_size] -x = 32 -y = 32 - -[cut_pos] -x = 16 -y = 16 \ No newline at end of file diff --git a/icons/obj/smooth_structures/platform/frame_faces/window_frame_gold.png.toml b/icons/obj/smooth_structures/platform/frame_faces/window_frame_gold.png.toml index 4e6708939b46..528983bb0509 100644 --- a/icons/obj/smooth_structures/platform/frame_faces/window_frame_gold.png.toml +++ b/icons/obj/smooth_structures/platform/frame_faces/window_frame_gold.png.toml @@ -1,14 +1,2 @@ output_name = "window_frame_gold" template = "bitmask/diagonal_32x32.toml" - -[icon_size] -x = 32 -y = 32 - -[output_icon_size] -x = 32 -y = 32 - -[cut_pos] -x = 16 -y = 16 \ No newline at end of file diff --git a/icons/obj/smooth_structures/platform/frame_faces/window_frame_iron.png.toml b/icons/obj/smooth_structures/platform/frame_faces/window_frame_iron.png.toml index f3ccff491485..db015e176b95 100644 --- a/icons/obj/smooth_structures/platform/frame_faces/window_frame_iron.png.toml +++ b/icons/obj/smooth_structures/platform/frame_faces/window_frame_iron.png.toml @@ -1,14 +1,2 @@ output_name = "window_frame_iron" template = "bitmask/diagonal_32x32.toml" - -[icon_size] -x = 32 -y = 32 - -[output_icon_size] -x = 32 -y = 32 - -[cut_pos] -x = 16 -y = 16 \ No newline at end of file diff --git a/icons/obj/smooth_structures/platform/frame_faces/window_frame_material.png.toml b/icons/obj/smooth_structures/platform/frame_faces/window_frame_material.png.toml index 7e11ef273921..4a19e2b0fafb 100644 --- a/icons/obj/smooth_structures/platform/frame_faces/window_frame_material.png.toml +++ b/icons/obj/smooth_structures/platform/frame_faces/window_frame_material.png.toml @@ -1,14 +1,2 @@ output_name = "window_frame_material" template = "bitmask/diagonal_32x32.toml" - -[icon_size] -x = 32 -y = 32 - -[output_icon_size] -x = 32 -y = 32 - -[cut_pos] -x = 16 -y = 16 \ No newline at end of file diff --git a/icons/obj/smooth_structures/platform/frame_faces/window_frame_normal.png.toml b/icons/obj/smooth_structures/platform/frame_faces/window_frame_normal.png.toml index 90dbfccbbcd2..b66c79fe0834 100644 --- a/icons/obj/smooth_structures/platform/frame_faces/window_frame_normal.png.toml +++ b/icons/obj/smooth_structures/platform/frame_faces/window_frame_normal.png.toml @@ -1,14 +1,2 @@ output_name = "window_frame_normal" template = "bitmask/diagonal_32x32.toml" - -[icon_size] -x = 32 -y = 32 - -[output_icon_size] -x = 32 -y = 32 - -[cut_pos] -x = 16 -y = 16 \ No newline at end of file diff --git a/icons/obj/smooth_structures/platform/frame_faces/window_frame_paperframe.png.toml b/icons/obj/smooth_structures/platform/frame_faces/window_frame_paperframe.png.toml index ee2a4a251e8f..ef7ad65c2c1d 100644 --- a/icons/obj/smooth_structures/platform/frame_faces/window_frame_paperframe.png.toml +++ b/icons/obj/smooth_structures/platform/frame_faces/window_frame_paperframe.png.toml @@ -1,14 +1,2 @@ output_name = "window_frame_paperframe" template = "bitmask/diagonal_32x32.toml" - -[icon_size] -x = 32 -y = 32 - -[output_icon_size] -x = 32 -y = 32 - -[cut_pos] -x = 16 -y = 16 \ No newline at end of file diff --git a/icons/obj/smooth_structures/platform/frame_faces/window_frame_pizza.png.toml b/icons/obj/smooth_structures/platform/frame_faces/window_frame_pizza.png.toml index ee2a4a251e8f..ef7ad65c2c1d 100644 --- a/icons/obj/smooth_structures/platform/frame_faces/window_frame_pizza.png.toml +++ b/icons/obj/smooth_structures/platform/frame_faces/window_frame_pizza.png.toml @@ -1,14 +1,2 @@ output_name = "window_frame_paperframe" template = "bitmask/diagonal_32x32.toml" - -[icon_size] -x = 32 -y = 32 - -[output_icon_size] -x = 32 -y = 32 - -[cut_pos] -x = 16 -y = 16 \ No newline at end of file diff --git a/icons/obj/smooth_structures/platform/frame_faces/window_frame_plastitanium.png.toml b/icons/obj/smooth_structures/platform/frame_faces/window_frame_plastitanium.png.toml index 722035c4576f..36cf38c58322 100644 --- a/icons/obj/smooth_structures/platform/frame_faces/window_frame_plastitanium.png.toml +++ b/icons/obj/smooth_structures/platform/frame_faces/window_frame_plastitanium.png.toml @@ -1,14 +1,2 @@ output_name = "window_frame_plastitanium" template = "bitmask/diagonal_32x32.toml" - -[icon_size] -x = 32 -y = 32 - -[output_icon_size] -x = 32 -y = 32 - -[cut_pos] -x = 16 -y = 16 \ No newline at end of file diff --git a/icons/obj/smooth_structures/platform/frame_faces/window_frame_rusty.png.toml b/icons/obj/smooth_structures/platform/frame_faces/window_frame_rusty.png.toml index 80f7eeffc4fc..fd608c6597ce 100644 --- a/icons/obj/smooth_structures/platform/frame_faces/window_frame_rusty.png.toml +++ b/icons/obj/smooth_structures/platform/frame_faces/window_frame_rusty.png.toml @@ -1,14 +1,2 @@ output_name = "window_frame_rusty" template = "bitmask/diagonal_32x32.toml" - -[icon_size] -x = 32 -y = 32 - -[output_icon_size] -x = 32 -y = 32 - -[cut_pos] -x = 16 -y = 16 \ No newline at end of file diff --git a/icons/obj/smooth_structures/platform/frame_faces/window_frame_sandstone.png.toml b/icons/obj/smooth_structures/platform/frame_faces/window_frame_sandstone.png.toml index 80f7eeffc4fc..fd608c6597ce 100644 --- a/icons/obj/smooth_structures/platform/frame_faces/window_frame_sandstone.png.toml +++ b/icons/obj/smooth_structures/platform/frame_faces/window_frame_sandstone.png.toml @@ -1,14 +1,2 @@ output_name = "window_frame_rusty" template = "bitmask/diagonal_32x32.toml" - -[icon_size] -x = 32 -y = 32 - -[output_icon_size] -x = 32 -y = 32 - -[cut_pos] -x = 16 -y = 16 \ No newline at end of file diff --git a/icons/obj/smooth_structures/platform/frame_faces/window_frame_shuttle.png.toml b/icons/obj/smooth_structures/platform/frame_faces/window_frame_shuttle.png.toml index 7b69b502b72d..8f1ebaabb6be 100644 --- a/icons/obj/smooth_structures/platform/frame_faces/window_frame_shuttle.png.toml +++ b/icons/obj/smooth_structures/platform/frame_faces/window_frame_shuttle.png.toml @@ -1,14 +1,2 @@ output_name = "window_frame_shuttle" template = "bitmask/diagonal_32x32.toml" - -[icon_size] -x = 32 -y = 32 - -[output_icon_size] -x = 32 -y = 32 - -[cut_pos] -x = 16 -y = 16 \ No newline at end of file diff --git a/icons/obj/smooth_structures/platform/frame_faces/window_frame_silver.png.toml b/icons/obj/smooth_structures/platform/frame_faces/window_frame_silver.png.toml index 0785dc4d1c73..bdc754a95b2b 100644 --- a/icons/obj/smooth_structures/platform/frame_faces/window_frame_silver.png.toml +++ b/icons/obj/smooth_structures/platform/frame_faces/window_frame_silver.png.toml @@ -1,14 +1,2 @@ output_name = "window_frame_silver" template = "bitmask/diagonal_32x32.toml" - -[icon_size] -x = 32 -y = 32 - -[output_icon_size] -x = 32 -y = 32 - -[cut_pos] -x = 16 -y = 16 \ No newline at end of file diff --git a/icons/obj/smooth_structures/platform/frame_faces/window_frame_uranium.png.toml b/icons/obj/smooth_structures/platform/frame_faces/window_frame_uranium.png.toml index 7d811bf0c73a..cbff8857a536 100644 --- a/icons/obj/smooth_structures/platform/frame_faces/window_frame_uranium.png.toml +++ b/icons/obj/smooth_structures/platform/frame_faces/window_frame_uranium.png.toml @@ -1,14 +1,2 @@ output_name = "window_frame_uranium" template = "bitmask/diagonal_32x32.toml" - -[icon_size] -x = 32 -y = 32 - -[output_icon_size] -x = 32 -y = 32 - -[cut_pos] -x = 16 -y = 16 diff --git a/icons/obj/storage/storage.dmi b/icons/obj/storage/storage.dmi index f77d72dcebdf..c9495d48325d 100644 Binary files a/icons/obj/storage/storage.dmi and b/icons/obj/storage/storage.dmi differ diff --git a/icons/obj/storage/storage_wide.dmi b/icons/obj/storage/storage_wide.dmi new file mode 100644 index 000000000000..ac71d433dccb Binary files /dev/null and b/icons/obj/storage/storage_wide.dmi differ diff --git a/icons/obj/weapons/guns/ammo.dmi b/icons/obj/weapons/guns/ammo.dmi index 183e67da699c..37533a6cdeb4 100644 Binary files a/icons/obj/weapons/guns/ammo.dmi and b/icons/obj/weapons/guns/ammo.dmi differ diff --git a/icons/obj/weapons/guns/projectiles_impact.dmi b/icons/obj/weapons/guns/projectiles_impact.dmi index 710507d4c85a..5aea86fa8dcb 100644 Binary files a/icons/obj/weapons/guns/projectiles_impact.dmi and b/icons/obj/weapons/guns/projectiles_impact.dmi differ diff --git a/icons/obj/weapons/guns/projectiles_muzzle.dmi b/icons/obj/weapons/guns/projectiles_muzzle.dmi index 9bf78ba4a539..095102f6d894 100644 Binary files a/icons/obj/weapons/guns/projectiles_muzzle.dmi and b/icons/obj/weapons/guns/projectiles_muzzle.dmi differ diff --git a/icons/obj/weapons/guns/projectiles_tracer.dmi b/icons/obj/weapons/guns/projectiles_tracer.dmi index ba3bd1f93776..d7246394e689 100644 Binary files a/icons/obj/weapons/guns/projectiles_tracer.dmi and b/icons/obj/weapons/guns/projectiles_tracer.dmi differ diff --git a/icons/obj/weapons/guns/wide_guns.dmi b/icons/obj/weapons/guns/wide_guns.dmi index e7f28f2ec38f..180c09c3e89f 100644 Binary files a/icons/obj/weapons/guns/wide_guns.dmi and b/icons/obj/weapons/guns/wide_guns.dmi differ diff --git a/icons/obj/weapons/improvised.dmi b/icons/obj/weapons/improvised.dmi index a98d5cad860d..dc24804c54a4 100644 Binary files a/icons/obj/weapons/improvised.dmi and b/icons/obj/weapons/improvised.dmi differ diff --git a/icons/obj/weapons/whip.dmi b/icons/obj/weapons/whip.dmi index b067b11af5b8..884c496ae8e7 100644 Binary files a/icons/obj/weapons/whip.dmi and b/icons/obj/weapons/whip.dmi differ diff --git a/icons/turf/smooth_wall.dmi b/icons/turf/smooth_wall.dmi index e46ea0ae7789..d7d58faded2e 100644 Binary files a/icons/turf/smooth_wall.dmi and b/icons/turf/smooth_wall.dmi differ diff --git a/icons/turf/smooth_wall.png b/icons/turf/smooth_wall.png new file mode 100644 index 000000000000..a13fd5985bc7 Binary files /dev/null and b/icons/turf/smooth_wall.png differ diff --git a/icons/turf/smooth_wall.png.toml b/icons/turf/smooth_wall.png.toml new file mode 100644 index 000000000000..9804c0e9ced2 --- /dev/null +++ b/icons/turf/smooth_wall.png.toml @@ -0,0 +1,2 @@ +output_name = "smooth_wall" +template = "bitmask/diagonal_corner_32x32" diff --git a/icons/turf/space.dmi b/icons/turf/space.dmi index 5123f115876b..e115c405954b 100644 Binary files a/icons/turf/space.dmi and b/icons/turf/space.dmi differ diff --git a/icons/turf/walls/abductor_wall.dmi b/icons/turf/walls/abductor_wall.dmi index 4f731d99f4cd..fbec7aeca5e9 100644 Binary files a/icons/turf/walls/abductor_wall.dmi and b/icons/turf/walls/abductor_wall.dmi differ diff --git a/icons/turf/walls/abductor_wall.png b/icons/turf/walls/abductor_wall.png new file mode 100644 index 000000000000..b42e86351025 Binary files /dev/null and b/icons/turf/walls/abductor_wall.png differ diff --git a/icons/turf/walls/abductor_wall.png.toml b/icons/turf/walls/abductor_wall.png.toml new file mode 100644 index 000000000000..f7ae578260f8 --- /dev/null +++ b/icons/turf/walls/abductor_wall.png.toml @@ -0,0 +1,2 @@ +output_name = "abductor_wall" +template = "bitmask/diagonal_corner_32x32" diff --git a/icons/turf/walls/misc_wall.dmi b/icons/turf/walls/misc_wall.dmi new file mode 100644 index 000000000000..99f0a553a017 Binary files /dev/null and b/icons/turf/walls/misc_wall.dmi differ diff --git a/icons/turf/walls/plastinum_wall.dmi b/icons/turf/walls/plastinum_wall.dmi index 30ea5dbf945a..7d9880abb05f 100644 Binary files a/icons/turf/walls/plastinum_wall.dmi and b/icons/turf/walls/plastinum_wall.dmi differ diff --git a/icons/turf/walls/plastinum_wall.png b/icons/turf/walls/plastinum_wall.png new file mode 100644 index 000000000000..9f26835b5613 Binary files /dev/null and b/icons/turf/walls/plastinum_wall.png differ diff --git a/icons/turf/walls/plastinum_wall.png.toml b/icons/turf/walls/plastinum_wall.png.toml new file mode 100644 index 000000000000..dfd0ce9953ad --- /dev/null +++ b/icons/turf/walls/plastinum_wall.png.toml @@ -0,0 +1,2 @@ +output_name = "plastinum_wall" +template = "bitmask/diagonal_corner_32x32" diff --git a/icons/turf/walls/plastitanium_wall.dmi b/icons/turf/walls/plastitanium_wall.dmi index 078d4642785a..ec1d09356f12 100644 Binary files a/icons/turf/walls/plastitanium_wall.dmi and b/icons/turf/walls/plastitanium_wall.dmi differ diff --git a/icons/turf/walls/plastitanium_wall.png b/icons/turf/walls/plastitanium_wall.png new file mode 100644 index 000000000000..1e5c17c5a158 Binary files /dev/null and b/icons/turf/walls/plastitanium_wall.png differ diff --git a/icons/turf/walls/plastitanium_wall.png.toml b/icons/turf/walls/plastitanium_wall.png.toml new file mode 100644 index 000000000000..48e4487f3612 --- /dev/null +++ b/icons/turf/walls/plastitanium_wall.png.toml @@ -0,0 +1,2 @@ +output_name = "plastitanium_wall" +template = "bitmask/diagonal_corner_32x32" diff --git a/icons/turf/walls/shuttle_wall.dmi b/icons/turf/walls/shuttle_wall.dmi index 3d9374b4a30d..f11a7dce2db2 100644 Binary files a/icons/turf/walls/shuttle_wall.dmi and b/icons/turf/walls/shuttle_wall.dmi differ diff --git a/icons/turf/walls/shuttle_wall.png b/icons/turf/walls/shuttle_wall.png new file mode 100644 index 000000000000..b3166417938b Binary files /dev/null and b/icons/turf/walls/shuttle_wall.png differ diff --git a/icons/turf/walls/shuttle_wall.png.toml b/icons/turf/walls/shuttle_wall.png.toml new file mode 100644 index 000000000000..87655f3687dd --- /dev/null +++ b/icons/turf/walls/shuttle_wall.png.toml @@ -0,0 +1,2 @@ +output_name = "shuttle_wall" +template = "bitmask/diagonal_corner_32x32.toml" diff --git a/icons/turf/walls/survival_pod_walls.dmi b/icons/turf/walls/survival_pod_walls.dmi index 01700f1ed6f9..74ea1da99ef8 100644 Binary files a/icons/turf/walls/survival_pod_walls.dmi and b/icons/turf/walls/survival_pod_walls.dmi differ diff --git a/icons/turf/walls/survival_pod_walls.png b/icons/turf/walls/survival_pod_walls.png new file mode 100644 index 000000000000..c3eb4b8e1c3b Binary files /dev/null and b/icons/turf/walls/survival_pod_walls.png differ diff --git a/icons/turf/walls/survival_pod_walls.png.toml b/icons/turf/walls/survival_pod_walls.png.toml new file mode 100644 index 000000000000..ea4f6553fa30 --- /dev/null +++ b/icons/turf/walls/survival_pod_walls.png.toml @@ -0,0 +1,2 @@ +output_name = "survival_pod_walls" +template = "bitmask/diagonal_corner_32x32" diff --git a/rust_g.dll b/rust_g.dll index 4401dd48583d..ee66aafe9d3f 100644 Binary files a/rust_g.dll and b/rust_g.dll differ diff --git a/sound/items/weapons/gun/tesla/attributions.txt b/sound/items/weapons/gun/tesla/attributions.txt new file mode 100644 index 000000000000..c0584097eb97 --- /dev/null +++ b/sound/items/weapons/gun/tesla/attributions.txt @@ -0,0 +1,7 @@ +{ + tesla_loop.ogg - https://freesound.org/people/Department64/sounds/554749/, License: CC BY 4.0 + tesla_start.ogg - https://freesound.org/people/Department64/sounds/554749/, https://freesound.org/people/iainmccurdy/sounds/759257/, License: CC BY 4.0 + click_creak.ogg - https://freesound.org/people/Sonicquinn/sounds/435834/, https://freesound.org/people/holisoysilvi/sounds/610182/, License: CC 0 + squeak_latch.ogg - https://freesound.org/people/Sonicquinn/sounds/435834/, https://freesound.org/people/holisoysilvi/sounds/610182/, License: CC 0 + power_breaker_fan.ogg - https://freesound.org/people/Yoyodaman234/sounds/183544/, https://freesound.org/people/jessepash/sounds/139970/, https://freesound.org/people/sribubba/sounds/130154/, License: CC 0 +} \ No newline at end of file diff --git a/sound/items/weapons/gun/tesla/click_creak.ogg b/sound/items/weapons/gun/tesla/click_creak.ogg new file mode 100644 index 000000000000..10327062765e Binary files /dev/null and b/sound/items/weapons/gun/tesla/click_creak.ogg differ diff --git a/sound/items/weapons/gun/tesla/power_breaker_fan.ogg b/sound/items/weapons/gun/tesla/power_breaker_fan.ogg new file mode 100644 index 000000000000..7896f50e46b9 Binary files /dev/null and b/sound/items/weapons/gun/tesla/power_breaker_fan.ogg differ diff --git a/sound/items/weapons/gun/tesla/squeak_latch.ogg b/sound/items/weapons/gun/tesla/squeak_latch.ogg new file mode 100644 index 000000000000..773aefcb32b5 Binary files /dev/null and b/sound/items/weapons/gun/tesla/squeak_latch.ogg differ diff --git a/sound/items/weapons/gun/tesla/tesla_loop.ogg b/sound/items/weapons/gun/tesla/tesla_loop.ogg new file mode 100644 index 000000000000..3cafcbf5a6cb Binary files /dev/null and b/sound/items/weapons/gun/tesla/tesla_loop.ogg differ diff --git a/sound/items/weapons/gun/tesla/tesla_start.ogg b/sound/items/weapons/gun/tesla/tesla_start.ogg new file mode 100644 index 000000000000..4869cee74594 Binary files /dev/null and b/sound/items/weapons/gun/tesla/tesla_start.ogg differ diff --git a/tgstation.dme b/tgstation.dme index 17ebe2a1d395..b875a49ca2a7 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -552,10 +552,14 @@ #include "code\_globalvars\lists\canisters.dm" #include "code\_globalvars\lists\cargo.dm" #include "code\_globalvars\lists\client.dm" +#include "code\_globalvars\lists\clothing.dm" #include "code\_globalvars\lists\color.dm" +#include "code\_globalvars\lists\communication.dm" #include "code\_globalvars\lists\crafting.dm" +#include "code\_globalvars\lists\department.dm" +#include "code\_globalvars\lists\disposals.dm" #include "code\_globalvars\lists\engineering.dm" -#include "code\_globalvars\lists\flavor_misc.dm" +#include "code\_globalvars\lists\ghost.dm" #include "code\_globalvars\lists\icons.dm" #include "code\_globalvars\lists\keybindings.dm" #include "code\_globalvars\lists\maintenance_loot.dm" @@ -572,6 +576,9 @@ #include "code\_globalvars\lists\reagents.dm" #include "code\_globalvars\lists\rtd.dm" #include "code\_globalvars\lists\silo.dm" +#include "code\_globalvars\lists\sound.dm" +#include "code\_globalvars\lists\status_display.dm" +#include "code\_globalvars\lists\strings.dm" #include "code\_globalvars\lists\typecache.dm" #include "code\_globalvars\lists\wiremod.dm" #include "code\_globalvars\lists\xenobiology.dm" @@ -1456,6 +1463,7 @@ #include "code\datums\dna\blocks\dna_features_block.dm" #include "code\datums\dna\blocks\dna_identity_block.dm" #include "code\datums\elements\_element.dm" +#include "code\datums\elements\above_mob_drop.dm" #include "code\datums\elements\ai_control_examine.dm" #include "code\datums\elements\ai_flee_while_injured.dm" #include "code\datums\elements\ai_held_item.dm" @@ -2361,15 +2369,18 @@ #include "code\game\objects\effects\anomalies\anomalies_hallucination.dm" #include "code\game\objects\effects\anomalies\anomalies_pyroclastic.dm" #include "code\game\objects\effects\anomalies\anomalies_vortex.dm" +#include "code\game\objects\effects\decals\chemspray.dm" #include "code\game\objects\effects\decals\cleanable.dm" #include "code\game\objects\effects\decals\crayon.dm" #include "code\game\objects\effects\decals\decal.dm" -#include "code\game\objects\effects\decals\misc.dm" #include "code\game\objects\effects\decals\remains.dm" +#include "code\game\objects\effects\decals\structure.dm" #include "code\game\objects\effects\decals\cleanable\aliens.dm" +#include "code\game\objects\effects\decals\cleanable\ants.dm" #include "code\game\objects\effects\decals\cleanable\blood.dm" #include "code\game\objects\effects\decals\cleanable\food.dm" -#include "code\game\objects\effects\decals\cleanable\misc.dm" +#include "code\game\objects\effects\decals\cleanable\fuel.dm" +#include "code\game\objects\effects\decals\cleanable\mess.dm" #include "code\game\objects\effects\decals\cleanable\robots.dm" #include "code\game\objects\effects\decals\turfdecal\dirt.dm" #include "code\game\objects\effects\decals\turfdecal\markings.dm" @@ -2386,10 +2397,12 @@ #include "code\game\objects\effects\effect_system\fluid_spread\effects_smoke.dm" #include "code\game\objects\effects\landmarks\atmospherics_sanity_landmarks.dm" #include "code\game\objects\effects\particles\acid.dm" +#include "code\game\objects\effects\particles\echo.dm" #include "code\game\objects\effects\particles\fire.dm" +#include "code\game\objects\effects\particles\food.dm" #include "code\game\objects\effects\particles\gravity.dm" -#include "code\game\objects\effects\particles\misc.dm" #include "code\game\objects\effects\particles\note_particles.dm" +#include "code\game\objects\effects\particles\plant.dm" #include "code\game\objects\effects\particles\slime.dm" #include "code\game\objects\effects\particles\smoke.dm" #include "code\game\objects\effects\particles\water.dm" @@ -3689,7 +3702,6 @@ #include "code\modules\bitrunning\abilities.dm" #include "code\modules\bitrunning\alerts.dm" #include "code\modules\bitrunning\areas.dm" -#include "code\modules\bitrunning\designs.dm" #include "code\modules\bitrunning\event.dm" #include "code\modules\bitrunning\job.dm" #include "code\modules\bitrunning\outfits.dm" @@ -4727,8 +4739,8 @@ #include "code\modules\mafia\map_pieces.dm" #include "code\modules\mafia\outfits.dm" #include "code\modules\mafia\abilities\abilities.dm" +#include "code\modules\mafia\abilities\investigative\autopsy.dm" #include "code\modules\mafia\abilities\investigative\investigate.dm" -#include "code\modules\mafia\abilities\investigative\pray.dm" #include "code\modules\mafia\abilities\investigative\reveal.dm" #include "code\modules\mafia\abilities\investigative\thoughtfeed.dm" #include "code\modules\mafia\abilities\killing\alert.dm" @@ -4737,6 +4749,7 @@ #include "code\modules\mafia\abilities\protective\heal.dm" #include "code\modules\mafia\abilities\protective\vest.dm" #include "code\modules\mafia\abilities\support\roleblock.dm" +#include "code\modules\mafia\abilities\support\seance.dm" #include "code\modules\mafia\abilities\support\self_reveal.dm" #include "code\modules\mafia\abilities\voting\changeling_kill.dm" #include "code\modules\mafia\abilities\voting\day_voting.dm" @@ -5618,11 +5631,11 @@ #include "code\modules\modular_computers\file_system\programs\messenger\messenger_data.dm" #include "code\modules\modular_computers\file_system\programs\messenger\messenger_program.dm" #include "code\modules\movespeed\_movespeed_modifier.dm" +#include "code\modules\movespeed\modifiers\admin.dm" #include "code\modules\movespeed\modifiers\components.dm" #include "code\modules\movespeed\modifiers\drugs.dm" #include "code\modules\movespeed\modifiers\innate.dm" #include "code\modules\movespeed\modifiers\items.dm" -#include "code\modules\movespeed\modifiers\misc.dm" #include "code\modules\movespeed\modifiers\mobs.dm" #include "code\modules\movespeed\modifiers\reagent.dm" #include "code\modules\movespeed\modifiers\status_effects.dm" @@ -5950,9 +5963,9 @@ #include "code\modules\reagents\reagent_containers\hypospray.dm" #include "code\modules\reagents\reagent_containers\jerrycan.dm" #include "code\modules\reagents\reagent_containers\medigel.dm" -#include "code\modules\reagents\reagent_containers\misc.dm" #include "code\modules\reagents\reagent_containers\patch.dm" #include "code\modules\reagents\reagent_containers\pill.dm" +#include "code\modules\reagents\reagent_containers\rag.dm" #include "code\modules\reagents\reagent_containers\spray.dm" #include "code\modules\reagents\reagent_containers\syringes.dm" #include "code\modules\reagents\reagent_containers\watering_can.dm" @@ -5962,6 +5975,7 @@ #include "code\modules\reagents\reagent_containers\cups\drinkingglass.dm" #include "code\modules\reagents\reagent_containers\cups\drinks.dm" #include "code\modules\reagents\reagent_containers\cups\glassbottle.dm" +#include "code\modules\reagents\reagent_containers\cups\mauna_mug.dm" #include "code\modules\reagents\reagent_containers\cups\organ_jar.dm" #include "code\modules\reagents\reagent_containers\cups\soda.dm" #include "code\modules\reagents\withdrawal\_addiction.dm" @@ -6094,6 +6108,7 @@ #include "code\modules\research\xenobiology\vatgrowing\samples\_micro_organism.dm" #include "code\modules\research\xenobiology\vatgrowing\samples\_sample.dm" #include "code\modules\research\xenobiology\vatgrowing\samples\cell_lines\common.dm" +#include "code\modules\research\xenobiology\vatgrowing\samples\cell_lines\organs.dm" #include "code\modules\research\xenobiology\vatgrowing\samples\viruses\_virus.dm" #include "code\modules\security_levels\keycard_authentication.dm" #include "code\modules\security_levels\security_level_datums.dm" @@ -6457,7 +6472,6 @@ #include "code\modules\vehicles\mecha\combat\durand.dm" #include "code\modules\vehicles\mecha\combat\gygax.dm" #include "code\modules\vehicles\mecha\combat\honker.dm" -#include "code\modules\vehicles\mecha\combat\justice.dm" #include "code\modules\vehicles\mecha\combat\marauder.dm" #include "code\modules\vehicles\mecha\combat\phazon.dm" #include "code\modules\vehicles\mecha\combat\reticence.dm" @@ -6474,7 +6488,6 @@ #include "code\modules\vehicles\mecha\medical\odysseus.dm" #include "code\modules\vehicles\mecha\working\clarke.dm" #include "code\modules\vehicles\mecha\working\ripley.dm" -#include "code\modules\vending\_vending.dm" #include "code\modules\vending\assist.dm" #include "code\modules\vending\autodrobe.dm" #include "code\modules\vending\boozeomat.dm" @@ -6483,6 +6496,7 @@ #include "code\modules\vending\clothesmate.dm" #include "code\modules\vending\coffee.dm" #include "code\modules\vending\cola.dm" +#include "code\modules\vending\custom.dm" #include "code\modules\vending\cytopro.dm" #include "code\modules\vending\donk.dm" #include "code\modules\vending\drinnerware.dm" @@ -6507,9 +6521,16 @@ #include "code\modules\vending\sovietsoda.dm" #include "code\modules\vending\subtype.dm" #include "code\modules\vending\sustenance.dm" +#include "code\modules\vending\syndichem.dm" #include "code\modules\vending\toys.dm" #include "code\modules\vending\wardrobes.dm" #include "code\modules\vending\youtool.dm" +#include "code\modules\vending\vendor\_vending.dm" +#include "code\modules\vending\vendor\interaction.dm" +#include "code\modules\vending\vendor\inventory.dm" +#include "code\modules\vending\vendor\throwing.dm" +#include "code\modules\vending\vendor\tilting.dm" +#include "code\modules\vending\vendor\ui_data.dm" #include "code\modules\visuals\render_steps.dm" #include "code\modules\wiremod\components\abstract\assoc_list_variable.dm" #include "code\modules\wiremod\components\abstract\compare.dm" diff --git a/tgui/packages/tgui-panel/chat/renderer.jsx b/tgui/packages/tgui-panel/chat/renderer.jsx index e73df1aab0b8..b2bd78f0fcbc 100644 --- a/tgui/packages/tgui-panel/chat/renderer.jsx +++ b/tgui/packages/tgui-panel/chat/renderer.jsx @@ -218,17 +218,20 @@ class ChatRenderer { const lines = String(text) .split(',') .map((str) => str.trim()) - .filter( - (str) => - // Must be longer than one character - str && - str.length > 1 && - // Must be alphanumeric (with some punctuation) - (allowedRegex.test(str) || - (str.charAt(0) === '/' && str.charAt(str.length - 1) === '/')) && - // Reset lastIndex so it does not mess up the next word - ((allowedRegex.lastIndex = 0) || true), - ); + .filter((str) => { + // Must be longer than one character + if (!str || str.length <= 1) return false; + + // Must be alphanumeric (with some punctuation) + const isValidFormat = + allowedRegex.test(str) || + (str.charAt(0) === '/' && str.charAt(str.length - 1) === '/'); + + // Reset lastIndex so it does not mess up the next word + allowedRegex.lastIndex = 0; + + return isValidFormat; + }); let highlightWords; let highlightRegex; // Nothing to match, reset highlighting diff --git a/tgui/packages/tgui-panel/chat/replaceInTextNode.js b/tgui/packages/tgui-panel/chat/replaceInTextNode.ts similarity index 60% rename from tgui/packages/tgui-panel/chat/replaceInTextNode.js rename to tgui/packages/tgui-panel/chat/replaceInTextNode.ts index 171043ceb43a..5a4bb526f898 100644 --- a/tgui/packages/tgui-panel/chat/replaceInTextNode.js +++ b/tgui/packages/tgui-panel/chat/replaceInTextNode.ts @@ -4,36 +4,47 @@ * @license MIT */ +type NodeCreator = (text: string) => Node; + +type ReplaceInTextNodeParams = { + node: Node; + regex: RegExp; + createNode: NodeCreator; + captureAdjust?: (str: string) => string; +}; + /** * Replaces text matching a regular expression with a custom node. */ -const regexParseNode = (params) => { +function regexParseNode(params: ReplaceInTextNodeParams): { + nodes: Node[]; + n: number; +} { const { node, regex, createNode, captureAdjust } = params; const text = node.textContent; + + if (!text || !regex) { + return { nodes: [], n: 0 }; + } + + const fragment = document.createDocumentFragment(); + const nodes: Node[] = []; const textLength = text.length; - let nodes; - let new_node; - let match; + let count = 0; let lastIndex = 0; - let fragment; + let match: RegExpExecArray | null; let n = 0; - let count = 0; - // eslint-disable-next-line no-cond-assign - while ((match = regex.exec(text))) { + let new_node: Node; + + while (true) { + match = regex.exec(text); + if (!match) break; n += 1; - // Safety check to prevent permanent - // client crashing + // Safety check to prevent permanent client crashing if (++count > 9999) { - return {}; - } - // Lazy init fragment - if (!fragment) { - fragment = document.createDocumentFragment(); - } - // Lazy init nodes - if (!nodes) { - nodes = []; + return { nodes: [], n: 0 }; } + const matchText = captureAdjust ? captureAdjust(match[0]) : match[0]; const matchLength = matchText.length; // If matchText is set to be a substring nested within the original @@ -59,70 +70,72 @@ const regexParseNode = (params) => { fragment.appendChild(new_node); } // Commit the fragment - node.parentNode.replaceChild(fragment, node); + node.parentNode?.replaceChild(fragment, node); } return { nodes: nodes, n: n, }; -}; +} /** - * Replace text of a node with custom nades if they match + * Replace text of a node with custom nodes if they match * a regex expression or are in a word list */ -export const replaceInTextNode = (regex, words, createNode) => (node) => { - let nodes; - let result; - let n = 0; +export const replaceInTextNode = + (regex: RegExp, words: string[] | null, createNode: NodeCreator) => + (node: Node) => { + let nodes; + let result; + let n = 0; - if (regex) { - result = regexParseNode({ - node: node, - regex: regex, - createNode: createNode, - }); - nodes = result.nodes; - n += result.n; - } + if (regex) { + result = regexParseNode({ + node: node, + regex: regex, + createNode: createNode, + }); + nodes = result.nodes; + n += result.n; + } - if (words) { - let i = 0; - let wordRegexStr = '('; - for (const word of words) { - // Capture if the word is at the beginning, end, middle, - // or by itself in a message - wordRegexStr += `^${word}\\s\\W|\\s\\W${word}\\s\\W|\\s\\W${word}$|^${word}\\s\\W$`; - // Make sure the last character for the expression is NOT '|' - if (++i !== words.length) { - wordRegexStr += '|'; + if (words) { + let i = 0; + let wordRegexStr = '('; + for (const word of words) { + // Capture if the word is at the beginning, end, middle, + // or by itself in a message + wordRegexStr += `^${word}\\s\\W|\\s\\W${word}\\s\\W|\\s\\W${word}$|^${word}\\s\\W$`; + // Make sure the last character for the expression is NOT '|' + if (++i !== words.length) { + wordRegexStr += '|'; + } } - } - wordRegexStr += ')'; - const wordRegex = new RegExp(wordRegexStr, 'gi'); - if (regex && nodes) { - for (const a_node of nodes) { + wordRegexStr += ')'; + const wordRegex = new RegExp(wordRegexStr, 'gi'); + if (regex && nodes) { + for (const a_node of nodes) { + result = regexParseNode({ + node: a_node, + regex: wordRegex, + createNode: createNode, + captureAdjust: (str) => str.replace(/^\W|\W$/g, ''), + }); + n += result.n; + } + } else { result = regexParseNode({ - node: a_node, + node: node, regex: wordRegex, createNode: createNode, captureAdjust: (str) => str.replace(/^\W|\W$/g, ''), }); n += result.n; } - } else { - result = regexParseNode({ - node: node, - regex: wordRegex, - createNode: createNode, - captureAdjust: (str) => str.replace(/^\W|\W$/g, ''), - }); - n += result.n; } - } - return n; -}; + return n; + }; // Highlight // -------------------------------------------------------- @@ -130,27 +143,25 @@ export const replaceInTextNode = (regex, words, createNode) => (node) => { /** * Default highlight node. */ -const createHighlightNode = (text) => { +function createHighlightNode(text: string): Node { const node = document.createElement('span'); node.setAttribute('style', 'background-color:#fd4;color:#000'); node.textContent = text; return node; -}; +} /** * Highlights the text in the node based on the provided regular expression. - * - * @param {Node} node Node which you want to process - * @param {RegExp} regex Regular expression to highlight - * @param {(text: string) => Node} createNode Highlight node creator - * @returns {number} Number of matches */ -export const highlightNode = ( - node, - regex, - words, - createNode = createHighlightNode, -) => { +export function highlightNode( + /** Node which you want to process */ + node: Node, + /** Regular expression to highlight */ + regex: RegExp, + /** List of words to highlight */ + words: string[], + createNode: NodeCreator = createHighlightNode, +): number { if (!createNode) { createNode = createHighlightNode; } @@ -166,7 +177,7 @@ export const highlightNode = ( } } return n; -}; +} // Linkify // -------------------------------------------------------- @@ -176,11 +187,8 @@ const URL_REGEX = /** * Highlights the text in the node based on the provided regular expression. - * - * @param {Node} node Node which you want to process - * @returns {number} Number of matches */ -export const linkifyNode = (node) => { +export function linkifyNode(node: Node): number { let n = 0; const childNodes = node.childNodes; for (let i = 0; i < childNodes.length; i++) { @@ -194,7 +202,7 @@ export const linkifyNode = (node) => { } } return n; -}; +} const linkifyTextNode = replaceInTextNode(URL_REGEX, null, (text) => { const node = document.createElement('a'); diff --git a/tgui/packages/tgui/backend.ts b/tgui/packages/tgui/backend.ts index 59833af5798d..83afa926022c 100644 --- a/tgui/packages/tgui/backend.ts +++ b/tgui/packages/tgui/backend.ts @@ -209,7 +209,10 @@ export const backendMiddleware = (store) => { suspendRenderer(); clearInterval(suspendInterval); suspendInterval = undefined; + // Tiny window to not show previous content when resumed Byond.winset(Byond.windowId, { + size: '1x1', + pos: '1,1', 'is-visible': false, }); setTimeout(() => focusMap()); diff --git a/tgui/packages/tgui/interfaces/Aquarium.tsx b/tgui/packages/tgui/interfaces/Aquarium.tsx index 2ab43d3fcdaa..cc6f75eec00e 100644 --- a/tgui/packages/tgui/interfaces/Aquarium.tsx +++ b/tgui/packages/tgui/interfaces/Aquarium.tsx @@ -44,7 +44,7 @@ type FishData = { fish_happiness: number; fish_icon: string; fish_icon_state: string; - fish_health: number; + fish_alive: BooleanLike; }; type PropData = { @@ -129,8 +129,8 @@ const FishInfo = (props: FishInfoProps) => { > {fish.fish_name} - 0 ? -4 : 1}> - {fish.fish_health > 0 ? ( + + {fish.fish_alive ? ( ) : ( diff --git a/tgui/packages/tgui/interfaces/MafiaPanel.tsx b/tgui/packages/tgui/interfaces/MafiaPanel.tsx index d6428945e6df..ba5dd2041a14 100644 --- a/tgui/packages/tgui/interfaces/MafiaPanel.tsx +++ b/tgui/packages/tgui/interfaces/MafiaPanel.tsx @@ -23,6 +23,7 @@ type RoleInfo = { desc: string; hud_icon: string; revealed_icon: string; + role_dead: string; }; type PlayerInfo = { @@ -286,7 +287,7 @@ const MafiaRole = (props) => {
{ } > - + - You are the {roleinfo.role} - {roleinfo.desc} + You are the {roleinfo.role} + {!!roleinfo.role_dead && ( + + You are currently dead. You may speak with the Chaplain at night, + if there is one. + + )} + {!roleinfo.role_dead && {roleinfo.desc}} { return ( - + {current_page === channels.length + 1 ? ( ) : current_page ? ( diff --git a/tgui/packages/tgui/interfaces/NtosCard.tsx b/tgui/packages/tgui/interfaces/NtosCard.tsx index 542d4b5f45c5..133788d96c79 100644 --- a/tgui/packages/tgui/interfaces/NtosCard.tsx +++ b/tgui/packages/tgui/interfaces/NtosCard.tsx @@ -1,8 +1,9 @@ import { - Box, Button, Dropdown, + Flex, Input, + NoticeBox, NumberInput, Section, Stack, @@ -14,20 +15,29 @@ import { NtosWindow } from '../layouts'; import type { NTOSData } from '../layouts/NtosWindow'; import { AccessList } from './common/AccessList'; -type Data = { - access_on_card: Array; - accessFlagNames: Record; - accessFlags: Record; - hasTrim: BooleanLike; +type CardData = { + has_trim: BooleanLike; id_age: number; id_owner: string; id_rank: string; + trim_access: string[]; + access_on_card: Array; + trim_assignment: string | null; + wildcard_slots: Record; +}; + +type Data = { + modified_card: CardData | null; + auth_card: CardData | null; + authed_user: string | null; + is_holding_id: BooleanLike; + // static data + access_flag_names: Record; + access_flags: Record; regions: Region[]; - showBasic: BooleanLike; + show_basic: BooleanLike; templates: Record; - trimAccess: string[]; - wildcardFlags: Record; - wildcardSlots: Record; + wildcard_flags: Record; } & NTOSData; type Region = { @@ -58,62 +68,65 @@ export const NtosCard = (props) => { export const NtosCardContent = (props) => { const { act, data } = useBackend(); const { - access_on_card = [], - accessFlagNames, - accessFlags, - authenticatedUser, - has_id, - regions = [], - showBasic, - templates = {}, - trimAccess, - wildcardFlags, - wildcardSlots, - hasTrim, + authed_user, + modified_card, + templates, + regions, + wildcard_flags, + access_flags, + access_flag_names, + show_basic, } = data; return ( - <> - - - + + + + + + + + + + + + {!!modified_card && !!authed_user && ( + +
+ } + > + {modified_card.has_trim ? ( + + ) : ( + 'Templates require a trim already applied to the card. Please use an ID Painter to apply a trim.' + )} +
-
- {!!has_id && !!authenticatedUser && ( -
- } - > - {hasTrim ? ( - - ) : ( - 'Templates require a trim already applied to the card. Please use an ID Painter to apply a trim.' - )} -
)} - - - {!!has_id && !!authenticatedUser && ( - + + + + {!!modified_card && !!authed_user && ( { }) } /> - - )} + )} + + +
+
+ ); +}; + +const LoginPage = () => { + const { act, data } = useBackend(); + const { authed_user, auth_card, is_holding_id } = data; + + return ( +
+ + + + {authed_user + ? `Login: ${authed_user}` + : 'Please log in to continue.'} + + + + + + + + + + + - +
); }; const IdCardPage = (props) => { const { act, data } = useBackend(); - const { authenticatedUser, id_rank, id_owner, has_id, id_age, authIDName } = - data; + const { authed_user, auth_card, modified_card, is_holding_id } = data; return ( -
- - - - Login: {authenticatedUser || '-----'} + + + + + + + + - {!!(has_id && authenticatedUser) && ( + {!!(modified_card && authed_user) && ( <> Details: act('PRG_edit', { name: value, @@ -197,7 +253,7 @@ const IdCardPage = (props) => { { act('PRG_assign', { assignment: value, diff --git a/tgui/packages/tgui/interfaces/Vending.tsx b/tgui/packages/tgui/interfaces/Vending.tsx index ae9216a1f950..7baae4c56589 100644 --- a/tgui/packages/tgui/interfaces/Vending.tsx +++ b/tgui/packages/tgui/interfaces/Vending.tsx @@ -14,47 +14,24 @@ import { useBackend } from '../backend'; import { Window } from '../layouts'; import { getLayoutState, LAYOUT, LayoutToggle } from './common/LayoutToggle'; -type VendingData = { - all_products_free: boolean; - onstation: boolean; - department: string; - jobDiscount: number; - displayed_currency_icon: string; - displayed_currency_name: string; - product_records: ProductRecord[]; - coin_records: CoinRecord[]; - hidden_records: HiddenRecord[]; - user: UserData; - stock: Record[]; - extended_inventory: boolean; - access: boolean; - vending_machine_input: CustomInput[]; - categories: Record; -}; - -type Category = { - icon: string; +type StockItem = { + amount: number; + free: boolean; }; type ProductRecord = { path: string; name: string; price: number; - max_amount: number; ref: string; category: string; + colorable: boolean; + premium: boolean; + image?: string; icon?: string; icon_state?: string; }; -type CoinRecord = ProductRecord & { - premium: boolean; -}; - -type HiddenRecord = ProductRecord & { - premium: boolean; -}; - type UserData = { name: string; cash: number; @@ -62,25 +39,34 @@ type UserData = { department: string; }; -type StockItem = { - name: string; - path: string; - amount: number; - colorable: boolean; +type Category = { + icon: string; }; -type CustomInput = { - path: string; - name: string; - price: number; - img: string; +type VendingData = { + all_products_free: boolean; + onstation: boolean; + ad: string; + department: string; + jobDiscount: number; + displayed_currency_icon: string; + displayed_currency_name: string; + product_records: ProductRecord[]; + coin_records: ProductRecord[]; + hidden_records: ProductRecord[]; + user: UserData; + stock: Record[]; + extended_inventory: boolean; + access: boolean; + categories: Record; }; -export const Vending = (props) => { +export const Vending = () => { const { data } = useBackend(); const { onstation, + ad, product_records = [], coin_records = [], hidden_records = [], @@ -94,19 +80,12 @@ export const Vending = (props) => { const [stockSearch, setStockSearch] = useState(''); const stockSearchFn = createSearch( stockSearch, - (item: ProductRecord | CustomInput) => item.name, + (item: ProductRecord) => item.name, ); - let inventory: (ProductRecord | CustomInput)[]; - let custom = false; - if (data.vending_machine_input) { - inventory = data.vending_machine_input; - custom = true; - } else { - inventory = [...product_records, ...coin_records]; - if (data.extended_inventory) { - inventory = [...inventory, ...hidden_records]; - } + let inventory: ProductRecord[] = [...product_records, ...coin_records]; + if (data.extended_inventory) { + inventory = [...inventory, ...hidden_records]; } // Just in case we still have undefined values in the list @@ -137,9 +116,13 @@ export const Vending = (props) => { )} + {ad && ( + + + + )} { }; /** Displays user details if an ID is present and the user is on the station */ -export const UserDetails = (props) => { +export const UserDetails = () => { const { data } = useBackend(); const { user } = data; @@ -184,17 +167,27 @@ export const UserDetails = (props) => { ); }; +const AdSection = (props: { AdDisplay: string }) => { + const { AdDisplay } = props; + + return ( + + + {AdDisplay} + + + ); +}; + /** Displays products in a section, with user balance at top */ const ProductDisplay = (props: { - custom: boolean; - inventory: (ProductRecord | CustomInput)[]; + inventory: ProductRecord[]; stockSearch: string; setStockSearch: (search: string) => void; selectedCategory: string | null; }) => { const { data } = useBackend(); - const { custom, inventory, stockSearch, setStockSearch, selectedCategory } = - props; + const { inventory, stockSearch, setStockSearch, selectedCategory } = props; const { stock, all_products_free, @@ -242,7 +235,6 @@ const ProductDisplay = (props: { @@ -251,25 +243,29 @@ const ProductDisplay = (props: { ); }; +type ProductProps = { + product: ProductRecord; + productStock: StockItem; + fluid: boolean; +}; + /** * An individual listing for an item. */ -const Product = (props) => { +const Product = (props: ProductProps) => { const { act, data } = useBackend(); - const { custom, product, productStock, fluid } = props; - const { access, department, jobDiscount, all_products_free, user } = data; + const { product, productStock, fluid } = props; + const { department, jobDiscount, all_products_free, user } = data; - const colorable = !!productStock?.colorable; - const free = all_products_free || product.price === 0; + const colorable = !!product.colorable; + const free = all_products_free || productStock.free || product.price === 0; const discount = !product.premium && department === user?.department; - const remaining = custom ? product.amount : productStock.amount; + const remaining = productStock.amount; const redPrice = Math.round(product.price * jobDiscount); const disabled = remaining === 0 || (!all_products_free && !user) || - (!all_products_free && - !access && - (discount ? redPrice : product.price) > user?.cash); + (!free && (discount ? redPrice : product.price) > user?.cash); const baseProps = { base64: product.image, @@ -285,19 +281,14 @@ const Product = (props) => { colorable: colorable, remaining: remaining, onClick: () => { - custom - ? act('dispense', { - item: product.path, - }) - : act('vend', { - ref: product.ref, - discountless: !!product.premium, - }); + act('vend', { + ref: product.ref, + discountless: !!product.premium, + }); }, }; const priceProps = { - custom: custom, discount: discount, free: free, product: product, @@ -311,7 +302,7 @@ const Product = (props) => { ); }; -const ProductGrid = (props) => { +const ProductGrid = (props: any) => { const { product, remaining, ...baseProps } = props; const { ...priceProps } = props; @@ -333,7 +324,7 @@ const ProductGrid = (props) => { ); }; -const ProductList = (props) => { +const ProductList = (props: any) => { const { colorable, product, remaining, ...baseProps } = props; const { ...priceProps } = props; @@ -365,7 +356,14 @@ const ProductList = (props) => { * In the case of customizable items, ie: shoes, * this displays a color wheel button that opens another window. */ -const ProductColorSelect = (props) => { + +type ProductColorSelectProps = { + disabled: boolean; + product: ProductRecord; + fluid: boolean; +}; + +const ProductColorSelect = (props: ProductColorSelectProps) => { const { act } = useBackend(); const { disabled, product, fluid } = props; @@ -375,37 +373,34 @@ const ProductColorSelect = (props) => { icon={'palette'} color={'transparent'} tooltip={'Change color'} - style={disabled && { pointerEvents: 'none', opacity: 0.5 }} + style={disabled ? { pointerEvents: 'none', opacity: 0.5 } : {}} onClick={() => act('select_colors', { ref: product.ref })} /> ); }; +type ProductPriceProps = { + discount: boolean; + free: boolean; + product: ProductRecord; + redPrice: number; +}; + /** The main button to purchase an item. */ -const ProductPrice = (props) => { - const { act, data } = useBackend(); - const { access, displayed_currency_name } = data; - const { custom, discount, free, product, redPrice } = props; - const customPrice = access ? 'Free' : product.price; - let standardPrice = product.price; +const ProductPrice = (props: ProductPriceProps) => { + const { data } = useBackend(); + const { displayed_currency_name } = data; + const { discount, free, product, redPrice } = props; + let standardPrice = product.price + ''; if (free) { - standardPrice = 'Free'; + standardPrice = 'FREE'; } else if (discount) { - standardPrice = redPrice; + standardPrice = redPrice + ''; } return ( - {custom ? ( - <> - {customPrice} - {!access && displayed_currency_name} - - ) : ( - <> - {standardPrice} - {!free && displayed_currency_name} - - )} + {standardPrice} + {!free && displayed_currency_name} ); }; diff --git a/tgui/packages/tgui/interfaces/common/AccessList.jsx b/tgui/packages/tgui/interfaces/common/AccessList.jsx index 61472b2cf25a..a072422a9b7a 100644 --- a/tgui/packages/tgui/interfaces/common/AccessList.jsx +++ b/tgui/packages/tgui/interfaces/common/AccessList.jsx @@ -1,5 +1,5 @@ import { sortBy } from 'es-toolkit'; -import { Button, Flex, Section, Tabs } from 'tgui-core/components'; +import { Button, Flex, Section, Stack, Tabs } from 'tgui-core/components'; import { useSharedState } from '../../backend'; @@ -100,8 +100,8 @@ export const AccessList = (props) => { return (
- - + + { basicUsed={selectedTrimAccess.length} basicMax={trimAccess.length} /> - - - - - - - - + + + + + + + + + + + +
); }; @@ -266,28 +270,36 @@ const RegionAccessList = (props) => { const wcUsage = wildcard ? wildcard.usage.length : 0; const wcAvail = wcLimit - wcUsage; - return selectedAccessEntries.map((entry) => { - const id = entry.ref; - const disableButton = - (wcAvail === 0 && wcAccess[id] !== selWildcard) || - (wcAvail > 0 && wcAccess[id] && wcAccess[id] !== selWildcard); - const entryName = - !wcAccess[id] && trimAccess.includes(id) - ? entry.desc - : `${entry.desc} (${accessFlagNames[accessFlags[id]]})`; - - return ( - - accessMod(entry.ref, selWildcard === 'None' ? null : selWildcard) - } - /> - ); - }); + return ( + + {selectedAccessEntries.map((entry) => { + const id = entry.ref; + const disableButton = + (wcAvail === 0 && wcAccess[id] !== selWildcard) || + (wcAvail > 0 && wcAccess[id] && wcAccess[id] !== selWildcard); + const entryName = + !wcAccess[id] && trimAccess.includes(id) + ? entry.desc + : `${entry.desc} (${accessFlagNames[accessFlags[id]]})`; + return ( + + + accessMod( + entry.ref, + selWildcard === 'None' ? null : selWildcard, + ) + } + /> + + ); + })} + + ); }; diff --git a/tgui/packages/tgui/layouts/NtosWindow.tsx b/tgui/packages/tgui/layouts/NtosWindow.tsx index 6771215b3c2e..3e674a611b9d 100644 --- a/tgui/packages/tgui/layouts/NtosWindow.tsx +++ b/tgui/packages/tgui/layouts/NtosWindow.tsx @@ -12,10 +12,7 @@ import { useBackend } from '../backend'; import { Window } from './Window'; export type NTOSData = { - authenticatedUser: string | null; - authIDName: string; comp_light_color: string; - has_id: BooleanLike; has_light: BooleanLike; id_name: string; light_on: BooleanLike; diff --git a/tools/UpdatePaths/Scripts/92157_no_id_for_dummies.txt b/tools/UpdatePaths/Scripts/92157_no_id_for_dummies.txt new file mode 100644 index 000000000000..30a8e6de8670 --- /dev/null +++ b/tools/UpdatePaths/Scripts/92157_no_id_for_dummies.txt @@ -0,0 +1 @@ +/obj/item/paper/fluff/ids_for_dummies : @DELETE diff --git a/tools/UpdatePaths/Scripts/92226_glitterening.txt b/tools/UpdatePaths/Scripts/92226_glitterening.txt new file mode 100644 index 000000000000..4d97ce829c69 --- /dev/null +++ b/tools/UpdatePaths/Scripts/92226_glitterening.txt @@ -0,0 +1,6 @@ +/obj/item/grenade/chem_grenade/glitter/white : /obj/item/grenade/chem_grenade/glitter{@OLD} +/obj/structure/closet/crate/pink : /obj/structure/closet/crate/glitter{@OLD} +/obj/structure/closet/crate/lavender : /obj/structure/closet/crate/glitter/lavender{@OLD} +/obj/effect/decal/cleanable/glitter/white : /obj/effect/decal/cleanable/glitter{@OLD} +/obj/effect/decal/cleanable/glitter/pink : /obj/effect/decal/cleanable/glitter{@OLD;color="ff8080"} +/obj/effect/decal/cleanable/glitter/blue : /obj/effect/decal/cleanable/glitter{@OLD;color="4040ff"} diff --git a/tools/UpdatePaths/Scripts/92322_colorless_nvg.txt b/tools/UpdatePaths/Scripts/92322_colorless_nvg.txt new file mode 100644 index 000000000000..2b7c9279b35e --- /dev/null +++ b/tools/UpdatePaths/Scripts/92322_colorless_nvg.txt @@ -0,0 +1,2 @@ +# Colorless NVG was removed alongside the forced tint +/obj/item/clothing/glasses/night/colorless : /obj/item/clothing/glasses/night{@OLD} diff --git a/tools/UpdatePaths/Scripts/92385_space_to_basic_space.txt b/tools/UpdatePaths/Scripts/92385_space_to_basic_space.txt new file mode 100644 index 000000000000..cdf169f3aee0 --- /dev/null +++ b/tools/UpdatePaths/Scripts/92385_space_to_basic_space.txt @@ -0,0 +1 @@ +/turf/open/space : /turf/open/space/basic {@OLD} diff --git a/tools/maplint/lints/use_basic_space.yml b/tools/maplint/lints/use_basic_space.yml new file mode 100644 index 000000000000..90e1366b135a --- /dev/null +++ b/tools/maplint/lints/use_basic_space.yml @@ -0,0 +1,3 @@ +help: "Use /turf/open/space/basic instead of /turf/open/space." +=/turf/open/space: + banned: true diff --git a/tools/pull_request_hooks/autoLabel.js b/tools/pull_request_hooks/autoLabel.js index 90109849f8ef..809e81f49c07 100644 --- a/tools/pull_request_hooks/autoLabel.js +++ b/tools/pull_request_hooks/autoLabel.js @@ -1,110 +1,177 @@ import * as autoLabelConfig from "./autoLabelConfig.js"; -function keyword_to_cl_label() { - const keyword_to_cl_label = {}; - for (const label in autoLabelConfig.changelog_labels) { - for (const keyword of autoLabelConfig.changelog_labels[label].keywords) { - keyword_to_cl_label[keyword] = label; +/** + * Precompute a lowercase keyword → changelog label map + */ +const keywordToClLabel = (() => { + const map = {}; + for (const [label, { keywords }] of Object.entries( + autoLabelConfig.changelog_labels + )) { + for (const keyword of keywords) { + map[keyword.toLowerCase()] = label; } } - return keyword_to_cl_label; -} + return map; +})(); + +/** + * Precompute title keyword Sets per label for O(1) lookup + */ +const titleKeywordSets = (() => { + const map = {}; + for (const [label, { keywords }] of Object.entries( + autoLabelConfig.title_labels + )) { + map[label] = new Set(keywords.map((k) => k.toLowerCase())); + } + return map; +})(); -// Checks the body (primarily the changelog) for labels to add +/** + * Precompute filepaths Sets per label for O(1) lookup + */ +const fileLabelFilepathSets = (() => { + const map = {}; + for (const [label, { filepaths = [], file_extensions = [], add_only }] of Object.entries( + autoLabelConfig.file_labels + )) { + map[label] = { filepaths: new Set(filepaths), file_extensions: new Set(file_extensions), add_only }; + } + return map; +})(); + +/** + * Checks the body (primarily the changelog) for labels to add + */ function check_body_for_labels(body) { const labels_to_add = []; - // if the body contains a github "fixes #1234" line, add the Fix tag - const fix_regex = new RegExp(`(fix[des]*|resolve[sd]*)\s*#\d+`, "gmi"); + // detect "fixes #1234" or "resolves #1234" in body + const fix_regex = /\b(?:fix(?:es|ed)?|resolve[sd]?)\s*#\d+\b/gim; if (fix_regex.test(body)) { labels_to_add.push("Fix"); } - const keywords = keyword_to_cl_label(); + const lines = body.split("\n"); + let inChangelog = false; - let found_cl = false; - for (const line of body.split("\n")) { + for (const line of lines) { if (line.startsWith(":cl:")) { - found_cl = true; - continue; - } else if (line.startsWith("/:cl:")) { - break; - } else if (!found_cl) { + inChangelog = true; continue; } + if (line.startsWith("/:cl:")) break; + if (!inChangelog) continue; + // see if the first segment of the line is one of the keywords - const found_label = keywords[line.split(":")[0]?.toLowerCase()]; - if (found_label) { - // don't add a billion tags if they forgot to clear all the default ones - const line_text = line.split(":")[1].trim(); - const cl_label = autoLabelConfig.changelog_labels[found_label]; - if ( - line_text !== cl_label.default_text && - line_text !== cl_label.alt_default_text - ) { - labels_to_add.push(found_label); - } + const keyword = line.split(":")[0]?.toLowerCase(); + const found_label = keywordToClLabel[keyword]; + if (!found_label) continue; + + // don't add a billion tags if they forgot to clear all the default ones + const line_text = line.split(":")[1]?.trim(); + const { default_text, alt_default_text } = + autoLabelConfig.changelog_labels[found_label]; + + if (line_text !== default_text && line_text !== alt_default_text) { + labels_to_add.push(found_label); } } + return labels_to_add; } -// Checks the title for labels to add +/** + * Checks the title for labels to add (O(1) keyword lookup) + */ function check_title_for_labels(title) { - const labels_to_add = []; const title_lower = title.toLowerCase(); - for (const label in autoLabelConfig.title_labels) { - let found = false; - for (const keyword of autoLabelConfig.title_labels[label].keywords) { + const labels_to_add = []; + + for (const [label, keywordSet] of Object.entries(titleKeywordSets)) { + for (const keyword of keywordSet) { if (title_lower.includes(keyword)) { - found = true; + labels_to_add.push(label); break; } } - if (found) { - labels_to_add.push(label); - } } return labels_to_add; } -function check_diff_line_for_element(diff, element) { - const tag_re = new RegExp(`^diff --git a/${element}/`); - return tag_re.test(diff); -} - -// Checks the file diff for labels to add or remove -async function check_diff_for_labels(diff_url) { +/** + * Checks changed files for labels to add/remove (O(1) filepath lookup) + */ +async function check_diff_files_for_labels(github, context) { const labels_to_add = []; const labels_to_remove = []; + try { - const diff = await fetch(diff_url); - if (diff.ok) { - const diff_txt = await diff.text(); - for (const label in autoLabelConfig.file_labels) { - let found = false; - const { filepaths, add_only } = autoLabelConfig.file_labels[label]; - for (const filepath of filepaths) { - if (check_diff_line_for_element(diff_txt, filepath)) { + // Use github.paginate to fetch all files (up to ~3000 max) + const allFiles = await github.paginate( + github.rest.pulls.listFiles, + { + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.payload.pull_request.number, + per_page: 100, // max per request + } + ); + + if (!allFiles?.length) { + console.error("No files returned in pagination."); + return { labels_to_add, labels_to_remove }; + } + + // Set of changed filenames for quick lookup + const changedFiles = new Set(allFiles.map((f) => f.filename)); + + for (const [label, { filepaths = new Set(), file_extensions = new Set(), add_only }] of Object.entries( + fileLabelFilepathSets + )) { + let found = false; + + // Filepath-based matching + for (const filename of changedFiles) { + for (const path of filepaths) { + if (filename.includes(path)) { found = true; break; } } - if (found) { - labels_to_add.push(label); - } else if (!add_only) { - labels_to_remove.push(label); + if (found) break; + } + + // File extension-based matching + if (!found && file_extensions.size) { + for (const filename of changedFiles) { + for (const ext of file_extensions) { + if (filename.endsWith(ext)) { + found = true; + break; + } + } + if (found) break; } } - } else { - console.error(`Failed to fetch diff: ${diff.status} ${diff.statusText}`); + + if (found) { + labels_to_add.push(label); + } else if (!add_only) { + labels_to_remove.push(label); + } } - } catch (e) { - console.error(e); + } catch (error) { + console.error("Error fetching paginated files:", error); } + return { labels_to_add, labels_to_remove }; } +/** + * Main function to get the updated label set + */ export async function get_updated_label_set({ github, context }) { const { action, pull_request } = context.payload; const { @@ -115,39 +182,30 @@ export async function get_updated_label_set({ github, context }) { title = "", } = pull_request; - const updated_labels = new Set(); - for (const label of labels) { - updated_labels.add(label.name); - } + const updated_labels = new Set(labels.map((l) => l.name)); - // diff is always checked + // Always check file diffs if (diff_url) { - const diff_tags = await check_diff_for_labels(diff_url); - for (const label of diff_tags.labels_to_add) { - updated_labels.add(label); - } - for (const label of diff_tags.labels_to_remove) { - updated_labels.delete(label); - } + const { labels_to_add, labels_to_remove } = + await check_diff_files_for_labels(github, context); + labels_to_add.forEach((label) => updated_labels.add(label)); + labels_to_remove.forEach((label) => updated_labels.delete(label)); } - // body and title are only checked on open, not on sync + + // Check body/title only when PR is opened, not on sync if (action === "opened") { - if (title) { - for (const label of check_title_for_labels(title)) { - updated_labels.add(label); - } - } - if (body) { - for (const label of check_body_for_labels(body)) { - updated_labels.add(label); - } - } + if (title) + check_title_for_labels(title).forEach((label) => + updated_labels.add(label) + ); + if (body) + check_body_for_labels(body).forEach((label) => updated_labels.add(label)); } - // this is always removed on updates + // Always remove Test Merge Candidate updated_labels.delete("Test Merge Candidate"); - // update merge conflict label + // Handle merge conflict label let merge_conflict = mergeable === false; // null means it was not reported yet // it is not normally included in the payload - a "get" is needed @@ -159,6 +217,7 @@ export async function get_updated_label_set({ github, context }) { pull_number: pull_request.number, }); // failed to find? still processing? try again in a few seconds + if (response.data.mergeable === null) { console.log("Awaiting GitHub response for merge status..."); await new Promise((r) => setTimeout(r, 10000)); @@ -177,6 +236,7 @@ export async function get_updated_label_set({ github, context }) { console.error(e); } } + if (merge_conflict) { updated_labels.add("Merge Conflict"); } else { diff --git a/tools/pull_request_hooks/autoLabelConfig.js b/tools/pull_request_hooks/autoLabelConfig.js index ca5c14b1d761..6d848fa715c8 100644 --- a/tools/pull_request_hooks/autoLabelConfig.js +++ b/tools/pull_request_hooks/autoLabelConfig.js @@ -7,31 +7,34 @@ // the label will not be removed export const file_labels = { GitHub: { - filepaths: [".github"], + filepaths: [".github/"], }, SQL: { - filepaths: ["SQL"], + filepaths: ["SQL/"], }, "Map Edit": { - filepaths: ["_maps"], + filepaths: ["_maps/"], + file_extensions: [".dmm"], }, Tools: { - filepaths: ["tools"], + filepaths: ["tools/"], }, "Config Update": { - filepaths: ["config", "code/controllers/configuration/entries"], + filepaths: ["config/", "code/controllers/configuration/entries/"], add_only: true, }, Sprites: { - filepaths: ["icons"], + filepaths: ["icons/"], + file_extensions: [".dmi"], add_only: true, }, Sound: { - filepaths: ["sound"], + filepaths: ["sound/"], + file_extensions: [".ogg"], add_only: true, }, UI: { - filepaths: ["tgui"], + filepaths: ["tgui/"], add_only: true, }, };