diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000000..84bd4fa20aad9 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + target-branch: master + schedule: + interval: daily + labels: + - GitHub + open-pull-requests-limit: 10 diff --git a/.github/guides/STANDARDS.md b/.github/guides/STANDARDS.md index 9c6496e0c4dc9..c27c8ae7417ec 100644 --- a/.github/guides/STANDARDS.md +++ b/.github/guides/STANDARDS.md @@ -513,6 +513,30 @@ The following is a list of procs, and their safe replacements. * Move away from something, taking turf density into account `walk_away()` -> `SSmove_manager.move_away()` * Move to a random place nearby. NOT random walk `walk_rand()` -> `SSmove_manager.move_rand()` is random walk, `SSmove_manager.move_to_rand()` is walk to a random place +### Avoid pointer use + +BYOND has a variable type called pointers, which allow you to reference a variable rather then its value. As an example of how this works: + +``` +var/pointed_at = "text" +var/value = pointed_at // copies the VALUE of pointed at +var/reference = &pointed_at // points at pointed_at itself + +// so we can retain a reference even if pointed_at changes +pointed_at = "text AGAIN" +world << (*reference) // Deref to get the value, outputs "text AGAIN" + +// or modify the var remotely +*reference = "text a THIRD TIME" +world << pointed_at // outputs "text a THIRD TIME" +``` + +The problem with this is twofold. +- First: if you use a pointer to reference a var on a datum, it is essentially as if you held an invisible reference to that datum. This risks hard deletes in very unclear ways that cannot be tested for. +- Second: People don't like, understand how pointers work? They mix them up with classical C pointers, when they're more like `std::shared_ptr`. This leads to code that just doesn't work properly, or is hard to follow without first getting your mind around it. It also risks hiding what code does in dumb ways because pointers don't have unique types. + +For these reasons and with the hope of avoiding pointers entering general use, be very careful using them, if you use them at all. + ### BYOND hellspawn What follows is documentation of inconsistent or strange behavior found in our engine, BYOND. diff --git a/.github/workflows/auto_changelog.yml b/.github/workflows/auto_changelog.yml index e08224dfb9a72..45303ec0c92af 100644 --- a/.github/workflows/auto_changelog.yml +++ b/.github/workflows/auto_changelog.yml @@ -28,7 +28,7 @@ jobs: APP_ID: ${{ secrets.APP_ID }} - name: Run auto changelog - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | const { processAutoChangelog } = await import('${{ github.workspace }}/tools/pull_request_hooks/autoChangelog.js') diff --git a/.github/workflows/ci_suite.yml b/.github/workflows/ci_suite.yml index 3c702625cc7ac..d0c4c16784f8c 100644 --- a/.github/workflows/ci_suite.yml +++ b/.github/workflows/ci_suite.yml @@ -286,9 +286,12 @@ jobs: max-required-client-version: ${{needs.collect_data.outputs.max_required_byond_client}} completion_gate: # Serves as a non-moving target for branch rulesets + if: always() && !cancelled() name: Completion Gate needs: [ test_windows, compare_screenshots, compile_all_maps, run_linters ] runs-on: ubuntu-latest steps: - - name: Mandatory Empty Step - run: exit 0 + - name: Decide whether the needed jobs succeeded or failed + uses: re-actors/alls-green@release/v1 + with: + jobs: ${{ toJSON(needs) }} diff --git a/.github/workflows/remove_guide_comments.yml b/.github/workflows/remove_guide_comments.yml index e3a4ac3feda06..621d860c5cd47 100644 --- a/.github/workflows/remove_guide_comments.yml +++ b/.github/workflows/remove_guide_comments.yml @@ -11,7 +11,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Remove guide comments - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | const { removeGuideComments } = await import('${{ github.workspace }}/tools/pull_request_hooks/removeGuideComments.js') diff --git a/.github/workflows/rerun_flaky_tests.yml b/.github/workflows/rerun_flaky_tests.yml index 7f498de144308..80ece468061b4 100644 --- a/.github/workflows/rerun_flaky_tests.yml +++ b/.github/workflows/rerun_flaky_tests.yml @@ -12,7 +12,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Rerun flaky tests - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | const { rerunFlakyTests } = await import('${{ github.workspace }}/tools/pull_request_hooks/rerunFlakyTests.js') @@ -24,7 +24,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Report flaky tests - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | const { reportFlakyTests } = await import('${{ github.workspace }}/tools/pull_request_hooks/rerunFlakyTests.js') diff --git a/.github/workflows/show_screenshot_test_results.yml b/.github/workflows/show_screenshot_test_results.yml index c61d09fa89057..b48ca983b35e7 100644 --- a/.github/workflows/show_screenshot_test_results.yml +++ b/.github/workflows/show_screenshot_test_results.yml @@ -34,7 +34,7 @@ jobs: npm install node-fetch - name: Show screenshot test results if: steps.secrets_set.outputs.SECRETS_ENABLED - uses: actions/github-script@v6 + uses: actions/github-script@v7 env: FILE_HOUSE_KEY: ${{ secrets.ARTIFACTS_FILE_HOUSE_KEY }} with: diff --git a/.github/workflows/test_merge_bot.yml b/.github/workflows/test_merge_bot.yml index c77e507794413..76dcd3cabc5b0 100644 --- a/.github/workflows/test_merge_bot.yml +++ b/.github/workflows/test_merge_bot.yml @@ -32,7 +32,7 @@ jobs: npm install node-fetch - name: Check for test merges if: steps.secrets_set.outputs.GET_TEST_MERGES_URL - uses: actions/github-script@v6 + uses: actions/github-script@v7 env: GET_TEST_MERGES_URL: ${{ secrets.GET_TEST_MERGES_URL }} with: diff --git a/_maps/RandomRuins/IceRuins/icemoon_surface_phonebooth.dmm b/_maps/RandomRuins/IceRuins/icemoon_surface_phonebooth.dmm index 2e500943b6430..905403954b67b 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_surface_phonebooth.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_surface_phonebooth.dmm @@ -70,7 +70,7 @@ /area/ruin/powered/icemoon_phone_booth) "W" = ( /obj/machinery/vending/cigarette{ - onstation_override = 1 + all_products_free = 0 }, /obj/structure/window/reinforced/spawner/directional/east, /turf/open/floor/plating/icemoon, diff --git a/_maps/RandomRuins/IceRuins/icemoon_surface_pizza.dmm b/_maps/RandomRuins/IceRuins/icemoon_surface_pizza.dmm index 121f9e4ea45d4..c9b3d35aa7264 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_surface_pizza.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_surface_pizza.dmm @@ -538,9 +538,7 @@ }, /area/ruin/pizzeria) "yP" = ( -/obj/machinery/vending/dinnerware{ - onstation = 0 - }, +/obj/machinery/vending/dinnerware, /obj/effect/turf_decal/tile/blue/opposingcorners{ dir = 1 }, diff --git a/_maps/RandomRuins/IceRuins/icemoon_underground_syndielab.dmm b/_maps/RandomRuins/IceRuins/icemoon_underground_syndielab.dmm new file mode 100644 index 0000000000000..8d90a5079dbb1 --- /dev/null +++ b/_maps/RandomRuins/IceRuins/icemoon_underground_syndielab.dmm @@ -0,0 +1,1247 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"aa" = ( +/obj/structure/table/reinforced/plastitaniumglass, +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/clipboard{ + pixel_y = 3; + pixel_x = -4 + }, +/obj/structure/noticeboard/directional/north, +/obj/item/petri_dish/random, +/obj/item/paper/fluff/junkmail_generic{ + name = "weird note" + }, +/obj/item/paper/guides/antag/supermatter_sliver, +/obj/item/stack/sheet/mineral/plasma{ + pixel_x = 5 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/syndielab) +"aP" = ( +/obj/item/reagent_containers/condiment/milk, +/obj/item/reagent_containers/cup/soda_cans/beer{ + pixel_x = -6 + }, +/obj/item/reagent_containers/cup/soda_cans/beer{ + pixel_x = 6 + }, +/obj/structure/closet/mini_fridge, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"bn" = ( +/obj/structure/table/reinforced/plastitaniumglass, +/obj/item/petri_dish{ + pixel_x = -10; + pixel_y = 10 + }, +/obj/item/reagent_containers/cup/mortar{ + pixel_x = -17; + pixel_y = 1 + }, +/obj/item/pestle{ + pixel_x = -12; + pixel_y = -2 + }, +/obj/structure/microscope, +/obj/machinery/airalarm/directional/north, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/syndielab) +"bx" = ( +/obj/item/cigbutt, +/turf/template_noop, +/area/template_noop) +"bC" = ( +/obj/machinery/navbeacon{ + location = "syndielab_beacon1"; + codes_txt = "patrol;next_patrol=syndielab_beacon2" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/dark/hidden, +/obj/structure/cable/layer1, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"cd" = ( +/obj/structure/chair/sofa/corp/left, +/obj/structure/extinguisher_cabinet/directional/north, +/obj/structure/cable/layer1, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"cg" = ( +/obj/structure/tank_dispenser/oxygen, +/obj/machinery/light/warm/directional/north, +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/sign/warning/gas_mask/directional/north, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"ci" = ( +/obj/structure/flora/bush/pointy/style_3{ + pixel_y = -4; + pixel_x = 6 + }, +/obj/structure/flora/bush/ferny/style_2{ + pixel_y = 6; + pixel_x = -3 + }, +/turf/open/floor/grass{ + initial_gas_mix = "o2=1000;n2=1100;TEMP=280" + }, +/area/ruin/syndielab) +"cu" = ( +/obj/machinery/door/airlock/security{ + desc = "It opens and closes. Menacingly!"; + name = "Syndicate Airlock" + }, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/obj/machinery/atmospherics/pipe/smart/manifold4w/dark/hidden, +/obj/effect/mapping_helpers/airlock/cutaiwire, +/obj/structure/cable/layer1, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"cM" = ( +/mob/living/basic/trooper/syndicate/ranged/shotgun, +/obj/structure/cable/layer1, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"cP" = ( +/obj/effect/mapping_helpers/bombable_wall, +/turf/closed/wall/r_wall/syndicate/nodiagonal{ + desc = "An ominous looking wall. It has extra insulation to keep the heat in."; + name = "plastitanium wall" + }, +/area/ruin/syndielab) +"dD" = ( +/obj/structure/table/wood, +/obj/item/reagent_containers/condiment/bbqsauce{ + pixel_y = 8; + pixel_x = -9 + }, +/obj/item/reagent_containers/condiment/donksauce{ + pixel_y = 5; + pixel_x = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"el" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/dark/hidden, +/obj/structure/cable/layer1, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"ex" = ( +/obj/structure/flora/tree/jungle/small/style_4{ + pixel_x = -14; + pixel_y = 5 + }, +/obj/structure/flora/bush/sunny{ + pixel_y = 12; + pixel_x = 12 + }, +/obj/structure/flora/bush/fullgrass/style_2, +/turf/open/floor/grass{ + initial_gas_mix = "o2=1000;n2=1100;TEMP=280" + }, +/area/ruin/syndielab) +"ey" = ( +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"gE" = ( +/obj/machinery/vending/donksnack{ + onstation_override = 1 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/syndielab) +"hl" = ( +/obj/machinery/navbeacon{ + location = "syndielab_beacon2"; + codes_txt = "patrol;next_patrol=syndielab_beacon3" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/dark/hidden, +/obj/structure/cable/layer1, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"hn" = ( +/obj/machinery/computer/telecomms/monitor{ + dir = 8; + icon_keyboard = "syndie_key" + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"hu" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"iy" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"iQ" = ( +/obj/structure/closet/crate/preopen, +/obj/item/radio/off{ + pixel_x = 8 + }, +/obj/item/radio/off{ + pixel_x = -5 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"lW" = ( +/obj/structure/filingcabinet, +/obj/item/paper/fluff/ruins/hauntedtradingpost/receipt/alternate, +/obj/item/pen, +/obj/item/paper/guides/antag/nuke_instructions, +/obj/item/cigarette/syndicate, +/obj/item/poster/random_contraband, +/obj/item/poster/random_contraband, +/obj/item/sticker/syndicate, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"mi" = ( +/obj/structure/sign/poster/contraband/cybersun_six_hundred/directional/west, +/obj/item/vending_refill/donksoft{ + pixel_x = 2; + pixel_y = 8 + }, +/obj/item/vending_refill/donksnackvendor, +/obj/structure/closet/crate/freezer/donk, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/syndielab) +"na" = ( +/obj/item/climbing_hook, +/obj/item/pickaxe/silver{ + pixel_x = 3; + pixel_y = 5 + }, +/obj/item/t_scanner/adv_mining_scanner{ + pixel_x = 3; + pixel_y = -1 + }, +/obj/item/hatchet/wooden{ + pixel_y = -7; + pixel_x = -3 + }, +/obj/structure/closet/crate/preopen, +/obj/structure/sign/poster/contraband/gorlex_recruitment/directional/west, +/obj/effect/decal/cleanable/plastic, +/obj/structure/extinguisher_cabinet/directional/north, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/syndielab) +"nD" = ( +/obj/structure/table/reinforced/plastitaniumglass, +/obj/machinery/microwave, +/obj/machinery/light/warm/directional/east, +/obj/machinery/airalarm/directional/east, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/syndielab) +"nT" = ( +/obj/machinery/atmospherics/components/binary/pump/on/dark/hidden{ + dir = 1; + target_pressure = 180 + }, +/obj/effect/spawner/structure/window/reinforced/plasma/plastitanium, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/syndielab) +"oA" = ( +/obj/structure/syndicate_uplink_beacon, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"oY" = ( +/obj/effect/mapping_helpers/apc/syndicate_access, +/obj/effect/mapping_helpers/apc/full_charge, +/obj/machinery/power/apc/auto_name/directional/east{ + cable_layer = 1 + }, +/obj/effect/mapping_helpers/apc/cut_AI_wire, +/obj/structure/cable/layer1, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"pK" = ( +/obj/structure/table/reinforced/plastitaniumglass, +/obj/machinery/airalarm/directional/north, +/obj/item/implanter/radio, +/obj/item/implantcase{ + pixel_x = -5; + pixel_y = 8 + }, +/obj/item/traitor_bug{ + pixel_y = 6; + pixel_x = 6 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/syndielab) +"qy" = ( +/obj/item/clothing/suit/hooded/explorer/syndicate{ + pixel_x = 8; + pixel_y = -2 + }, +/obj/item/clothing/mask/gas/syndicate, +/obj/structure/rack, +/obj/machinery/light/warm/directional/north, +/obj/machinery/atmospherics/components/unary/vent_pump/on, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"qC" = ( +/obj/effect/spawner/structure/window/reinforced/plasma/plastitanium, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/syndielab) +"ry" = ( +/obj/item/clothing/shoes/workboots/mining{ + pixel_x = -7; + pixel_y = 10 + }, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"rH" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/dark/hidden, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"rO" = ( +/obj/structure/chair/comfy/black{ + dir = 8 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"sa" = ( +/obj/effect/decal/cleanable/ash, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"sj" = ( +/obj/structure/chair/office/tactical{ + dir = 8 + }, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"sp" = ( +/obj/effect/decal/cleanable/plastic, +/obj/structure/mop_bucket/janitorialcart{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"sV" = ( +/obj/machinery/vending/donksofttoyvendor{ + onstation_override = 1 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/syndielab) +"tb" = ( +/obj/machinery/light/warm/directional/north, +/obj/effect/decal/cleanable/oil/streak, +/obj/machinery/atmospherics/pipe/smart/manifold4w/dark/hidden, +/obj/structure/cable/layer1, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"tC" = ( +/obj/structure/cable/layer1, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"uT" = ( +/obj/structure/table/wood, +/obj/item/ammo_casing/shotgun/scatterlaser{ + pixel_y = 6; + pixel_x = 1 + }, +/obj/item/ammo_casing/shotgun/buckshot{ + pixel_y = 4; + pixel_x = 8 + }, +/turf/open/floor/carpet/red, +/area/ruin/syndielab) +"uX" = ( +/obj/structure/flora/bush/ferny{ + pixel_y = 2; + pixel_x = -2 + }, +/obj/machinery/air_sensor{ + chamber_id = "syndielab_biodome" + }, +/turf/open/floor/grass{ + initial_gas_mix = "o2=1000;n2=1100;TEMP=280" + }, +/area/ruin/syndielab) +"vr" = ( +/obj/structure/sign/poster/contraband/revolver/directional/east, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"vE" = ( +/obj/structure/safe, +/obj/item/book/granter/crafting_recipe/donk_secret_recipe, +/obj/item/stack/sheet/mineral/plasma/thirty, +/obj/item/storage/wallet/money{ + desc = "It can hold a few small and personal things." + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"vO" = ( +/obj/machinery/door/airlock/survival_pod{ + dir = 4 + }, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/obj/effect/decal/cleanable/dirt, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 4 + }, +/obj/structure/fans/tiny, +/obj/effect/mapping_helpers/airlock/cutaiwire, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"wh" = ( +/obj/structure/table/reinforced/plastitaniumglass, +/obj/item/trash/ready_donk{ + pixel_x = 6 + }, +/obj/structure/sign/poster/contraband/eat/directional/east, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/syndielab) +"wj" = ( +/obj/structure/chair/comfy/black{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/manifold4w/dark/hidden, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"wl" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"wJ" = ( +/obj/structure/rack, +/obj/item/storage/backpack/satchel, +/obj/item/clothing/mask/gas/syndicate, +/obj/item/clothing/suit/hooded/explorer/syndicate{ + pixel_x = 8; + pixel_y = -2 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"xa" = ( +/obj/structure/extinguisher_cabinet/directional/south, +/obj/machinery/atmospherics/pipe/smart/manifold4w/dark/hidden, +/obj/structure/cable/layer1, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"xg" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"xr" = ( +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/obj/machinery/door/airlock/security{ + desc = "It opens and closes. Menacingly!"; + name = "Syndicate Airlock" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/dark/hidden, +/obj/effect/mapping_helpers/airlock/cutaiwire, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"yW" = ( +/turf/open/floor/carpet/red, +/area/ruin/syndielab) +"AD" = ( +/obj/structure/bookcase, +/obj/item/book/manual/fish_catalog{ + pixel_x = -3; + pixel_y = -6 + }, +/obj/item/book/manual/nuclear{ + pixel_x = -5; + pixel_y = 1 + }, +/obj/item/book/manual/wiki/cytology{ + pixel_x = 6; + pixel_y = -2 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"AR" = ( +/turf/closed/wall/r_wall/syndicate/nodiagonal{ + desc = "An ominous looking wall. It has extra insulation to keep the heat in."; + name = "plastitanium wall" + }, +/area/ruin/syndielab) +"AX" = ( +/obj/item/ammo_casing/shotgun/buckshot/spent{ + pixel_y = -6; + pixel_x = 4 + }, +/turf/open/floor/carpet/red, +/area/ruin/syndielab) +"Co" = ( +/obj/structure/chair/comfy/black{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"CS" = ( +/obj/machinery/airalarm/directional/east, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"Dd" = ( +/obj/item/storage/bag/trash/filled, +/obj/structure/closet/crate/bin, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"De" = ( +/obj/structure/table/reinforced/plastitaniumglass, +/obj/item/trash/semki{ + pixel_y = 12 + }, +/obj/item/soap/syndie, +/obj/structure/noticeboard/directional/east, +/obj/item/paper/fluff/junkmail_generic{ + name = "weird note" + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/syndielab) +"EY" = ( +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/obj/machinery/door/airlock/security/glass{ + desc = "It opens and closes. Menacingly!"; + name = "Syndicate Airlock" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/dark/hidden, +/obj/effect/mapping_helpers/airlock/cutaiwire, +/obj/structure/cable/layer1, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"Fz" = ( +/obj/structure/cable/layer1, +/obj/machinery/power/terminal{ + cable_layer = 1 + }, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"FJ" = ( +/obj/machinery/light/warm/directional/south, +/obj/machinery/atmospherics/pipe/smart/manifold4w/dark/hidden, +/obj/structure/cable/layer1, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"Gi" = ( +/obj/machinery/navbeacon{ + location = "syndielab_beacon4"; + codes_txt = "patrol;next_patrol=syndielab_beacon1" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/dark/hidden, +/obj/structure/cable/layer1, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"GL" = ( +/obj/structure/chair/office/tactical, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"GV" = ( +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/obj/machinery/door/airlock/security{ + desc = "It opens and closes. Menacingly!"; + name = "Syndicate Airlock" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/dark/hidden, +/obj/effect/mapping_helpers/airlock/cutaiwire, +/obj/structure/cable/layer1, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"Hq" = ( +/obj/item/seeds/lavaland/cactus{ + pixel_x = -8; + pixel_y = 4 + }, +/obj/item/seeds/lavaland/cactus{ + pixel_y = 6; + pixel_x = 8 + }, +/obj/item/seeds/lavaland/fireblossom{ + pixel_y = 3; + pixel_x = 3 + }, +/obj/item/stack/ore/glass/basalt{ + amount = 50; + pixel_y = -3; + pixel_x = -3 + }, +/obj/structure/closet/crate/secure/cybersun/dawn, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/syndielab) +"Hs" = ( +/obj/structure/rack, +/obj/item/storage/bag/trash, +/obj/item/pushbroom, +/obj/item/storage/bag/trash{ + pixel_x = 9; + pixel_y = -3 + }, +/obj/machinery/airalarm/directional/south, +/obj/structure/cable/layer1, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"HH" = ( +/obj/structure/table/reinforced/plastitaniumglass, +/obj/item/paper/guides/antag/hdd_extraction{ + pixel_x = -4; + pixel_y = 4 + }, +/obj/item/book/manual/wiki/tcomms{ + pixel_x = 12; + pixel_y = 1 + }, +/obj/structure/sign/poster/contraband/interdyne_gene_clinics/directional/north, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/syndielab) +"HS" = ( +/obj/structure/rack, +/obj/item/storage/toolbox/syndicate, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"IQ" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/dark/hidden, +/mob/living/basic/bot/dedbot, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"Jc" = ( +/obj/effect/overloader_trap{ + uses_remaining = 1; + shock_damage = 55; + shock_range = 2; + machine_overload_damage = 160 + }, +/obj/machinery/telecomms/hub, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/syndielab) +"JF" = ( +/obj/structure/table/reinforced/plastitaniumglass, +/obj/structure/sign/poster/contraband/hacking_guide/directional/north, +/obj/item/assembly/signaler/cyborg{ + pixel_y = 5; + pixel_x = 6 + }, +/obj/item/assembly/voice{ + pixel_x = -5; + pixel_y = 3 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/syndielab) +"Ka" = ( +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/obj/machinery/door/airlock/security/glass{ + desc = "It opens and closes. Menacingly!"; + name = "Syndicate Airlock" + }, +/obj/effect/mapping_helpers/airlock/cutaiwire, +/obj/structure/cable/layer1, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"KV" = ( +/obj/machinery/computer/atmos_control/noreconnect{ + atmos_chambers = list("syndielab_biodome"="Biodome Atmos"); + dir = 4; + name = "gas tank monitor"; + desc = "This computer connects to and controls the sensors and equipment in a nearby pressurised gas reservoir."; + icon_keyboard = "syndie_key" + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"Lt" = ( +/obj/item/paper/fluff/operative, +/obj/structure/noticeboard/directional/north, +/obj/structure/cable/layer1, +/obj/item/ammo_casing/shotgun/buckshot/spent{ + pixel_x = 8; + pixel_y = 4 + }, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"MW" = ( +/turf/template_noop, +/area/template_noop) +"NM" = ( +/obj/structure/sign/poster/contraband/donk_co/directional/east, +/obj/structure/cable/layer1, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"Qj" = ( +/obj/structure/flora/bush/grassy{ + pixel_x = 15; + pixel_y = 3 + }, +/obj/structure/flora/bush, +/obj/machinery/atmospherics/components/unary/vent_pump/siphon/monitored/oxygen_output{ + dir = 1; + chamber_id = "syndielab_biodome" + }, +/turf/open/floor/grass{ + initial_gas_mix = "o2=1000;n2=1100;TEMP=280" + }, +/area/ruin/syndielab) +"QO" = ( +/obj/structure/table/reinforced/plastitaniumglass, +/obj/item/computer_disk/syndicate/camera_app{ + pixel_y = 4; + pixel_x = -5 + }, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/crowbar/hammer{ + pixel_x = 3; + pixel_y = 1 + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/syndielab) +"Sq" = ( +/obj/structure/rack, +/obj/item/pinata/donk{ + pixel_y = 10 + }, +/obj/item/storage/box/party_poppers{ + pixel_y = 1; + pixel_x = 7 + }, +/obj/item/storage/box/firecrackers{ + pixel_x = -8 + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, +/obj/structure/cable/layer1, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"Te" = ( +/obj/machinery/navbeacon{ + location = "syndielab_beacon3"; + codes_txt = "patrol;next_patrol=syndielab_beacon4" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/dark/hidden, +/obj/structure/cable/layer1, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"Tl" = ( +/obj/item/stack/tile/carpet/donk/thirty{ + pixel_x = 6; + pixel_y = -5 + }, +/obj/item/toy/plush/donkpocket{ + pixel_x = 12; + pixel_y = 3 + }, +/obj/item/stack/tile/carpet/donk/thirty{ + pixel_x = -6; + pixel_y = -5 + }, +/obj/item/toy/plush/donkpocket{ + pixel_x = -4; + pixel_y = 3 + }, +/obj/item/stack/package_wrap, +/obj/structure/closet/crate/preopen, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/syndielab) +"Ts" = ( +/obj/structure/table/reinforced/plastitaniumglass, +/obj/structure/sign/poster/contraband/c20r/directional/north, +/obj/item/anomaly_releaser{ + pixel_y = 6 + }, +/obj/item/anomaly_releaser, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/syndielab) +"TB" = ( +/obj/structure/chair/comfy/black{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"UF" = ( +/obj/machinery/door/airlock/survival_pod/glass{ + dir = 4 + }, +/obj/effect/mapping_helpers/airlock/access/all/syndicate/general, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, +/obj/structure/fans/tiny, +/obj/machinery/atmospherics/pipe/smart/manifold4w/dark/hidden, +/obj/effect/mapping_helpers/airlock/cutaiwire, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"UM" = ( +/obj/item/ammo_box/c9mm, +/obj/item/ammo_box/magazine/m9mm, +/obj/structure/closet/crate/secure/gorlex_weapons{ + req_one_access = list("syndicate") + }, +/turf/open/floor/mineral/plastitanium/red, +/area/ruin/syndielab) +"Vf" = ( +/obj/effect/decal/cleanable/molten_object, +/obj/machinery/atmospherics/components/unary/vent_pump/on, +/obj/item/stack/ore/plasma{ + pixel_x = 7; + pixel_y = 10 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"Vu" = ( +/obj/structure/aquarium/donkfish, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"VO" = ( +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"Wn" = ( +/obj/machinery/computer/terminal{ + dir = 4; + upperinfo = "ERROR - NO FINGERPRINT MATCH ON FILE!"; + tguitheme = "syndicate"; + desc = "An state-of-the-art lab terminal. The Cybersun Industries logo is imprinted just below the screen."; + content = list("*Solid Matter Analyzer and Research Terminal*"); + name = "lab terminal"; + icon_screen = "tcboss"; + icon_keyboard = "syndie_key" + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"Wo" = ( +/obj/structure/table/wood, +/obj/item/ammo_casing/shotgun/fletchette{ + pixel_y = 6 + }, +/obj/item/ammo_casing/shotgun/fletchette{ + pixel_x = 8; + pixel_y = 6 + }, +/obj/item/gun/ballistic/shotgun/musket, +/turf/open/floor/carpet/red, +/area/ruin/syndielab) +"WO" = ( +/obj/item/trash/boritos/red{ + pixel_y = -9; + pixel_x = -5 + }, +/obj/structure/cable/layer1, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) +"Xe" = ( +/obj/structure/closet/crate/cardboard, +/obj/item/paint/red{ + pixel_y = 2; + pixel_x = -6 + }, +/obj/item/paint_palette{ + pixel_y = 6; + pixel_x = 8 + }, +/obj/item/mod/paint, +/obj/structure/sign/poster/contraband/energy_swords/directional/south, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"Xm" = ( +/obj/structure/closet/crate/secure/trashcart, +/obj/item/relic, +/obj/item/storage/bag/trash/filled{ + pixel_y = 1; + pixel_x = 6 + }, +/obj/item/storage/bag/trash/filled{ + pixel_x = -6; + pixel_y = 1 + }, +/obj/item/storage/bag/trash/filled{ + pixel_y = -1 + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 8 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"Xt" = ( +/turf/closed/mineral/snowmountain/icemoon, +/area/icemoon/underground/explored) +"YH" = ( +/obj/item/storage/medkit, +/obj/structure/sign/poster/contraband/free_key/directional/south, +/obj/structure/rack, +/obj/item/stack/medical/suture, +/obj/item/clothing/neck/stethoscope, +/obj/item/reagent_containers/hypospray/medipen/atropine, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"Ze" = ( +/obj/machinery/porta_turret/syndicate/energy/cybersun, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"Zx" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/power/smes/magical/cybersun{ + cable_layer = 1; + input_level = 180000; + output_level = 200000; + dir = 1 + }, +/obj/structure/cable/layer1, +/turf/open/floor/mineral/plastitanium, +/area/ruin/syndielab) +"ZW" = ( +/obj/structure/chair/sofa/corp/right, +/mob/living/basic/trooper/syndicate/ranged/shotgun, +/obj/machinery/light/warm/directional/north, +/obj/structure/cable/layer1, +/turf/open/floor/iron/dark/textured, +/area/ruin/syndielab) + +(1,1,1) = {" +MW +MW +MW +MW +Xt +Xt +bx +MW +MW +Xt +MW +MW +MW +MW +MW +MW +"} +(2,1,1) = {" +MW +MW +MW +MW +Xt +AR +AR +vO +AR +Xt +Xt +Xt +Xt +MW +MW +MW +"} +(3,1,1) = {" +MW +MW +Xt +Xt +Xt +AR +cg +xg +AR +AR +cP +AR +Xt +Xt +Xt +MW +"} +(4,1,1) = {" +MW +AR +AR +AR +AR +AR +AR +UF +AR +na +mi +AR +AR +AR +Xt +Xt +"} +(5,1,1) = {" +Xt +AR +aa +Wn +bC +EY +el +el +AR +iQ +iy +vE +Xe +AR +AR +Xt +"} +(6,1,1) = {" +Xt +AR +Ts +sj +FJ +AR +qy +el +AR +AD +ry +ey +VO +Tl +AR +Xt +"} +(7,1,1) = {" +Xt +AR +bn +Vf +xa +AR +Ze +Gi +cu +el +ey +wl +sa +Hq +AR +Xt +"} +(8,1,1) = {" +Xt +AR +AR +AR +EY +AR +qC +qC +AR +tb +HS +ey +sp +UM +AR +Xt +"} +(9,1,1) = {" +Xt +AR +pK +KV +el +nT +Qj +ex +qC +el +Sq +cM +Hs +AR +AR +Xt +"} +(10,1,1) = {" +Xt +AR +JF +sj +el +qC +uX +ci +qC +el +oY +Fz +Zx +AR +Xt +Xt +"} +(11,1,1) = {" +Xt +AR +Jc +oA +FJ +AR +qC +qC +AR +GV +AR +qC +qC +AR +Xt +MW +"} +(12,1,1) = {" +Xt +AR +HH +GL +hl +IQ +rH +rH +xr +Te +hu +TB +lW +AR +Xt +MW +"} +(13,1,1) = {" +Xt +AR +QO +hn +el +Xm +rO +aP +AR +Lt +AX +yW +YH +AR +Xt +MW +"} +(14,1,1) = {" +Xt +AR +AR +AR +EY +qC +qC +qC +AR +ZW +uT +yW +Vu +AR +Xt +MW +"} +(15,1,1) = {" +Xt +Xt +AR +gE +el +wj +dD +Co +AR +cd +Wo +yW +Dd +AR +Xt +MW +"} +(16,1,1) = {" +MW +Xt +AR +sV +NM +tC +tC +tC +Ka +WO +vr +CS +wJ +AR +Xt +MW +"} +(17,1,1) = {" +MW +Xt +AR +AR +AR +nD +wh +De +AR +AR +AR +AR +AR +AR +MW +MW +"} +(18,1,1) = {" +MW +MW +Xt +Xt +AR +AR +AR +AR +AR +Xt +Xt +Xt +Xt +Xt +Xt +MW +"} +(19,1,1) = {" +MW +MW +MW +Xt +Xt +Xt +Xt +Xt +Xt +Xt +MW +MW +MW +MW +MW +MW +"} diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_phonebooth.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_phonebooth.dmm index 851cfe35548b6..4cbf3478bc233 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_phonebooth.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_phonebooth.dmm @@ -13,7 +13,7 @@ /area/ruin/powered/lavaland_phone_booth) "k" = ( /obj/machinery/vending/snack/green{ - onstation_override = 1 + all_products_free = 0 }, /obj/structure/window/reinforced/spawner/directional/east, /turf/open/floor/plating/lavaland_atmos, @@ -66,7 +66,7 @@ /area/ruin/powered/lavaland_phone_booth) "W" = ( /obj/machinery/vending/cigarette{ - onstation_override = 1 + all_products_free = 0 }, /obj/structure/window/reinforced/spawner/directional/east, /turf/open/floor/plating/lavaland_atmos, diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm index 6df974f9ea279..b73cf11fda63e 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm @@ -18,19 +18,19 @@ "aj" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/obj/machinery/vending/medical/syndicate_access, +/obj/machinery/vending/medical/syndicate, /turf/open/floor/iron/white/side{ dir = 4 }, /area/ruin/syndicate_lava_base/virology) "ak" = ( -/obj/machinery/vending/boozeomat/syndicate_access, +/obj/machinery/vending/boozeomat/syndicate, /turf/closed/wall/mineral/plastitanium/nodiagonal, /area/ruin/syndicate_lava_base/bar) "al" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/obj/machinery/vending/medical/syndicate_access, +/obj/machinery/vending/medical/syndicate, /turf/open/floor/iron/white, /area/ruin/syndicate_lava_base/medbay) "ap" = ( diff --git a/_maps/RandomRuins/SpaceRuins/forgottenship.dmm b/_maps/RandomRuins/SpaceRuins/forgottenship.dmm index 7b12e87992c8a..cb2a35084f93e 100644 --- a/_maps/RandomRuins/SpaceRuins/forgottenship.dmm +++ b/_maps/RandomRuins/SpaceRuins/forgottenship.dmm @@ -613,7 +613,7 @@ /turf/open/floor/mineral/plastitanium, /area/ruin/space/has_grav/syndicate_forgotten_ship) "ct" = ( -/obj/machinery/vending/medical/syndicate_access/cybersun, +/obj/machinery/vending/medical/syndicate/cybersun, /turf/open/floor/plastic, /area/ruin/space/has_grav/syndicate_forgotten_ship) "cu" = ( diff --git a/_maps/RandomRuins/SpaceRuins/hauntedtradingpost.dmm b/_maps/RandomRuins/SpaceRuins/hauntedtradingpost.dmm index 50e0bffd56727..df3c3ca64277e 100644 --- a/_maps/RandomRuins/SpaceRuins/hauntedtradingpost.dmm +++ b/_maps/RandomRuins/SpaceRuins/hauntedtradingpost.dmm @@ -139,7 +139,7 @@ "bq" = ( /obj/structure/cable/layer1, /obj/machinery/vending/sovietsoda{ - onstation_override = 1 + all_products_free = 0 }, /obj/structure/sign/poster/contraband/clown/directional/east, /obj/machinery/duct, @@ -527,7 +527,7 @@ "dU" = ( /obj/structure/cable/layer1, /obj/machinery/vending/cigarette/syndicate{ - onstation_override = 1 + all_products_free = 0 }, /obj/machinery/duct, /obj/effect/mapping_helpers/broken_machine, @@ -544,7 +544,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer4, /obj/machinery/duct, /obj/machinery/vending/clothing{ - onstation_override = 1 + all_products_free = 0 }, /obj/machinery/firealarm/directional/south, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ @@ -1378,7 +1378,7 @@ /area/ruin/space/has_grav/hauntedtradingpost/office/meetingroom) "lT" = ( /obj/machinery/vending/cola/black{ - onstation_override = 1 + all_products_free = 0 }, /obj/machinery/duct, /obj/effect/mapping_helpers/broken_machine, @@ -1866,7 +1866,7 @@ /obj/structure/cable/layer1, /obj/machinery/duct, /obj/machinery/vending/assist{ - onstation_override = 1 + all_products_free = 0 }, /obj/machinery/camera/xray/directional/west, /turf/open/floor/catwalk_floor/iron_smooth, @@ -2475,7 +2475,7 @@ /obj/structure/cable/layer1, /obj/machinery/duct, /obj/machinery/vending/cola/shamblers{ - onstation_override = 1 + all_products_free = 0 }, /turf/open/floor/catwalk_floor/iron_smooth, /area/ruin/space/has_grav/hauntedtradingpost/public/corridor) @@ -4199,7 +4199,7 @@ "KH" = ( /obj/structure/cable/layer1, /obj/machinery/vending/donksnack{ - onstation_override = 1 + all_products_free = 0 }, /obj/machinery/duct, /obj/machinery/camera/autoname/directional/west{ @@ -4516,7 +4516,7 @@ "MO" = ( /obj/machinery/duct, /obj/machinery/vending/snack{ - onstation_override = 1 + all_products_free = 0 }, /turf/open/floor/catwalk_floor/iron_smooth, /area/ruin/space/has_grav/hauntedtradingpost/public/corridor) @@ -4616,7 +4616,7 @@ "NY" = ( /obj/structure/cable/layer1, /obj/machinery/vending/coffee{ - onstation_override = 1 + all_products_free = 0 }, /obj/machinery/duct, /turf/open/floor/catwalk_floor/iron_smooth, @@ -4755,7 +4755,7 @@ "Pk" = ( /obj/structure/cable/layer1, /obj/machinery/vending/tool{ - onstation_override = 1 + all_products_free = 0 }, /obj/structure/sign/poster/contraband/donk_co/directional/west, /obj/machinery/duct, @@ -4886,7 +4886,7 @@ "QM" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer4, /obj/machinery/vending/sovietsoda{ - onstation_override = 1 + all_products_free = 0 }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ pipe_color = "#FF7B00"; @@ -5415,7 +5415,7 @@ /obj/structure/cable/layer1, /obj/machinery/duct, /obj/machinery/vending/medical{ - onstation_override = 1; + all_products_free = 0; name = "\improper CyberMed +" }, /turf/open/floor/catwalk_floor/iron_smooth, @@ -5635,7 +5635,7 @@ /area/ruin/space/has_grav/hauntedtradingpost/office) "Ww" = ( /obj/machinery/vending/coffee{ - onstation_override = 1 + all_products_free = 0 }, /obj/structure/cable/layer1, /obj/machinery/duct, @@ -5712,7 +5712,7 @@ "Xe" = ( /obj/structure/cable/layer1, /obj/machinery/vending/cola/shamblers{ - onstation_override = 1 + all_products_free = 0 }, /obj/machinery/duct, /obj/effect/overloader_trap, @@ -5802,7 +5802,7 @@ /area/ruin/space/has_grav/hauntedtradingpost/public) "XK" = ( /obj/machinery/vending/donksnack{ - onstation_override = 1 + all_products_free = 0 }, /obj/machinery/duct, /turf/open/floor/catwalk_floor/iron_smooth, diff --git a/_maps/RandomRuins/SpaceRuins/infested_frigate.dmm b/_maps/RandomRuins/SpaceRuins/infested_frigate.dmm index abccc6b550eb1..c925d017ad3a3 100644 --- a/_maps/RandomRuins/SpaceRuins/infested_frigate.dmm +++ b/_maps/RandomRuins/SpaceRuins/infested_frigate.dmm @@ -690,7 +690,7 @@ /turf/open/floor/mineral/plastitanium, /area/ruin/space/has_grav/infested_frigate) "kw" = ( -/obj/machinery/vending/boozeomat/syndicate_access, +/obj/machinery/vending/boozeomat/syndicate, /turf/open/floor/iron/freezer, /area/ruin/space/has_grav/infested_frigate) "kS" = ( diff --git a/_maps/RandomRuins/SpaceRuins/interdyne.dmm b/_maps/RandomRuins/SpaceRuins/interdyne.dmm index cf8c7f8c0d408..9c802b0be434c 100644 --- a/_maps/RandomRuins/SpaceRuins/interdyne.dmm +++ b/_maps/RandomRuins/SpaceRuins/interdyne.dmm @@ -140,7 +140,7 @@ /turf/open/floor/mineral/plastitanium, /area/ruin/space/has_grav/interdyne) "fS" = ( -/obj/machinery/vending/medical/syndicate_access, +/obj/machinery/vending/medical/syndicate, /turf/open/floor/mineral/plastitanium, /area/ruin/space/has_grav/interdyne) "ga" = ( diff --git a/_maps/RandomRuins/SpaceRuins/oldstation.dmm b/_maps/RandomRuins/SpaceRuins/oldstation.dmm index 55f0f884f165a..0c3c231b5f225 100644 --- a/_maps/RandomRuins/SpaceRuins/oldstation.dmm +++ b/_maps/RandomRuins/SpaceRuins/oldstation.dmm @@ -1645,9 +1645,7 @@ /area/ruin/space/ancientstation/charlie/hall) "hr" = ( /obj/effect/decal/cleanable/dirt, -/obj/machinery/vending/dinnerware{ - onstation = 0 - }, +/obj/machinery/vending/dinnerware, /turf/open/floor/iron/cafeteria, /area/ruin/space/ancientstation/charlie/kitchen) "ht" = ( @@ -2368,9 +2366,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/cobweb/cobweb2, /obj/effect/decal/cleanable/dirt, -/obj/machinery/vending/coffee{ - onstation = 0 - }, +/obj/machinery/vending/coffee, /turf/open/floor/iron, /area/ruin/space/ancientstation/charlie/dorms) "ku" = ( @@ -2744,9 +2740,7 @@ /turf/open/floor/plating, /area/ruin/space/ancientstation/charlie/hall) "lU" = ( -/obj/machinery/vending/hydronutrients{ - onstation = 0 - }, +/obj/machinery/vending/hydronutrients, /obj/effect/turf_decal/tile/green/anticorner/contrasted, /turf/open/floor/iron, /area/ruin/space/ancientstation/charlie/hydro) diff --git a/_maps/RandomRuins/SpaceRuins/phonebooth.dmm b/_maps/RandomRuins/SpaceRuins/phonebooth.dmm index 2eb0698ebbfd5..1cf0f64e7ff0a 100644 --- a/_maps/RandomRuins/SpaceRuins/phonebooth.dmm +++ b/_maps/RandomRuins/SpaceRuins/phonebooth.dmm @@ -13,7 +13,7 @@ /area/ruin/space/has_grav/powered/space_phone_booth) "k" = ( /obj/machinery/vending/snack/green{ - onstation_override = 1 + all_products_free = 1 }, /obj/structure/window/reinforced/spawner/directional/east, /turf/open/floor/plating/airless, @@ -66,7 +66,7 @@ /area/ruin/space/has_grav/powered/space_phone_booth) "W" = ( /obj/machinery/vending/cigarette{ - onstation_override = 1 + all_products_free = 0 }, /obj/structure/window/reinforced/spawner/directional/east, /turf/open/floor/plating/airless, diff --git a/_maps/RandomRuins/SpaceRuins/spinwardsmoothies.dmm b/_maps/RandomRuins/SpaceRuins/spinwardsmoothies.dmm index 91f7771f0ea69..1ac14090b39ce 100644 --- a/_maps/RandomRuins/SpaceRuins/spinwardsmoothies.dmm +++ b/_maps/RandomRuins/SpaceRuins/spinwardsmoothies.dmm @@ -44,9 +44,7 @@ }, /area/ruin/space/has_grav/spinwardsmoothies) "ti" = ( -/obj/machinery/vending/boozeomat/all_access{ - onstation = 0 - }, +/obj/machinery/vending/boozeomat, /turf/open/floor/wood/tile, /area/ruin/space/has_grav/spinwardsmoothies) "wv" = ( diff --git a/_maps/RandomRuins/SpaceRuins/whiteshipruin_box.dmm b/_maps/RandomRuins/SpaceRuins/whiteshipruin_box.dmm index 602aa1a273b9d..12bc608bda910 100644 --- a/_maps/RandomRuins/SpaceRuins/whiteshipruin_box.dmm +++ b/_maps/RandomRuins/SpaceRuins/whiteshipruin_box.dmm @@ -1331,9 +1331,7 @@ /obj/effect/turf_decal/tile/blue/anticorner/contrasted{ dir = 8 }, -/obj/machinery/vending/medical{ - onstation = 0 - }, +/obj/machinery/vending/medical, /turf/open/floor/iron/showroomfloor/airless, /area/ruin/space/has_grav/whiteship/box) "PV" = ( diff --git a/_maps/RandomZLevels/TheBeach.dmm b/_maps/RandomZLevels/TheBeach.dmm index 41fcd3280d490..d179a7dc5148c 100644 --- a/_maps/RandomZLevels/TheBeach.dmm +++ b/_maps/RandomZLevels/TheBeach.dmm @@ -738,7 +738,7 @@ /turf/open/floor/iron/white/textured_large, /area/awaymission/beach) "jF" = ( -/obj/machinery/vending/boozeomat/all_access{ +/obj/machinery/vending/boozeomat{ desc = "A technological marvel, supposedly able to mix just the mixture you'd like to drink the moment you ask for one. May not work for bartenders that don't have Nanotrasen bank accounts." }, /turf/open/floor/wood/large, @@ -2766,7 +2766,7 @@ /turf/open/floor/iron/white/textured_large, /area/awaymission/beach) "Il" = ( -/obj/machinery/vending/autodrobe/all_access, +/obj/machinery/vending/autodrobe, /turf/open/misc/beach/sand, /area/awaymission/beach) "It" = ( diff --git a/_maps/RandomZLevels/museum.dmm b/_maps/RandomZLevels/museum.dmm index afd0cd888fdcd..88bf95847b9a4 100644 --- a/_maps/RandomZLevels/museum.dmm +++ b/_maps/RandomZLevels/museum.dmm @@ -2720,7 +2720,7 @@ "wi" = ( /obj/machinery/door/poddoor/shutters/indestructible{ dir = 8; - id = "museum_secret" + id = "museum_right_wing" }, /turf/open/floor/iron, /area/awaymission/museum) @@ -3128,7 +3128,7 @@ /turf/open/floor/bluespace, /area/awaymission/museum) "zC" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /turf/open/floor/wood/tile, /area/awaymission/museum) "zE" = ( @@ -3958,7 +3958,7 @@ /area/awaymission/museum) "FO" = ( /obj/effect/decal/cleanable/crayon/puzzle/pin{ - puzzle_id = "museum_r_wing_puzzle" + puzzle_id = "museum_right_wing" }, /turf/closed/indestructible/reinforced, /area/awaymission/museum) @@ -4152,7 +4152,7 @@ /obj/effect/turf_decal/siding/dark_blue, /obj/machinery/door/poddoor/shutters/indestructible{ dir = 8; - id = "museum_secret" + id = "museum_right_wing" }, /turf/open/floor/iron/dark, /area/awaymission/museum) @@ -4221,7 +4221,7 @@ /area/awaymission/museum) "Id" = ( /obj/effect/decal/cleanable/crayon/puzzle/pin{ - puzzle_id = "museum_r_wing_puzzle" + puzzle_id = "museum_right_wing" }, /turf/closed/indestructible/wood, /area/awaymission/museum) @@ -5246,7 +5246,7 @@ /obj/structure/fluff/fake_camera, /obj/effect/decal/puzzle_dots{ pixel_y = -32; - id = "museum_r_wing_puzzle" + id = "museum_right_wing" }, /turf/open/floor/iron/dark, /area/awaymission/museum) @@ -5332,10 +5332,10 @@ }, /obj/machinery/door/poddoor/shutters/indestructible{ dir = 8; - id = "museum_secret" + id = "museum_right_wing" }, /obj/machinery/puzzle/password/pin/directional/south{ - id = "museum_r_wing_puzzle"; + id = "museum_right_wing"; late_initialize_pop = 1 }, /turf/open/floor/iron/dark, @@ -5349,7 +5349,7 @@ /obj/machinery/light/directional/west, /obj/effect/decal/cleanable/crayon/puzzle/pin{ pixel_x = -32; - puzzle_id = "museum_r_wing_puzzle" + puzzle_id = "museum_right_wing" }, /turf/open/floor/iron/white/small, /area/awaymission/museum) diff --git a/_maps/deathmatch/ragin_mages.dmm b/_maps/deathmatch/ragin_mages.dmm index 1a3d307181d08..96249fcf6928d 100644 --- a/_maps/deathmatch/ragin_mages.dmm +++ b/_maps/deathmatch/ragin_mages.dmm @@ -479,9 +479,6 @@ /turf/open/floor/engine/cult, /area/deathmatch) "DK" = ( -/obj/structure/railing{ - dir = 8 - }, /obj/structure/railing{ dir = 8 }, diff --git a/_maps/map_files/Basketball/stadium.dmm b/_maps/map_files/Basketball/stadium.dmm index bcbb91ce4b7ef..c6b6901672553 100644 --- a/_maps/map_files/Basketball/stadium.dmm +++ b/_maps/map_files/Basketball/stadium.dmm @@ -405,7 +405,7 @@ /turf/open/floor/wood, /area/centcom/basketball) "Ax" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /turf/open/floor/wood, /area/centcom/basketball) "AC" = ( diff --git a/_maps/map_files/Birdshot/birdshot.dmm b/_maps/map_files/Birdshot/birdshot.dmm index 09040a5d9031f..06be9312ae9f9 100644 --- a/_maps/map_files/Birdshot/birdshot.dmm +++ b/_maps/map_files/Birdshot/birdshot.dmm @@ -1680,17 +1680,17 @@ "aGI" = ( /obj/structure/table, /obj/effect/decal/cleanable/dirt, -/obj/item/trash/can/food/pine_nuts{ - pixel_x = 16; - pixel_y = 6 - }, /obj/machinery/cell_charger{ pixel_x = -1; - pixel_y = 2 + pixel_y = 4 }, /obj/item/stock_parts/power_store/cell/high{ pixel_x = -1; - pixel_y = 1 + pixel_y = 4 + }, +/obj/item/assembly/timer{ + pixel_x = 14; + pixel_y = 6 }, /turf/open/floor/iron/dark, /area/station/commons/storage/tools) @@ -1759,12 +1759,15 @@ /area/station/maintenance/department/engine/atmos) "aIr" = ( /obj/structure/table/reinforced, -/obj/machinery/door/window/right/directional/south, /obj/machinery/door/poddoor/shutters/preopen{ id = "kitchenshutters"; name = "Kitchen Shutters" }, -/turf/open/floor/iron/kitchen/small, +/obj/effect/turf_decal/siding/end{ + dir = 8 + }, +/obj/machinery/door/window/left/directional/south, +/turf/open/floor/iron/dark/textured_large, /area/station/service/kitchen) "aIu" = ( /obj/structure/bookcase/random/reference, @@ -8780,6 +8783,7 @@ /obj/effect/decal/cleanable/dirt, /obj/machinery/light_switch/directional/west, /obj/effect/landmark/event_spawn, +/obj/machinery/portable_atmospherics/pump/lil_pump, /turf/open/floor/iron/dark, /area/station/science/ordnance) "dpH" = ( @@ -11105,9 +11109,11 @@ }, /obj/machinery/door/poddoor/shutters/preopen{ id = "kitchenshutters"; - name = "Kitchen Shutters" + name = "Kitchen Shutters"; + dir = 4 }, -/turf/open/floor/plating, +/obj/effect/turf_decal/siding/end, +/turf/open/floor/iron/dark/textured_large, /area/station/service/kitchen) "elc" = ( /obj/structure/cable, @@ -14993,9 +14999,13 @@ /obj/machinery/smartfridge, /obj/machinery/door/poddoor/shutters/preopen{ id = "kitchenshutters"; - name = "Kitchen Shutters" + name = "Kitchen Shutters"; + dir = 4 }, -/turf/open/floor/iron/kitchen/small, +/obj/effect/turf_decal/siding/end{ + dir = 1 + }, +/turf/open/floor/iron/dark/textured_large, /area/station/service/kitchen) "fGT" = ( /obj/effect/turf_decal/tile/neutral{ @@ -18623,6 +18633,7 @@ /obj/structure/window/spawner/directional/east, /obj/structure/closet/crate, /obj/effect/turf_decal/bot_white, +/obj/item/clothing/gloves/color/fyellow, /obj/item/stack/package_wrap{ pixel_y = 5 }, @@ -18633,6 +18644,12 @@ desc = "It smells of monkey business..."; name = "Empty Gorillacube Box" }, +/obj/item/weldingtool, +/obj/item/radio{ + pixel_y = 3; + pixel_x = -6 + }, +/obj/item/assembly/signaler, /turf/open/floor/iron/smooth, /area/station/commons/storage/tools) "gRm" = ( @@ -19580,17 +19597,11 @@ /area/station/commons/storage/tools) "hgd" = ( /obj/structure/table, -/obj/item/clothing/head/collectable/paper{ - pixel_x = -6; - pixel_y = -2 - }, -/obj/item/paper/crumpled{ - pixel_x = 5; - pixel_y = 8 +/obj/item/screwdriver{ + pixel_y = -6 }, -/obj/item/trash/candle{ - pixel_x = 7; - pixel_y = 1 +/obj/item/storage/toolbox/mechanical{ + pixel_y = 7 }, /turf/open/floor/iron/dark, /area/station/commons/storage/tools) @@ -19953,6 +19964,10 @@ pixel_x = 5; pixel_y = 3 }, +/obj/item/gps{ + pixel_y = 5; + pixel_x = 13 + }, /obj/item/storage/toolbox/emergency/old, /turf/open/floor/iron/dark, /area/station/commons/storage/tools) @@ -20005,21 +20020,20 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/table, /obj/effect/decal/cleanable/dirt, -/obj/item/storage/toolbox/mechanical/old{ - pixel_x = 15; - pixel_y = 15 - }, /obj/item/crowbar/large{ pixel_y = 18 }, /obj/item/clothing/head/costume/pirate{ - pixel_x = 17; - pixel_y = -10 + pixel_x = 15; + pixel_y = -3 }, /obj/item/clothing/suit/hazardvest{ pixel_x = -3; pixel_y = -2 }, +/obj/item/wrench{ + pixel_y = 15 + }, /turf/open/floor/iron/dark, /area/station/commons/storage/tools) "hnf" = ( @@ -20217,9 +20231,11 @@ /obj/machinery/door/window/right/directional/west, /obj/machinery/door/poddoor/shutters/preopen{ id = "kitchenshutters"; - name = "Kitchen Shutters" + name = "Kitchen Shutters"; + dir = 8 }, -/turf/open/floor/iron, +/obj/effect/turf_decal/siding/end, +/turf/open/floor/iron/dark/textured_large, /area/station/service/kitchen) "hrx" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -20399,6 +20415,7 @@ }, /obj/effect/turf_decal/delivery/white, /obj/structure/rack, +/obj/item/hand_labeler, /obj/item/stack/cable_coil/five, /obj/item/pickaxe, /obj/item/wrench, @@ -34445,6 +34462,10 @@ "lNN" = ( /obj/structure/table, /obj/item/toy/foamblade, +/obj/item/analyzer{ + pixel_y = 8; + pixel_x = -9 + }, /turf/open/floor/iron/dark/small, /area/station/commons/fitness/locker_room) "lNQ" = ( @@ -34861,6 +34882,7 @@ dir = 1 }, /obj/effect/landmark/start/atmospheric_technician, +/obj/structure/cable, /turf/open/floor/wood, /area/station/engineering/break_room) "lVy" = ( @@ -35175,6 +35197,18 @@ }, /turf/open/floor/plating, /area/station/maintenance/department/engine/atmos) +"lZs" = ( +/obj/structure/table/reinforced, +/obj/machinery/door/window/right/directional/south, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "kitchenshutters"; + name = "Kitchen Shutters" + }, +/obj/effect/turf_decal/siding/end{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured_large, +/area/station/service/kitchen) "lZt" = ( /obj/machinery/portable_atmospherics/canister/air, /turf/open/floor/plating, @@ -35237,13 +35271,13 @@ /area/station/hallway/secondary/dock) "lZP" = ( /obj/structure/table, -/obj/item/clothing/head/fedora/det_hat/minor{ - pixel_x = 7; - pixel_y = 9 - }, /obj/item/toy/eightball{ pixel_x = -4 }, +/obj/item/wirecutters{ + pixel_y = 17; + pixel_x = 4 + }, /turf/open/floor/iron/dark/small, /area/station/commons/fitness/locker_room) "lZR" = ( @@ -36170,7 +36204,9 @@ }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/table, -/obj/item/folder/red, +/obj/item/folder/red{ + pixel_y = 3 + }, /obj/item/food/monkeycube/bee{ name = "monkey cube"; pixel_y = 17 @@ -36181,6 +36217,9 @@ name = "monkey cube"; desc = "A new Nanotrasen classic, the monkey cube. Tastes like everything!" }, +/obj/item/wirecutters{ + pixel_y = 6 + }, /turf/open/floor/iron/dark, /area/station/commons/storage/tools) "msg" = ( @@ -36584,6 +36623,10 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos) +"mzv" = ( +/obj/docking_port/stationary/syndicate/northeast, +/turf/open/space/basic, +/area/space) "mzx" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -39820,6 +39863,7 @@ pixel_x = 15; pixel_y = 7 }, +/obj/structure/cable, /turf/open/floor/wood, /area/station/engineering/break_room) "nHu" = ( @@ -40240,9 +40284,16 @@ }, /obj/machinery/door/poddoor/shutters/preopen{ id = "kitchenshutters"; - name = "Kitchen Shutters" + name = "Kitchen Shutters"; + dir = 4 }, -/turf/open/floor/plating, +/obj/effect/turf_decal/siding{ + dir = 4 + }, +/obj/effect/turf_decal/siding{ + dir = 8 + }, +/turf/open/floor/iron/dark/textured_large, /area/station/service/kitchen) "nQa" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -40324,6 +40375,7 @@ }, /obj/machinery/holopad, /obj/effect/decal/cleanable/dirt/dust, +/obj/structure/cable, /turf/open/floor/iron/small, /area/station/engineering/break_room) "nQH" = ( @@ -46988,6 +47040,7 @@ }, /obj/item/kirbyplants/random, /obj/machinery/firealarm/directional/south, +/obj/item/storage/belt/utility, /turf/open/floor/iron/smooth, /area/station/commons/storage/tools) "qhh" = ( @@ -47783,6 +47836,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/structure/cable, /turf/open/floor/plating/elevatorshaft, /area/station/engineering/break_room) "qxN" = ( @@ -51211,6 +51265,7 @@ pixel_y = 6 }, /obj/structure/disposalpipe/segment, +/obj/structure/cable, /turf/open/floor/wood, /area/station/engineering/break_room) "rDj" = ( @@ -52253,12 +52308,19 @@ /obj/machinery/door/firedoor/border_only{ dir = 4 }, +/obj/effect/spawner/random/food_or_drink/condiment, /obj/machinery/door/poddoor/shutters/preopen{ id = "kitchenshutters"; - name = "Kitchen Shutters" + name = "Kitchen Shutters"; + dir = 4 }, -/obj/effect/spawner/random/food_or_drink/condiment, -/turf/open/floor/plating, +/obj/effect/turf_decal/siding{ + dir = 4 + }, +/obj/effect/turf_decal/siding{ + dir = 8 + }, +/turf/open/floor/iron/dark/textured_large, /area/station/service/kitchen) "rVy" = ( /obj/effect/turf_decal/stripes/red/line{ @@ -55501,12 +55563,19 @@ /obj/machinery/door/firedoor/border_only{ dir = 4 }, +/obj/effect/spawner/random/food_or_drink/donuts, /obj/machinery/door/poddoor/shutters/preopen{ id = "kitchenshutters"; - name = "Kitchen Shutters" + name = "Kitchen Shutters"; + dir = 4 }, -/obj/effect/spawner/random/food_or_drink/donuts, -/turf/open/floor/plating, +/obj/effect/turf_decal/siding{ + dir = 4 + }, +/obj/effect/turf_decal/siding{ + dir = 8 + }, +/turf/open/floor/iron/dark/textured_large, /area/station/service/kitchen) "sZo" = ( /obj/effect/turf_decal/siding/thinplating_new/light{ @@ -59045,6 +59114,13 @@ }, /turf/open/floor/iron/dark, /area/station/command/heads_quarters/rd) +"ugt" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/cable, +/turf/open/floor/iron/small, +/area/station/engineering/break_room) "ugA" = ( /obj/effect/turf_decal/siding/yellow{ dir = 1 @@ -63695,6 +63771,7 @@ "vDS" = ( /obj/structure/closet/secure_closet/engineering_personal, /obj/item/clothing/suit/hooded/wintercoat/engineering, +/obj/structure/cable, /turf/open/floor/iron/small, /area/station/engineering/break_room) "vDV" = ( @@ -65710,6 +65787,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 1 }, +/obj/structure/cable, /turf/open/floor/iron/smooth_large, /area/station/engineering/supermatter/room) "wjG" = ( @@ -67671,6 +67749,20 @@ /obj/effect/decal/cleanable/molten_object, /obj/effect/landmark/event_spawn, /obj/structure/table, +/obj/item/reagent_containers/cup/bottle/welding_fuel{ + pixel_y = -3; + pixel_x = 13 + }, +/obj/item/stack/sheet/iron/ten{ + pixel_y = -6; + pixel_x = -2 + }, +/obj/item/hand_labeler{ + pixel_y = -15 + }, +/obj/item/reagent_containers/cup/watering_can{ + pixel_y = 12 + }, /turf/open/floor/iron/dark, /area/station/commons/storage/tools) "wPd" = ( @@ -70031,6 +70123,7 @@ /area/station/maintenance/starboard/central) "xwn" = ( /obj/machinery/atmospherics/pipe/smart/simple/dark/visible, +/obj/machinery/portable_atmospherics/pump, /turf/open/floor/iron/dark, /area/station/science/ordnance) "xwr" = ( @@ -72485,7 +72578,7 @@ /turf/closed/wall, /area/station/medical/surgery/theatre) "yfF" = ( -/obj/machinery/vending/autodrobe/all_access, +/obj/machinery/vending/autodrobe, /obj/effect/turf_decal/siding/wideplating/dark{ dir = 8 }, @@ -88358,9 +88451,9 @@ kMe kMe nDJ lWV -mWB +cYt wjw -kMe +gAV tDu ccA oPa @@ -90934,9 +91027,9 @@ awH gAV qkq wRy -ayK +urz vDS -aWA +ugt lVv nHq exQ @@ -98462,7 +98555,7 @@ sJL sne aTg aTg -aIr +lZs bIN nUd bmY @@ -118682,7 +118775,7 @@ dDB dDB dDB dDB -dDB +mzv dDB dDB dDB diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 39d7cd24bdd2e..da57feb278136 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -2842,6 +2842,9 @@ /obj/structure/cable, /obj/effect/turf_decal/tile/neutral/fourcorners, /obj/effect/landmark/event_spawn, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, /turf/open/floor/iron/dark, /area/station/service/library/printer) "aII" = ( @@ -3233,15 +3236,15 @@ /area/station/ai_monitored/command/storage/eva) "aNM" = ( /obj/structure/cable, -/obj/structure/disposalpipe/junction{ - dir = 4 - }, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 8 }, /obj/effect/decal/cleanable/dirt, /obj/machinery/duct, /obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/structure/disposalpipe/segment{ + dir = 6 + }, /turf/open/floor/iron, /area/station/maintenance/department/chapel) "aNP" = ( @@ -12209,9 +12212,6 @@ "cXb" = ( /obj/structure/cable, /obj/effect/turf_decal/delivery, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/duct, /obj/effect/turf_decal/tile/neutral/anticorner/contrasted{ @@ -16925,9 +16925,6 @@ /turf/open/floor/plating, /area/station/cargo/storage) "ehg" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, /obj/machinery/newscaster/directional/west, /obj/structure/table/wood, /obj/item/clipboard, @@ -30878,7 +30875,6 @@ /turf/open/misc/sandy_dirt, /area/station/security/prison/garden) "hHo" = ( -/obj/structure/disposalpipe/trunk, /obj/machinery/chem_heater/withbuffer, /obj/effect/turf_decal/bot_red, /obj/effect/turf_decal/stripes/line{ @@ -32868,9 +32864,6 @@ "ifr" = ( /obj/structure/cable, /obj/effect/turf_decal/delivery, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/duct, /obj/effect/turf_decal/tile/neutral/half/contrasted{ @@ -33704,9 +33697,6 @@ /area/station/hallway/primary/central/fore) "irx" = ( /obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/decal/cleanable/dirt, /obj/machinery/duct, @@ -39806,7 +39796,7 @@ /area/station/tcommsat/server) "jQx" = ( /obj/effect/decal/cleanable/cobweb/cobweb2, -/obj/machinery/vending/autodrobe/all_access, +/obj/machinery/vending/autodrobe, /turf/open/floor/plating, /area/station/maintenance/fore) "jQB" = ( @@ -42974,6 +42964,9 @@ }, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, /turf/open/floor/iron/dark, /area/station/service/library/printer) "kHp" = ( @@ -44585,13 +44578,13 @@ /turf/open/floor/iron, /area/station/engineering/atmos) "ldl" = ( -/obj/structure/disposalpipe/segment, /obj/machinery/disposal/bin, /obj/effect/turf_decal/bot, /obj/effect/turf_decal/stripes/line{ dir = 6 }, /obj/effect/turf_decal/tile/yellow/opposingcorners, +/obj/structure/disposalpipe/trunk, /turf/open/floor/iron/dark, /area/station/medical/pharmacy) "ldm" = ( @@ -45387,9 +45380,6 @@ /area/station/engineering/atmos/storage/gas) "lni" = ( /obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 5 - }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/landmark/generic_maintenance_landmark, @@ -46664,6 +46654,9 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/cable, /obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, /turf/open/floor/iron/dark, /area/station/service/library/printer) "lDV" = ( @@ -47502,7 +47495,7 @@ /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/ai) "lMF" = ( -/obj/machinery/vending/autodrobe/all_access, +/obj/machinery/vending/autodrobe, /obj/effect/turf_decal/siding/dark_blue{ dir = 8 }, @@ -52931,9 +52924,6 @@ /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 = 4 - }, /obj/effect/turf_decal/tile/brown/half/contrasted{ dir = 4 }, @@ -56033,9 +56023,6 @@ /obj/structure/sign/painting/library_private{ pixel_y = -32 }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, /obj/machinery/modular_computer/preset/curator{ dir = 1 }, @@ -64198,6 +64185,9 @@ dir = 8 }, /obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, /turf/open/floor/iron/dark, /area/station/service/library/printer) "qaF" = ( @@ -66387,9 +66377,6 @@ /turf/open/floor/iron/white, /area/station/medical/medbay) "qEj" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, /obj/machinery/light/small/directional/south, /obj/structure/table/wood, /obj/item/paper_bin{ @@ -67689,7 +67676,7 @@ "qVn" = ( /obj/machinery/light/small/directional/south, /obj/effect/decal/cleanable/dirt, -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /obj/structure/sign/poster/contraband/random/directional/south, /turf/open/floor/plating, /area/station/service/abandoned_gambling_den) @@ -72153,13 +72140,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/service/theater/abandoned) -"rZL" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/grille, -/turf/closed/wall/r_wall, -/area/station/engineering/atmos) "rZU" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/line{ @@ -80582,9 +80562,6 @@ /area/station/commons/toilet/locker) "ufz" = ( /obj/machinery/firealarm/directional/south, -/obj/structure/disposalpipe/segment{ - dir = 9 - }, /obj/effect/turf_decal/bot_white, /obj/structure/filingcabinet, /turf/open/floor/iron/dark, @@ -89971,8 +89948,10 @@ "wwN" = ( /obj/machinery/power/apc/auto_name/directional/east, /obj/structure/cable, -/obj/structure/disposalpipe/segment, /obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/structure/disposalpipe/segment{ + dir = 9 + }, /turf/open/floor/iron/dark, /area/station/service/library/printer) "wwP" = ( @@ -90329,9 +90308,6 @@ /turf/open/floor/plating, /area/station/maintenance/starboard/aft) "wAZ" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, /obj/structure/table/wood, /obj/item/taperecorder, /obj/item/camera, @@ -96090,9 +96066,6 @@ dir = 4 }, /obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, /obj/effect/mapping_helpers/airlock/access/all/engineering/maintenance, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/duct, @@ -117147,7 +117120,7 @@ pxN yfC pxN pxN -rZL +pxN pxN pxN qYo diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index 80c768e6a52a8..ce8f714c0e456 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -2371,12 +2371,6 @@ /obj/structure/fluff/shower_drain, /turf/open/floor/iron/freezer, /area/station/commons/toilet) -"aJj" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/closed/wall, -/area/station/service/library) "aJm" = ( /obj/structure/cable, /obj/machinery/door/window/left/directional/east{ @@ -21813,7 +21807,7 @@ /turf/open/floor/plating, /area/station/engineering/lobby) "gkN" = ( -/obj/machinery/vending/autodrobe/all_access, +/obj/machinery/vending/autodrobe, /turf/open/floor/iron/dark/textured, /area/station/security/prison) "gkP" = ( @@ -25804,7 +25798,7 @@ "hul" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /obj/machinery/status_display/evac/directional/north, -/obj/machinery/vending/autodrobe/all_access, +/obj/machinery/vending/autodrobe, /turf/open/floor/iron, /area/station/commons/locker) "huq" = ( @@ -38494,6 +38488,7 @@ pixel_y = 32; idExterior = "virology_airlock_exterior"; idInterior = "virology_airlock_interior"; + idSelf = "virology_airlock_control"; interior_airlock = "virology_airlock_control"; name = "Virology Access Controller"; req_access = list("virology") @@ -40898,10 +40893,7 @@ /turf/open/floor/iron, /area/station/maintenance/department/electrical) "lOV" = ( -/obj/machinery/disposal/bin{ - desc = "A pneumatic waste disposal unit. This one leads to the morgue."; - name = "corpse disposal" - }, +/obj/machinery/disposal/bin, /obj/structure/disposalpipe/trunk{ dir = 4 }, @@ -42554,7 +42546,7 @@ }, /area/station/security/brig/entrance) "mqI" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /turf/open/floor/plating, /area/station/maintenance/port/aft) "mqL" = ( @@ -74196,7 +74188,7 @@ /area/station/security/prison/rec) "vwG" = ( /obj/machinery/vending/security{ - onstation_override = 1 + all_products_free = 0 }, /obj/effect/turf_decal/tile/red/half/contrasted{ dir = 8 @@ -257791,7 +257783,7 @@ qMm hUD pyJ lPh -aJj +hUD hUD ebb cYE diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index a3b90c665b221..920c3c93f8d55 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -268,6 +268,10 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/iron, /area/station/engineering/main) +"afW" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/station/security/checkpoint/supply) "afZ" = ( /obj/machinery/vending/coffee, /obj/structure/disposalpipe/segment, @@ -278,6 +282,14 @@ /mob/living/simple_animal/bot/secbot/beepsky/armsky, /turf/open/floor/iron/dark, /area/station/ai_monitored/security/armory) +"agd" = ( +/obj/effect/turf_decal/tile/red/fourcorners, +/obj/structure/closet/secure_closet/security/cargo, +/obj/machinery/power/apc/auto_name/directional/west, +/obj/structure/extinguisher_cabinet/directional/east, +/obj/machinery/newscaster/directional/east, +/turf/open/floor/iron/dark, +/area/station/security/checkpoint/supply) "agi" = ( /obj/effect/spawner/random/maintenance, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -448,6 +460,18 @@ /obj/structure/window/spawner/directional/east, /turf/open/floor/iron/dark, /area/station/commons/fitness/recreation) +"aiy" = ( +/obj/effect/turf_decal/tile/red/anticorner/contrasted{ + dir = 8 + }, +/obj/machinery/computer/records/security{ + dir = 1 + }, +/obj/machinery/light/small/directional/west, +/obj/machinery/firealarm/directional/west, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron/dark, +/area/station/security/checkpoint/supply) "aja" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -1216,14 +1240,6 @@ "ayr" = ( /turf/open/floor/iron, /area/station/engineering/break_room) -"ayz" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/turf_decal/tile/brown/opposingcorners, -/obj/effect/decal/cleanable/wrapping, -/turf/open/floor/iron, -/area/station/cargo/sorting) "ayH" = ( /obj/effect/spawner/random/engineering/atmospherics_portable, /turf/open/floor/plating, @@ -1479,6 +1495,14 @@ /obj/machinery/duct, /turf/open/floor/iron/freezer, /area/station/commons/toilet/restrooms) +"aCO" = ( +/obj/machinery/computer/exodrone_control_console{ + dir = 8 + }, +/obj/structure/railing, +/obj/machinery/light/small/directional/east, +/turf/open/floor/plating/reinforced, +/area/station/cargo/storage) "aCQ" = ( /obj/effect/turf_decal/trimline/red/filled/line{ dir = 1 @@ -1621,6 +1645,10 @@ /obj/effect/spawner/random/bureaucracy/paper, /turf/open/floor/wood, /area/station/commons/dorms) +"aFz" = ( +/obj/machinery/vending/autodrobe, +/turf/open/floor/plating, +/area/station/maintenance/port) "aFW" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/mirror/directional/west, @@ -1961,17 +1989,6 @@ }, /turf/open/floor/iron, /area/station/security/checkpoint/engineering) -"aKN" = ( -/obj/structure/chair/office, -/obj/machinery/requests_console/directional/north{ - department = "Quartermaster's Desk"; - name = "Security Requests Console" - }, -/obj/effect/mapping_helpers/requests_console/supplies, -/obj/effect/mapping_helpers/requests_console/assistance, -/obj/effect/landmark/start/depsec/supply, -/turf/open/floor/iron, -/area/station/security/checkpoint/supply) "aKO" = ( /obj/effect/landmark/event_spawn, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -2307,6 +2324,15 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/science/server) +"aQb" = ( +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/effect/turf_decal/siding/white/corner{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/cargo/storage) "aQe" = ( /obj/machinery/light/small/directional/west, /obj/machinery/camera/directional/west{ @@ -2503,6 +2529,14 @@ /obj/effect/spawner/structure/window/reinforced/plasma, /turf/open/floor/plating, /area/station/engineering/supermatter/room) +"aUU" = ( +/obj/machinery/light/directional/east, +/obj/machinery/light_switch/directional/east, +/obj/structure/rack, +/obj/effect/decal/cleanable/greenglow/filled, +/obj/effect/spawner/random/maintenance/no_decals/eight, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "aVd" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -2830,6 +2864,17 @@ }, /turf/open/floor/plating, /area/station/maintenance/aft/lesser) +"aZz" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 1 + }, +/obj/item/stock_parts/power_store/cell/lead{ + pixel_y = 1; + pixel_x = -3 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "aZA" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -3163,6 +3208,30 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /turf/open/floor/iron/dark, /area/station/science/ordnance) +"bfw" = ( +/obj/machinery/light_switch/directional/south, +/obj/machinery/conveyor_switch/oneway{ + id = "packageSort2"; + name = "Sort and Deliver"; + pixel_x = -2; + pixel_y = 12 + }, +/obj/machinery/conveyor_switch/oneway{ + dir = 8; + id = "packageExternal"; + name = "Crate Returns"; + pixel_x = -5; + pixel_y = -3 + }, +/obj/effect/turf_decal/trimline/brown/warning{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/brown/filled/corner, +/obj/effect/turf_decal/trimline/white/corner, +/obj/structure/disposalpipe/segment, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/iron, +/area/station/cargo/sorting) "bfM" = ( /obj/machinery/door/airlock/public/glass{ name = "Art Storage" @@ -3198,11 +3267,6 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /turf/open/floor/iron/white/smooth_large, /area/station/medical/chemistry) -"bgx" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron, -/area/station/cargo/storage) "bgS" = ( /obj/machinery/firealarm/directional/north, /obj/machinery/camera/directional/west{ @@ -4097,28 +4161,6 @@ }, /turf/open/floor/iron, /area/station/commons/locker) -"bvl" = ( -/obj/machinery/newscaster/directional/east, -/obj/structure/table, -/obj/item/stack/package_wrap{ - pixel_x = 2; - pixel_y = -3 - }, -/obj/item/stack/package_wrap{ - pixel_x = -2; - pixel_y = 4 - }, -/obj/item/pen{ - pixel_x = -7; - pixel_y = 10 - }, -/obj/item/reagent_containers/cup/glass/waterbottle{ - pixel_y = 16 - }, -/obj/machinery/digital_clock/directional/north, -/obj/effect/turf_decal/tile/brown/opposingcorners, -/turf/open/floor/iron, -/area/station/cargo/sorting) "bvJ" = ( /obj/effect/spawner/structure/window, /turf/open/floor/plating, @@ -4951,11 +4993,6 @@ /obj/structure/window/spawner/directional/west, /turf/open/floor/iron/dark, /area/station/service/cafeteria) -"bLj" = ( -/obj/effect/turf_decal/trimline/blue/filled/line, -/obj/effect/turf_decal/trimline/brown/filled/warning, -/turf/open/floor/iron, -/area/station/cargo/sorting) "bLm" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/carpet/green, @@ -4967,19 +5004,6 @@ /obj/structure/window/reinforced/spawner/directional/west, /turf/open/floor/plating/airless, /area/space/nearstation) -"bLY" = ( -/obj/effect/turf_decal/trimline/red/filled/corner{ - dir = 1 - }, -/obj/structure/extinguisher_cabinet/directional/north, -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 4 - }, -/obj/effect/turf_decal/siding/thinplating_new{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/cargo/storage) "bMa" = ( /obj/structure/disposaloutlet{ dir = 4; @@ -5088,6 +5112,14 @@ }, /turf/open/floor/plating, /area/station/maintenance/starboard/greater) +"bNw" = ( +/obj/structure/railing/corner, +/obj/structure/chair/office/light{ + dir = 4 + }, +/obj/effect/landmark/start/cargo_technician, +/turf/open/floor/plating/reinforced, +/area/station/cargo/storage) "bNE" = ( /obj/machinery/light/directional/east, /obj/structure/cable, @@ -5182,18 +5214,6 @@ /obj/item/bodypart/arm/left, /turf/open/floor/plating/airless, /area/station/science/ordnance/bomb) -"bQl" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/turf_decal/tile/brown/opposingcorners, -/obj/structure/table, -/obj/machinery/fax{ - fax_name = "Cargo Office"; - name = "Cargo Office Fax Machine" - }, -/turf/open/floor/iron, -/area/station/cargo/sorting) "bQN" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /obj/machinery/computer/security/telescreen/entertainment/directional/north, @@ -5777,6 +5797,14 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, /area/station/security/courtroom) +"cap" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron, +/area/station/cargo/sorting) "caO" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable, @@ -6488,14 +6516,6 @@ /obj/effect/spawner/random/engineering/atmospherics_portable, /turf/open/floor/plating, /area/station/maintenance/starboard/aft) -"cqy" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/turf_decal/trimline/red/filled/line{ - dir = 1 - }, -/turf/open/floor/iron, -/area/station/cargo/storage) "cqD" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 8 @@ -7454,6 +7474,15 @@ }, /turf/open/floor/plating, /area/station/science/genetics) +"cIl" = ( +/obj/effect/turf_decal/tile/brown{ + dir = 1 + }, +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/turf/open/floor/iron, +/area/station/cargo/lobby) "cIK" = ( /obj/machinery/smartfridge/chemistry/preloaded, /obj/effect/turf_decal/tile/yellow/fourcorners, @@ -7527,21 +7556,6 @@ /obj/structure/sign/directions/evac, /turf/closed/wall/r_wall, /area/station/medical/chemistry) -"cJS" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/turf_decal/tile/brown{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/turf/open/floor/iron, -/area/station/hallway/primary/port) "cJT" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/rack, @@ -7581,6 +7595,20 @@ /obj/effect/landmark/start/hangover, /turf/open/floor/carpet, /area/station/commons/dorms) +"cKD" = ( +/obj/structure/rack, +/obj/item/circuitboard/machine/exoscanner{ + pixel_y = 3 + }, +/obj/item/circuitboard/machine/exoscanner, +/obj/item/exodrone{ + pixel_y = 11 + }, +/obj/structure/railing{ + dir = 10 + }, +/turf/open/floor/plating/reinforced, +/area/station/cargo/storage) "cKN" = ( /obj/structure/table/wood, /obj/structure/cable, @@ -8029,6 +8057,11 @@ }, /turf/open/floor/wood, /area/station/security/office) +"cUt" = ( +/obj/effect/turf_decal/stripes/line, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/station/cargo/miningoffice) "cUw" = ( /obj/machinery/power/apc/auto_name/directional/east, /obj/structure/cable, @@ -8195,15 +8228,6 @@ }, /turf/open/floor/iron/white, /area/station/medical/office) -"cXE" = ( -/obj/structure/disposalpipe/segment{ - dir = 10 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/turf_decal/trimline/brown/filled/line, -/turf/open/floor/iron, -/area/station/cargo/sorting) "cXH" = ( /obj/effect/turf_decal/tile/yellow/half/contrasted{ dir = 4 @@ -8595,6 +8619,14 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/wood, /area/station/service/theater) +"dfa" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 1 + }, +/obj/item/storage/test_tube_rack/full, +/turf/open/floor/iron, +/area/station/hallway/primary/central) "dfh" = ( /obj/effect/spawner/random/structure/closet_maintenance, /turf/open/floor/plating, @@ -8627,15 +8659,6 @@ "dfC" = ( /turf/open/floor/iron/grimy, /area/station/tcommsat/computer) -"dfK" = ( -/obj/structure/disposalpipe/segment, -/obj/structure/chair/office{ - dir = 1 - }, -/obj/effect/landmark/start/cargo_technician, -/obj/effect/turf_decal/tile/brown/opposingcorners, -/turf/open/floor/iron, -/area/station/cargo/sorting) "dfO" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -8648,11 +8671,6 @@ /obj/effect/turf_decal/box/corners, /turf/open/floor/iron, /area/station/engineering/atmos) -"dfU" = ( -/obj/effect/turf_decal/stripes/line, -/obj/structure/extinguisher_cabinet/directional/east, -/turf/open/floor/plating, -/area/station/cargo/drone_bay) "dgc" = ( /obj/structure/cable, /obj/structure/disposalpipe/junction{ @@ -9359,6 +9377,16 @@ }, /turf/open/floor/iron, /area/station/service/hydroponics) +"dsJ" = ( +/obj/machinery/power/apc/auto_name/directional/east, +/obj/structure/cable, +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron, +/area/station/cargo/storage) "dsQ" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/door/poddoor/preopen{ @@ -9386,35 +9414,24 @@ }, /turf/open/floor/iron, /area/station/commons/dorms) +"dtw" = ( +/obj/machinery/door/airlock/mining{ + name = "Deliveries" + }, +/obj/machinery/door/firedoor, +/obj/structure/cable, +/obj/effect/mapping_helpers/airlock/access/any/supply/shipping, +/obj/effect/turf_decal/tile/brown/opposingcorners, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron, +/area/station/cargo/sorting) "dtB" = ( /obj/machinery/atmospherics/pipe/smart/manifold/purple/visible{ dir = 8 }, /turf/open/floor/iron, /area/station/engineering/atmos) -"dtE" = ( -/obj/structure/table/reinforced, -/obj/item/stamp/denied{ - pixel_x = 4; - pixel_y = -2 - }, -/obj/item/stamp{ - pixel_x = -3; - pixel_y = 3 - }, -/obj/item/pen/red{ - pixel_y = 10 - }, -/obj/item/dest_tagger{ - pixel_x = 9; - pixel_y = 10 - }, -/obj/item/pen/screwdriver{ - pixel_x = -7; - pixel_y = 7 - }, -/turf/open/floor/iron, -/area/station/cargo/sorting) "dtY" = ( /obj/machinery/meter/monitored/waste_loop, /obj/machinery/atmospherics/pipe/smart/manifold/scrubbers/visible{ @@ -9727,12 +9744,6 @@ /obj/structure/window/reinforced/spawner/directional/north, /turf/open/floor/iron/cafeteria, /area/station/security/prison) -"dAk" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment, -/turf/open/floor/iron, -/area/station/cargo/storage) "dBb" = ( /obj/effect/turf_decal/tile/purple/opposingcorners, /obj/structure/window/reinforced/spawner/directional/north, @@ -9997,14 +10008,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron/white, /area/station/medical/surgery/theatre) -"dGC" = ( -/obj/structure/reagent_dispensers/water_cooler, -/obj/effect/turf_decal/trimline/brown/filled/end{ - dir = 1 - }, -/obj/effect/decal/cleanable/cobweb, -/turf/open/floor/iron, -/area/station/cargo/sorting) "dGD" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -10042,15 +10045,6 @@ /obj/effect/turf_decal/tile/brown/fourcorners, /turf/open/floor/iron, /area/station/cargo/lobby) -"dHz" = ( -/obj/effect/turf_decal/trimline/brown/corner{ - dir = 1 - }, -/obj/effect/turf_decal/trimline/brown/line{ - dir = 6 - }, -/turf/open/floor/iron, -/area/station/cargo/lobby) "dHG" = ( /obj/machinery/atmospherics/components/binary/crystallizer{ dir = 4 @@ -10725,32 +10719,6 @@ /obj/effect/turf_decal/tile/brown/anticorner/contrasted, /turf/open/floor/iron, /area/station/cargo/miningoffice) -"dSH" = ( -/obj/structure/table/reinforced, -/obj/item/storage/box/shipping{ - pixel_x = -6; - pixel_y = 15 - }, -/obj/item/multitool{ - pixel_x = -3; - pixel_y = -4 - }, -/obj/item/storage/box/lights/mixed{ - pixel_x = 8; - pixel_y = 11 - }, -/obj/item/flashlight/lamp{ - pixel_x = -7; - pixel_y = 5 - }, -/obj/item/storage/box/shipping{ - pixel_x = 8 - }, -/obj/effect/turf_decal/trimline/brown/filled/corner{ - dir = 8 - }, -/turf/open/floor/iron, -/area/station/cargo/sorting) "dSJ" = ( /obj/effect/turf_decal/siding/wood, /obj/structure/sign/poster/random/directional/north, @@ -11099,25 +11067,6 @@ /obj/effect/spawner/random/engineering/tracking_beacon, /turf/open/floor/iron, /area/station/security/courtroom) -"dYi" = ( -/obj/structure/table, -/obj/item/stock_parts/micro_laser{ - pixel_x = -6; - pixel_y = 4 - }, -/obj/item/stock_parts/micro_laser{ - pixel_x = -2; - pixel_y = 2 - }, -/obj/item/stock_parts/micro_laser{ - pixel_x = 2 - }, -/obj/item/stock_parts/micro_laser{ - pixel_x = 6; - pixel_y = -2 - }, -/turf/open/floor/iron, -/area/station/cargo/drone_bay) "dYl" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, @@ -11264,12 +11213,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron, /area/station/cargo/sorting) -"ebg" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/turf_decal/tile/brown/opposingcorners, -/turf/open/floor/iron, -/area/station/cargo/storage) "ebr" = ( /obj/machinery/navbeacon{ codes_txt = "patrol;next_patrol=0-SecurityDesk"; @@ -11782,6 +11725,34 @@ }, /turf/open/floor/iron/dark, /area/station/medical/medbay/central) +"ejD" = ( +/obj/effect/turf_decal/tile/brown/opposingcorners, +/obj/structure/table, +/obj/item/stack/wrapping_paper, +/obj/item/paper_bin/carbon{ + pixel_y = 8; + pixel_x = 6 + }, +/obj/item/pen/fourcolor{ + pixel_y = 8; + pixel_x = 6 + }, +/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/effect/decal/cleanable/wrapping, +/obj/item/sales_tagger{ + pixel_x = -5; + pixel_y = 4 + }, +/obj/item/dest_tagger{ + pixel_x = -2; + pixel_y = 4 + }, +/turf/open/floor/iron, +/area/station/cargo/sorting) "ejF" = ( /obj/effect/turf_decal/trimline/brown/warning{ dir = 5 @@ -11852,13 +11823,6 @@ }, /turf/open/floor/wood, /area/station/service/lawoffice) -"ekb" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 1 - }, -/turf/open/floor/iron, -/area/station/cargo/sorting) "ekh" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -12003,19 +11967,6 @@ }, /turf/open/floor/iron, /area/station/engineering/break_room) -"elz" = ( -/obj/structure/rack, -/obj/item/circuitboard/machine/exoscanner{ - pixel_y = 3 - }, -/obj/item/circuitboard/machine/exoscanner, -/obj/item/circuitboard/machine/exoscanner{ - pixel_y = -3 - }, -/obj/machinery/power/apc/auto_name/directional/east, -/obj/structure/cable, -/turf/open/floor/iron, -/area/station/cargo/drone_bay) "elJ" = ( /turf/closed/wall/r_wall, /area/station/science/server) @@ -12054,15 +12005,6 @@ }, /turf/open/floor/iron/white, /area/station/science/research) -"eml" = ( -/obj/machinery/light/directional/south, -/obj/structure/chair{ - dir = 1 - }, -/obj/effect/landmark/start/assistant, -/obj/effect/turf_decal/tile/brown/anticorner/contrasted, -/turf/open/floor/iron, -/area/station/cargo/lobby) "emN" = ( /obj/machinery/door/airlock/external, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ @@ -12329,6 +12271,16 @@ /obj/item/radio/intercom/directional/east, /turf/open/floor/wood, /area/station/service/library) +"erU" = ( +/obj/machinery/light/directional/south, +/obj/effect/turf_decal/tile/brown/anticorner/contrasted{ + dir = 8 + }, +/obj/machinery/computer/cargo/request{ + dir = 1 + }, +/turf/open/floor/iron, +/area/station/cargo/lobby) "esd" = ( /obj/item/reagent_containers/cup/glass/drinkingglass{ pixel_x = 4; @@ -12702,6 +12654,13 @@ /obj/structure/cable, /turf/open/floor/iron/freezer, /area/station/security/prison/shower) +"exB" = ( +/obj/effect/turf_decal/trimline/yellow/filled/line, +/obj/effect/turf_decal/trimline/brown/filled/warning, +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron, +/area/station/cargo/sorting) "exC" = ( /obj/effect/turf_decal/plaque{ icon_state = "L3" @@ -12932,6 +12891,12 @@ }, /turf/closed/wall/r_wall, /area/station/command/heads_quarters/captain/private) +"eDO" = ( +/obj/effect/turf_decal/siding/white{ + dir = 5 + }, +/turf/open/floor/iron, +/area/station/cargo/storage) "eDX" = ( /obj/structure/sign/departments/science/directional/east, /obj/effect/turf_decal/tile/purple{ @@ -13905,6 +13870,10 @@ }, /turf/open/floor/iron, /area/station/commons/locker) +"eVG" = ( +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "eVX" = ( /obj/machinery/firealarm/directional/west, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ @@ -14350,13 +14319,6 @@ }, /turf/open/floor/iron/white, /area/station/science/xenobiology) -"fea" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/reagent_dispensers/wall/peppertank/directional/east, -/obj/effect/landmark/start/depsec/supply, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron, -/area/station/security/checkpoint/supply) "fec" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/green/visible, /turf/closed/wall/r_wall, @@ -15245,9 +15207,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white, /area/station/science/xenobiology/hallway) -"fru" = ( -/turf/closed/wall, -/area/station/cargo/drone_bay) "frw" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/cobweb/cobweb2, @@ -15388,14 +15347,6 @@ /obj/effect/turf_decal/tile/brown/opposingcorners, /turf/open/floor/iron, /area/station/cargo/storage) -"fwd" = ( -/obj/machinery/power/apc/auto_name/directional/east, -/obj/structure/cable, -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/cargo/storage) "fwz" = ( /obj/machinery/portable_atmospherics/canister/nitrogen, /turf/open/floor/iron/dark, @@ -15536,6 +15487,16 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating/airless, /area/station/solars/port/fore) +"fzo" = ( +/obj/effect/turf_decal/stripes/line, +/obj/item/stock_parts/micro_laser{ + pixel_x = 6; + pixel_y = -2 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/turf_decal/caution, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "fzr" = ( /obj/structure/window/spawner/directional/south, /obj/structure/window/spawner/directional/west, @@ -15743,6 +15704,15 @@ /obj/structure/cable, /turf/open/floor/circuit/red, /area/station/ai_monitored/turret_protected/ai_upload) +"fEV" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/turf_decal/tile/brown/fourcorners, +/obj/machinery/door/airlock/security/glass{ + name = "Security Post - Cargo" + }, +/turf/open/floor/iron/dark, +/area/station/security/checkpoint/supply) "fEW" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -16111,15 +16081,6 @@ /obj/effect/mapping_helpers/airlock/access/all/medical/general, /turf/open/floor/plating, /area/station/maintenance/port/aft) -"fLp" = ( -/obj/structure/disposalpipe/junction{ - dir = 8 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/iron, -/area/station/hallway/primary/port) "fLq" = ( /obj/machinery/door/window/left/directional/north{ name = "Inner Pipe Access"; @@ -16156,6 +16117,14 @@ /obj/machinery/power/tracker, /turf/open/floor/plating/airless, /area/station/solars/starboard/fore) +"fMa" = ( +/obj/structure/rack, +/obj/effect/spawner/random/trash/ghetto_containers, +/obj/effect/spawner/random/trash/ghetto_containers, +/obj/effect/spawner/random/trash/ghetto_containers, +/obj/effect/spawner/random/trash/ghetto_containers, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "fMf" = ( /obj/structure/chair/office{ dir = 1 @@ -16192,6 +16161,16 @@ }, /turf/open/floor/plating, /area/station/maintenance/aft/greater) +"fMC" = ( +/obj/effect/turf_decal/tile/red/half/contrasted{ + dir = 4 + }, +/obj/structure/chair/office/light{ + dir = 1 + }, +/obj/effect/landmark/start/depsec/supply, +/turf/open/floor/iron/dark, +/area/station/security/checkpoint/supply) "fMN" = ( /obj/machinery/firealarm/directional/west, /obj/structure/disposalpipe/segment{ @@ -16601,14 +16580,6 @@ /obj/effect/turf_decal/tile/red/fourcorners, /turf/open/floor/iron/white, /area/station/security/prison/safe) -"fWn" = ( -/obj/structure/disposalpipe/segment{ - dir = 6 - }, -/obj/effect/turf_decal/tile/brown/opposingcorners, -/obj/structure/closet/crate, -/turf/open/floor/iron, -/area/station/cargo/sorting) "fWw" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -16825,6 +16796,26 @@ }, /turf/open/floor/iron/white, /area/station/science/ordnance/storage) +"gav" = ( +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/tile/brown/opposingcorners, +/obj/structure/table, +/obj/machinery/photocopier{ + pixel_y = 9 + }, +/obj/item/paper/fluff{ + pixel_y = 8; + pixel_x = 4; + default_raw_text = "Next CT to photocopy their ass is getting thrown under the shuttle. I'm serious here.
- QM"; + name = "note" + }, +/obj/machinery/newscaster/directional/east, +/obj/item/pen/screwdriver{ + pixel_x = 1; + pixel_y = 11 + }, +/turf/open/floor/iron, +/area/station/cargo/sorting) "gaG" = ( /obj/effect/spawner/random/maintenance, /obj/structure/cable, @@ -17034,22 +17025,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/grass, /area/station/medical/virology) -"geR" = ( -/obj/structure/table, -/obj/item/papercutter{ - pixel_x = 9; - pixel_y = 4 - }, -/obj/item/stamp/denied{ - pixel_x = -7; - pixel_y = 7 - }, -/obj/item/stamp/granted{ - pixel_x = -7 - }, -/obj/effect/turf_decal/tile/brown/opposingcorners, -/turf/open/floor/iron, -/area/station/cargo/sorting) "geV" = ( /obj/structure/sink/directional/east, /obj/machinery/light_switch/directional/west, @@ -17150,6 +17125,10 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central) +"ggW" = ( +/obj/machinery/space_heater/improvised_chem_heater, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "ggZ" = ( /obj/effect/turf_decal/stripes/line, /obj/structure/disposalpipe/segment{ @@ -17739,6 +17718,19 @@ }, /turf/open/floor/iron/kitchen_coldroom/freezerfloor, /area/station/service/kitchen/coldroom) +"gsV" = ( +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/effect/turf_decal/tile/brown/opposingcorners, +/obj/effect/turf_decal/siding/white/corner{ + dir = 4 + }, +/obj/structure/railing/corner/end{ + dir = 1 + }, +/turf/open/floor/iron, +/area/station/cargo/storage) "gsW" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/medical/glass{ @@ -18026,32 +18018,6 @@ }, /turf/open/floor/iron/checker, /area/station/engineering/atmos/storage/gas) -"gxM" = ( -/obj/effect/turf_decal/tile/brown/opposingcorners, -/obj/structure/table, -/obj/item/stack/package_wrap{ - pixel_x = 2; - pixel_y = -3 - }, -/obj/item/stack/package_wrap{ - pixel_x = 1; - pixel_y = 6 - }, -/obj/item/stack/package_wrap{ - pixel_x = -4; - pixel_y = 8 - }, -/obj/item/dest_tagger{ - pixel_x = -9; - pixel_y = 12 - }, -/obj/item/hand_labeler_refill{ - pixel_x = -11; - pixel_y = -3 - }, -/obj/item/stack/wrapping_paper, -/turf/open/floor/iron, -/area/station/cargo/sorting) "gya" = ( /obj/structure/table, /obj/item/storage/box/hug{ @@ -19005,6 +18971,10 @@ /obj/machinery/light/small/directional/west, /turf/open/floor/engine, /area/station/science/xenobiology) +"gOO" = ( +/obj/effect/decal/cleanable/shreds, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "gOS" = ( /obj/structure/cable, /obj/structure/table/glass, @@ -19047,24 +19017,16 @@ /obj/effect/mapping_helpers/requests_console/assistance, /turf/open/floor/iron/dark, /area/station/medical/morgue) +"gPw" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/dark, +/area/station/security/checkpoint/supply) "gPA" = ( /obj/structure/table/wood, /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/carpet, /area/station/command/heads_quarters/captain/private) -"gPN" = ( -/obj/effect/turf_decal/trimline/brown/filled/corner{ - dir = 4 - }, -/obj/effect/turf_decal/trimline/brown/warning{ - dir = 8 - }, -/obj/structure/extinguisher_cabinet/directional/north, -/obj/machinery/light/small/directional/north, -/obj/structure/disposalpipe/segment, -/turf/open/floor/iron, -/area/station/cargo/sorting) "gPY" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -19524,6 +19486,16 @@ /obj/effect/mapping_helpers/mail_sorting/service/kitchen, /turf/open/floor/iron, /area/station/maintenance/starboard/greater) +"gZq" = ( +/obj/effect/turf_decal/tile/red/half/contrasted{ + dir = 8 + }, +/obj/structure/chair/office/light, +/obj/effect/landmark/start/depsec/supply, +/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/security/checkpoint/supply) "gZu" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -19559,6 +19531,16 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/engineering/main) +"hab" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 1 + }, +/obj/effect/turf_decal/tile/brown/opposingcorners, +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron, +/area/station/cargo/sorting) "hav" = ( /obj/machinery/door/airlock/maintenance, /obj/structure/cable, @@ -19595,6 +19577,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/engineering/main) +"haZ" = ( +/obj/item/reagent_containers/cup/glass/mug/britcup, +/obj/effect/decal/cleanable/cobweb, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "hbv" = ( /turf/closed/wall/r_wall, /area/station/medical/coldroom) @@ -20053,9 +20041,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/starboard) -"hkj" = ( -/turf/open/floor/plating, -/area/station/cargo/drone_bay) "hko" = ( /obj/effect/turf_decal/bot{ dir = 1 @@ -20207,6 +20192,10 @@ }, /turf/open/floor/engine/vacuum, /area/space/nearstation) +"hlT" = ( +/obj/structure/falsewall, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "hmf" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/cable, @@ -20437,11 +20426,6 @@ /obj/machinery/atmospherics/pipe/heat_exchanging/simple/layer2, /turf/open/floor/iron/dark/airless, /area/station/science/ordnance/freezerchamber) -"hrC" = ( -/obj/structure/cable, -/obj/effect/spawner/structure/window/reinforced, -/turf/open/floor/plating, -/area/station/security/checkpoint/supply) "hrG" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -20473,17 +20457,6 @@ dir = 8 }, /area/station/service/chapel/office) -"hsx" = ( -/obj/machinery/door/airlock/mining{ - name = "Drone Bay" - }, -/obj/effect/mapping_helpers/airlock/access/any/supply/maintenance, -/obj/effect/landmark/navigate_destination, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/plating, -/area/station/cargo/drone_bay) "hsF" = ( /obj/machinery/door/airlock{ id_tag = "AuxToilet3"; @@ -20655,31 +20628,6 @@ /obj/structure/window/reinforced/spawner/directional/north, /turf/open/floor/plating, /area/station/security/checkpoint/customs) -"hvk" = ( -/obj/effect/spawner/random/bureaucracy/birthday_wrap, -/obj/item/stack/package_wrap{ - pixel_y = 5 - }, -/obj/item/stack/package_wrap{ - pixel_y = 2 - }, -/obj/item/stack/package_wrap, -/obj/machinery/light/directional/south, -/obj/machinery/firealarm/directional/south, -/obj/structure/table, -/obj/effect/turf_decal/tile/brown/anticorner/contrasted{ - dir = 8 - }, -/turf/open/floor/iron, -/area/station/cargo/lobby) -"hvo" = ( -/obj/structure/filingcabinet, -/obj/effect/turf_decal/tile/red/anticorner/contrasted{ - dir = 8 - }, -/obj/machinery/light/small/directional/north, -/turf/open/floor/iron, -/area/station/security/checkpoint/supply) "hvr" = ( /obj/machinery/camera/directional/south{ c_tag = "Central Primary Hallway - Fore - Courtroom" @@ -21157,6 +21105,13 @@ }, /turf/open/floor/iron/white, /area/station/medical/treatment_center) +"hCh" = ( +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/turf/open/floor/iron, +/area/station/cargo/sorting) "hCl" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, @@ -21236,11 +21191,6 @@ /obj/effect/turf_decal/trimline/red/filled/line, /turf/open/floor/iron/white, /area/station/security/prison) -"hDX" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/cable, -/turf/open/floor/plating, -/area/station/security/checkpoint/supply) "hEc" = ( /obj/effect/spawner/structure/window, /obj/machinery/door/poddoor/shutters/preopen{ @@ -21609,12 +21559,6 @@ }, /turf/open/floor/iron/white, /area/station/science/cytology) -"hLL" = ( -/obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron, -/area/station/cargo/storage) "hLZ" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/disposalpipe/junction{ @@ -21890,6 +21834,13 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/security/brig) +"hRJ" = ( +/obj/effect/turf_decal/tile/red/anticorner/contrasted, +/obj/item/paper_bin/carbon, +/obj/item/pen/red/security, +/obj/structure/table/reinforced, +/turf/open/floor/iron/dark, +/area/station/security/checkpoint/supply) "hRQ" = ( /obj/machinery/disposal/bin{ pixel_x = -2; @@ -22211,13 +22162,6 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/iron, /area/station/commons/locker) -"hWK" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/obj/effect/landmark/start/depsec/supply, -/obj/machinery/power/apc/auto_name/directional/east, -/obj/structure/cable, -/turf/open/floor/iron, -/area/station/security/checkpoint/supply) "hWW" = ( /obj/structure/bookcase/random, /turf/open/floor/iron, @@ -22652,6 +22596,24 @@ /obj/structure/disposalpipe/segment, /turf/closed/wall, /area/station/cargo/sorting) +"ieD" = ( +/obj/structure/table/wood, +/obj/item/reagent_containers/hypospray/medipen/pumpup, +/obj/item/reagent_containers/hypospray/medipen/pumpup{ + pixel_y = 3 + }, +/obj/item/reagent_containers/cup/mortar{ + pixel_x = 3 + }, +/obj/item/extinguisher/crafted{ + pixel_y = 9; + pixel_x = 3 + }, +/obj/item/pestle{ + pixel_x = 4 + }, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "ieH" = ( /obj/effect/turf_decal/trimline/blue/filled/corner{ dir = 8 @@ -22992,10 +22954,6 @@ /obj/effect/mapping_helpers/airlock/access/all/command/minisat, /turf/open/floor/iron/dark, /area/station/ai_monitored/command/storage/satellite) -"ikL" = ( -/obj/structure/cable, -/turf/open/floor/iron, -/area/station/cargo/drone_bay) "ikO" = ( /obj/machinery/newscaster/directional/north, /obj/structure/table/glass, @@ -23149,6 +23107,13 @@ }, /turf/open/floor/engine, /area/station/science/xenobiology) +"imT" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, +/turf/open/floor/iron/dark, +/area/station/security/checkpoint/supply) "imU" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -24123,24 +24088,6 @@ /obj/effect/landmark/start/security_officer, /turf/open/floor/iron/dark, /area/station/security/range) -"iDG" = ( -/obj/structure/table, -/obj/item/stock_parts/scanning_module{ - pixel_x = -5; - pixel_y = 7 - }, -/obj/item/stock_parts/scanning_module{ - pixel_x = 5; - pixel_y = 7 - }, -/obj/item/stock_parts/scanning_module{ - pixel_x = -5 - }, -/obj/item/stock_parts/scanning_module{ - pixel_x = 5 - }, -/turf/open/floor/iron, -/area/station/cargo/drone_bay) "iDN" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -24314,16 +24261,6 @@ /obj/structure/window/reinforced/spawner/directional/south, /turf/open/floor/engine, /area/station/science/xenobiology) -"iHS" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/door/airlock/security/glass{ - name = "Security Post - Cargo" - }, -/obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/access/all/security/general, -/turf/open/floor/iron, -/area/station/security/checkpoint/supply) "iId" = ( /obj/machinery/conveyor{ id = "mining" @@ -24816,6 +24753,22 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/security/brig) +"iQb" = ( +/obj/effect/turf_decal/tile/red/half/contrasted{ + dir = 4 + }, +/obj/structure/table/reinforced, +/obj/item/book/manual/wiki/security_space_law{ + pixel_x = 9 + }, +/obj/item/pen/red{ + pixel_y = 7; + pixel_x = 9 + }, +/obj/machinery/recharger, +/obj/machinery/digital_clock/directional/east, +/turf/open/floor/iron/dark, +/area/station/security/checkpoint/supply) "iQd" = ( /obj/machinery/door/poddoor/shutters{ id = "supplybridge" @@ -26177,12 +26130,6 @@ }, /turf/open/floor/plating, /area/station/maintenance/port) -"jmR" = ( -/obj/structure/closet/secure_closet/security/cargo, -/obj/machinery/airalarm/directional/north, -/obj/effect/turf_decal/tile/red/half/contrasted, -/turf/open/floor/iron, -/area/station/security/checkpoint/supply) "jmT" = ( /obj/effect/landmark/start/hangover, /obj/effect/turf_decal/tile/neutral{ @@ -26379,16 +26326,6 @@ /obj/effect/spawner/random/maintenance/two, /turf/open/floor/plating, /area/station/maintenance/port) -"jqr" = ( -/obj/machinery/computer/security/mining{ - dir = 4 - }, -/obj/item/radio/intercom/directional/west, -/obj/effect/turf_decal/tile/red/half/contrasted{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/security/checkpoint/supply) "jqQ" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/visible, /obj/effect/turf_decal/tile/blue/fourcorners, @@ -26424,6 +26361,11 @@ }, /turf/open/floor/iron, /area/station/commons/locker) +"jrQ" = ( +/obj/effect/turf_decal/loading_area, +/obj/effect/landmark/navigate_destination, +/turf/open/floor/plating/reinforced, +/area/station/cargo/storage) "jrY" = ( /obj/machinery/door/airlock/external{ name = "Transport Airlock" @@ -26957,6 +26899,17 @@ "jzp" = ( /turf/closed/wall, /area/station/commons/vacant_room/office) +"jzq" = ( +/obj/structure/table/wood, +/obj/structure/chem_separator{ + pixel_y = 10 + }, +/obj/item/reagent_containers/cup/glass/trophy{ + pixel_y = 15; + pixel_x = 5 + }, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "jzw" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment, @@ -27076,29 +27029,6 @@ /obj/effect/turf_decal/bot_white, /turf/open/floor/iron, /area/station/cargo/storage) -"jBy" = ( -/obj/machinery/light_switch/directional/south, -/obj/machinery/conveyor_switch/oneway{ - id = "packageSort2"; - name = "Sort and Deliver"; - pixel_x = -2; - pixel_y = 12 - }, -/obj/machinery/conveyor_switch/oneway{ - dir = 8; - id = "packageExternal"; - name = "Crate Returns"; - pixel_x = -5; - pixel_y = -3 - }, -/obj/effect/turf_decal/trimline/brown/warning{ - dir = 8 - }, -/obj/effect/turf_decal/trimline/brown/filled/corner, -/obj/effect/turf_decal/trimline/white/corner, -/obj/structure/disposalpipe/segment, -/turf/open/floor/iron, -/area/station/cargo/sorting) "jBC" = ( /obj/structure/table, /obj/item/clothing/head/soft/grey{ @@ -27165,6 +27095,11 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron/white/smooth_large, /area/station/medical/medbay/central) +"jCs" = ( +/obj/effect/decal/cleanable/cobweb, +/obj/machinery/vending/boozeomat, +/turf/open/floor/wood, +/area/station/maintenance/port/aft) "jCw" = ( /obj/effect/mapping_helpers/burnt_floor, /turf/open/floor/plating, @@ -27418,6 +27353,13 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/circuit, /area/station/ai_monitored/turret_protected/ai_upload) +"jHM" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/landmark/start/cargo_technician, +/turf/open/floor/iron, +/area/station/cargo/sorting) "jHQ" = ( /obj/structure/chair/sofa/corp/left{ dir = 1 @@ -27428,12 +27370,6 @@ /obj/machinery/status_display/evac/directional/south, /turf/open/floor/iron/dark, /area/station/medical/break_room) -"jHW" = ( -/obj/effect/turf_decal/trimline/yellow/filled/line, -/obj/effect/turf_decal/trimline/brown/filled/warning, -/obj/structure/disposalpipe/segment, -/turf/open/floor/iron, -/area/station/cargo/sorting) "jHX" = ( /obj/effect/turf_decal/stripes/line{ dir = 5 @@ -28010,28 +27946,6 @@ "jRg" = ( /turf/open/floor/engine/co2, /area/station/engineering/atmos) -"jRo" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/turf_decal/tile/brown/opposingcorners, -/obj/structure/table, -/obj/item/hand_labeler_refill{ - pixel_x = 12; - pixel_y = -3 - }, -/obj/effect/spawner/random/bureaucracy/birthday_wrap{ - pixel_x = -2; - pixel_y = 8 - }, -/obj/item/stack/package_wrap{ - pixel_x = -6; - pixel_y = 18 - }, -/obj/item/hand_labeler, -/obj/item/stack/package_wrap, -/turf/open/floor/iron, -/area/station/cargo/sorting) "jRz" = ( /obj/effect/spawner/random/structure/closet_maintenance, /obj/effect/spawner/random/maintenance, @@ -28915,6 +28829,20 @@ /obj/structure/window/reinforced/spawner/directional/west, /turf/open/floor/iron, /area/station/science/xenobiology) +"kgZ" = ( +/obj/structure/sign/poster/official/random/directional/south, +/obj/item/wallframe/camera{ + pixel_y = 9; + pixel_x = -3 + }, +/obj/structure/fermenting_barrel, +/obj/item/clothing/head/fedora{ + pixel_y = 13; + name = "porkpie hat"; + desc = "This hat reeks of bad decisions and chemical compounds. There's some odd white dust covering it." + }, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "kha" = ( /obj/structure/disposalpipe/segment, /obj/machinery/airalarm/directional/east, @@ -29078,6 +29006,13 @@ /obj/machinery/atmospherics/pipe/smart/simple/supply/hidden, /turf/open/floor/iron/dark, /area/station/engineering/atmos/storage/gas) +"kkA" = ( +/obj/effect/turf_decal/tile/red/anticorner/contrasted{ + dir = 4 + }, +/obj/machinery/computer/security, +/turf/open/floor/iron/dark, +/area/station/security/checkpoint/supply) "kkB" = ( /obj/machinery/mineral/ore_redemption{ dir = 4; @@ -29626,17 +29561,6 @@ /obj/structure/cable, /turf/open/floor/plating/airless, /area/station/solars/port/fore) -"kuS" = ( -/obj/item/kirbyplants/random, -/obj/effect/turf_decal/tile/brown/anticorner{ - dir = 8 - }, -/turf/open/floor/iron, -/area/station/cargo/storage) -"kuW" = ( -/obj/effect/turf_decal/stripes/line, -/turf/open/floor/plating, -/area/station/cargo/drone_bay) "kvd" = ( /obj/machinery/light/directional/west, /obj/structure/cable, @@ -29695,14 +29619,6 @@ /obj/machinery/light/small/directional/east, /turf/open/floor/iron/dark, /area/station/engineering/atmos) -"kwh" = ( -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/turf_decal/tile/brown/opposingcorners, -/turf/open/floor/iron, -/area/station/cargo/storage) "kwp" = ( /obj/machinery/door/firedoor, /obj/effect/turf_decal/delivery, @@ -29834,6 +29750,16 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron/dark, /area/station/engineering/storage/tech) +"kyf" = ( +/obj/machinery/computer/exoscanner_control, +/obj/item/reagent_containers/cup/glass/coffee{ + pixel_y = 19; + pixel_x = -6 + }, +/obj/structure/sign/departments/exodrone/directional/north, +/obj/machinery/light/small/directional/north, +/turf/open/floor/plating/reinforced, +/area/station/cargo/storage) "kyh" = ( /obj/machinery/power/apc/auto_name/directional/east, /obj/structure/cable, @@ -30110,6 +30036,13 @@ }, /turf/open/floor/iron/white, /area/station/medical/medbay/central) +"kDb" = ( +/obj/structure/chair/office/light{ + dir = 1 + }, +/obj/effect/landmark/start/depsec/supply, +/turf/open/floor/iron/dark, +/area/station/security/checkpoint/supply) "kDk" = ( /obj/machinery/door/airlock/security/glass{ name = "Permabrig Visitation" @@ -30200,15 +30133,16 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/engineering/main) -"kFa" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/start/cargo_technician, -/obj/structure/chair/office{ +"kFb" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/turf_decal/tile/brown/opposingcorners, +/obj/effect/turf_decal/siding/white/corner{ dir = 4 }, /turf/open/floor/iron, -/area/station/cargo/sorting) +/area/station/cargo/storage) "kFg" = ( /obj/effect/turf_decal/tile/yellow/half/contrasted{ dir = 1 @@ -30237,6 +30171,16 @@ /obj/structure/cable, /turf/open/floor/carpet, /area/station/service/library) +"kFQ" = ( +/obj/structure/railing/corner{ + dir = 8 + }, +/obj/structure/chair/office/light{ + dir = 1 + }, +/obj/effect/landmark/start/cargo_technician, +/turf/open/floor/plating/reinforced, +/area/station/cargo/storage) "kFS" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 8 @@ -30394,6 +30338,24 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating/airless, /area/station/science/ordnance/bomb) +"kJk" = ( +/obj/effect/turf_decal/tile/red/half/contrasted{ + dir = 8 + }, +/obj/machinery/camera/directional/west, +/obj/machinery/requests_console/directional/west, +/obj/effect/mapping_helpers/requests_console/assistance, +/obj/effect/mapping_helpers/requests_console/supplies, +/obj/item/dest_tagger{ + pixel_x = -9; + pixel_y = 12 + }, +/obj/item/hand_labeler_refill{ + pixel_x = -11; + pixel_y = -3 + }, +/turf/open/floor/iron/dark, +/area/station/security/checkpoint/supply) "kJx" = ( /obj/structure/chair/office, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -31385,14 +31347,6 @@ /obj/effect/spawner/random/trash/janitor_supplies, /turf/open/floor/plating, /area/station/maintenance/aft/greater) -"lak" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/cargo/sorting) "lav" = ( /obj/structure/girder, /obj/effect/spawner/random/structure/grille, @@ -31494,6 +31448,22 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/command/gateway) +"lcI" = ( +/obj/effect/turf_decal/trimline/red/filled/corner{ + dir = 1 + }, +/obj/structure/extinguisher_cabinet/directional/north, +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 4 + }, +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 4 + }, +/obj/effect/turf_decal/siding/white/corner{ + dir = 1 + }, +/turf/open/floor/iron, +/area/station/cargo/storage) "lcJ" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -31867,6 +31837,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/carpet, /area/station/command/bridge) +"ljT" = ( +/obj/machinery/exodrone_launcher, +/obj/item/exodrone, +/obj/effect/turf_decal/box, +/turf/open/floor/plating/reinforced, +/area/station/cargo/storage) "lkc" = ( /obj/machinery/barsign, /turf/closed/wall, @@ -32087,10 +32063,6 @@ /obj/machinery/meter, /turf/closed/wall/r_wall, /area/station/engineering/atmos) -"lpt" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, -/turf/open/floor/iron, -/area/station/construction/storage_wing) "lpA" = ( /obj/machinery/air_sensor/nitrogen_tank, /turf/open/floor/engine/n2, @@ -32258,27 +32230,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/security/brig) -"lsU" = ( -/obj/effect/turf_decal/tile/brown/opposingcorners, -/obj/structure/table, -/obj/item/stack/package_wrap{ - pixel_x = -2; - pixel_y = 1 - }, -/obj/effect/spawner/random/bureaucracy/birthday_wrap{ - pixel_x = -2; - pixel_y = 8 - }, -/obj/item/dest_tagger{ - pixel_x = 7; - pixel_y = 1 - }, -/obj/item/stack/wrapping_paper{ - pixel_x = -4; - pixel_y = -7 - }, -/turf/open/floor/iron, -/area/station/cargo/sorting) "lsV" = ( /obj/effect/turf_decal/siding/purple{ dir = 10 @@ -32451,11 +32402,6 @@ }, /turf/open/floor/iron/freezer, /area/station/commons/toilet/restrooms) -"lvY" = ( -/obj/effect/decal/cleanable/cobweb, -/obj/machinery/vending/boozeomat/all_access, -/turf/open/floor/wood, -/area/station/maintenance/port/aft) "lvZ" = ( /obj/machinery/door/firedoor, /obj/structure/disposalpipe/segment, @@ -32583,6 +32529,15 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/command) +"lzD" = ( +/obj/structure/cable, +/obj/effect/turf_decal/trimline/brown/filled/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, +/area/station/cargo/sorting) "lzJ" = ( /obj/structure/cable, /turf/open/floor/iron/solarpanel/airless, @@ -34908,12 +34863,6 @@ }, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) -"muq" = ( -/obj/structure/disposalpipe/segment{ - dir = 10 - }, -/turf/open/floor/iron, -/area/station/cargo/storage) "mur" = ( /obj/machinery/light/directional/north, /obj/machinery/status_display/evac/directional/north, @@ -35048,14 +34997,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/engineering/main) -"mwP" = ( -/obj/structure/cable, -/obj/structure/extinguisher_cabinet/directional/east, -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 6 - }, -/turf/open/floor/iron, -/area/station/cargo/storage) "mwY" = ( /obj/effect/spawner/random/trash/garbage, /obj/effect/landmark/generic_maintenance_landmark, @@ -35090,13 +35031,6 @@ /obj/structure/window/spawner/directional/south, /turf/open/floor/iron, /area/station/engineering/atmos) -"mxx" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/spawner/structure/window, -/turf/open/floor/plating, -/area/station/cargo/sorting) "mxI" = ( /obj/structure/disposalpipe/junction/flip, /obj/structure/cable, @@ -35164,10 +35098,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/engineering/gravity_generator) -"myZ" = ( -/obj/machinery/vending/autodrobe/all_access, -/turf/open/floor/plating, -/area/station/maintenance/port) "mzg" = ( /obj/structure/cable, /obj/effect/turf_decal/siding/red, @@ -35175,16 +35105,6 @@ /obj/effect/turf_decal/tile/red/opposingcorners, /turf/open/floor/iron, /area/station/security/checkpoint/science) -"mzj" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/power/apc/auto_name/directional/north, -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 1 - }, -/obj/machinery/light/directional/north, -/turf/open/floor/iron, -/area/station/cargo/sorting) "mzm" = ( /obj/structure/table, /obj/item/reagent_containers/condiment/saltshaker{ @@ -36390,12 +36310,6 @@ /obj/effect/turf_decal/trimline/brown/filled/line, /turf/open/floor/iron, /area/station/cargo/miningoffice) -"mUF" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 1 - }, -/turf/open/floor/iron, -/area/station/cargo/drone_bay) "mUL" = ( /obj/machinery/door/airlock/atmos{ name = "Hypertorus Fusion Reactor" @@ -37272,6 +37186,10 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central) +"nkq" = ( +/obj/effect/turf_decal/loading_area, +/turf/open/floor/plating/reinforced, +/area/station/cargo/storage) "nkG" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/green/visible, /obj/machinery/meter, @@ -37554,6 +37472,16 @@ /obj/structure/window/spawner/directional/east, /turf/open/floor/iron/dark, /area/station/engineering/atmos) +"npX" = ( +/obj/structure/cable, +/obj/structure/extinguisher_cabinet/directional/east, +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 6 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron, +/area/station/cargo/storage) "npY" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/public/glass{ @@ -37938,12 +37866,6 @@ }, /turf/open/floor/iron/white, /area/station/medical/office) -"nut" = ( -/obj/structure/cable, -/obj/effect/turf_decal/bot_white, -/obj/effect/spawner/random/maintenance, -/turf/open/floor/iron, -/area/station/cargo/storage) "nuB" = ( /obj/structure/secure_safe/directional/south, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ @@ -38147,6 +38069,15 @@ /obj/structure/cable, /turf/open/floor/wood, /area/station/service/bar/backroom) +"nxI" = ( +/obj/effect/turf_decal/trimline/red/filled/corner{ + dir = 4 + }, +/obj/structure/railing{ + dir = 4 + }, +/turf/open/floor/iron/stairs, +/area/station/cargo/storage) "nxO" = ( /obj/structure/chair/office{ dir = 8 @@ -38829,20 +38760,6 @@ }, /turf/open/space/basic, /area/space) -"nKu" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 4 - }, -/obj/item/reagent_containers/cup/glass/waterbottle{ - pixel_y = 48; - pixel_x = 9 - }, -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 1 - }, -/turf/open/floor/iron, -/area/station/cargo/sorting) "nKE" = ( /obj/effect/turf_decal/trimline/blue/filled/line, /turf/open/floor/iron/white, @@ -38896,13 +38813,6 @@ /obj/machinery/airalarm/directional/south, /turf/open/floor/wood, /area/station/service/library) -"nLx" = ( -/obj/structure/cable, -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 1 - }, -/turf/open/floor/iron, -/area/station/cargo/sorting) "nLz" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, @@ -39729,17 +39639,17 @@ /obj/effect/landmark/start/hangover, /turf/open/floor/wood, /area/station/commons/dorms) -"obF" = ( -/obj/machinery/computer/exoscanner_control{ +"oby" = ( +/obj/effect/turf_decal/tile/red/half/contrasted{ dir = 1 }, -/obj/machinery/camera/directional/south{ - c_tag = "Cargo Bay - Drone Launch Room"; - pixel_x = 14 +/obj/machinery/computer/security/mining, +/obj/structure/reagent_dispensers/wall/peppertank/directional/north, +/obj/machinery/light/small/directional/north{ + pixel_x = -11 }, -/obj/structure/sign/poster/official/random/directional/south, -/turf/open/floor/iron, -/area/station/cargo/drone_bay) +/turf/open/floor/iron/dark, +/area/station/security/checkpoint/supply) "obG" = ( /turf/closed/wall, /area/station/service/theater) @@ -40240,6 +40150,15 @@ /obj/structure/sign/poster/random/directional/south, /turf/open/floor/plating, /area/station/hallway/secondary/service) +"omc" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/siding/white{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/cargo/storage) "omd" = ( /obj/structure/table, /obj/machinery/cell_charger, @@ -41448,6 +41367,12 @@ }, /turf/open/floor/iron/dark, /area/station/security/office) +"oHm" = ( +/obj/structure/railing{ + dir = 8 + }, +/turf/open/floor/iron/stairs, +/area/station/cargo/storage) "oHw" = ( /obj/structure/cable, /turf/open/floor/iron/white/corner, @@ -41751,6 +41676,11 @@ /obj/effect/spawner/structure/window, /turf/open/floor/plating, /area/station/medical/office) +"oNR" = ( +/obj/effect/turf_decal/bot_white, +/obj/effect/spawner/random/maintenance, +/turf/open/floor/iron, +/area/station/cargo/storage) "oOl" = ( /obj/machinery/flasher/directional/north{ id = "AI" @@ -41796,6 +41726,12 @@ /obj/structure/window/reinforced/spawner/directional/north, /turf/open/space, /area/space/nearstation) +"oOY" = ( +/obj/structure/rack, +/obj/item/fuel_pellet, +/obj/item/fuel_pellet, +/turf/open/floor/plating/reinforced, +/area/station/cargo/storage) "oOZ" = ( /obj/machinery/power/port_gen/pacman/pre_loaded, /turf/open/floor/plating, @@ -41924,6 +41860,15 @@ }, /turf/open/floor/iron/cafeteria, /area/station/service/kitchen) +"oRx" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 1 + }, +/obj/effect/turf_decal/siding/white{ + dir = 9 + }, +/turf/open/floor/iron, +/area/station/cargo/storage) "oRM" = ( /obj/machinery/atmospherics/pipe/smart/simple/yellow/visible{ dir = 4 @@ -42020,16 +41965,6 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos) -"oTw" = ( -/obj/machinery/door/airlock/mining{ - name = "Deliveries" - }, -/obj/machinery/door/firedoor, -/obj/structure/cable, -/obj/effect/mapping_helpers/airlock/access/any/supply/shipping, -/obj/effect/turf_decal/tile/brown/opposingcorners, -/turf/open/floor/iron, -/area/station/cargo/sorting) "oTD" = ( /obj/structure/frame/computer, /turf/open/floor/plating/airless, @@ -42296,6 +42231,11 @@ /obj/machinery/light/small/red/directional/west, /turf/open/floor/plating/airless, /area/space/nearstation) +"oYs" = ( +/obj/machinery/vending/autodrobe, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/turf/open/floor/iron/dark, +/area/station/commons/locker) "oYv" = ( /obj/effect/decal/cleanable/cobweb, /obj/structure/bed, @@ -42396,15 +42336,6 @@ "paD" = ( /turf/closed/wall, /area/station/cargo/bitrunning/den) -"paQ" = ( -/obj/structure/window/spawner/directional/south, -/obj/machinery/computer/cargo/request{ - dir = 1 - }, -/obj/effect/turf_decal/tile/brown/fourcorners, -/obj/machinery/door/firedoor, -/turf/open/floor/iron, -/area/station/cargo/sorting) "paU" = ( /obj/machinery/door/airlock/maintenance, /obj/effect/mapping_helpers/airlock/unres{ @@ -42782,14 +42713,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/ai) -"phP" = ( -/obj/structure/table, -/obj/item/exodrone{ - pixel_y = 8 - }, -/obj/item/radio/intercom/directional/east, -/turf/open/floor/iron, -/area/station/cargo/drone_bay) "phR" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -42899,6 +42822,19 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/commons/fitness/recreation) +"pjX" = ( +/obj/effect/turf_decal/trimline/brown/filled/corner{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/brown/warning{ + dir = 8 + }, +/obj/structure/extinguisher_cabinet/directional/north, +/obj/machinery/light/small/directional/north, +/obj/structure/disposalpipe/segment, +/obj/effect/spawner/random/structure/crate, +/turf/open/floor/iron, +/area/station/cargo/sorting) "pke" = ( /obj/effect/turf_decal/siding/red{ dir = 6 @@ -42916,13 +42852,6 @@ }, /turf/open/floor/iron/white, /area/station/command/heads_quarters/rd) -"pkF" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/photocopier, -/turf/open/floor/iron, -/area/station/cargo/sorting) "pkH" = ( /obj/structure/rack, /obj/item/restraints/handcuffs, @@ -43082,6 +43011,15 @@ }, /turf/open/floor/plating/airless, /area/station/science/ordnance/bomb) +"pnl" = ( +/obj/effect/turf_decal/stripes/line, +/obj/structure/extinguisher_cabinet/directional/east, +/obj/item/wallframe/apc, +/obj/item/phone, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/turf_decal/caution, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "pnx" = ( /obj/structure/cable, /obj/effect/decal/cleanable/dirt, @@ -43135,6 +43073,12 @@ /obj/effect/turf_decal/tile/bar/opposingcorners, /turf/open/floor/iron, /area/station/service/bar) +"pog" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/closed/wall, +/area/station/security/checkpoint/supply) "poj" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -43886,19 +43830,6 @@ /obj/machinery/newscaster/directional/north, /turf/open/floor/iron/dark, /area/station/medical/break_room) -"pCs" = ( -/obj/machinery/camera/directional/south{ - c_tag = "Cargo Bay - Mailroom" - }, -/obj/machinery/light/directional/south, -/obj/effect/turf_decal/trimline/brown/filled/corner{ - dir = 8 - }, -/obj/effect/turf_decal/trimline/white/corner{ - dir = 8 - }, -/turf/open/floor/iron, -/area/station/cargo/sorting) "pCt" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -43944,6 +43875,13 @@ /obj/machinery/power/apc/auto_name/directional/east, /turf/open/floor/iron/grimy, /area/station/tcommsat/computer) +"pDf" = ( +/obj/machinery/requests_console/directional/south{ + department = "Mining"; + name = "Mining Requests Console" + }, +/turf/open/floor/iron, +/area/station/cargo/miningoffice) "pDl" = ( /obj/effect/turf_decal/delivery, /obj/machinery/door/window/left/directional/north{ @@ -44136,6 +44074,11 @@ }, /turf/open/floor/iron/freezer, /area/station/commons/toilet/restrooms) +"pGJ" = ( +/obj/item/chair/wood/wings, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "pGZ" = ( /obj/machinery/shower/directional/east, /obj/structure/cable, @@ -44634,6 +44577,18 @@ /obj/structure/cable, /turf/open/floor/iron/grimy, /area/station/security/interrogation) +"pPm" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/turf_decal/trimline/brown/filled/corner{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/brown/filled/corner{ + dir = 4 + }, +/obj/effect/decal/cleanable/wrapping, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron, +/area/station/cargo/sorting) "pPp" = ( /obj/effect/decal/cleanable/cobweb/cobweb2, /obj/structure/chair/comfy/black{ @@ -44969,6 +44924,20 @@ /obj/item/radio/intercom/directional/east, /turf/open/floor/iron/grimy, /area/station/security/interrogation) +"pVK" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/turf_decal/tile/brown{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/turf/open/floor/iron, +/area/station/hallway/primary/port) "pVM" = ( /obj/machinery/light/small/directional/south, /obj/machinery/camera/directional/south{ @@ -45826,6 +45795,12 @@ }, /turf/open/floor/iron/dark, /area/station/command/bridge) +"qlh" = ( +/obj/structure/railing/corner{ + dir = 8 + }, +/turf/open/floor/plating/reinforced, +/area/station/cargo/storage) "qlz" = ( /obj/effect/spawner/random/vending/colavend, /obj/machinery/light/directional/north, @@ -45856,6 +45831,11 @@ /obj/machinery/light/directional/west, /turf/open/floor/iron, /area/station/construction/storage_wing) +"qme" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, +/obj/item/storage/test_tube_rack/full, +/turf/open/floor/iron, +/area/station/construction/storage_wing) "qmf" = ( /obj/machinery/power/apc/auto_name/directional/east, /obj/structure/table/wood, @@ -46042,12 +46022,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/carpet, /area/station/service/library) -"qqr" = ( -/obj/effect/decal/cleanable/dirt/dust, -/obj/effect/turf_decal/stripes/line, -/obj/structure/cable, -/turf/open/floor/iron, -/area/station/cargo/miningoffice) "qqs" = ( /obj/structure/table, /obj/item/multitool{ @@ -46108,13 +46082,6 @@ /obj/machinery/computer/security/telescreen/minisat/directional/south, /turf/open/floor/carpet, /area/station/command/heads_quarters/captain/private) -"qrF" = ( -/obj/machinery/computer/exodrone_control_console{ - dir = 1 - }, -/obj/machinery/newscaster/directional/south, -/turf/open/floor/iron, -/area/station/cargo/drone_bay) "qrL" = ( /obj/effect/decal/cleanable/oil/streak, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, @@ -46909,12 +46876,6 @@ /obj/effect/turf_decal/tile/neutral/half/contrasted, /turf/open/floor/iron, /area/station/hallway/primary/port) -"qHa" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron, -/area/station/cargo/drone_bay) "qHh" = ( /obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ dir = 9 @@ -46948,6 +46909,10 @@ /obj/effect/spawner/random/structure/grille, /turf/open/floor/plating, /area/station/maintenance/port/aft) +"qHW" = ( +/obj/item/storage/test_tube_rack/full, +/turf/closed/wall/r_wall, +/area/station/security/prison/safe) "qHY" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 8 @@ -47062,11 +47027,6 @@ /obj/machinery/light/small/directional/east, /turf/open/floor/iron/white, /area/station/medical/pharmacy) -"qJH" = ( -/obj/machinery/vending/autodrobe/all_access, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron/dark, -/area/station/commons/locker) "qJU" = ( /obj/structure/sign/map/right{ desc = "A framed picture of the station. Clockwise from security at the top (red), you see engineering (yellow), science (purple), escape (red and white), medbay (green), arrivals (blue and white), and finally cargo (brown)."; @@ -47354,6 +47314,13 @@ }, /turf/open/floor/iron, /area/station/security/prison) +"qNL" = ( +/obj/effect/turf_decal/tile/red/half/contrasted, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/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/security/checkpoint/supply) "qNO" = ( /obj/structure/table/glass, /obj/item/folder/blue{ @@ -47463,16 +47430,6 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos) -"qOZ" = ( -/obj/machinery/requests_console/directional/south{ - department = "Mining"; - name = "Mining Requests Console" - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/cargo/miningoffice) "qPs" = ( /obj/structure/lattice/catwalk, /obj/structure/marker_beacon/indigo, @@ -47731,9 +47688,6 @@ /obj/machinery/light_switch/directional/north, /turf/open/floor/iron/dark, /area/station/science/ordnance) -"qST" = ( -/turf/open/floor/iron, -/area/station/cargo/drone_bay) "qTf" = ( /obj/effect/turf_decal/tile/brown/anticorner/contrasted{ dir = 1 @@ -48469,18 +48423,6 @@ }, /turf/open/floor/iron/white, /area/station/medical/virology) -"rgL" = ( -/obj/structure/table, -/obj/item/reagent_containers/cup/glass/mug/britcup{ - pixel_x = -6; - pixel_y = 11 - }, -/obj/item/phone{ - pixel_x = 6; - pixel_y = 1 - }, -/turf/open/floor/iron, -/area/station/cargo/drone_bay) "rgS" = ( /obj/machinery/modular_computer/preset/civilian{ dir = 1 @@ -48490,6 +48432,11 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/science/robotics/lab) +"rgW" = ( +/obj/machinery/exodrone_launcher, +/obj/effect/turf_decal/box, +/turf/open/floor/plating/reinforced, +/area/station/cargo/storage) "rgZ" = ( /obj/structure/disposalpipe/segment{ dir = 9 @@ -48708,6 +48655,14 @@ /obj/item/target/syndicate, /turf/open/floor/engine, /area/station/science/explab) +"rkX" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "rla" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -48781,13 +48736,6 @@ /obj/effect/mapping_helpers/airlock/access/all/service/lawyer, /turf/open/floor/plating, /area/station/maintenance/fore) -"rmL" = ( -/obj/structure/disposalpipe/segment, -/obj/effect/decal/cleanable/wrapping, -/obj/effect/turf_decal/tile/brown/opposingcorners, -/obj/effect/landmark/start/cargo_technician, -/turf/open/floor/iron, -/area/station/cargo/sorting) "rmO" = ( /obj/structure/chair/comfy/black{ dir = 8 @@ -48929,16 +48877,6 @@ /obj/machinery/light/floor, /turf/open/floor/iron, /area/station/construction/mining/aux_base) -"roG" = ( -/obj/machinery/firealarm/directional/west, -/obj/structure/disposalpipe/trunk{ - dir = 4 - }, -/obj/machinery/disposal/bin/tagger, -/obj/structure/sign/poster/official/random/directional/south, -/obj/effect/turf_decal/trimline/brown/filled/corner, -/turf/open/floor/iron, -/area/station/cargo/sorting) "rps" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 4 @@ -49165,6 +49103,20 @@ /obj/machinery/light/directional/east, /turf/open/floor/iron, /area/station/hallway/primary/aft) +"rtG" = ( +/obj/effect/turf_decal/trimline/brown/corner{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/brown/line{ + dir = 6 + }, +/obj/effect/landmark/start/assistant, +/obj/structure/chair{ + dir = 1 + }, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/iron, +/area/station/cargo/lobby) "rtI" = ( /obj/effect/landmark/secequipment, /obj/effect/turf_decal/bot, @@ -49691,6 +49643,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/hallway/secondary/entry) +"rBB" = ( +/obj/effect/turf_decal/tile/red/anticorner/contrasted{ + dir = 1 + }, +/turf/open/floor/iron/dark, +/area/station/security/checkpoint/supply) "rBU" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -49920,6 +49878,19 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/carpet, /area/station/command/heads_quarters/hop) +"rGk" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/power/apc/auto_name/directional/north, +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 1 + }, +/obj/machinery/light/directional/north, +/obj/machinery/airalarm/directional/north, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/modular_computer/preset/cargochat/cargo, +/turf/open/floor/iron, +/area/station/cargo/sorting) "rGm" = ( /obj/machinery/door/firedoor, /obj/machinery/door/poddoor/shutters{ @@ -50249,6 +50220,10 @@ /obj/machinery/light/small/directional/south, /turf/open/floor/plating, /area/station/maintenance/department/engine) +"rMd" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "rMe" = ( /obj/structure/table, /obj/machinery/button/door{ @@ -50338,6 +50313,11 @@ }, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat_interior) +"rNA" = ( +/obj/structure/disposalpipe/segment, +/obj/effect/spawner/random/structure/crate, +/turf/open/floor/iron, +/area/station/cargo/sorting) "rNI" = ( /obj/machinery/door/airlock/maintenance, /obj/structure/cable, @@ -50449,13 +50429,6 @@ /obj/structure/chair/stool/directional/east, /turf/open/floor/wood, /area/station/commons/lounge) -"rPO" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 1 - }, -/turf/open/floor/iron, -/area/station/hallway/primary/central) "rQd" = ( /obj/structure/cable, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ @@ -51184,14 +51157,6 @@ /obj/machinery/light/directional/east, /turf/open/floor/iron/cafeteria, /area/station/service/kitchen) -"sbP" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/turf_decal/tile/brown/opposingcorners, -/obj/effect/landmark/start/cargo_technician, -/turf/open/floor/iron, -/area/station/cargo/storage) "sbX" = ( /obj/machinery/hydroponics/soil, /obj/effect/decal/cleanable/dirt, @@ -51418,6 +51383,12 @@ /obj/structure/window/spawner/directional/west, /turf/open/floor/iron/dark, /area/station/engineering/atmos) +"sgZ" = ( +/obj/structure/disposalpipe/segment, +/obj/machinery/door/firedoor, +/obj/effect/spawner/structure/window, +/turf/open/floor/plating, +/area/station/cargo/sorting) "shl" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -51650,16 +51621,6 @@ /obj/machinery/door/airlock/public/glass/incinerator/atmos_exterior, /turf/open/floor/engine/vacuum, /area/station/maintenance/disposal/incinerator) -"sml" = ( -/obj/structure/disposalpipe/segment{ - dir = 6 - }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 1 - }, -/obj/effect/turf_decal/tile/brown/opposingcorners, -/turf/open/floor/iron, -/area/station/cargo/sorting) "smt" = ( /obj/machinery/atmospherics/pipe/bridge_pipe/yellow/visible{ dir = 4 @@ -51921,6 +51882,30 @@ /obj/effect/mapping_helpers/airlock/access/all/security/general, /turf/open/floor/iron/grimy, /area/station/security/office) +"ssu" = ( +/obj/structure/table/wood, +/obj/item/reagent_containers/spray/syndicate{ + pixel_y = 4; + pixel_x = 7 + }, +/obj/item/reagent_containers/pill/maintenance{ + pixel_x = -4; + pixel_y = -1 + }, +/obj/item/reagent_containers/pill/maintenance{ + pixel_x = -4; + pixel_y = 1 + }, +/obj/item/reagent_containers/pill/maintenance{ + pixel_x = -4; + pixel_y = 2 + }, +/obj/item/reagent_containers/pill/happy{ + pixel_y = 6; + pixel_x = -4 + }, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "ssI" = ( /obj/machinery/power/emitter, /turf/open/floor/plating, @@ -51988,33 +51973,6 @@ }, /turf/open/floor/engine, /area/station/engineering/supermatter/room) -"sul" = ( -/obj/structure/table, -/obj/item/paper_bin{ - pixel_x = 8; - pixel_y = 1 - }, -/obj/item/paper_bin{ - pixel_x = 8; - pixel_y = 6 - }, -/obj/item/paper_bin{ - pixel_x = 8; - pixel_y = 11 - }, -/obj/item/folder/yellow{ - pixel_x = -6; - pixel_y = 8 - }, -/obj/item/folder/yellow{ - pixel_x = -9; - pixel_y = 1 - }, -/obj/item/paper{ - pixel_x = -5 - }, -/turf/open/floor/iron, -/area/station/cargo/sorting) "sus" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -52352,6 +52310,13 @@ /obj/machinery/telecomms/server/presets/engineering, /turf/open/floor/circuit/telecomms/mainframe, /area/station/tcommsat/server) +"sAt" = ( +/obj/effect/turf_decal/tile/brown/opposingcorners, +/obj/effect/turf_decal/siding/white/corner{ + dir = 1 + }, +/turf/open/floor/iron, +/area/station/cargo/storage) "sAv" = ( /obj/machinery/stasis, /obj/machinery/defibrillator_mount/directional/north, @@ -52902,6 +52867,11 @@ }, /turf/open/floor/iron/dark, /area/station/science/ordnance) +"sJq" = ( +/obj/machinery/exoscanner, +/obj/effect/turf_decal/delivery/white, +/turf/open/floor/plating/reinforced, +/area/station/cargo/storage) "sJL" = ( /obj/item/crowbar, /obj/structure/cable, @@ -53175,6 +53145,19 @@ }, /turf/open/floor/iron/white, /area/station/medical/medbay/central) +"sOE" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/turf_decal/tile/brown/opposingcorners, +/obj/effect/turf_decal/siding/white/corner{ + dir = 1 + }, +/obj/structure/railing/corner/end{ + dir = 8 + }, +/turf/open/floor/iron, +/area/station/cargo/storage) "sOF" = ( /obj/structure/light_construct/directional/east, /turf/open/floor/wood, @@ -53278,11 +53261,6 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/iron, /area/station/hallway/primary/central) -"sQp" = ( -/obj/machinery/exodrone_launcher, -/obj/item/exodrone, -/turf/open/floor/plating, -/area/station/cargo/drone_bay) "sQq" = ( /obj/structure/closet/crate/hydroponics, /obj/item/paper/guides/jobs/hydroponics, @@ -53924,6 +53902,12 @@ dir = 1 }, /area/station/hallway/secondary/entry) +"sZT" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/security/checkpoint/supply) "sZU" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -54107,10 +54091,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/green/visible, /turf/open/floor/engine, /area/station/engineering/supermatter/room) -"tdg" = ( -/obj/effect/spawner/structure/window/reinforced, -/turf/open/floor/plating, -/area/station/cargo/drone_bay) "tds" = ( /obj/effect/turf_decal/box/corners{ dir = 8 @@ -54389,6 +54369,19 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) +"tjt" = ( +/obj/item/sticker/syndicate/apc{ + pixel_x = 25 + }, +/obj/effect/spawner/random/engineering/tank, +/obj/structure/railing{ + dir = 10 + }, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/obj/effect/decal/cleanable/fuel_pool, +/obj/structure/cable, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "tju" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 4 @@ -55681,6 +55674,18 @@ /obj/item/radio/intercom/directional/west, /turf/open/floor/carpet, /area/station/command/heads_quarters/captain/private) +"tIU" = ( +/obj/machinery/door/airlock/maintenance/glass, +/obj/effect/mapping_helpers/airlock/access/any/supply/maintenance, +/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/abandoned, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 4 + }, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "tJb" = ( /obj/machinery/firealarm/directional/north, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ @@ -55967,22 +55972,6 @@ /obj/structure/sign/poster/contraband/random/directional/east, /turf/open/floor/plating, /area/station/maintenance/port/aft) -"tMY" = ( -/obj/structure/cable, -/obj/structure/table/reinforced, -/obj/machinery/recharger{ - pixel_y = 4 - }, -/obj/item/radio/off{ - pixel_x = -11; - pixel_y = -3 - }, -/obj/effect/turf_decal/tile/red/half/contrasted{ - dir = 1 - }, -/obj/item/binoculars, -/turf/open/floor/iron, -/area/station/security/checkpoint/supply) "tNg" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -56214,14 +56203,6 @@ /obj/item/clothing/mask/surgical, /turf/open/floor/iron/showroomfloor, /area/station/maintenance/starboard/lesser) -"tPW" = ( -/obj/structure/disposalpipe/segment{ - dir = 9 - }, -/obj/effect/turf_decal/tile/brown/opposingcorners, -/obj/structure/filingcabinet/filingcabinet, -/turf/open/floor/iron, -/area/station/cargo/sorting) "tQp" = ( /obj/structure/cable, /obj/effect/turf_decal/siding/wood{ @@ -56720,13 +56701,6 @@ /obj/effect/mapping_helpers/airlock/access/all/security/general, /turf/open/floor/plating, /area/station/security/execution/transfer) -"tYU" = ( -/obj/structure/disposalpipe/segment{ - dir = 10 - }, -/obj/effect/turf_decal/tile/brown/opposingcorners, -/turf/open/floor/iron, -/area/station/cargo/storage) "tYW" = ( /obj/machinery/light/directional/south, /obj/structure/cable, @@ -56916,11 +56890,6 @@ /obj/machinery/telecomms/broadcaster/preset_left, /turf/open/floor/circuit/telecomms/mainframe, /area/station/tcommsat/server) -"ubn" = ( -/obj/effect/turf_decal/trimline/purple/filled/line, -/obj/effect/turf_decal/trimline/brown/filled/warning, -/turf/open/floor/iron, -/area/station/cargo/sorting) "ubp" = ( /obj/structure/girder, /obj/effect/spawner/random/structure/grille, @@ -57190,14 +57159,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/hallway/secondary/entry) -"uha" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 4 - }, -/obj/effect/landmark/start/depsec/supply, -/obj/structure/cable, -/turf/open/floor/iron, -/area/station/security/checkpoint/supply) "uhq" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -57335,11 +57296,6 @@ /obj/structure/mirror/directional/east, /turf/open/floor/iron/freezer, /area/station/commons/toilet/restrooms) -"ujT" = ( -/obj/machinery/airalarm/directional/west, -/obj/effect/spawner/random/structure/tank_holder, -/turf/open/floor/iron, -/area/station/cargo/drone_bay) "uke" = ( /obj/structure/rack, /obj/effect/spawner/random/food_or_drink/booze{ @@ -57818,15 +57774,6 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/exit/departure_lounge) -"usJ" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 1 - }, -/obj/machinery/light/directional/north, -/turf/open/floor/iron, -/area/station/cargo/sorting) "usK" = ( /obj/structure/table, /obj/item/storage/toolbox/emergency, @@ -57878,14 +57825,6 @@ }, /turf/open/floor/wood, /area/station/security/office) -"uth" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 8 - }, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron, -/area/station/cargo/drone_bay) "utk" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -57942,17 +57881,6 @@ dir = 8 }, /area/station/service/chapel) -"uud" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/turf_decal/trimline/brown/filled/corner{ - dir = 1 - }, -/obj/effect/turf_decal/trimline/brown/filled/corner{ - dir = 4 - }, -/obj/effect/decal/cleanable/wrapping, -/turf/open/floor/iron, -/area/station/cargo/sorting) "uuv" = ( /obj/machinery/holopad, /obj/effect/turf_decal/stripes/line{ @@ -57972,6 +57900,19 @@ }, /turf/open/floor/iron, /area/station/security/mechbay) +"uuW" = ( +/obj/effect/turf_decal/tile/brown/opposingcorners, +/obj/structure/table, +/obj/machinery/fax{ + fax_name = "Cargo Office"; + name = "Cargo Office Fax Machine" + }, +/obj/item/papercutter{ + pixel_x = 8; + pixel_y = 8 + }, +/turf/open/floor/plating, +/area/station/cargo/sorting) "uvw" = ( /obj/machinery/status_display/supply{ pixel_y = 32 @@ -58027,26 +57968,6 @@ /obj/machinery/duct, /turf/open/floor/iron, /area/station/engineering/main) -"uwf" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/table/reinforced, -/obj/item/paper_bin{ - pixel_x = 1; - pixel_y = 9 - }, -/obj/item/pen{ - pixel_x = 1; - pixel_y = 9 - }, -/obj/item/book/manual/wiki/security_space_law, -/obj/machinery/camera/directional/south{ - c_tag = "Security Post - Cargo" - }, -/obj/effect/turf_decal/tile/red/anticorner/contrasted{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/security/checkpoint/supply) "uwh" = ( /obj/structure/chair/comfy{ dir = 1 @@ -58074,12 +57995,6 @@ /obj/effect/landmark/start/roboticist, /turf/open/floor/iron, /area/station/science/robotics/lab) -"uwM" = ( -/obj/effect/landmark/start/depsec/supply, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron, -/area/station/security/checkpoint/supply) "uwQ" = ( /turf/closed/wall/r_wall, /area/station/engineering/atmos) @@ -58178,6 +58093,37 @@ }, /turf/open/floor/iron/white, /area/station/command/heads_quarters/cmo) +"uyP" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/turf_decal/tile/brown/opposingcorners, +/obj/structure/table, +/obj/machinery/light/directional/east, +/obj/item/radio/intercom/directional/east, +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/item/stamp/granted{ + pixel_x = -7; + pixel_y = 4 + }, +/obj/item/stamp/denied{ + pixel_x = -7; + pixel_y = 15 + }, +/obj/item/storage/box/lights/mixed{ + pixel_x = 5; + pixel_y = 12 + }, +/obj/item/storage/box/lights/mixed{ + pixel_x = 5; + pixel_y = 24 + }, +/turf/open/floor/iron, +/area/station/cargo/sorting) "uyY" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -58187,13 +58133,6 @@ "uza" = ( /turf/closed/wall/r_wall, /area/station/security/prison/visit) -"uzb" = ( -/obj/structure/rack, -/obj/machinery/light/directional/east, -/obj/item/fuel_pellet, -/obj/machinery/light_switch/directional/east, -/turf/open/floor/iron, -/area/station/cargo/drone_bay) "uzc" = ( /obj/structure/cable, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, @@ -58366,6 +58305,15 @@ /obj/machinery/airalarm/directional/west, /turf/open/floor/wood, /area/station/command/corporate_showroom) +"uCR" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/hallway/primary/port) "uCS" = ( /obj/structure/chair/stool/directional/south, /turf/open/floor/iron, @@ -59190,6 +59138,20 @@ /obj/machinery/light/small/directional/east, /turf/open/floor/iron, /area/station/maintenance/disposal/incinerator) +"uQm" = ( +/obj/item/radio/intercom/directional/east, +/obj/structure/table/wood, +/obj/item/ph_booklet{ + pixel_y = 6; + pixel_x = 5 + }, +/obj/item/burner/oil{ + pixel_y = 6; + pixel_x = -5 + }, +/obj/item/storage/test_tube_rack/full, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "uQF" = ( /obj/structure/lattice, /obj/item/stack/rods, @@ -59293,6 +59255,13 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/station/security/prison) +"uSh" = ( +/obj/item/stack/sheet/iron/five, +/obj/item/stack/cable_coil/five, +/obj/effect/decal/cleanable/robot_debris/down, +/obj/effect/turf_decal/box, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "uSz" = ( /obj/structure/table, /obj/item/phone{ @@ -59635,15 +59604,6 @@ "uYp" = ( /turf/closed/wall, /area/station/medical/break_room) -"uYB" = ( -/obj/structure/cable, -/obj/effect/turf_decal/bot_white, -/obj/effect/spawner/random/maintenance, -/obj/effect/turf_decal/arrows/red{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/cargo/storage) "uYD" = ( /obj/structure/disposalpipe/segment, /obj/effect/turf_decal/stripes/line, @@ -59651,6 +59611,19 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/port) +"uYE" = ( +/obj/effect/turf_decal/tile/red/half/contrasted{ + dir = 4 + }, +/obj/structure/table/reinforced, +/obj/item/binoculars, +/obj/machinery/airalarm/directional/east, +/obj/machinery/light/small/directional/east, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/station/security/checkpoint/supply) "uYH" = ( /obj/structure/reflector/double/anchored{ dir = 5 @@ -60410,15 +60383,6 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/plating, /area/station/maintenance/port/aft) -"vlP" = ( -/obj/structure/disposalpipe/segment{ - dir = 9 - }, -/obj/effect/turf_decal/tile/brown{ - dir = 1 - }, -/turf/open/floor/iron, -/area/station/cargo/lobby) "vlY" = ( /obj/structure/table/reinforced, /obj/machinery/camera/directional/north{ @@ -61045,6 +61009,13 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, /area/station/hallway/secondary/entry) +"vwg" = ( +/obj/machinery/light/directional/south, +/obj/effect/turf_decal/tile/brown/anticorner/contrasted, +/obj/structure/table, +/obj/effect/spawner/random/bureaucracy/birthday_wrap, +/turf/open/floor/iron, +/area/station/cargo/lobby) "vwi" = ( /obj/structure/table, /obj/item/cigarette/pipe, @@ -61900,12 +61871,6 @@ }, /turf/open/floor/carpet/royalblue, /area/station/service/library) -"vKC" = ( -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/cargo/storage) "vKL" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 1 @@ -62509,6 +62474,20 @@ /obj/effect/turf_decal/tile/green/half/contrasted, /turf/open/floor/iron/white, /area/station/medical/virology) +"vUL" = ( +/obj/item/circuitboard/machine/exoscanner{ + pixel_y = -3 + }, +/obj/item/stock_parts/scanning_module{ + pixel_x = 5; + pixel_y = 7 + }, +/obj/item/stock_parts/scanning_module{ + pixel_x = 5 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "vUM" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -63183,6 +63162,13 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/port/fore) +"wfp" = ( +/obj/effect/turf_decal/siding/white{ + dir = 5 + }, +/obj/item/kirbyplants/random, +/turf/open/floor/iron, +/area/station/cargo/storage) "wfu" = ( /obj/structure/chair/office{ dir = 8 @@ -63542,6 +63528,12 @@ }, /turf/open/floor/iron/dark, /area/station/security/evidence) +"wme" = ( +/obj/machinery/door/airlock/security/glass{ + name = "Security Post - Cargo" + }, +/turf/open/floor/plating, +/area/station/security/checkpoint/supply) "wmf" = ( /obj/effect/spawner/random/trash/garbage{ spawn_scatter_radius = 1 @@ -63736,14 +63728,6 @@ /obj/effect/mapping_helpers/airlock/access/all/command/ai_upload, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/ai_upload) -"wpO" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/turf_decal/tile/brown/opposingcorners, -/obj/effect/spawner/random/structure/crate, -/turf/open/floor/iron, -/area/station/cargo/sorting) "wqh" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ @@ -63810,12 +63794,6 @@ }, /turf/open/floor/carpet, /area/station/service/theater) -"wsk" = ( -/obj/structure/railing/corner/end/flip, -/obj/effect/turf_decal/stripes/corner, -/obj/structure/cable, -/turf/open/floor/iron, -/area/station/cargo/miningoffice) "wsq" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/security{ @@ -63869,6 +63847,14 @@ /obj/effect/turf_decal/tile/blue/fourcorners, /turf/open/floor/iron/white, /area/station/medical/treatment_center) +"wsx" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron, +/area/station/cargo/storage) "wsD" = ( /obj/structure/reagent_dispensers/fueltank, /turf/open/floor/iron, @@ -64020,14 +64006,6 @@ }, /turf/open/floor/iron, /area/station/security/holding_cell) -"wuo" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment, -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 1 - }, -/turf/open/floor/iron, -/area/station/cargo/sorting) "wuM" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, @@ -64126,6 +64104,13 @@ /obj/effect/turf_decal/tile/purple/fourcorners, /turf/open/floor/iron, /area/station/science/robotics/mechbay) +"wwN" = ( +/obj/effect/landmark/event_spawn, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/item/chair/wood, +/obj/effect/decal/cleanable/oil/slippery, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "wwW" = ( /obj/effect/turf_decal/trimline/purple/line{ dir = 1 @@ -64251,14 +64236,6 @@ /obj/machinery/bouldertech/refinery/smelter, /turf/open/floor/iron, /area/station/cargo/miningoffice) -"wyS" = ( -/obj/machinery/computer/cargo{ - dir = 4 - }, -/obj/structure/window/spawner/directional/west, -/obj/effect/turf_decal/tile/brown/opposingcorners, -/turf/open/floor/iron, -/area/station/cargo/sorting) "wyV" = ( /turf/open/floor/carpet/orange, /area/station/command/heads_quarters/qm) @@ -64395,6 +64372,15 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /turf/open/floor/iron, /area/station/hallway/primary/central) +"wBK" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/siding/white/corner{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/cargo/storage) "wBM" = ( /obj/machinery/door/firedoor, /obj/structure/cable, @@ -65239,17 +65225,6 @@ /obj/structure/reagent_dispensers/fueltank/large, /turf/open/floor/iron, /area/station/engineering/atmos) -"wTv" = ( -/obj/machinery/airalarm/directional/north, -/obj/machinery/modular_computer/preset/cargochat/cargo{ - dir = 8 - }, -/obj/effect/decal/cleanable/cobweb/cobweb2, -/obj/effect/turf_decal/trimline/brown/filled/corner{ - dir = 1 - }, -/turf/open/floor/iron, -/area/station/cargo/sorting) "wTF" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -65683,6 +65658,13 @@ }, /turf/open/floor/iron, /area/station/command/gateway) +"xbu" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/station/security/checkpoint/supply) "xbT" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -67119,11 +67101,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/engineering/main) -"xBq" = ( -/obj/effect/landmark/event_spawn, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron, -/area/station/cargo/drone_bay) "xBw" = ( /obj/machinery/door/airlock/engineering{ name = "Starboard Quarter Solar Access" @@ -67554,10 +67531,23 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/starboard/lesser) +"xJj" = ( +/obj/effect/turf_decal/tile/red/half/contrasted{ + dir = 8 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/station/security/checkpoint/supply) "xJv" = ( /obj/machinery/light/directional/north, /turf/open/floor/iron/recharge_floor, /area/station/security/mechbay) +"xJy" = ( +/obj/effect/turf_decal/tile/brown/opposingcorners, +/turf/closed/wall, +/area/station/security/checkpoint/supply) "xJA" = ( /obj/structure/sign/warning/docking, /turf/closed/wall, @@ -67604,6 +67594,12 @@ }, /turf/open/floor/iron/white, /area/station/science/ordnance/testlab) +"xKh" = ( +/obj/structure/railing{ + dir = 10 + }, +/turf/open/floor/plating/reinforced, +/area/station/cargo/storage) "xKk" = ( /obj/machinery/photocopier, /turf/open/floor/iron/white, @@ -67632,15 +67628,6 @@ }, /turf/open/floor/wood, /area/station/commons/vacant_room/office) -"xLA" = ( -/obj/machinery/computer/records/security{ - dir = 4 - }, -/obj/effect/turf_decal/tile/red/half/contrasted{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/security/checkpoint/supply) "xLR" = ( /obj/structure/table, /obj/item/stack/sheet/iron/fifty, @@ -67660,10 +67647,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/central) -"xMx" = ( -/obj/structure/chair/office, -/turf/open/floor/iron, -/area/station/cargo/drone_bay) "xMz" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -67891,10 +67874,6 @@ /obj/structure/cable/layer3, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/ai) -"xQO" = ( -/obj/machinery/exodrone_launcher, -/turf/open/floor/plating, -/area/station/cargo/drone_bay) "xQT" = ( /obj/machinery/power/apc/auto_name/directional/south, /obj/effect/turf_decal/siding/wood{ @@ -67932,6 +67911,15 @@ /obj/effect/mapping_helpers/airlock/access/all/engineering/atmos, /turf/open/floor/plating, /area/station/engineering/atmos) +"xRO" = ( +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 1 + }, +/turf/open/floor/iron, +/area/station/cargo/sorting) "xRR" = ( /obj/structure/bodycontainer/morgue/beeper_off, /obj/structure/bodycontainer/morgue/beeper_off{ @@ -67958,6 +67946,12 @@ "xRZ" = ( /turf/open/floor/iron, /area/station/engineering/atmos/pumproom) +"xSc" = ( +/obj/structure/frame/machine/secured, +/obj/effect/decal/cleanable/robot_debris, +/obj/effect/turf_decal/box, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "xSO" = ( /obj/effect/turf_decal/siding/wood{ dir = 1 @@ -68492,14 +68486,6 @@ /obj/machinery/incident_display/delam/directional/north, /turf/open/floor/iron, /area/station/engineering/main) -"ybn" = ( -/obj/structure/cable, -/obj/structure/disposalpipe/segment, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/hallway/primary/port) "ybu" = ( /obj/machinery/portable_atmospherics/canister/carbon_dioxide, /obj/machinery/atmospherics/components/unary/portables_connector/visible{ @@ -68626,6 +68612,11 @@ }, /turf/open/floor/iron/dark, /area/station/engineering/atmos) +"ydi" = ( +/obj/structure/railing/corner/end/flip, +/obj/effect/turf_decal/stripes/corner, +/turf/open/floor/iron, +/area/station/cargo/miningoffice) "ydj" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/pipe/smart/manifold4w/dark/visible, @@ -68778,6 +68769,10 @@ }, /turf/open/floor/wood, /area/station/service/library) +"yfX" = ( +/obj/effect/decal/cleanable/ash, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "ygb" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -68790,6 +68785,12 @@ }, /turf/open/floor/iron, /area/station/engineering/break_room) +"ygk" = ( +/obj/effect/turf_decal/trimline/purple/filled/line, +/obj/effect/turf_decal/trimline/brown/filled/warning, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron, +/area/station/cargo/sorting) "ygp" = ( /obj/machinery/status_display/ai/directional/north, /obj/structure/cable, @@ -68955,18 +68956,6 @@ /obj/effect/spawner/random/bureaucracy/stamp, /turf/open/floor/wood, /area/station/commons/vacant_room/office) -"ykb" = ( -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/mining{ - name = "Deliveries" - }, -/obj/effect/mapping_helpers/airlock/access/any/supply/shipping, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment, -/obj/effect/turf_decal/tile/brown/fourcorners, -/turf/open/floor/iron, -/area/station/cargo/sorting) "ykn" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper, /obj/machinery/door/airlock/external{ @@ -69067,14 +69056,6 @@ /obj/machinery/light/directional/east, /turf/open/floor/iron, /area/station/commons/dorms) -"ylO" = ( -/obj/machinery/firealarm/directional/north, -/obj/machinery/light/directional/north, -/obj/effect/turf_decal/trimline/red/filled/corner{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/cargo/storage) "ylQ" = ( /obj/machinery/door/firedoor, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -82353,7 +82334,7 @@ pOa rJS pOa jUb -lvY +jCs sZK heE kzZ @@ -86415,7 +86396,7 @@ paD jpG kRe nVG -qOZ +pDf hKg hKg ouu @@ -86454,7 +86435,7 @@ vsr wfZ soa pOa -myZ +aFz sXI sNM tYi @@ -86933,8 +86914,8 @@ poj hnV tPt gUH -dAk -dAk +omc +wBK rhn qnj iqt @@ -87185,17 +87166,17 @@ aZj cSP cLj kRe +kRe tid qTf -oor -oor -hDX -hrC -kuS -muq +hKg +cbz +cKD +wfp +aQb oRO -bgx -uYB +aok +pkM aok mml aok @@ -87442,17 +87423,17 @@ jXu hzb cLj kRe +kRe cBZ wyP -oor -jqr -xLA -hrC -hrC -mmR -kwh -iqt -nut +hKg +kyf +kFQ +xKh +eDO +kFb +aok +oNR aok pkM aok @@ -87697,18 +87678,18 @@ omV fhn cuh jBp -wsk +cLj +ydi qHt dxo hlE -oor -aKN -uha -tMY -hDX +hKg +ljT +jrQ +qlh +oHm +sOE aok -sbP -bgx aok aok xtH @@ -87954,18 +87935,18 @@ cAf dve jXu pVV -qqr +cLj +cUt iId tkf wZo -oor -hvo -uwM -uwf -oor -ylO -tYU -hLL +hKg +rgW +nkq +bNw +nxI +gsV +dfk dfk dfk rQD @@ -88215,14 +88196,14 @@ oMx hKg hKg hKg -oor -jmR -hWK -fea -iHS -cqy -ebg -ebg +hKg +hKg +sJq +oOY +aCO +oRx +sAt +fwb fwb kQO qvV @@ -88456,9 +88437,9 @@ pma pma pma hZQ +hlT jXu -jXu -hsx +tIU jXu jXu jXu @@ -88477,7 +88458,7 @@ jXu jXu jXu cbz -bLY +lcI gQa dit uBj @@ -88491,10 +88472,10 @@ xgx rzo quT iev -gPN +pjX ebd ebd -jBy +bfw iev iev bBy @@ -88711,14 +88692,14 @@ aaa aaa aaa aaa -tdg -hkj -sQp -kuW -qHa -ujT -dYi -iDG +nmg +haZ +uSh +fzo +rNP +ieD +ssu +ggW jXu fpn knQ @@ -88744,11 +88725,11 @@ cgZ hIp ksM lQf -vKC -fwd -mwP -oTw -nLx +wsx +dsJ +npX +dtw +lzD sHX uyh hvB @@ -88968,14 +88949,14 @@ aaa aaa aaa aaa -tdg -hkj -hkj -kuW -uth -xBq -mUF -obF +nmg +gOO +rMd +eVG +rkX +wwN +aZz +kgZ jXu fpn jXu @@ -89005,9 +88986,9 @@ kkB lVp bzH bzH -mzj -sml -rmL +rGk +xRO +rNA hOh lAi bzH @@ -89225,14 +89206,14 @@ sjP sjP lMJ lMJ -tdg -hkj -xQO -dfU -ikL -qST -xMx -qrF +nmg +vUL +xSc +pnl +xgB +yfX +pGJ +fMa jXu vxO jXu @@ -89256,16 +89237,16 @@ nwm izI kQP eRd -vlP +cIl qxJ vNp -hvk -bzH -dGC -uud -wbW -fWn -jHW +erU +aqG +uuW +pPm +jHM +hCh +exB vjU bzH buH @@ -89482,14 +89463,14 @@ dMH sjP aaa aaa -tdg -tdg -tdg -fru -elz -uzb -phP -rgL +nmg +nmg +nmg +jXu +tjt +aUU +uQm +jzq jXu paU jXu @@ -89517,12 +89498,12 @@ rVn qxJ sik ryV -paQ -wyS -ekb -wpO +mhM +qCx +cap +wbW wbW -ubn +ygk hld iev rKI @@ -89774,12 +89755,12 @@ aUm jvv bNN rod -mhM -dfK -wuo -tPW -ayz -bLj +sgZ +gav +hab +uyP +ejD +rUd rnh iev nJJ @@ -90030,15 +90011,15 @@ vdW oac fhB hxd -dHz -aqG -geR -ekb -lsU -bQl -pCs -bzH -bzH +rtG +oor +xJy +wme +oor +xbu +sZT +oor +oor pNk ivB qaw @@ -90287,15 +90268,15 @@ pUk upN qxJ ajq -eml -bzH -bvl -nKu -gxM -jRo -qCx -roG -bzH +vwg +afW +agd +rBB +kJk +xJj +gZq +aiy +afW mnP tEr iOc @@ -90530,7 +90511,7 @@ okj rlU qYC pNC -lpt +qme cNg kQP kQP @@ -90545,17 +90526,17 @@ hIu liX jUs nDG -bzH -bzH -usJ -kFa -lak -rUd -cXE -ykb -cJS -ybn -fLp +oor +oor +oby +kDb +imT +gPw +qNL +fEV +pVK +xOw +uCR sVY sDT mjr @@ -90803,13 +90784,13 @@ isA eKG iit pWb -bzH -wTv -sul -pkF -dtE -dSH -aqG +afW +kkA +fMC +uYE +iQb +hRJ +afW mnP xOw iOc @@ -91060,13 +91041,13 @@ lgg uLE cSu nPN -bzH -aqG -aqG -mxx -aqG -aqG -aqG +oor +afW +afW +pog +oor +afW +afW uGU mFo npY @@ -91796,7 +91777,7 @@ hDE wZz wZz wZz -sjP +qHW iPb iPb uza @@ -93628,7 +93609,7 @@ aaa ihq ooP hZZ -rPO +dfa gmI aKb xel @@ -104419,7 +104400,7 @@ pJE pJE nFn uUl -qJH +oYs qXB wzK tcC diff --git a/_maps/map_files/Mining/Lavaland.dmm b/_maps/map_files/Mining/Lavaland.dmm index 01234def93289..caa7913d2fc20 100644 --- a/_maps/map_files/Mining/Lavaland.dmm +++ b/_maps/map_files/Mining/Lavaland.dmm @@ -8836,7 +8836,7 @@ /area/mine/laborcamp/security) "Ya" = ( /obj/machinery/vending/security{ - onstation_override = 1 + all_products_free = 0 }, /obj/effect/turf_decal/trimline/red/filled/line{ dir = 10 diff --git a/_maps/map_files/NorthStar/north_star.dmm b/_maps/map_files/NorthStar/north_star.dmm index 0d591a0ea0e1b..cafc8754cd887 100644 --- a/_maps/map_files/NorthStar/north_star.dmm +++ b/_maps/map_files/NorthStar/north_star.dmm @@ -52888,7 +52888,7 @@ /area/station/hallway/secondary/exit) "nDj" = ( /obj/machinery/door/firedoor, -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /turf/open/floor/plating, /area/station/medical/abandoned) "nDk" = ( @@ -55522,7 +55522,7 @@ /turf/open/floor/pod/light, /area/station/maintenance/floor2/port/fore) "omh" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /turf/open/floor/wood/tile, /area/station/command/heads_quarters/captain/private) "omj" = ( @@ -67719,7 +67719,7 @@ /turf/open/floor/pod/light, /area/station/maintenance/floor1/starboard/fore) "rtH" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /obj/effect/decal/cleanable/dirt, /turf/open/floor/wood, /area/station/service/abandoned_gambling_den) diff --git a/_maps/map_files/debug/runtimestation.dmm b/_maps/map_files/debug/runtimestation.dmm index dfab71ec7974e..280fcdfc858e7 100644 --- a/_maps/map_files/debug/runtimestation.dmm +++ b/_maps/map_files/debug/runtimestation.dmm @@ -2541,8 +2541,7 @@ "Xg" = ( /obj/machinery/light/directional/east, /obj/machinery/vending/syndichem{ - onstation = 0; - req_access = null + onstation = 0 }, /turf/open/floor/iron, /area/station/medical/chemistry) diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index bcf24651157e8..9480252ff1386 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -56951,7 +56951,7 @@ /turf/closed/wall, /area/station/maintenance/port/aft) "tdR" = ( -/obj/machinery/vending/autodrobe/all_access, +/obj/machinery/vending/autodrobe, /obj/effect/turf_decal/tile/blue/opposingcorners{ dir = 1 }, diff --git a/_maps/map_files/wawastation/wawastation.dmm b/_maps/map_files/wawastation/wawastation.dmm index 47ed0380935d8..59c71329b21fb 100644 --- a/_maps/map_files/wawastation/wawastation.dmm +++ b/_maps/map_files/wawastation/wawastation.dmm @@ -15077,7 +15077,7 @@ /turf/open/floor/iron, /area/station/hallway/primary/central) "ftK" = ( -/obj/machinery/vending/autodrobe/all_access, +/obj/machinery/vending/autodrobe, /obj/effect/turf_decal/tile/red/half/contrasted, /obj/machinery/firealarm/directional/south, /turf/open/floor/iron/dark, @@ -33124,7 +33124,7 @@ /area/station/hallway/secondary/exit/departure_lounge) "lIZ" = ( /obj/effect/turf_decal/sand/plating, -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /turf/open/floor/plating, /area/station/maintenance/central/greater) "lJo" = ( @@ -34147,7 +34147,7 @@ /turf/open/floor/iron, /area/station/cargo/lobby) "mds" = ( -/obj/machinery/vending/autodrobe/all_access, +/obj/machinery/vending/autodrobe, /obj/effect/turf_decal/tile/neutral/fourcorners, /obj/effect/turf_decal/delivery, /obj/machinery/camera/autoname/directional/west, diff --git a/_maps/shuttles/emergency_cruise.dmm b/_maps/shuttles/emergency_cruise.dmm index c111505c14789..13b160b653190 100644 --- a/_maps/shuttles/emergency_cruise.dmm +++ b/_maps/shuttles/emergency_cruise.dmm @@ -220,7 +220,7 @@ /turf/open/floor/iron, /area/shuttle/escape) "fL" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /turf/open/floor/carpet/executive, /area/shuttle/escape) "fY" = ( @@ -2262,7 +2262,7 @@ /turf/template_noop, /area/shuttle/escape) "Xu" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /obj/effect/turf_decal/siding/wood{ dir = 1 }, diff --git a/_maps/shuttles/emergency_humpback.dmm b/_maps/shuttles/emergency_humpback.dmm index f76d06925a343..195f342cd3caa 100644 --- a/_maps/shuttles/emergency_humpback.dmm +++ b/_maps/shuttles/emergency_humpback.dmm @@ -115,7 +115,7 @@ /area/shuttle/escape/brig) "gW" = ( /obj/structure/window/reinforced/plasma/spawner/directional/east, -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /turf/open/floor/mineral/plastitanium, /area/shuttle/escape) "hd" = ( diff --git a/_maps/shuttles/emergency_imfedupwiththisworld.dmm b/_maps/shuttles/emergency_imfedupwiththisworld.dmm index 6513f090c53c8..cf53733c42351 100644 --- a/_maps/shuttles/emergency_imfedupwiththisworld.dmm +++ b/_maps/shuttles/emergency_imfedupwiththisworld.dmm @@ -30,9 +30,7 @@ /area/shuttle/escape) "k" = ( /obj/machinery/light/directional/east, -/obj/machinery/vending/boozeomat{ - req_access = null - }, +/obj/machinery/vending/boozeomat, /obj/effect/turf_decal/tile/bar/opposingcorners, /turf/open/floor/iron, /area/shuttle/escape) diff --git a/_maps/shuttles/emergency_luxury.dmm b/_maps/shuttles/emergency_luxury.dmm index 74b18ef61b4de..1e1ae99d2ea5b 100644 --- a/_maps/shuttles/emergency_luxury.dmm +++ b/_maps/shuttles/emergency_luxury.dmm @@ -589,7 +589,7 @@ /turf/open/floor/carpet/green, /area/shuttle/escape/luxury) "zq" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /turf/closed/indestructible/riveted/plastinum/nodiagonal, /area/shuttle/escape/brig) "zt" = ( diff --git a/_maps/shuttles/emergency_tranquility.dmm b/_maps/shuttles/emergency_tranquility.dmm index 4563d89631cd6..ae3924becbc02 100644 --- a/_maps/shuttles/emergency_tranquility.dmm +++ b/_maps/shuttles/emergency_tranquility.dmm @@ -453,7 +453,7 @@ /area/shuttle/escape) "jb" = ( /obj/machinery/barsign/all_access/directional/north, -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /turf/open/floor/stone, /area/shuttle/escape) "jl" = ( diff --git a/_maps/shuttles/hunter_mi13_foodtruck.dmm b/_maps/shuttles/hunter_mi13_foodtruck.dmm index 5fe7324e8e83b..6ece8822d802a 100644 --- a/_maps/shuttles/hunter_mi13_foodtruck.dmm +++ b/_maps/shuttles/hunter_mi13_foodtruck.dmm @@ -123,7 +123,7 @@ /turf/open/floor/circuit/red/off, /area/shuttle/hunter/mi13_foodtruck) "eA" = ( -/obj/machinery/vending/medical/syndicate_access/cybersun, +/obj/machinery/vending/medical/syndicate/cybersun, /obj/machinery/airalarm/directional/west, /obj/effect/mapping_helpers/airalarm/syndicate_access, /turf/open/floor/circuit/red/off, diff --git a/_maps/shuttles/infiltrator_advanced.dmm b/_maps/shuttles/infiltrator_advanced.dmm index 9f93df25b0479..1800d638fc540 100644 --- a/_maps/shuttles/infiltrator_advanced.dmm +++ b/_maps/shuttles/infiltrator_advanced.dmm @@ -710,7 +710,7 @@ /area/shuttle/syndicate/eva) "bP" = ( /obj/effect/turf_decal/bot, -/obj/machinery/vending/medical/syndicate_access, +/obj/machinery/vending/medical/syndicate, /turf/open/floor/mineral/plastitanium, /area/shuttle/syndicate/medical) "bQ" = ( diff --git a/_maps/shuttles/pirate_default.dmm b/_maps/shuttles/pirate_default.dmm index 43c72a9d2bfa3..182f51ad3b6a2 100644 --- a/_maps/shuttles/pirate_default.dmm +++ b/_maps/shuttles/pirate_default.dmm @@ -567,9 +567,7 @@ /turf/open/floor/iron, /area/shuttle/pirate) "bH" = ( -/obj/machinery/vending/boozeomat/all_access{ - onstation = 0 - }, +/obj/machinery/vending/boozeomat, /obj/effect/turf_decal/tile/bar/opposingcorners, /turf/open/floor/iron, /area/shuttle/pirate) diff --git a/_maps/shuttles/pirate_dutchman.dmm b/_maps/shuttles/pirate_dutchman.dmm index 1d1a0b0902b86..a00fff6e7e9fb 100644 --- a/_maps/shuttles/pirate_dutchman.dmm +++ b/_maps/shuttles/pirate_dutchman.dmm @@ -359,10 +359,33 @@ }, /turf/open/floor/carpet/blue/airless, /area/shuttle/pirate/flying_dutchman) +"nb" = ( +/obj/structure/mounted_gun/canister_gatling, +/turf/open/floor/wood/airless, +/area/shuttle/pirate/flying_dutchman) "pG" = ( /obj/structure/window/reinforced/shuttle/survival_pod, /turf/open/floor/wood/airless, /area/shuttle/pirate/flying_dutchman) +"qG" = ( +/obj/item/ammo_casing/canister_shot{ + pixel_y = 8; + pixel_x = -8 + }, +/obj/item/ammo_casing/canister_shot{ + pixel_y = -8; + pixel_x = -8 + }, +/obj/item/ammo_casing/canister_shot{ + pixel_x = 6; + pixel_y = -8 + }, +/obj/item/ammo_casing/canister_shot{ + pixel_y = 8; + pixel_x = 6 + }, +/turf/open/floor/wood/airless, +/area/shuttle/pirate/flying_dutchman) "rd" = ( /obj/effect/turf_decal/siding/wood/corner, /obj/effect/turf_decal/siding/wood/corner{ @@ -1234,7 +1257,7 @@ fW St QM da -WB +nb WB RQ eG @@ -1261,7 +1284,7 @@ km sC mG bn -WB +qG WB xY WR diff --git a/_maps/shuttles/pirate_ex_interdyne.dmm b/_maps/shuttles/pirate_ex_interdyne.dmm index 4036972b7a87a..3896e755f85d9 100644 --- a/_maps/shuttles/pirate_ex_interdyne.dmm +++ b/_maps/shuttles/pirate_ex_interdyne.dmm @@ -775,7 +775,7 @@ /area/shuttle/pirate) "OL" = ( /obj/effect/turf_decal/tile/dark_blue/half/contrasted, -/obj/machinery/vending/medical/syndicate_access, +/obj/machinery/vending/medical/syndicate, /turf/open/floor/iron/dark, /area/shuttle/pirate) "Po" = ( diff --git a/_maps/shuttles/pirate_grey.dmm b/_maps/shuttles/pirate_grey.dmm index db02acbdd48f5..50594b83d9b59 100644 --- a/_maps/shuttles/pirate_grey.dmm +++ b/_maps/shuttles/pirate_grey.dmm @@ -183,7 +183,7 @@ /turf/open/floor/plating, /area/shuttle/pirate) "gQ" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /turf/closed/wall, /area/shuttle/pirate) "hk" = ( diff --git a/_maps/shuttles/pirate_irs.dmm b/_maps/shuttles/pirate_irs.dmm index 4fd5a8c357342..c78c73a75380e 100644 --- a/_maps/shuttles/pirate_irs.dmm +++ b/_maps/shuttles/pirate_irs.dmm @@ -946,9 +946,7 @@ }, /area/shuttle/pirate) "Cf" = ( -/obj/machinery/vending/autodrobe{ - onstation = 0 - }, +/obj/machinery/vending/autodrobe, /obj/effect/turf_decal/siding/dark_green{ dir = 6 }, @@ -1642,9 +1640,7 @@ /turf/open/floor/wood, /area/shuttle/pirate) "QT" = ( -/obj/machinery/vending/boozeomat/all_access{ - onstation = 0 - }, +/obj/machinery/vending/boozeomat, /turf/closed/wall/mineral/titanium, /area/shuttle/pirate) "QV" = ( diff --git a/_maps/shuttles/pirate_silverscale.dmm b/_maps/shuttles/pirate_silverscale.dmm index 6d9c7537bde18..b95c32be7d1e7 100644 --- a/_maps/shuttles/pirate_silverscale.dmm +++ b/_maps/shuttles/pirate_silverscale.dmm @@ -492,9 +492,7 @@ /turf/open/floor/iron/dark, /area/shuttle/pirate) "CW" = ( -/obj/machinery/vending/boozeomat/all_access{ - onstation = 0 - }, +/obj/machinery/vending/boozeomat, /turf/open/floor/iron/dark/textured, /area/shuttle/pirate) "DX" = ( @@ -967,9 +965,7 @@ /turf/open/floor/carpet/royalblack, /area/shuttle/pirate) "XB" = ( -/obj/machinery/vending/boozeomat/all_access{ - onstation = 0 - }, +/obj/machinery/vending/boozeomat, /obj/machinery/light/small/directional/south, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ dir = 10 diff --git a/_maps/shuttles/whiteship_box.dmm b/_maps/shuttles/whiteship_box.dmm index 8aa60f4e93bd2..ed2e2a17b9077 100644 --- a/_maps/shuttles/whiteship_box.dmm +++ b/_maps/shuttles/whiteship_box.dmm @@ -1272,9 +1272,7 @@ /area/shuttle/abandoned/medbay) "cL" = ( /obj/effect/decal/cleanable/dirt, -/obj/machinery/vending/medical{ - req_access = null - }, +/obj/machinery/vending/medical, /obj/machinery/airalarm/directional/north, /obj/effect/mapping_helpers/airalarm/all_access, /turf/open/floor/iron/white, diff --git a/_maps/shuttles/whiteship_cere.dmm b/_maps/shuttles/whiteship_cere.dmm index df697dc1739c1..fbcca99889a4e 100644 --- a/_maps/shuttles/whiteship_cere.dmm +++ b/_maps/shuttles/whiteship_cere.dmm @@ -581,7 +581,7 @@ /turf/open/floor/pod/dark, /area/shuttle/abandoned/cargo) "CC" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /obj/effect/decal/cleanable/dirt, /obj/machinery/airalarm/directional/east, /obj/effect/mapping_helpers/airalarm/unlocked, diff --git a/_maps/shuttles/whiteship_delta.dmm b/_maps/shuttles/whiteship_delta.dmm index efc2302379730..f75f87001b517 100644 --- a/_maps/shuttles/whiteship_delta.dmm +++ b/_maps/shuttles/whiteship_delta.dmm @@ -101,7 +101,7 @@ /turf/open/floor/plating, /area/shuttle/abandoned/crew) "ap" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, diff --git a/_maps/shuttles/whiteship_obelisk.dmm b/_maps/shuttles/whiteship_obelisk.dmm index 0f1e07b1a213e..9a680e80e2b08 100644 --- a/_maps/shuttles/whiteship_obelisk.dmm +++ b/_maps/shuttles/whiteship_obelisk.dmm @@ -732,9 +732,7 @@ /turf/open/floor/mineral/titanium/white, /area/shuttle/abandoned/medbay) "Qp" = ( -/obj/machinery/vending/medical{ - req_access = null - }, +/obj/machinery/vending/medical, /turf/open/floor/mineral/titanium/white, /area/shuttle/abandoned/medbay) "RG" = ( diff --git a/_maps/templates/battlecruiser_starfury.dmm b/_maps/templates/battlecruiser_starfury.dmm index 59d6b325fdaac..15d7485c99bf3 100644 --- a/_maps/templates/battlecruiser_starfury.dmm +++ b/_maps/templates/battlecruiser_starfury.dmm @@ -1061,7 +1061,7 @@ }, /area/shuttle/sbc_starfury) "ea" = ( -/obj/machinery/vending/medical/syndicate_access/cybersun, +/obj/machinery/vending/medical/syndicate/cybersun, /turf/open/floor/iron, /area/shuttle/sbc_starfury) "ec" = ( @@ -1723,7 +1723,7 @@ /turf/open/floor/pod/light, /area/shuttle/sbc_starfury) "gH" = ( -/obj/machinery/vending/boozeomat/syndicate_access, +/obj/machinery/vending/boozeomat/syndicate, /obj/effect/turf_decal/siding/wood{ dir = 8 }, diff --git a/_maps/templates/lazy_templates/wizard_den.dmm b/_maps/templates/lazy_templates/wizard_den.dmm index 887e1c0817639..a909cc94c23b2 100644 --- a/_maps/templates/lazy_templates/wizard_den.dmm +++ b/_maps/templates/lazy_templates/wizard_den.dmm @@ -665,9 +665,6 @@ /turf/open/floor/engine/cult, /area/centcom/wizard_station) "KL" = ( -/obj/structure/railing{ - dir = 8 - }, /obj/structure/railing{ dir = 8 }, diff --git a/_maps/templates/shelter_3.dmm b/_maps/templates/shelter_3.dmm index d4681507a37e4..2bae50e8ba790 100644 --- a/_maps/templates/shelter_3.dmm +++ b/_maps/templates/shelter_3.dmm @@ -35,9 +35,7 @@ /turf/open/floor/pod/dark, /area/misc/survivalpod) "h" = ( -/obj/machinery/vending/boozeomat/all_access{ - onstation = 0 - }, +/obj/machinery/vending/boozeomat, /turf/open/floor/pod/dark, /area/misc/survivalpod) "i" = ( @@ -146,9 +144,7 @@ /turf/open/floor/carpet/black, /area/misc/survivalpod) "z" = ( -/obj/machinery/vending/cigarette{ - onstation = 0 - }, +/obj/machinery/vending/cigarette, /turf/open/floor/carpet/black, /area/misc/survivalpod) "A" = ( @@ -226,10 +222,7 @@ /turf/open/floor/carpet/black, /area/misc/survivalpod) "L" = ( -/obj/machinery/vending/snack/blue{ - req_access = null; - onstation = 0 - }, +/obj/machinery/vending/snack/blue, /turf/open/floor/carpet/black, /area/misc/survivalpod) "M" = ( diff --git a/_maps/virtual_domains/island_brawl.dmm b/_maps/virtual_domains/island_brawl.dmm index c9010062f54b1..62a63f81bab2e 100644 --- a/_maps/virtual_domains/island_brawl.dmm +++ b/_maps/virtual_domains/island_brawl.dmm @@ -3416,7 +3416,7 @@ /turf/open/floor/wood/parquet, /area/virtual_domain) "QX" = ( -/obj/machinery/vending/boozeomat/all_access{ +/obj/machinery/vending/boozeomat{ desc = "A technological marvel, supposedly able to mix just the mixture you'd like to drink the moment you ask for one. May not work for bartenders that don't have Nanotrasen bank accounts." }, /turf/open/floor/wood/large, @@ -3808,7 +3808,7 @@ /turf/open/floor/iron/dark/diagonal, /area/virtual_domain) "Uk" = ( -/obj/machinery/vending/autodrobe/all_access, +/obj/machinery/vending/autodrobe, /turf/open/misc/beach/sand, /area/virtual_domain/fullbright) "Um" = ( diff --git a/_maps/virtual_domains/meta_central.dmm b/_maps/virtual_domains/meta_central.dmm index bf821cc6e3433..2fc87ae17c818 100644 --- a/_maps/virtual_domains/meta_central.dmm +++ b/_maps/virtual_domains/meta_central.dmm @@ -112,7 +112,7 @@ /turf/open/floor/iron/dark, /area/virtual_domain) "aT" = ( -/obj/effect/mob_spawn/ghost_role/human/pirate/skeleton/captain, +/obj/effect/mob_spawn/ghost_role/human/virtual_domain/pirate, /turf/open/floor/plating, /area/virtual_domain) "aV" = ( @@ -4413,14 +4413,14 @@ /area/virtual_domain) "Lq" = ( /obj/structure/table/reinforced, -/obj/item/clothing/glasses/hud/security/night{ - pixel_x = -8; - pixel_y = -6 +/obj/item/clothing/glasses/night/colorless{ + pixel_x = 5; + pixel_y = 7 }, -/obj/item/clothing/glasses/hud/security/night, -/obj/item/clothing/glasses/hud/security/night{ - pixel_x = 8; - pixel_y = 8 +/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) @@ -5023,7 +5023,7 @@ /turf/open/floor/iron, /area/virtual_domain) "PR" = ( -/obj/machinery/vending/boozeomat/syndicate_access, +/obj/machinery/vending/boozeomat/syndicate, /obj/effect/turf_decal/tile/bar, /turf/open/floor/iron, /area/virtual_domain) diff --git a/_maps/virtual_domains/syndicate_assault.dmm b/_maps/virtual_domains/syndicate_assault.dmm index d825152e480e7..d8c63675d77b2 100644 --- a/_maps/virtual_domains/syndicate_assault.dmm +++ b/_maps/virtual_domains/syndicate_assault.dmm @@ -1103,7 +1103,7 @@ /turf/open/floor/iron/dark, /area/virtual_domain) "SX" = ( -/obj/machinery/vending/medical/syndicate_access/cybersun, +/obj/machinery/vending/medical/syndicate/cybersun, /turf/open/floor/plastic, /area/virtual_domain) "TB" = ( diff --git a/code/__DEFINES/_flags.dm b/code/__DEFINES/_flags.dm index 687f5365f6d4a..9b3b239034b96 100644 --- a/code/__DEFINES/_flags.dm +++ b/code/__DEFINES/_flags.dm @@ -140,6 +140,8 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define BINARY_JAMMING (1<<17) /// This area prevents Bag of Holding rifts from being opened. #define NO_BOH (1<<18) +/// This area prevents fishing from removing unique/limited loot from sources that're also used outside of it. +#define UNLIMITED_FISHING (1<<19) /* These defines are used specifically with the atom/pass_flags bitmask diff --git a/code/__DEFINES/atom_hud.dm b/code/__DEFINES/atom_hud.dm index 1af3003bb8577..57dc338d3ebc3 100644 --- a/code/__DEFINES/atom_hud.dm +++ b/code/__DEFINES/atom_hud.dm @@ -81,6 +81,7 @@ #define SECHUD_ASSISTANT "hudassistant" #define SECHUD_ATMOSPHERIC_TECHNICIAN "hudatmospherictechnician" #define SECHUD_BARTENDER "hudbartender" +#define SECHUD_BUSSER "hudbusser" #define SECHUD_BITAVATAR "hudbitavatar" #define SECHUD_BITRUNNER "hudbitrunner" #define SECHUD_BOTANIST "hudbotanist" diff --git a/code/__DEFINES/chat.dm b/code/__DEFINES/chat.dm index f4f88df6c706e..40f342df26834 100644 --- a/code/__DEFINES/chat.dm +++ b/code/__DEFINES/chat.dm @@ -45,6 +45,8 @@ #define debug_world_log(msg) if (GLOB.Debug2) log_world("DEBUG: [msg]") /// Adds a generic box around whatever message you're sending in chat. Really makes things stand out. #define examine_block(str) ("
" + str + "
") +/// Makes a fieldset with a name in the middle top part. Can apply additional classes +#define fieldset_block(title, content, classes) ("
" + title + "
" + content + "
") /// Makes a horizontal line with text in the middle #define separator_hr(str) ("
" + str + "
") /// Emboldens runechat messages diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index 60cd3a7b018b7..439d803fb942d 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -76,15 +76,12 @@ #define CANUNCONSCIOUS (1<<2) /// If set, this mob can be grabbed or pushed when bumped into #define CANPUSH (1<<3) -/// Mob godmode. Prevents most statuses and damage from being taken, but is more often than not a crapshoot. Use with caution. -#define GODMODE (1<<4) DEFINE_BITFIELD(status_flags, list( "CAN STUN" = CANSTUN, "CAN KNOCKDOWN" = CANKNOCKDOWN, "CAN UNCONSCIOUS" = CANUNCONSCIOUS, "CAN PUSH" = CANPUSH, - "GOD MODE" = GODMODE, )) //Health Defines diff --git a/code/__DEFINES/crafting.dm b/code/__DEFINES/crafting.dm index 54dc479aa7306..cb7930e9d1fb6 100644 --- a/code/__DEFINES/crafting.dm +++ b/code/__DEFINES/crafting.dm @@ -28,6 +28,10 @@ #define CRAFT_CHECK_DENSITY (1<<5) /// If the created atom will gain custom mat datums #define CRAFT_APPLIES_MATS (1<<6) +/// Crafting passes reagents of components to the finished product +#define CRAFT_TRANSFERS_REAGENTS (1<<7) +/// Crafting clears all reagents present in the finished product +#define CRAFT_CLEARS_REAGENTS (1<<8) //food/drink crafting defines //When adding new defines, please make sure to also add them to the encompassing list diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm index 3282c9387a1e5..2e42957aa3a08 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm @@ -9,6 +9,8 @@ #define COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON "atom_init_success_on" ///from base of atom/examine(): (/mob, list/examine_text) #define COMSIG_ATOM_EXAMINE "atom_examine" +///from base of atom/examine_tags(): (/mob, list/examine_tags) +#define COMSIG_ATOM_EXAMINE_TAGS "atom_examine_tags" ///from base of atom/get_examine_name(): (/mob, list/overrides) #define COMSIG_ATOM_GET_EXAMINE_NAME "atom_examine_name" //Positions for overrides list diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_x_act.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_x_act.dm index 6448be3fecb74..46e179ee567ba 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_x_act.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_x_act.dm @@ -89,7 +89,6 @@ /// Sent from [atom/proc/item_interaction], when this atom is used as a tool and an event occurs #define COMSIG_ITEM_TOOL_ACTED "tool_item_acted" -/// This is sent via item interaction (IE, item clicking on atom) right before the item's inserted into the atom's storage -/// Args: (obj/item/inserting, mob/living/user) -#define COMSIG_ATOM_STORAGE_ITEM_INTERACT_INSERT "atom_storage_item_interact_insert" - #define BLOCK_STORAGE_INSERT (1<<0) +/// from /obj/projectile/energy/fisher/on_hit() or /obj/item/gun/energy/recharge/fisher when striking a target +#define COMSIG_ATOM_SABOTEUR_ACT "hit_by_saboteur" + #define COMSIG_SABOTEUR_SUCCESS 1 diff --git a/code/__DEFINES/dcs/signals/signals_fish.dm b/code/__DEFINES/dcs/signals/signals_fish.dm index 8af3b8dfca79c..9b614f924549f 100644 --- a/code/__DEFINES/dcs/signals/signals_fish.dm +++ b/code/__DEFINES/dcs/signals/signals_fish.dm @@ -8,6 +8,13 @@ ///The item won't be inserted into the aquarium, but will early return attackby anyway. #define COMSIG_CANNOT_INSERT_IN_AQUARIUM (1<<1) +///Updates the appearance of a newly generated aquarium content visual:(visual) +#define COMSIG_AQUARIUM_CONTENT_GENERATE_APPEARANCE "aquarium_content_apply_appearance" +///Updates the base position of an aquarium content visual:(aquarium, visual) +#define AQUARIUM_CONTENT_RANDOMIZE_POSITION "aquarium_content_randomize_position" +///Updates the animation of an aquarium content visual:(aquarium, visual) +#define COMSIG_AQUARIUM_CONTENT_DO_ANIMATION "aquarium_content_do_animation" + // Fish signals #define COMSIG_FISH_STATUS_CHANGED "fish_status_changed" #define COMSIG_FISH_STIRRED "fish_stirred" @@ -15,19 +22,32 @@ #define COMSIG_FISH_LIFE "fish_life" ///From /datum/fish_trait/eat_fish: (predator) #define COMSIG_FISH_EATEN_BY_OTHER_FISH "fish_eaten_by_other_fish" +///From /obj/item/fish/generate_reagents_to_add, which returns a holder when the fish is eaten or composted for example: (list/reagents) +#define COMSIG_GENERATE_REAGENTS_TO_ADD "generate_reagents_to_add" ///From /obj/item/fish/feed: (fed_reagents, fed_reagent_type) #define COMSIG_FISH_FED "fish_on_fed" -///from /obj/item/fish/pet_fish -#define COMSIG_FISH_PETTED "fish_petted" ///From /obj/item/fish/update_size_and_weight: (new_size, new_weight) #define COMSIG_FISH_UPDATE_SIZE_AND_WEIGHT "fish_update_size_and_weight" ///From /obj/item/fish/update_fish_force: (weight_rank, bonus_malus) #define COMSIG_FISH_FORCE_UPDATED "fish_force_updated" +///From /obj/item/fish/interact_with_atom_secondary, sent to the target: (fish) +#define COMSIG_FISH_RELEASED_INTO "fish_released_into" + +///From /datum/fishing_challenge/New: (datum/fishing_challenge/challenge) +#define COMSIG_MOB_BEGIN_FISHING "mob_begin_fishing" +///From /datum/fishing_challenge/start_minigame_phase: (datum/fishing_challenge/challenge) +#define COMSIG_MOB_BEGIN_FISHING_MINIGAME "mob_begin_fishing_minigame" +///From /datum/fishing_challenge/completed: (datum/fishing_challenge/challenge, win) +#define COMSIG_MOB_COMPLETE_FISHING "mob_complete_fishing" + +/// Rolling a reward path for a fishing challenge +#define COMSIG_FISHING_CHALLENGE_ROLL_REWARD "fishing_roll_reward" +/// Adjusting the difficulty of a rishing challenge, often based on the reward path +#define COMSIG_FISHING_CHALLENGE_GET_DIFFICULTY "fishing_get_difficulty" /// Fishing challenge completed -#define COMSIG_FISHING_CHALLENGE_COMPLETED "fishing_completed" /// Sent to the fisherman when the reward is dispensed: (reward) -#define COMSIG_FISH_SOURCE_REWARD_DISPENSED "mob_fish_source_reward_dispensed" +#define COMSIG_FISH_SOURCE_REWARD_DISPENSED "fish_source_reward_dispensed" /// Called when you try to use fishing rod on anything #define COMSIG_PRE_FISHING "pre_fishing" diff --git a/code/__DEFINES/dcs/signals/signals_global_object.dm b/code/__DEFINES/dcs/signals/signals_global_object.dm index bed06ff176c1f..d100f47a3c97c 100644 --- a/code/__DEFINES/dcs/signals/signals_global_object.dm +++ b/code/__DEFINES/dcs/signals/signals_global_object.dm @@ -1,9 +1,9 @@ /// signals from globally accessible objects -///from SSJob whenever SetupOccupations() is called, all occupations are set +///from SSJob whenever setup_occupations() is called, all occupations are set #define COMSIG_OCCUPATIONS_SETUP "occupations_setup" -///from SSJob when DivideOccupations is called +///from SSJob when divide_occupations() is called #define COMSIG_OCCUPATIONS_DIVIDED "occupations_divided" ///from SSsun when the sun changes position : (azimuth) diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_ai.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_ai.dm index 16f7e00e78a19..1c6fcbffbda3d 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_ai.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_ai.dm @@ -11,3 +11,6 @@ #define COMSIG_BOT_RESET "bot_reset" ///Sent off /mob/living/basic/bot/proc/set_mode_flags() : (new_flags) #define COMSIG_BOT_MODE_FLAGS_SET "bot_mode_flags_set" + +///Signal sent off of ai/movement/proc/start_moving_towards +#define COMSIG_MOB_AI_MOVEMENT_STARTED "mob_ai_movement_started" diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm index 56d5ddf452471..b95ffba607fd3 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm @@ -118,7 +118,7 @@ ///Applied preferences to a human #define COMSIG_HUMAN_PREFS_APPLIED "human_prefs_applied" -///Whenever EquipRanked is called, called after job is set +///Whenever equip_rank is called, called after job is set #define COMSIG_JOB_RECEIVED "job_received" ///from /mob/living/carbon/human/proc/set_coretemperature(): (oldvalue, newvalue) #define COMSIG_HUMAN_CORETEMP_CHANGE "human_coretemp_change" diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm index 1b2d82ca9c5d7..5fe266bc3f0d1 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm @@ -140,6 +140,11 @@ #define SPEECH_SAYMODE 10 #define SPEECH_MODS 11 +///from /datum/component/speechmod/handle_speech(): () +#define COMSIG_TRY_MODIFY_SPEECH "try_modify_speech" + ///Return value if we prevent speech from being modified + #define PREVENT_MODIFY_SPEECH 1 + ///from /mob/say_dead(): (mob/speaker, message) #define COMSIG_MOB_DEADSAY "mob_deadsay" #define MOB_DEADSAY_SIGNAL_INTERCEPT (1<<0) diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_silicon.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_silicon.dm index 47f5b7485991b..aee6f2df79bb7 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_silicon.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_silicon.dm @@ -8,3 +8,12 @@ #define COMSIG_BORG_HUG_HANDLED 1 ///called from /mob/living/silicon/attack_hand proc #define COMSIG_MOB_PAT_BORG "mob_pat_borg" +///called when someone is inquiring about an AI's linked core +#define COMSIG_SILICON_AI_CORE_STATUS "AI_core_status" + #define COMPONENT_CORE_ALL_GOOD (1<<0) + #define COMPONENT_CORE_DISCONNECTED (1<<1) +///called when an AI (malf or perhaps combat upgraded or some other circumstance that has them inhabit +///an APC) enters an APC +#define COMSIG_SILICON_AI_OCCUPY_APC "AI_occupy_apc" +///called when an AI vacates an APC +#define COMSIG_SILICON_AI_VACATE_APC "AI_vacate_apc" diff --git a/code/__DEFINES/dcs/signals/signals_object.dm b/code/__DEFINES/dcs/signals/signals_object.dm index 797256017d456..1b167de3354d2 100644 --- a/code/__DEFINES/dcs/signals/signals_object.dm +++ b/code/__DEFINES/dcs/signals/signals_object.dm @@ -194,6 +194,8 @@ #define COMSIG_TOOL_IN_USE "tool_in_use" ///from base of [/obj/item/proc/tool_start_check]: (mob/living/user) #define COMSIG_TOOL_START_USE "tool_start_use" +/// From /obj/item/multitool/remove_buffer(): (buffer) +#define COMSIG_MULTITOOL_REMOVE_BUFFER "multitool_remove_buffer" ///from [/obj/item/proc/disableEmbedding]: #define COMSIG_ITEM_DISABLE_EMBED "item_disable_embed" ///from [/obj/effect/mine/proc/triggermine]: @@ -416,10 +418,6 @@ ///sent to the projectile when spawning the item (shrapnel) that may be embedded: (new_item) #define COMSIG_PROJECTILE_ON_SPAWN_EMBEDDED "projectile_on_spawn_embedded" -/// from /obj/projectile/energy/fisher/on_hit() or /obj/item/gun/energy/recharge/fisher when striking a target -#define COMSIG_HIT_BY_SABOTEUR "hit_by_saboteur" - #define COMSIG_SABOTEUR_SUCCESS (1<<0) - // /obj/vehicle/sealed/car/vim signals ///from /datum/action/vehicle/sealed/noise/chime/Trigger(): () diff --git a/code/__DEFINES/dcs/signals/signals_spell.dm b/code/__DEFINES/dcs/signals/signals_spell.dm index 8d02affded85a..08074116be2c3 100644 --- a/code/__DEFINES/dcs/signals/signals_spell.dm +++ b/code/__DEFINES/dcs/signals/signals_spell.dm @@ -68,6 +68,9 @@ #define COMSIG_SPELL_TOUCH_HAND_HIT "spell_touch_hand_cast" // Jaunt Spells +/// Sent from datum/action/cooldown/spell/jaunt/before_cast, before the mob enters jaunting as a pre-check: (datum/action/cooldown/spell/spell) +#define COMSIG_MOB_PRE_JAUNT "spell_mob_pre_jaunt" + #define COMPONENT_BLOCK_JAUNT (1<<0) /// Sent from datum/action/cooldown/spell/jaunt/enter_jaunt, to the mob jaunting: (obj/effect/dummy/phased_mob/jaunt, datum/action/cooldown/spell/spell) #define COMSIG_MOB_ENTER_JAUNT "spell_mob_enter_jaunt" /// Set from /obj/effect/dummy/phased_mob after the mob is ejected from its contents: (obj/effect/dummy/phased_mob/jaunt, mob/living/unjaunter) diff --git a/code/__DEFINES/fish.dm b/code/__DEFINES/fish.dm index 04557b4a8e606..43e0e8587f9aa 100644 --- a/code/__DEFINES/fish.dm +++ b/code/__DEFINES/fish.dm @@ -6,6 +6,11 @@ // Baseline fishing difficulty levels #define FISHING_DEFAULT_DIFFICULTY 15 #define FISHING_EASY_DIFFICULTY 10 +/** + * The minimum value of the difficulty of the minigame (unless it reaches 0 than it's auto-win) + * Any lower than this and the fish will be way too lethargic for the minigame to be engaging in the slightest. + */ +#define FISHING_MINIMUM_DIFFICULTY 6 /// Difficulty modifier when bait is fish's favorite #define FAV_BAIT_DIFFICULTY_MOD -5 @@ -136,12 +141,27 @@ #define FISH_WEIGHT_SLOWDOWN_EXPONENT 0.54 ///Used to calculate the force of the fish by comparing (1 + log(weight/this_define)) and the w_class of the item. #define FISH_WEIGHT_FORCE_DIVISOR 250 +///The multiplier used in the FISH_WEIGHT_BITE_DIVISOR define +#define FISH_WEIGHT_GRIND_TO_BITE_MULT 0.4 +///Used to calculate how many bites a fish can take and therefore the amount of reagents it has. +#define FISH_WEIGHT_BITE_DIVISOR (FISH_GRIND_RESULTS_WEIGHT_DIVISOR * FISH_WEIGHT_GRIND_TO_BITE_MULT) ///The breeding timeout for newly instantiated fish is multiplied by this. #define NEW_FISH_BREEDING_TIMEOUT_MULT 2 ///The last feeding timestamp of newly instantiated fish is multiplied by this: ergo, they spawn 50% hungry. #define NEW_FISH_LAST_FEEDING_MULT 0.5 +//IF YOU ADD ANY NEW FLAG, ADD IT TO THE RESPECTIVE BITFIELD in _globalvars/bitfields.dm TOO! + +///This fish is shown in the catalog and on the wiki (this only matters as an initial, compile-time value) +#define FISH_FLAG_SHOW_IN_CATALOG (1<<0) +///This fish has a flopping animation done through matrices +#define FISH_DO_FLOP_ANIM (1<<1) +///This fish has been petted in the last 30 seconds +#define FISH_FLAG_PETTED (1<<2) +///This fish can be scanned to complete fish scanning experiments +#define FISH_FLAG_EXPERIMENT_SCANNABLE (1<<3) + #define MIN_AQUARIUM_TEMP T0C #define MAX_AQUARIUM_TEMP (T0C + 100) #define DEFAULT_AQUARIUM_TEMP (T0C + 24) @@ -158,8 +178,8 @@ #define AQUARIUM_FLUID_SALTWATER "Saltwater" #define AQUARIUM_FLUID_SULPHWATEVER "Sulfuric Water" #define AQUARIUM_FLUID_AIR "Air" -#define AQUARIUM_FLUID_ANADROMOUS "Adaptive to both Freshwater and Saltwater" -#define AQUARIUM_FLUID_ANY_WATER "Adaptive to all kind of water" +#define AQUARIUM_FLUID_ANADROMOUS "Anadromous" +#define AQUARIUM_FLUID_ANY_WATER "Any Fluid" ///Fluff. The name of the aquarium company shown in the fish catalog #define AQUARIUM_COMPANY "Aquatech Ltd." @@ -185,10 +205,15 @@ /// The height of the minigame slider. Not in pixels, but minigame units. #define FISHING_MINIGAME_AREA 1000 +///The fish needs to be cooked for at least this long so that it can be safely eaten +#define FISH_SAFE_COOKING_DURATION 30 SECONDS + ///Defines for fish properties from the collect_fish_properties proc #define FISH_PROPERTIES_FAV_BAIT "fav_bait" #define FISH_PROPERTIES_BAD_BAIT "bad_bait" #define FISH_PROPERTIES_TRAITS "fish_traits" +#define FISH_PROPERTIES_BEAUTY_SCORE "beauty_score" +#define FISH_PROPERTIES_EVOLUTIONS "evolutions" ///Define for favorite and disliked baits that aren't just item typepaths. #define FISH_BAIT_TYPE "Type" @@ -196,3 +221,27 @@ #define FISH_BAIT_REAGENT "Reagent" #define FISH_BAIT_VALUE "Value" #define FISH_BAIT_AMOUNT "Amount" + + +///We multiply the weight of fish inside the loot table by this value if we are goofy enough to fish without a bait. +#define FISH_WEIGHT_MULT_WITHOUT_BAIT 0.15 + +/** + * A macro to ensure the wikimedia filenames of fish icons are unique, especially since there're a couple fish that have + * quite ambiguous names/icon_states like "checkered" or "pike" + */ +#define FISH_AUTOWIKI_FILENAME(fish) SANITIZE_FILENAME("[initial(fish.icon_state)]_wiki_fish") + +///The list keys for the autowiki for fish sources +#define FISH_SOURCE_AUTOWIKI_NAME "name" +#define FISH_SOURCE_AUTOWIKI_ICON "icon" +#define FISH_SOURCE_AUTOWIKI_WEIGHT "weight" +#define FISH_SOURCE_AUTOWIKI_WEIGHT_SUFFIX "weight_suffix" +#define FISH_SOURCE_AUTOWIKI_NOTES "notes" + +///Special value for the name key that always comes first when the data is sorted, regardless of weight. +#define FISH_SOURCE_AUTOWIKI_DUD "Nothing" +///Special value for the name key that always comes last +#define FISH_SOURCE_AUTOWIKI_OTHER "Other Stuff" +///The filename for the icon for "other stuff" which we don't articulate about on the autowiki +#define FISH_SOURCE_AUTOWIKI_QUESTIONMARK "questionmark" diff --git a/code/__DEFINES/food.dm b/code/__DEFINES/food.dm index c9b7cb43cf0d9..b7e5b38482d16 100644 --- a/code/__DEFINES/food.dm +++ b/code/__DEFINES/food.dm @@ -170,12 +170,21 @@ GLOBAL_LIST_INIT(food_buffs, list( #define FOOD_IN_CONTAINER (1<<0) /// Finger food can be eaten while walking / running around #define FOOD_FINGER_FOOD (1<<1) +/// Examining this edible won't show infos on food types, bites and remote tasting etc. +#define FOOD_NO_EXAMINE (1<<2) +/// This food item doesn't track bitecounts, use responsibly. +#define FOOD_NO_BITECOUNT (1<<3) DEFINE_BITFIELD(food_flags, list( "FOOD_FINGER_FOOD" = FOOD_FINGER_FOOD, "FOOD_IN_CONTAINER" = FOOD_IN_CONTAINER, + "FOOD_NO_EXAMINE" = FOOD_NO_EXAMINE, + "FOOD_NO_BITECOUNT" = FOOD_NO_BITECOUNT, )) +///Define for return value of the after_eat callback that will call OnConsume if it hasn't already. +#define FOOD_AFTER_EAT_CONSUME_ANYWAY 2 + #define STOP_SERVING_BREAKFAST (15 MINUTES) #define FOOD_MEAT_HUMAN 50 diff --git a/code/__DEFINES/hud.dm b/code/__DEFINES/hud.dm index e762b406d1eb4..3c46589002475 100644 --- a/code/__DEFINES/hud.dm +++ b/code/__DEFINES/hud.dm @@ -77,7 +77,7 @@ #define ui_building "EAST-4:22,SOUTH:21" #define ui_language_menu "EAST-4:6,SOUTH:21" #define ui_navigate_menu "EAST-4:22,SOUTH:5" -#define ui_floor_menu "EAST-4:14,SOUTH:37" +#define ui_floor_changer "EAST-3:24, SOUTH+1:3" //Upper left (action buttons) #define ui_action_palette "WEST+0:23,NORTH-1:5" @@ -110,6 +110,9 @@ #define ui_living_pull "EAST-1:28,CENTER-3:15" #define ui_living_healthdoll "EAST-1:28,CENTER-1:15" +//Humans +#define ui_human_floor_changer "EAST-4:22, SOUTH+1:7" + //Drones #define ui_drone_drop "CENTER+1:18,SOUTH:5" #define ui_drone_pull "CENTER+1.5:2,SOUTH:5" @@ -132,7 +135,7 @@ #define ui_borg_alerts "CENTER+4:21,SOUTH:5" #define ui_borg_language_menu "CENTER+4:19,SOUTH+1:6" #define ui_borg_navigate_menu "CENTER+4:19,SOUTH+1:6" -#define ui_borg_floor_menu "CENTER+4:-13,SOUTH+1:6" +#define ui_borg_floor_changer "EAST-1:28,SOUTH+1:39" //Aliens #define ui_alien_health "EAST,CENTER-1:15" @@ -141,7 +144,6 @@ #define ui_alien_storage_r "CENTER+1:18,SOUTH:5" #define ui_alien_language_menu "EAST-4:20,SOUTH:5" #define ui_alien_navigate_menu "EAST-4:20,SOUTH:5" -#define ui_alien_floor_menu "EAST-4:-12,SOUTH:5" //AI #define ui_ai_core "BOTTOM:6,RIGHT-4" @@ -150,7 +152,6 @@ #define ui_ai_state_laws "BOTTOM:6,RIGHT-1" #define ui_ai_mod_int "BOTTOM:6,RIGHT" #define ui_ai_language_menu "BOTTOM+1:8,RIGHT-1:30" -#define ui_ai_floor_menu "BOTTOM+1:8,RIGHT-1:14" #define ui_ai_crew_monitor "BOTTOM:6,CENTER-1" #define ui_ai_crew_manifest "BOTTOM:6,CENTER" @@ -192,8 +193,8 @@ #define ui_ghost_teleport "SOUTH:6,CENTER:24" #define ui_ghost_pai "SOUTH: 6, CENTER+1:24" #define ui_ghost_minigames "SOUTH: 6, CENTER+2:24" -#define ui_ghost_language_menu "SOUTH: 22, CENTER+3:8" -#define ui_ghost_floor_menu "SOUTH: 6, CENTER+3:8" +#define ui_ghost_language_menu "SOUTH: 22, CENTER+3:22" +#define ui_ghost_floor_changer "SOUTH: 6, CENTER+3:23" //Blobbernauts #define ui_blobbernaut_overmind_health "EAST-1:28,CENTER+0:19" diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm index 3fdb5376aa723..ffba025270e42 100644 --- a/code/__DEFINES/inventory.dm +++ b/code/__DEFINES/inventory.dm @@ -110,6 +110,8 @@ DEFINE_BITFIELD(no_equip_flags, list( #define HIDEMUTWINGS (1<<13) ///hides belts and riggings #define HIDEBELT (1<<14) +///hides antennae +#define HIDEANTENNAE (1<<15) //bitflags for clothing coverage - also used for limbs #define HEAD (1<<0) diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 8846672efe1b7..38f39437fac75 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -279,6 +279,8 @@ GLOBAL_LIST_INIT(turfs_pass_meteor, typecacheof(list( #define is_reagent_container(O) (istype(O, /obj/item/reagent_containers)) +#define isapc(A) (istype(A, /obj/machinery/power/apc)) + //Assemblies #define isassembly(O) (istype(O, /obj/item/assembly)) diff --git a/code/__DEFINES/jobs.dm b/code/__DEFINES/jobs.dm index 2c3b151855cef..953e7648009b8 100644 --- a/code/__DEFINES/jobs.dm +++ b/code/__DEFINES/jobs.dm @@ -93,6 +93,7 @@ #define JOB_LAWYER "Lawyer" #define JOB_CHAPLAIN "Chaplain" #define JOB_PSYCHOLOGIST "Psychologist" +#define JOB_PUN_PUN "Pun Pun" //ERTs #define JOB_ERT_DEATHSQUAD "Death Commando" #define JOB_ERT_COMMANDER "Emergency Response Team Commander" @@ -136,31 +137,32 @@ #define JOB_DISPLAY_ORDER_LAWYER 12 #define JOB_DISPLAY_ORDER_CHAPLAIN 13 #define JOB_DISPLAY_ORDER_PSYCHOLOGIST 14 -#define JOB_DISPLAY_ORDER_AI 15 -#define JOB_DISPLAY_ORDER_CYBORG 16 -#define JOB_DISPLAY_ORDER_CHIEF_ENGINEER 17 -#define JOB_DISPLAY_ORDER_STATION_ENGINEER 18 -#define JOB_DISPLAY_ORDER_ATMOSPHERIC_TECHNICIAN 19 -#define JOB_DISPLAY_ORDER_QUARTERMASTER 20 -#define JOB_DISPLAY_ORDER_CARGO_TECHNICIAN 21 -#define JOB_DISPLAY_ORDER_SHAFT_MINER 22 -#define JOB_DISPLAY_ORDER_BITRUNNER 23 -#define JOB_DISPLAY_ORDER_CARGO_GORILLA 24 -#define JOB_DISPLAY_ORDER_CHIEF_MEDICAL_OFFICER 25 -#define JOB_DISPLAY_ORDER_MEDICAL_DOCTOR 26 -#define JOB_DISPLAY_ORDER_PARAMEDIC 27 -#define JOB_DISPLAY_ORDER_CHEMIST 28 -#define JOB_DISPLAY_ORDER_CORONER 29 -#define JOB_DISPLAY_ORDER_RESEARCH_DIRECTOR 30 -#define JOB_DISPLAY_ORDER_SCIENTIST 31 -#define JOB_DISPLAY_ORDER_ROBOTICIST 32 -#define JOB_DISPLAY_ORDER_GENETICIST 33 -#define JOB_DISPLAY_ORDER_HEAD_OF_SECURITY 34 -#define JOB_DISPLAY_ORDER_VETERAN_ADVISOR 35 -#define JOB_DISPLAY_ORDER_WARDEN 36 -#define JOB_DISPLAY_ORDER_DETECTIVE 37 -#define JOB_DISPLAY_ORDER_SECURITY_OFFICER 38 -#define JOB_DISPLAY_ORDER_PRISONER 39 +#define JOB_DISPLAY_ORDER_PUN_PUN 15 +#define JOB_DISPLAY_ORDER_AI 16 +#define JOB_DISPLAY_ORDER_CYBORG 17 +#define JOB_DISPLAY_ORDER_CHIEF_ENGINEER 18 +#define JOB_DISPLAY_ORDER_STATION_ENGINEER 19 +#define JOB_DISPLAY_ORDER_ATMOSPHERIC_TECHNICIAN 20 +#define JOB_DISPLAY_ORDER_QUARTERMASTER 21 +#define JOB_DISPLAY_ORDER_CARGO_TECHNICIAN 22 +#define JOB_DISPLAY_ORDER_SHAFT_MINER 23 +#define JOB_DISPLAY_ORDER_BITRUNNER 24 +#define JOB_DISPLAY_ORDER_CARGO_GORILLA 25 +#define JOB_DISPLAY_ORDER_CHIEF_MEDICAL_OFFICER 26 +#define JOB_DISPLAY_ORDER_MEDICAL_DOCTOR 27 +#define JOB_DISPLAY_ORDER_PARAMEDIC 28 +#define JOB_DISPLAY_ORDER_CHEMIST 29 +#define JOB_DISPLAY_ORDER_CORONER 30 +#define JOB_DISPLAY_ORDER_RESEARCH_DIRECTOR 31 +#define JOB_DISPLAY_ORDER_SCIENTIST 32 +#define JOB_DISPLAY_ORDER_ROBOTICIST 33 +#define JOB_DISPLAY_ORDER_GENETICIST 34 +#define JOB_DISPLAY_ORDER_HEAD_OF_SECURITY 35 +#define JOB_DISPLAY_ORDER_VETERAN_ADVISOR 36 +#define JOB_DISPLAY_ORDER_WARDEN 37 +#define JOB_DISPLAY_ORDER_DETECTIVE 38 +#define JOB_DISPLAY_ORDER_SECURITY_OFFICER 39 +#define JOB_DISPLAY_ORDER_PRISONER 40 #define DEPARTMENT_UNASSIGNED "No Department" @@ -203,7 +205,7 @@ DEFINE_BITFIELD(departments_bitflags, list( #define JOB_ANNOUNCE_ARRIVAL (1<<0) /// Whether the mob is added to the crew manifest. #define JOB_CREW_MANIFEST (1<<1) -/// Whether the mob is equipped through SSjob.EquipRank() on spawn. +/// Whether the mob is equipped through SSjob.equip_rank() on spawn. #define JOB_EQUIP_RANK (1<<2) /// Whether the job is considered a regular crew member of the station. Equipment such as AI and cyborgs not included. #define JOB_CREW_MEMBER (1<<3) diff --git a/code/__DEFINES/machines.dm b/code/__DEFINES/machines.dm index 56e39fd198899..25893cae63f72 100644 --- a/code/__DEFINES/machines.dm +++ b/code/__DEFINES/machines.dm @@ -139,6 +139,15 @@ /// Max length of a status line in the status display #define MAX_STATUS_LINE_LENGTH 40 +///Define for automated system arrival announcement +#define AUTO_ANNOUNCE_ARRIVAL "ARRIVAL" +///Define for automated system announcement when a head of staff arrives +#define AUTO_ANNOUNCE_NEWHEAD "NEWHEAD" +///Define for automated system announcement for when the arrival shuttle is broken +#define AUTO_ANNOUNCE_ARRIVALS_BROKEN "ARRIVALS_BROKEN" +///Define for automated system announcement for researched nodes +#define AUTO_ANNOUNCE_NODE "NODE" + /// Blank Status Display #define SD_BLANK 0 /// Shows the emergency shuttle timer diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 3a4e34463a27e..247a7a964c183 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -710,6 +710,10 @@ GLOBAL_LIST_INIT(human_heights_to_offsets, list( #define FRONT_MUTATIONS_LAYER 29 /// Damage indicators (cuts and burns) #define DAMAGE_LAYER 28 +/// DOPPLER SHIFT ADDITION BEGIN +/// Just below clothing layer +#define UNDER_UNIFORM_LAYER 27.5 +/// DOPPLER SHIFT ADDITION END /// Jumpsuit clothing layer #define UNIFORM_LAYER 27 /// DOPPLER SHIFT ADDITION BEGIN diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm index d6b62da97d470..5fb9d9447bbc0 100644 --- a/code/__DEFINES/preferences.dm +++ b/code/__DEFINES/preferences.dm @@ -80,6 +80,7 @@ //Job preferences levels +#define JP_ANY 0 #define JP_LOW 1 #define JP_MEDIUM 2 #define JP_HIGH 3 diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index ead7764d60523..121cf5a072d17 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -37,7 +37,7 @@ /// Does this by inverting the passed in flags and seeing if we're still incapacitated #define INCAPACITATED_IGNORING(mob, flags) (mob.incapacitated & ~(flags)) -/// Maxamounts of fire stacks a mob can get +/// Max amounts of fire stacks a mob can get #define MAX_FIRE_STACKS 20 /// If a mob has a higher threshold than this, the icon shown will be increased to the big fire icon. #define MOB_BIG_FIRE_STACK_THRESHOLD 3 diff --git a/code/__DEFINES/tools.dm b/code/__DEFINES/tools.dm index 2348bd49f194b..794c56691a6da 100644 --- a/code/__DEFINES/tools.dm +++ b/code/__DEFINES/tools.dm @@ -39,3 +39,16 @@ /// Combination flag for any item interaction that blocks the rest of the attack chain #define ITEM_INTERACT_ANY_BLOCKER (ITEM_INTERACT_SUCCESS | ITEM_INTERACT_BLOCKING) + +/// How many seconds between each fuel depletion tick ("use" proc) +#define TOOL_FUEL_BURN_INTERVAL 5 + +///This is a number I got by quickly searching up the temperature to melt iron/glass, though not really realistic. +///This is used for places where lighters should not be hot enough to be used as a welding tool on. +#define HIGH_TEMPERATURE_REQUIRED 1500 + +/** + * A helper for checking if an item interaction should be skipped. + * This is only used explicitly because some interactions may not want to ever be skipped. + */ +#define SHOULD_SKIP_INTERACTION(target, item, user) (HAS_TRAIT(target, TRAIT_COMBAT_MODE_SKIP_INTERACTION) && user.combat_mode) diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index 5a8c06adcad85..c911181c43166 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -26,6 +26,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_RESTRAINED "restrained" /// Apply this to make a mob not dense, and remove it when you want it to no longer make them undense, other sources of undesity will still apply. Always define a unique source when adding a new instance of this! #define TRAIT_UNDENSE "undense" +/// Makes the mob immune to damage and several other ailments. +#define TRAIT_GODMODE "godmode" /// Expands our FOV by 30 degrees if restricted #define TRAIT_EXPANDED_FOV "expanded_fov" /// Doesn't miss attacks @@ -112,6 +114,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_STABLELIVER "stable_liver" #define TRAIT_VATGROWN "vatgrown" #define TRAIT_RESISTHEAT "resist_heat" +/// Trait for when you can no longer gain body heat +#define TRAIT_HYPOTHERMIC "body_hypothermic" ///For when you've gotten a power from a dna vault #define TRAIT_USED_DNA_VAULT "used_dna_vault" /// For when you want to be able to touch hot things, but still want fire to be an issue. @@ -219,22 +223,30 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_NO_STAGGER "no_stagger" /// Getting hit by thrown movables won't push you away #define TRAIT_NO_THROW_HITPUSH "no_throw_hitpush" +/// This mob likes to eat fish. Raw, uncut fish. +#define TRAIT_FISH_EATER "fish_eater" ///Added to mob or mind, changes the icons of the fish shown in the minigame UI depending on the possible reward. #define TRAIT_REVEAL_FISH "reveal_fish" ///This trait gets you a list of fishes that can be caught when examining a fishing spot. #define TRAIT_EXAMINE_FISHING_SPOT "examine_fishing_spot" ///lobstrosities and carps will prioritize/flee from those that have this trait (given by the skill-locked hat) #define TRAIT_SCARY_FISHERMAN "scary_fisherman" +/// Atoms with this trait can be right-clicked with a fish to release them, presumably back in the fishing spot they were caught from. +#define TRAIT_CATCH_AND_RELEASE "catch_and_release" ///This trait lets you get the size and weight of the fish by examining them #define TRAIT_EXAMINE_FISH "examine_fish" ///This trait lets you roughly know if the fish is dead, starving, drowning or sick by examining them #define TRAIT_EXAMINE_DEEPER_FISH "examine_deeper_fish" ///Trait given to turfs or objects that can be fished from #define TRAIT_FISHING_SPOT "fishing_spot" +///This trait prevents the fishing spot from being linked to the fish-porter when a multitool is being used. +#define TRAIT_UNLINKABLE_FISHING_SPOT "unlinkable_fishing_spot" ///Trait given to mobs that can fish without a rod #define TRAIT_PROFOUND_FISHER "profound_fisher" /// If an atom has this trait, then you can toss a bottle with a message in it. #define TRAIT_MESSAGE_IN_A_BOTTLE_LOCATION "message_in_a_bottle_location" +/// Stops other objects of the same type from being inserted inside the same aquarium it's in. +#define TRAIT_UNIQUE_AQUARIUM_CONTENT "unique_aquarium_content" /// This trait lets you evaluate someone's fitness level against your own #define TRAIT_EXAMINE_FITNESS "reveal_power_level" /// These mobs have particularly hygienic tongues @@ -656,7 +668,6 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_ASHSTORM_IMMUNE "ashstorm_immune" #define TRAIT_SNOWSTORM_IMMUNE "snowstorm_immune" #define TRAIT_RADSTORM_IMMUNE "radstorm_immune" -#define TRAIT_VOIDSTORM_IMMUNE "voidstorm_immune" #define TRAIT_WEATHER_IMMUNE "weather_immune" //Immune to ALL weather effects. /// Cannot be grabbed by goliath tentacles @@ -738,6 +749,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_T_RAY_VISIBLE "t-ray-visible" /// If this item's been fried #define TRAIT_FOOD_FRIED "food_fried" +/// If this item's been bbq grilled +#define TRAIT_FOOD_BBQ_GRILLED "food_bbq_grilled" /// This is a silver slime created item #define TRAIT_FOOD_SILVER "food_silver" /// If this item's been made by a chef instead of being map-spawned or admin-spawned or such @@ -799,6 +812,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_HAUNTED "haunted" /// An item that, if it has contents, will ignore its contents when scanning for contraband. #define TRAIT_CONTRABAND_BLOCKER "contraband_blocker" +/// For edible items that cannot be composted inside hydro trays +#define TRAIT_UNCOMPOSTABLE "uncompostable" //quirk traits #define TRAIT_ALCOHOL_TOLERANCE "alcohol_tolerance" @@ -835,6 +850,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_THROWINGARM "throwing_arm" #define TRAIT_SETTLER "settler" #define TRAIT_STRONG_STOMACH "strong_stomach" +#define TRAIT_VEGETARIAN "trait_vegetarian" /// This mob always lands on their feet when they fall, for better or for worse. #define TRAIT_CATLIKE_GRACE "catlike_grace" @@ -959,6 +975,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_FISH_AMPHIBIOUS "fish_amphibious" ///Trait needed for the lubefish evolution #define TRAIT_FISH_FED_LUBE "fish_fed_lube" +#define TRAIT_FISH_WELL_COOKED "fish_well_cooked" #define TRAIT_FISH_NO_HUNGER "fish_no_hunger" ///It comes from a fish case. Relevant for bounties so far. #define TRAIT_FISH_FROM_CASE "fish_from_case" @@ -1119,11 +1136,6 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// this object has been frozen #define TRAIT_FROZEN "frozen" -/// Currently fishing -#define TRAIT_GONE_FISHING "fishing" -/// Currently fishing, and it's the active minigame phase -#define TRAIT_ACTIVELY_FISHING "actively_fishing" - /// Makes a character be better/worse at tackling depending on their wing's status #define TRAIT_TACKLING_WINGED_ATTACKER "tacking_winged_attacker" @@ -1275,6 +1287,19 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai ///Trait which allows mobs to parry mining mob projectiles #define TRAIT_MINING_PARRYING "mining_parrying" +/** + * + * This trait is used in some interactions very high in the interaction chain to allow + * certain atoms to be skipped by said interactions if the user is in combat mode. + * + * Its primarily use case is for stuff like storage and tables, to allow things like emags to be bagged + * (because in some contexts you might want to be emagging a bag, and in others you might want to be storing it.) + * + * This is only checked by certain items explicitly so you can't just add the trait and expect it to work. + * (This may be changed later but I chose to do it this way to avoid messing up interactions which require combat mode) + */ +#define TRAIT_COMBAT_MODE_SKIP_INTERACTION "combat_mode_skip_interaction" + ///A "fake" effect that should not be subject to normal effect removal methods (like the effect remover component) #define TRAIT_ILLUSORY_EFFECT "illusory_effect" diff --git a/code/__DEFINES/traits/sources.dm b/code/__DEFINES/traits/sources.dm index 0648dd4dd3748..e3d1f9f065b18 100644 --- a/code/__DEFINES/traits/sources.dm +++ b/code/__DEFINES/traits/sources.dm @@ -301,3 +301,6 @@ /// Trait added by style component #define STYLE_TRAIT "style" + +/// Trait from an engraving +#define ENGRAVED_TRAIT "engraved" diff --git a/code/__DEFINES/~doppler_defines/declarations.dm b/code/__DEFINES/~doppler_defines/declarations.dm index 37dbb5fd21780..1461f8cae6e67 100644 --- a/code/__DEFINES/~doppler_defines/declarations.dm +++ b/code/__DEFINES/~doppler_defines/declarations.dm @@ -2,3 +2,5 @@ #define TRAIT_TWITCH_ADAPTED "twitch_adapted" /// Given to the detective, if they have this, they can see syndicate special descriptions. #define TRAIT_DETECTIVE "detective_ability" +/// Trait for the excitable quirk, woof! +#define TRAIT_EXCITABLE "wagwag" diff --git a/code/__DEFINES/~doppler_defines/is_helpers.dm b/code/__DEFINES/~doppler_defines/is_helpers.dm index f9c1c52531c29..02e0c61088246 100644 --- a/code/__DEFINES/~doppler_defines/is_helpers.dm +++ b/code/__DEFINES/~doppler_defines/is_helpers.dm @@ -3,5 +3,6 @@ //Customization bases #define isfeline(A) (isfelinid(A) || HAS_TRAIT(A, TRAIT_FELINE)) #define isinsectoid(A) (is_species(A, /datum/species/insectoid)) +#define issnail(A) (is_species(A, /datum/species/snail)) //Species with green blood #define hasgreenblood(A) (isinsectoid(A) || HAS_TRAIT(A, TRAIT_GREEN_BLOOD)) diff --git a/code/__DEFINES/~doppler_defines/mobs.dm b/code/__DEFINES/~doppler_defines/mobs.dm new file mode 100644 index 0000000000000..9e06c02bb5eaa --- /dev/null +++ b/code/__DEFINES/~doppler_defines/mobs.dm @@ -0,0 +1 @@ +#define BODYPART_ICON_SNAIL 'modular_doppler/modular_species/species_types/snails/icons/bodyparts/snail_bodyparts.dmi' diff --git a/code/__HELPERS/atoms.dm b/code/__HELPERS/atoms.dm index 646410026a054..6fc9086b81cc7 100644 --- a/code/__HELPERS/atoms.dm +++ b/code/__HELPERS/atoms.dm @@ -63,17 +63,19 @@ var/turf/target_turf = get_turf(target) if(get_dist(source, target) > length) return FALSE - if(current == target_turf || source.CanReach(target))//they are on the same turf or in reach, source can see the target + if(current == target_turf) return TRUE - var/list/steps = get_steps_to(source, target) - if(isnull(steps) || length(steps) > length) - return FALSE - for(var/direction in steps) - current = get_step(current, direction) - if(current == target_turf) - break + var/steps = 1 + if(current == target_turf)//they are on the same turf, source can see the target + return TRUE + current = get_step_towards(current, target_turf) + while(current != target_turf) + if(steps > length) + return FALSE if(IS_OPAQUE_TURF(current)) return FALSE + current = get_step_towards(current, target_turf) + steps++ return TRUE ///Get the cardinal direction between two atoms diff --git a/code/__HELPERS/cmp.dm b/code/__HELPERS/cmp.dm index f9957f4c7393e..76651964e24e0 100644 --- a/code/__HELPERS/cmp.dm +++ b/code/__HELPERS/cmp.dm @@ -195,3 +195,20 @@ /proc/cmp_deathmatch_mods(datum/deathmatch_modifier/a, datum/deathmatch_modifier/b) return sorttext(b.name, a.name) + +/** + * Orders fish types following this order (freshwater -> saltwater -> anadromous -> sulphuric water -> any water -> air) + * If both share the same required fluid type, they'll be ordered by name instead. + */ +/proc/cmp_fish_fluid(obj/item/fish/a, obj/item/fish/b) + var/static/list/fluids_priority = list( + AQUARIUM_FLUID_FRESHWATER, + AQUARIUM_FLUID_SALTWATER, + AQUARIUM_FLUID_ANADROMOUS, + AQUARIUM_FLUID_SULPHWATEVER, + AQUARIUM_FLUID_ANY_WATER, + AQUARIUM_FLUID_AIR, + ) + var/position_a = fluids_priority.Find(initial(a.required_fluid_type)) + var/position_b = fluids_priority.Find(initial(b.required_fluid_type)) + return cmp_numeric_asc(position_a, position_b) || cmp_text_asc(initial(b.name), initial(a.name)) diff --git a/code/__HELPERS/colors.dm b/code/__HELPERS/colors.dm index 3a20e5ad60c09..f5dd398d72fcd 100644 --- a/code/__HELPERS/colors.dm +++ b/code/__HELPERS/colors.dm @@ -1,8 +1,13 @@ /// Given a color in the format of "#RRGGBB", will return if the color /// is dark. /proc/is_color_dark(color, threshold = 25) - var/hsl = rgb2num(color, COLORSPACE_HSL) - return hsl[3] < threshold + /// DOPPLER SHIFT REMOVAL BEGIN - BEGONE SNOWFLAKE FUNCTION! + /*var/hsl = rgb2num(color, COLORSPACE_HSL) + return hsl[3] < threshold*/ + /// DOPPLER SHIFT REMOVAL END - WE DON'T CARE IF SOMEONE MAKES THEIR FLASHLIGHT USELESS! + /// DOPPLER SHIFT ADDITION BEGIN - NOR DO WE CARE IF SOMEONE'S CHARACTER IS LITERALLY MADE OF VANTABLACK! + return FALSE + /// DOPPLER SHIFT ADDITION END - TEEGEE'S CRUSADE AGAINST POWERGAMERS, BEGONE!! /// Given a 3 character color (no hash), converts it into #RRGGBB (with hash) /proc/expand_three_digit_color(color) diff --git a/code/__HELPERS/dynamic_human_icon_gen.dm b/code/__HELPERS/dynamic_human_icon_gen.dm index df8f4716bb918..f1f3be038a86b 100644 --- a/code/__HELPERS/dynamic_human_icon_gen.dm +++ b/code/__HELPERS/dynamic_human_icon_gen.dm @@ -57,6 +57,7 @@ GLOBAL_LIST_EMPTY(dynamic_human_appearances) /proc/set_dynamic_human_appearance(list/arguments) var/atom/target = arguments[1] //1st argument is the target var/dynamic_appearance = get_dynamic_human_appearance(arglist(arguments.Copy(2))) //the rest of the arguments starting from 2 matter to the proc - target.icon = 'icons/blanks/32x32.dmi' - target.icon_state = "nothing" + target.icon = 'icons/mob/human/human.dmi' + target.icon_state = "" + target.appearance_flags |= KEEP_TOGETHER target.copy_overlays(dynamic_appearance, cut_old = TRUE) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index ce48e593980b5..699ae8aa72cdd 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -181,7 +181,7 @@ //First we spawn a dude. var/mob/living/carbon/human/new_character = new//The mob being spawned. - SSjob.SendToLateJoin(new_character) + SSjob.send_to_late_join(new_character) ghost_player.client.prefs.safe_transfer_prefs_to(new_character) new_character.dna.update_dna_identity() @@ -243,8 +243,16 @@ if(!(character.mind.assigned_role.job_flags & JOB_ANNOUNCE_ARRIVAL)) return - var/obj/machinery/announcement_system/announcer = pick(GLOB.announcement_systems) - announcer.announce("ARRIVAL", character.real_name, rank, list()) //make the list empty to make it announce it in common + var/obj/machinery/announcement_system/announcer + var/list/available_machines = list() + for(var/obj/machinery/announcement_system/announce as anything in GLOB.announcement_systems) + if(announce.arrival_toggle) + available_machines += announce + break + if(!length(available_machines)) + return + announcer = pick(available_machines) + announcer.announce(AUTO_ANNOUNCE_ARRIVAL, character.real_name, rank, list()) //make the list empty to make it announce it in common ///Check if the turf pressure allows specialized equipment to work /proc/lavaland_equipment_pressure_check(turf/turf_to_check) diff --git a/code/__HELPERS/hallucinations.dm b/code/__HELPERS/hallucinations.dm index 00fee61e2b1ca..d3d4a2630ed05 100644 --- a/code/__HELPERS/hallucinations.dm +++ b/code/__HELPERS/hallucinations.dm @@ -250,7 +250,7 @@ ADMIN_VERB(debug_hallucination_weighted_list_per_type, R_DEBUG, "Show Hallucinat if(!custom_icon_state) return - var/custom_name = tgui_input_text(user, "What name should it show up as? (Can be empty)", "Custom Delusion: Name") + var/custom_name = tgui_input_text(user, "What name should it show up as? (Can be empty)", "Custom Delusion: Name", max_length = MAX_NAME_LEN) delusion_args += list( custom_icon_file = custom_icon_file, diff --git a/code/__HELPERS/hearted.dm b/code/__HELPERS/hearted.dm index adae298516ec6..d8f7832cbc06b 100644 --- a/code/__HELPERS/hearted.dm +++ b/code/__HELPERS/hearted.dm @@ -45,11 +45,11 @@ var/heart_nominee switch(attempt) if(1) - heart_nominee = tgui_input_text(src, "What was their name? Just a first or last name may be enough.", "<3?") + heart_nominee = tgui_input_text(src, "What was their name? Just a first or last name may be enough.", "<3?", max_length = MAX_NAME_LEN) if(2) - heart_nominee = tgui_input_text(src, "Try again, what was their name? Just a first or last name may be enough.", "<3?") + heart_nominee = tgui_input_text(src, "Try again, what was their name? Just a first or last name may be enough.", "<3?", max_length = MAX_NAME_LEN) if(3) - heart_nominee = tgui_input_text(src, "One more try, what was their name? Just a first or last name may be enough.", "<3?") + heart_nominee = tgui_input_text(src, "One more try, what was their name? Just a first or last name may be enough.", "<3?", max_length = MAX_NAME_LEN) if(!heart_nominee) return diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index 127ae5387e1b0..4c0cf3038f58f 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -466,25 +466,24 @@ world 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 - //Try to remove/optimize this section ASAP, CPU hog. - //Determines if there's directionals. - if(render_icon && curdir != SOUTH) - if ( - !length(icon_states(icon(curicon, curstate, NORTH))) \ - && !length(icon_states(icon(curicon, curstate, EAST))) \ - && !length(icon_states(icon(curicon, curstate, WEST))) \ - ) - base_icon_dir = SOUTH + if(render_icon) + //Try to remove/optimize this section if you can, it's a CPU hog. + //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. + 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 - // Expand our canvas to fit if we're too big - if(render_icon) - var/icon/active_icon = icon(curicon) - if(active_icon.Width() != 32 || active_icon.Height() != 32) - flat.Scale(active_icon.Width(), active_icon.Height()) - var/curblend = appearance.blend_mode || defblend if(appearance.overlays.len || appearance.underlays.len) diff --git a/code/__HELPERS/spatial_info.dm b/code/__HELPERS/spatial_info.dm index 2a8b61bd01db8..529532f50cf4d 100644 --- a/code/__HELPERS/spatial_info.dm +++ b/code/__HELPERS/spatial_info.dm @@ -195,12 +195,8 @@ var/turf/inbetween_turf = center_turf //this is the lowest overhead way of doing a loop in dm other than a goto. distance is guaranteed to be >= steps taken to target by this algorithm - var/list/steps = get_steps_to(inbetween_turf, target_turf) - if(isnull(steps)) - return - steps.Cut(distance + 1) - for(var/direction in steps) - inbetween_turf = get_step(inbetween_turf, direction) + for(var/step_counter in 1 to distance) + inbetween_turf = get_step_towards(inbetween_turf, target_turf) if(inbetween_turf == target_turf)//we've gotten to target's turf without returning due to turf opacity, so we must be able to see target break diff --git a/code/__byond_version_compat.dm b/code/__byond_version_compat.dm index 0f19332934d09..6680e655551f5 100644 --- a/code/__byond_version_compat.dm +++ b/code/__byond_version_compat.dm @@ -9,6 +9,11 @@ #error You need version 515.1627 or higher #endif +// Unable to compile this version thanks to mutable appearance changes +#if (DM_VERSION == 515 && DM_BUILD == 1643) +#error This version of BYOND cannot compile this project. Visit www.byond.com/download/build to download an older version or update (if possible). +#endif + // Keep savefile compatibilty at minimum supported level /savefile/byond_version = MIN_COMPILER_VERSION diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index 8db59bccc3532..45afc0e0c85a6 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -65,6 +65,7 @@ DEFINE_BITFIELD(area_flags, list( "VALID_TERRITORY" = VALID_TERRITORY, "XENOBIOLOGY_COMPATIBLE" = XENOBIOLOGY_COMPATIBLE, "NO_BOH" = NO_BOH, + "UNLIMITED_FISHING" = UNLIMITED_FISHING, )) DEFINE_BITFIELD(turf_flags, list( @@ -560,6 +561,13 @@ DEFINE_BITFIELD(gun_flags, list( "TURRET_INCOMPATIBLE" = TURRET_INCOMPATIBLE, )) +DEFINE_BITFIELD(fish_flags, list( + "FISH_FLAG_SHOW_IN_CATALOG" = FISH_FLAG_SHOW_IN_CATALOG, + "FISH_DO_FLOP_ANIM" = FISH_DO_FLOP_ANIM, + "FISH_FLAG_PETTED" = FISH_FLAG_PETTED, + "FISH_FLAG_EXPERIMENT_SCANNABLE" = FISH_FLAG_EXPERIMENT_SCANNABLE, +)) + DEFINE_BITFIELD(bot_mode_flags, list( "POWER_ON" = BOT_MODE_ON, "AUTO_PATROL" = BOT_MODE_AUTOPATROL, diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 4837cf47551a3..85ba6893a8edc 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -10,6 +10,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_AI_PAUSED" = TRAIT_AI_PAUSED, "TRAIT_BANNED_FROM_CARGO_SHUTTLE" = TRAIT_BANNED_FROM_CARGO_SHUTTLE, "TRAIT_BEING_SHOCKED" = TRAIT_BEING_SHOCKED, + "TRAIT_CATCH_AND_RELEASE" = TRAIT_CATCH_AND_RELEASE, "TRAIT_COMMISSIONED" = TRAIT_COMMISSIONED, "TRAIT_CLIMBABLE" = TRAIT_CLIMBABLE, "TRAIT_CURRENTLY_CLEANING" = TRAIT_CURRENTLY_CLEANING, @@ -17,6 +18,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_DO_NOT_SPLASH" = TRAIT_DO_NOT_SPLASH, "TRAIT_DRIED" = TRAIT_DRIED, "TRAIT_DRYABLE" = TRAIT_DRYABLE, + "TRAIT_FISHING_SPOT" = TRAIT_FISHING_SPOT, "TRAIT_FOOD_CHEF_MADE" = TRAIT_FOOD_CHEF_MADE, "TRAIT_FOOD_FRIED" = TRAIT_FOOD_FRIED, "TRAIT_QUALITY_FOOD_INGREDIENT" = TRAIT_QUALITY_FOOD_INGREDIENT, @@ -29,6 +31,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_SPINNING" = TRAIT_SPINNING, "TRAIT_STICKERED" = TRAIT_STICKERED, "TRAIT_UNHITTABLE_BY_PROJECTILES" = TRAIT_UNHITTABLE_BY_PROJECTILES, + "TRAIT_UNLINKABLE_FISHING_SPOT" = TRAIT_UNLINKABLE_FISHING_SPOT, ), /atom/movable = list( "TRAIT_ACTIVE_STORAGE" = TRAIT_ACTIVE_STORAGE, @@ -37,6 +40,8 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_BLOCKING_EXPLOSIVES" = TRAIT_BLOCKING_EXPLOSIVES, "TRAIT_BOULDER_BREAKER" = TRAIT_BOULDER_BREAKER, "TRAIT_CASTABLE_LOC" = TRAIT_CASTABLE_LOC, + "TRAIT_CHASM_STOPPER" = TRAIT_CHASM_STOPPER, + "TRAIT_COMBAT_MODE_SKIP_INTERACTION" = TRAIT_COMBAT_MODE_SKIP_INTERACTION, "TRAIT_DEL_ON_SPACE_DUMP" = TRAIT_DEL_ON_SPACE_DUMP, "TRAIT_FISH_CASE_COMPATIBILE" = TRAIT_FISH_CASE_COMPATIBILE, "TRAIT_FROZEN" = TRAIT_FROZEN, @@ -50,28 +55,26 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_MOVE_FLYING" = TRAIT_MOVE_FLYING, "TRAIT_MOVE_GROUND" = TRAIT_MOVE_GROUND, "TRAIT_MOVE_PHASING" = TRAIT_MOVE_PHASING, - "TRAIT_MOVE_VENTCRAWLING" = TRAIT_MOVE_VENTCRAWLING, "TRAIT_MOVE_UPSIDE_DOWN" = TRAIT_MOVE_UPSIDE_DOWN, + "TRAIT_MOVE_VENTCRAWLING" = TRAIT_MOVE_VENTCRAWLING, + "TRAIT_NOT_ENGRAVABLE" = TRAIT_NOT_ENGRAVABLE, "TRAIT_NO_FLOATING_ANIM" = TRAIT_NO_FLOATING_ANIM, "TRAIT_NO_MANIFEST_CONTENTS_ERROR" = TRAIT_NO_MANIFEST_CONTENTS_ERROR, "TRAIT_NO_MISSING_ITEM_ERROR" = TRAIT_NO_MISSING_ITEM_ERROR, "TRAIT_NO_THROW_HITPUSH" = TRAIT_NO_THROW_HITPUSH, - "TRAIT_NOT_ENGRAVABLE" = TRAIT_NOT_ENGRAVABLE, - "TRAIT_SPELLS_TRANSFER_TO_LOC" = TRAIT_SPELLS_TRANSFER_TO_LOC, "TRAIT_ODD_CUSTOMIZABLE_FOOD_INGREDIENT" = TRAIT_ODD_CUSTOMIZABLE_FOOD_INGREDIENT, "TRAIT_ON_HIT_EFFECT" = TRAIT_ON_HIT_EFFECT, "TRAIT_RUNECHAT_HIDDEN" = TRAIT_RUNECHAT_HIDDEN, "TRAIT_SCARY_FISHERMAN" = TRAIT_SCARY_FISHERMAN, "TRAIT_SECLUDED_LOCATION" = TRAIT_SECLUDED_LOCATION, "TRAIT_SNOWSTORM_IMMUNE" = TRAIT_SNOWSTORM_IMMUNE, + "TRAIT_SPELLS_TRANSFER_TO_LOC" = TRAIT_SPELLS_TRANSFER_TO_LOC, "TRAIT_TELEKINESIS_CONTROLLED" = TRAIT_TELEKINESIS_CONTROLLED, "TRAIT_UNDERFLOOR" = TRAIT_UNDERFLOOR, "TRAIT_UNIQUE_IMMERSE" = TRAIT_UNIQUE_IMMERSE, - "TRAIT_VOIDSTORM_IMMUNE" = TRAIT_VOIDSTORM_IMMUNE, - "TRAIT_WAS_RENAMED" = TRAIT_WAS_RENAMED, "TRAIT_WADDLING" = TRAIT_WADDLING, + "TRAIT_WAS_RENAMED" = TRAIT_WAS_RENAMED, "TRAIT_WEATHER_IMMUNE" = TRAIT_WEATHER_IMMUNE, - "TRAIT_CHASM_STOPPER" = TRAIT_CHASM_STOPPER, ), /datum/controller/subsystem/economy = list( "TRAIT_MARKET_CRASHING" = TRAIT_MARKET_CRASHING, @@ -123,7 +126,6 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_ABDUCTOR_TRAINING" = TRAIT_ABDUCTOR_TRAINING, "TRAIT_ACT_AS_CULTIST" = TRAIT_ACT_AS_CULTIST, "TRAIT_ACT_AS_HERETIC" = TRAIT_ACT_AS_HERETIC, - "TRAIT_ACTIVELY_FISHING" = TRAIT_ACTIVELY_FISHING, "TRAIT_ADAMANTINE_EXTRACT_ARMOR" = TRAIT_ADAMANTINE_EXTRACT_ARMOR, "TRAIT_ADVANCEDTOOLUSER" = TRAIT_ADVANCEDTOOLUSER, "TRAIT_AGENDER" = TRAIT_AGENDER, @@ -238,6 +240,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_FEARLESS" = TRAIT_FEARLESS, "TRAIT_FENCE_CLIMBER" = TRAIT_FENCE_CLIMBER, "TRAIT_FINGERPRINT_PASSTHROUGH" = TRAIT_FINGERPRINT_PASSTHROUGH, + "TRAIT_FISH_EATER" = TRAIT_FISH_EATER, "TRAIT_FIST_MINING" = TRAIT_FIST_MINING, "TRAIT_FIXED_MUTANT_COLORS" = TRAIT_FIXED_MUTANT_COLORS, "TRAIT_FLESH_DESIRE" = TRAIT_FLESH_DESIRE, @@ -257,7 +260,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_GARLIC_BREATH" = TRAIT_GARLIC_BREATH, "TRAIT_GENELESS" = TRAIT_GENELESS, "TRAIT_GIANT" = TRAIT_GIANT, - "TRAIT_GONE_FISHING" = TRAIT_GONE_FISHING, + "TRAIT_GODMODE" = TRAIT_GODMODE, "TRAIT_GOOD_HEARING" = TRAIT_GOOD_HEARING, "TRAIT_GRABWEAKNESS" = TRAIT_GRABWEAKNESS, "TRAIT_GREENTEXT_CURSED" = TRAIT_GREENTEXT_CURSED, @@ -282,6 +285,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_HOT_SPRING_CURSED" = TRAIT_HOT_SPRING_CURSED, "TRAIT_HULK" = TRAIT_HULK, "TRAIT_HUSK" = TRAIT_HUSK, + "TRAIT_HYPOTHERMIC" = TRAIT_HYPOTHERMIC, "TRAIT_ID_APPRAISER" = TRAIT_ID_APPRAISER, "TRAIT_IGNORE_ELEVATION" = TRAIT_IGNORE_ELEVATION, "TRAIT_IGNORESLOWDOWN" = TRAIT_IGNORESLOWDOWN, @@ -522,6 +526,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_USER_SCOPED" = TRAIT_USER_SCOPED, "TRAIT_USES_SKINTONES" = TRAIT_USES_SKINTONES, "TRAIT_VATGROWN" = TRAIT_VATGROWN, + "TRAIT_VEGETARIAN" = TRAIT_VEGETARIAN, "TRAIT_VENTCRAWLER_ALWAYS" = TRAIT_VENTCRAWLER_ALWAYS, "TRAIT_VENTCRAWLER_NUDE" = TRAIT_VENTCRAWLER_NUDE, "TRAIT_VIRUSIMMUNE" = TRAIT_VIRUSIMMUNE, @@ -556,6 +561,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_CUSTOM_TAP_SOUND" = TRAIT_CUSTOM_TAP_SOUND, "TRAIT_DANGEROUS_OBJECT" = TRAIT_DANGEROUS_OBJECT, "TRAIT_FISHING_BAIT" = TRAIT_FISHING_BAIT, + "TRAIT_FOOD_BBQ_GRILLED" = TRAIT_FOOD_BBQ_GRILLED, "TRAIT_GERM_SENSITIVE" = TRAIT_GERM_SENSITIVE, "TRAIT_GOOD_QUALITY_BAIT" = TRAIT_GOOD_QUALITY_BAIT, "TRAIT_GREAT_QUALITY_BAIT" = TRAIT_GREAT_QUALITY_BAIT, @@ -576,6 +582,8 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_T_RAY_VISIBLE" = TRAIT_T_RAY_VISIBLE, "TRAIT_TRANSFORM_ACTIVE" = TRAIT_TRANSFORM_ACTIVE, "TRAIT_UNCATCHABLE" = TRAIT_UNCATCHABLE, + "TRAIT_UNCOMPOSTABLE" = TRAIT_UNCOMPOSTABLE, + "TRAIT_UNIQUE_AQUARIUM_CONTENT" = TRAIT_UNIQUE_AQUARIUM_CONTENT, "TRAIT_WIELDED" = TRAIT_WIELDED, ), /obj/item/ammo_casing = list( @@ -617,6 +625,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_FISH_STINGER" = TRAIT_FISH_STINGER, "TRAIT_FISH_TOXIN_IMMUNE" = TRAIT_FISH_TOXIN_IMMUNE, "TRAIT_RESIST_EMULSIFY" = TRAIT_RESIST_EMULSIFY, + "TRAIT_FISH_WELL_COOKED" = TRAIT_FISH_WELL_COOKED, "TRAIT_YUCKY_FISH" = TRAIT_YUCKY_FISH, ), /obj/item/fishing_rod = list( @@ -669,7 +678,6 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_CONTAINMENT_FIELD" = TRAIT_CONTAINMENT_FIELD, "TRAIT_ELEVATED_TURF" = TRAIT_ELEVATED_TURF, "TRAIT_FIREDOOR_STOP" = TRAIT_FIREDOOR_STOP, - "TRAIT_FISHING_SPOT" = TRAIT_FISHING_SPOT, "TRAIT_HYPERSPACE_STOPPED" = TRAIT_HYPERSPACE_STOPPED, "TRAIT_IMMERSE_STOPPED" = TRAIT_IMMERSE_STOPPED, "TRAIT_LAVA_STOPPED" = TRAIT_LAVA_STOPPED, @@ -685,6 +693,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_GLASSBLOWING" = TRAIT_GLASSBLOWING, "TRAIT_XENOARCH_QUALIFIED" = TRAIT_XENOARCH_QUALIFIED, "TRAIT_DETECTIVE" = TRAIT_DETECTIVE, + "TRAIT_EXCITABLE" = TRAIT_EXCITABLE, "TRAIT_TWITCH_ADAPTED" = TRAIT_TWITCH_ADAPTED, ), // DOPPLER EDIT ADDITION END diff --git a/code/_globalvars/traits/admin_tooling.dm b/code/_globalvars/traits/admin_tooling.dm index 26045c4e7c075..f3ee2ecfbc05a 100644 --- a/code/_globalvars/traits/admin_tooling.dm +++ b/code/_globalvars/traits/admin_tooling.dm @@ -4,8 +4,9 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( /atom = list( - "TRAIT_UNHITTABLE_BY_PROJECTILES" = TRAIT_UNHITTABLE_BY_PROJECTILES, + "TRAIT_CATCH_AND_RELEASE" = TRAIT_CATCH_AND_RELEASE, "TRAIT_KEEP_TOGETHER" = TRAIT_KEEP_TOGETHER, + "TRAIT_UNHITTABLE_BY_PROJECTILES" = TRAIT_UNHITTABLE_BY_PROJECTILES, ), /atom/movable = list( "TRAIT_ASHSTORM_IMMUNE" = TRAIT_ASHSTORM_IMMUNE, @@ -20,7 +21,6 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_RUNECHAT_HIDDEN" = TRAIT_RUNECHAT_HIDDEN, "TRAIT_SCARY_FISHERMAN" = TRAIT_SCARY_FISHERMAN, "TRAIT_SNOWSTORM_IMMUNE" = TRAIT_SNOWSTORM_IMMUNE, - "TRAIT_VOIDSTORM_IMMUNE" = TRAIT_VOIDSTORM_IMMUNE, "TRAIT_WEATHER_IMMUNE" = TRAIT_WEATHER_IMMUNE, ), /mob = list( @@ -102,6 +102,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_FAT" = TRAIT_FAT, "TRAIT_FEARLESS" = TRAIT_FEARLESS, "TRAIT_FENCE_CLIMBER" = TRAIT_FENCE_CLIMBER, + "TRAIT_FISH_EATER" = TRAIT_FISH_EATER, "TRAIT_FIST_MINING" = TRAIT_FIST_MINING, "TRAIT_FIXED_MUTANT_COLORS" = TRAIT_FIXED_MUTANT_COLORS, "TRAIT_FLESH_DESIRE" = TRAIT_FLESH_DESIRE, @@ -118,6 +119,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_GARLIC_BREATH" = TRAIT_GARLIC_BREATH, "TRAIT_GENELESS" = TRAIT_GENELESS, "TRAIT_GIANT" = TRAIT_GIANT, + "TRAIT_GODMODE" = TRAIT_GODMODE, "TRAIT_GOOD_HEARING" = TRAIT_GOOD_HEARING, "TRAIT_GRABWEAKNESS" = TRAIT_GRABWEAKNESS, "TRAIT_GREENTEXT_CURSED" = TRAIT_GREENTEXT_CURSED, @@ -300,6 +302,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_UNSTABLE" = TRAIT_UNSTABLE, "TRAIT_USED_DNA_VAULT" = TRAIT_USED_DNA_VAULT, "TRAIT_USES_SKINTONES" = TRAIT_USES_SKINTONES, + "TRAIT_VEGETARIAN" = TRAIT_VEGETARIAN, "TRAIT_VENTCRAWLER_ALWAYS" = TRAIT_VENTCRAWLER_ALWAYS, "TRAIT_VENTCRAWLER_NUDE" = TRAIT_VENTCRAWLER_NUDE, "TRAIT_VIRUSIMMUNE" = TRAIT_VIRUSIMMUNE, @@ -376,6 +379,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_GLASSBLOWING" = TRAIT_GLASSBLOWING, "TRAIT_XENOARCH_QUALIFIED" = TRAIT_XENOARCH_QUALIFIED, "TRAIT_DETECTIVE" = TRAIT_DETECTIVE, + "TRAIT_EXCITABLE" = TRAIT_EXCITABLE, "TRAIT_TWITCH_ADAPTED" = TRAIT_TWITCH_ADAPTED, ), // DOPPLER EDIT ADDITION END diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 6696d985d0b8c..0c441ba928ee4 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -247,8 +247,7 @@ return TRUE /proc/CheckToolReach(atom/movable/here, atom/movable/there, reach) - . = FALSE - if(QDELETED(here) || QDELETED(there)) + if(!here || !there) return switch(reach) if(0) @@ -259,18 +258,14 @@ var/obj/dummy = new(get_turf(here)) dummy.pass_flags |= PASSTABLE dummy.SetInvisibility(INVISIBILITY_ABSTRACT) - var/list/steps = get_steps_to(dummy, there) - if(isnull(steps) || length(steps) > reach) // If the path is further than the reach, no way we can reach it anyways. - qdel(dummy) - return FALSE - for(var/direction in steps) - var/turf/next_step = get_step(dummy, direction) + for(var/i in 1 to reach) //Limit it to that many tries + var/turf/T = get_step(dummy, get_dir(dummy, there)) if(dummy.CanReach(there)) qdel(dummy) return TRUE - if(!dummy.Move(next_step)) // We're blocked, nope. + if(!dummy.Move(T)) //we're blocked! qdel(dummy) - return FALSE + return qdel(dummy) /// Default behavior: ignore double clicks (the second click that makes the doubleclick call already calls for a normal click) diff --git a/code/_onclick/hud/alien.dm b/code/_onclick/hud/alien.dm index 476140acb1edd..b9a0e3bf655f4 100644 --- a/code/_onclick/hud/alien.dm +++ b/code/_onclick/hud/alien.dm @@ -59,14 +59,15 @@ H.leap_icon.screen_loc = ui_alien_storage_r static_inventory += H.leap_icon + floor_change = new /atom/movable/screen/floor_changer(null, src) + floor_change.icon = ui_style + floor_change.screen_loc = ui_above_intent + static_inventory += floor_change + using = new/atom/movable/screen/language_menu(null, src) using.screen_loc = ui_alien_language_menu static_inventory += using - using = new /atom/movable/screen/floor_menu(null, src) - using.screen_loc = ui_alien_floor_menu - static_inventory += using - using = new /atom/movable/screen/navigate(null, src) using.screen_loc = ui_alien_navigate_menu static_inventory += using diff --git a/code/_onclick/hud/alien_larva.dm b/code/_onclick/hud/alien_larva.dm index 77d135ce2c663..bb2b9fcb14aee 100644 --- a/code/_onclick/hud/alien_larva.dm +++ b/code/_onclick/hud/alien_larva.dm @@ -10,6 +10,11 @@ action_intent.screen_loc = ui_combat_toggle static_inventory += action_intent + floor_change = new /atom/movable/screen/floor_changer(null, src) + floor_change.icon = ui_style + floor_change.screen_loc = ui_above_intent + static_inventory += floor_change + healths = new /atom/movable/screen/healths/alien(null, src) infodisplay += healths @@ -32,10 +37,6 @@ using.screen_loc = ui_alien_language_menu static_inventory += using - using = new /atom/movable/screen/floor_menu(null, src) - using.screen_loc = ui_alien_floor_menu - static_inventory += using - using = new /atom/movable/screen/navigate(null, src) using.screen_loc = ui_alien_navigate_menu static_inventory += using diff --git a/code/_onclick/hud/generic_dextrous.dm b/code/_onclick/hud/generic_dextrous.dm index aac5a2b75ccaa..4048fd91b16f6 100644 --- a/code/_onclick/hud/generic_dextrous.dm +++ b/code/_onclick/hud/generic_dextrous.dm @@ -33,6 +33,10 @@ action_intent.screen_loc = ui_combat_toggle static_inventory += action_intent + floor_change = new /atom/movable/screen/floor_changer(null, src) + floor_change.icon = 'icons/hud/screen_midnight.dmi' + static_inventory += floor_change + zone_select = new /atom/movable/screen/zone_sel(null, src) zone_select.icon = ui_style diff --git a/code/_onclick/hud/ghost.dm b/code/_onclick/hud/ghost.dm index e20c1ede2f663..9f90076a3ac71 100644 --- a/code/_onclick/hud/ghost.dm +++ b/code/_onclick/hud/ghost.dm @@ -91,10 +91,10 @@ using.icon = ui_style static_inventory += using - using = new /atom/movable/screen/floor_menu(null, src) - using.screen_loc = ui_ghost_floor_menu - using.icon = ui_style - static_inventory += using + floor_change = new /atom/movable/screen/floor_changer/vertical(null, src) + floor_change.icon = ui_style + floor_change.screen_loc = ui_ghost_floor_changer + static_inventory += floor_change /datum/hud/ghost/show_hud(version = 0, mob/viewmob) // don't show this HUD if observing; show the HUD of the observee diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 73497bf418ff1..90370d267162b 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -41,6 +41,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list( var/atom/movable/screen/rest_icon var/atom/movable/screen/throw_icon var/atom/movable/screen/module_store_icon + var/atom/movable/screen/floor_change var/list/static_inventory = list() //the screen objects which are static var/list/toggleable_inventory = list() //the screen objects which can be hidden @@ -228,6 +229,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list( zone_select = null pull_icon = null rest_icon = null + floor_change = null hand_slots.Cut() QDEL_LIST(toggleable_inventory) @@ -419,6 +421,11 @@ GLOBAL_LIST_INIT(available_ui_styles, list( return update_robot_modules_display() +/datum/hud/new_player/show_hud(version = 0, mob/viewmob) + . = ..() + if(.) + show_station_trait_buttons() + /datum/hud/proc/hidden_inventory_update() return diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 5834a3973555c..0ab0f022ca22e 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -70,15 +70,16 @@ using.icon = ui_style static_inventory += using - using = new /atom/movable/screen/floor_menu(null, src) - using.icon = ui_style - static_inventory += using - action_intent = new /atom/movable/screen/combattoggle/flashy(null, src) action_intent.icon = ui_style action_intent.screen_loc = ui_combat_toggle static_inventory += action_intent + floor_change = new /atom/movable/screen/floor_changer(null, src) + floor_change.icon = ui_style + floor_change.screen_loc = ui_human_floor_changer + static_inventory += floor_change + using = new /atom/movable/screen/mov_intent(null, src) using.icon = ui_style diff --git a/code/_onclick/hud/living.dm b/code/_onclick/hud/living.dm index 70084b1ecd9c6..d70d2f7d55d39 100644 --- a/code/_onclick/hud/living.dm +++ b/code/_onclick/hud/living.dm @@ -15,6 +15,10 @@ action_intent.screen_loc = ui_combat_toggle static_inventory += action_intent + floor_change = new /atom/movable/screen/floor_changer(null, src) + floor_change.icon = 'icons/hud/screen_midnight.dmi' + static_inventory += floor_change + combo_display = new /atom/movable/screen/combo(null, src) infodisplay += combo_display diff --git a/code/_onclick/hud/new_player.dm b/code/_onclick/hud/new_player.dm index 371341aec0bf5..1c794b5566d2d 100644 --- a/code/_onclick/hud/new_player.dm +++ b/code/_onclick/hud/new_player.dm @@ -6,6 +6,7 @@ /datum/hud/new_player ///Whether the menu is currently on the client's screen or not var/menu_hud_status = TRUE + var/list/shown_station_trait_buttons /datum/hud/new_player/New(mob/owner) . = ..() @@ -26,31 +27,58 @@ if (!lobbyscreen.always_shown) lobbyscreen.RegisterSignal(src, COMSIG_HUD_LOBBY_COLLAPSED, TYPE_PROC_REF(/atom/movable/screen/lobby, collapse_button)) lobbyscreen.RegisterSignal(src, COMSIG_HUD_LOBBY_EXPANDED, TYPE_PROC_REF(/atom/movable/screen/lobby, expand_button)) - if (istype(lobbyscreen, /atom/movable/screen/lobby/button)) - var/atom/movable/screen/lobby/button/lobby_button = lobbyscreen - lobby_button.owner = REF(owner) - add_station_trait_buttons() -/// Display buttons for relevant station traits -/datum/hud/new_player/proc/add_station_trait_buttons() +/// Load and then display the buttons for relevant station traits +/datum/hud/new_player/proc/show_station_trait_buttons() if (!mymob?.client || mymob.client.interviewee || !length(GLOB.lobby_station_traits)) return - var/buttons_created = 0 - var/y_offset = 397 - var/y_button_offset = 27 for (var/datum/station_trait/trait as anything in GLOB.lobby_station_traits) - if (!trait.can_display_lobby_button(mymob.client)) + if (QDELETED(trait) || !trait.can_display_lobby_button(mymob.client)) + remove_station_trait_button(trait) + continue + if(LAZYACCESS(shown_station_trait_buttons, trait)) continue var/atom/movable/screen/lobby/button/sign_up/sign_up_button = new(our_hud = src) - sign_up_button.SlowInit() - sign_up_button.owner = REF(mymob) - sign_up_button.screen_loc = offset_to_screen_loc(233, y_offset, mymob.client.view) - y_offset += y_button_offset - static_inventory += sign_up_button trait.setup_lobby_button(sign_up_button) - buttons_created++ - if (buttons_created >= MAX_STATION_TRAIT_BUTTONS_VERTICAL) - return + static_inventory |= sign_up_button + LAZYSET(shown_station_trait_buttons, trait, sign_up_button) + RegisterSignal(trait, COMSIG_QDELETING, PROC_REF(remove_station_trait_button)) + + place_station_trait_buttons() + +/// Display the buttosn for relevant station traits. +/datum/hud/new_player/proc/place_station_trait_buttons() + if(hud_version != HUD_STYLE_STANDARD || !mymob?.client) + return + + var/y_offset = 397 + var/x_offset = 233 + var/y_button_offset = 27 + var/x_button_offset = -27 + var/iteration = 0 + for(var/trait in shown_station_trait_buttons) + var/atom/movable/screen/lobby/button/sign_up/sign_up_button = shown_station_trait_buttons[trait] + iteration++ + sign_up_button.screen_loc = offset_to_screen_loc(x_offset, y_offset, mymob.client.view) + mymob.client.screen |= sign_up_button + if (iteration >= MAX_STATION_TRAIT_BUTTONS_VERTICAL) + iteration = 0 + y_offset = 397 + x_offset += x_button_offset + else + y_offset += y_button_offset + +/// Remove a station trait button, then re-order the rest. +/datum/hud/new_player/proc/remove_station_trait_button(datum/station_trait/trait) + SIGNAL_HANDLER + var/atom/movable/screen/lobby/button/sign_up/button = LAZYACCESS(shown_station_trait_buttons, trait) + if(!button) + return + LAZYREMOVE(shown_station_trait_buttons, trait) + UnregisterSignal(trait, COMSIG_QDELETING) + static_inventory -= button + qdel(button) + place_station_trait_buttons() /atom/movable/screen/lobby plane = SPLASHSCREEN_PLANE @@ -94,11 +122,9 @@ var/enabled = TRUE ///Is the button currently being hovered over with the mouse? var/highlighted = FALSE - /// The ref of the mob that owns this button. Only the owner can click on it. - var/owner /atom/movable/screen/lobby/button/Click(location, control, params) - if(owner != REF(usr)) + if(usr != get_mob()) return if(!usr.client || usr.client.interviewee) @@ -113,7 +139,7 @@ return TRUE /atom/movable/screen/lobby/button/MouseEntered(location,control,params) - if(owner != REF(usr)) + if(usr != get_mob()) return if(!usr.client || usr.client.interviewee) @@ -124,7 +150,7 @@ update_appearance(UPDATE_ICON) /atom/movable/screen/lobby/button/MouseExited() - if(owner != REF(usr)) + if(usr != get_mob()) return if(!usr.client || usr.client.interviewee) diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm index e2e534443691a..2d82bb0c1e6e8 100644 --- a/code/_onclick/hud/robot.dm +++ b/code/_onclick/hud/robot.dm @@ -87,11 +87,6 @@ using.screen_loc = ui_borg_navigate_menu static_inventory += using -// Z-level floor change - using = new /atom/movable/screen/floor_menu(null, src) - using.screen_loc = ui_borg_floor_menu - static_inventory += using - //Radio using = new /atom/movable/screen/robot/radio(null, src) using.screen_loc = ui_borg_radio @@ -149,6 +144,11 @@ action_intent.screen_loc = ui_combat_toggle static_inventory += action_intent + floor_change = new /atom/movable/screen/floor_changer(null, src) + floor_change.icon = ui_style + floor_change.screen_loc = ui_borg_floor_changer + static_inventory += floor_change + //Health healths = new /atom/movable/screen/healths/robot(null, src) infodisplay += healths diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index cb06e00d116ef..31390c62cbb91 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -160,33 +160,6 @@ /atom/movable/screen/language_menu/Click() usr.get_language_holder().open_language_menu(usr) -/atom/movable/screen/floor_menu - name = "change floor" - icon = 'icons/hud/screen_midnight.dmi' - icon_state = "floor_change" - screen_loc = ui_floor_menu - -/atom/movable/screen/floor_menu/Initialize(mapload) - . = ..() - register_context() - -/atom/movable/screen/floor_menu/add_context(atom/source, list/context, obj/item/held_item, mob/user) - . = ..() - - context[SCREENTIP_CONTEXT_LMB] = "Go up a floor" - context[SCREENTIP_CONTEXT_RMB] = "Go down a floor" - return CONTEXTUAL_SCREENTIP_SET - -/atom/movable/screen/floor_menu/Click(location,control,params) - var/list/modifiers = params2list(params) - - if(LAZYACCESS(modifiers, RIGHT_CLICK) || LAZYACCESS(modifiers, ALT_CLICK)) - usr.down() - return - - usr.up() - return - /atom/movable/screen/inventory /// The identifier for the slot. It has nothing to do with ID cards. var/slot_id @@ -380,6 +353,34 @@ icon = 'icons/hud/screen_cyborg.dmi' screen_loc = ui_borg_intents +/atom/movable/screen/floor_changer + name = "change floor" + icon = 'icons/hud/screen_midnight.dmi' + icon_state = "floor_change" + screen_loc = ui_floor_changer + var/vertical = FALSE + +/atom/movable/screen/floor_changer/Click(location,control,params) + var/list/modifiers = params2list(params) + + var/mouse_position + + if(vertical) + mouse_position = text2num(LAZYACCESS(modifiers, ICON_Y)) + else + mouse_position = text2num(LAZYACCESS(modifiers, ICON_X)) + + if(mouse_position > 16) + usr.up() + return + + usr.down() + return + +/atom/movable/screen/floor_changer/vertical + icon_state = "floor_change_v" + vertical = TRUE + /atom/movable/screen/spacesuit name = "Space suit cell status" icon_state = "spacesuit_0" diff --git a/code/controllers/subsystem/ai_controllers.dm b/code/controllers/subsystem/ai_controllers.dm index e7aa6b53fdc21..49c571a9a0763 100644 --- a/code/controllers/subsystem/ai_controllers.dm +++ b/code/controllers/subsystem/ai_controllers.dm @@ -23,14 +23,12 @@ SUBSYSTEM_DEF(ai_controllers) /datum/controller/subsystem/ai_controllers/fire(resumed) var/timer = TICK_USAGE_REAL for(var/datum/ai_controller/ai_controller as anything in GLOB.ai_controllers_by_status[planning_status]) - if(!COOLDOWN_FINISHED(ai_controller, failed_planning_cooldown)) - continue - if(!ai_controller.able_to_plan) continue ai_controller.SelectBehaviors(wait * 0.1) + if(!length(ai_controller.current_behaviors)) //Still no plan - COOLDOWN_START(ai_controller, failed_planning_cooldown, AI_FAILED_PLANNING_COOLDOWN) + ai_controller.planning_failed() our_cost = MC_AVERAGE(our_cost, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer)) diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm index 4557e153db190..bbc21becc0f3b 100644 --- a/code/controllers/subsystem/air.dm +++ b/code/controllers/subsystem/air.dm @@ -488,29 +488,26 @@ SUBSYSTEM_DEF(air) T.excited = FALSE ///Adds a turf to active processing, handles duplicates. Call this with blockchanges == TRUE if you want to nuke the assoc excited group -/datum/controller/subsystem/air/proc/add_to_active(turf/open/T, blockchanges = FALSE) - if(istype(T) && T.air) - T.significant_share_ticker = 0 - if(blockchanges && T.excited_group) //This is used almost exclusivly for shuttles, so the excited group doesn't stay behind - T.excited_group.garbage_collect() //Nuke it - if(T.excited) //Don't keep doing it if there's no point +/datum/controller/subsystem/air/proc/add_to_active(turf/open/activate, blockchanges = FALSE) + if(istype(activate) && activate.air) + activate.significant_share_ticker = 0 + if(blockchanges && activate.excited_group) //This is used almost exclusivly for shuttles, so the excited group doesn't stay behind + activate.excited_group.garbage_collect() //Nuke it + if(activate.excited) //Don't keep doing it if there's no point return #ifdef VISUALIZE_ACTIVE_TURFS - T.add_atom_colour(COLOR_VIBRANT_LIME, TEMPORARY_COLOUR_PRIORITY) + activate.add_atom_colour(COLOR_VIBRANT_LIME, TEMPORARY_COLOUR_PRIORITY) #endif - T.excited = TRUE - active_turfs += T - if(currentpart == SSAIR_ACTIVETURFS) - currentrun += T - else if(T.flags_1 & INITIALIZED_1) - for(var/turf/S in T.atmos_adjacent_turfs) - add_to_active(S, TRUE) + activate.excited = TRUE + active_turfs += activate + else if(activate.flags_1 & INITIALIZED_1) + for(var/turf/neighbor as anything in activate.atmos_adjacent_turfs) + add_to_active(neighbor, TRUE) else if(map_loading) if(queued_for_activation) - queued_for_activation[T] = T - return + queued_for_activation[activate] = activate else - T.requires_activation = TRUE + activate.requires_activation = TRUE /datum/controller/subsystem/air/StartLoadingMap() LAZYINITLIST(queued_for_activation) @@ -560,8 +557,8 @@ SUBSYSTEM_DEF(air) if(enemy_tile.current_cycle == -INFINITE) continue // .air instead of .return_air() because we can guarantee that the proc won't do anything - if(potential_diff.air.compare(enemy_tile.air)) - //testing("Active turf found. Return value of compare(): [T.air.compare(enemy_tile.air)]") + if(potential_diff.air.compare(enemy_tile.air, MOLES)) + //testing("Active turf found. Return value of compare(): [T.air.compare(enemy_tile.air, MOLES)]") if(!potential_diff.excited) potential_diff.excited = TRUE SSair.active_turfs += potential_diff diff --git a/code/controllers/subsystem/bitrunning.dm b/code/controllers/subsystem/bitrunning.dm index 78afb101945b0..63c2561f0f496 100644 --- a/code/controllers/subsystem/bitrunning.dm +++ b/code/controllers/subsystem/bitrunning.dm @@ -25,7 +25,7 @@ SUBSYSTEM_DEF(bitrunning) var/can_view_reward = domain.difficulty < (scanner_tier + 1) && domain.cost <= points + 3 UNTYPED_LIST_ADD(levels, list( - "announce_ghosts"= domain.announce_to_ghosts, + "announce_ghosts" = domain.announce_to_ghosts, "cost" = domain.cost, "desc" = can_view ? domain.desc : "Limited scanning capabilities. Cannot infer domain details.", "difficulty" = domain.difficulty, diff --git a/code/controllers/subsystem/dynamic/dynamic.dm b/code/controllers/subsystem/dynamic/dynamic.dm index 2092b3efacd8f..c3edc30dc6866 100644 --- a/code/controllers/subsystem/dynamic/dynamic.dm +++ b/code/controllers/subsystem/dynamic/dynamic.dm @@ -526,7 +526,7 @@ SUBSYSTEM_DEF(dynamic) //To new_player and such, and we want the datums to just free when the roundstart work is done var/list/roundstart_rules = init_rulesets(/datum/dynamic_ruleset/roundstart) - SSjob.DivideOccupations(pure = TRUE, allow_all = TRUE) + SSjob.divide_occupations(pure = TRUE, allow_all = TRUE) for(var/i in GLOB.new_player_list) var/mob/dead/new_player/player = i if(player.ready == PLAYER_READY_TO_PLAY && player.mind && player.check_preferences()) @@ -541,7 +541,7 @@ SUBSYSTEM_DEF(dynamic) else roundstart_pop_ready++ candidates.Add(player) - SSjob.ResetOccupations() + SSjob.reset_occupations() log_dynamic("Listing [roundstart_rules.len] round start rulesets, and [candidates.len] players ready.") if (candidates.len <= 0) log_dynamic("[candidates.len] candidates.") @@ -1018,7 +1018,7 @@ SUBSYSTEM_DEF(dynamic) var/list/reopened_jobs = list() for(var/mob/living/quitter in GLOB.suicided_mob_list) - var/datum/job/job = SSjob.GetJob(quitter.job) + var/datum/job/job = SSjob.get_job(quitter.job) if(!job || !(job.job_flags & JOB_REOPEN_ON_ROUNDSTART_LOSS)) continue if(!include_command && job.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND) diff --git a/code/controllers/subsystem/dynamic/dynamic_rulesets.dm b/code/controllers/subsystem/dynamic/dynamic_rulesets.dm index c77cce50d0157..0d3242a4d17b2 100644 --- a/code/controllers/subsystem/dynamic/dynamic_rulesets.dm +++ b/code/controllers/subsystem/dynamic/dynamic_rulesets.dm @@ -283,7 +283,7 @@ if(length(exclusive_roles)) var/exclusive_candidate = FALSE for(var/role in exclusive_roles) - var/datum/job/job = SSjob.GetJob(role) + var/datum/job/job = SSjob.get_job(role) if((role in candidate_client.prefs.job_preferences) && SSjob.check_job_eligibility(candidate_player, job, "Dynamic Roundstart TC", add_job_to_log = TRUE) == JOB_AVAILABLE) exclusive_candidate = TRUE diff --git a/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm b/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm index 3476702e741ed..efe857b936ddf 100644 --- a/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm +++ b/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm @@ -413,7 +413,7 @@ return ..() /datum/dynamic_ruleset/midround/from_ghosts/nuclear/finish_setup(mob/new_character, index) - new_character.mind.set_assigned_role(SSjob.GetJobType(/datum/job/nuclear_operative)) + new_character.mind.set_assigned_role(SSjob.get_job_type(/datum/job/nuclear_operative)) new_character.mind.special_role = ROLE_NUCLEAR_OPERATIVE if(index == 1) var/datum/antagonist/nukeop/leader/leader_antag_datum = new() @@ -572,7 +572,7 @@ var/mob/living/carbon/human/new_nightmare = new (find_maintenance_spawn(atmos_sensitive = TRUE, require_darkness = TRUE)) player_mind.transfer_to(new_nightmare) - player_mind.set_assigned_role(SSjob.GetJobType(/datum/job/nightmare)) + player_mind.set_assigned_role(SSjob.get_job_type(/datum/job/nightmare)) player_mind.special_role = ROLE_NIGHTMARE player_mind.add_antag_datum(/datum/antagonist/nightmare) new_nightmare.set_species(/datum/species/shadow/nightmare) @@ -991,7 +991,7 @@ var/mob/living/carbon/human/voidwalker = new (space_turf) player_mind.transfer_to(voidwalker) - player_mind.set_assigned_role(SSjob.GetJobType(/datum/job/voidwalker)) + player_mind.set_assigned_role(SSjob.get_job_type(/datum/job/voidwalker)) player_mind.special_role = antag_flag player_mind.add_antag_datum(antag_datum) diff --git a/code/controllers/subsystem/dynamic/dynamic_rulesets_roundstart.dm b/code/controllers/subsystem/dynamic/dynamic_rulesets_roundstart.dm index 999cd156b18d8..79eedc0adb8d7 100644 --- a/code/controllers/subsystem/dynamic/dynamic_rulesets_roundstart.dm +++ b/code/controllers/subsystem/dynamic/dynamic_rulesets_roundstart.dm @@ -63,7 +63,7 @@ GLOBAL_VAR_INIT(revolutionary_win, FALSE) flags = HIGH_IMPACT_RULESET /datum/dynamic_ruleset/roundstart/malf_ai/ready(forced) - var/datum/job/ai_job = SSjob.GetJobType(/datum/job/ai) + var/datum/job/ai_job = SSjob.get_job_type(/datum/job/ai) // If we're not forced, we're going to make sure we can actually have an AI in this shift, if(!forced && min(ai_job.total_positions - ai_job.current_positions, ai_job.spawn_positions) <= 0) @@ -75,7 +75,7 @@ GLOBAL_VAR_INIT(revolutionary_win, FALSE) /datum/dynamic_ruleset/roundstart/malf_ai/pre_execute(population) . = ..() - var/datum/job/ai_job = SSjob.GetJobType(/datum/job/ai) + var/datum/job/ai_job = SSjob.get_job_type(/datum/job/ai) // Maybe a bit too pedantic, but there should never be more malf AIs than there are available positions, spawn positions or antag cap allocations. var/num_malf = min(get_antag_cap(population), min(ai_job.total_positions - ai_job.current_positions, ai_job.spawn_positions)) for (var/i in 1 to num_malf) @@ -296,7 +296,7 @@ GLOBAL_VAR_INIT(revolutionary_win, FALSE) var/mob/M = pick_n_take(candidates) if (M) assigned += M.mind - M.mind.set_assigned_role(SSjob.GetJobType(/datum/job/space_wizard)) + M.mind.set_assigned_role(SSjob.get_job_type(/datum/job/space_wizard)) M.mind.special_role = ROLE_WIZARD return TRUE @@ -429,7 +429,7 @@ GLOBAL_VAR_INIT(revolutionary_win, FALSE) break var/mob/M = pick_n_take(candidates) assigned += M.mind - M.mind.set_assigned_role(SSjob.GetJobType(job_type)) + M.mind.set_assigned_role(SSjob.get_job_type(job_type)) M.mind.special_role = required_role return TRUE diff --git a/code/controllers/subsystem/id_access.dm b/code/controllers/subsystem/id_access.dm index b80e5718128bd..faa2df1050ec2 100644 --- a/code/controllers/subsystem/id_access.dm +++ b/code/controllers/subsystem/id_access.dm @@ -409,6 +409,12 @@ SUBSYSTEM_DEF(id_access) if(trim.assignment) id_card.assignment = trim.assignment + var/datum/job/trim_job = trim.find_job() + if (!isnull(trim_job) && !isnull(id_card.registered_account)) + var/datum/job/old_job = id_card.registered_account.account_job + id_card.registered_account.account_job = trim_job + id_card.registered_account.update_account_job_lists(trim_job, old_job) + id_card.update_label() id_card.update_icon() diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index b1629237dc6bf..0b04b25c59721 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -22,7 +22,7 @@ SUBSYSTEM_DEF(job) var/list/unassigned = list() //Players who need jobs var/initial_players_to_assign = 0 //used for checking against population caps - // Whether to run DivideOccupations pure so that there are no side-effects from calling it other than + // Whether to run divide_occupations pure so that there are no side-effects from calling it other than // a player's assigned_role being set to some value. var/run_divide_occupation_pure = FALSE @@ -31,7 +31,7 @@ SUBSYSTEM_DEF(job) var/overflow_role = /datum/job/assistant - var/list/level_order = list(JP_HIGH,JP_MEDIUM,JP_LOW) + var/list/level_order = list(JP_HIGH, JP_MEDIUM, JP_LOW) /// Lazylist of mob:occupation_string pairs. var/list/dynamic_forced_occupations @@ -88,7 +88,7 @@ SUBSYSTEM_DEF(job) setup_job_lists() job_config_datum_singletons = generate_config_singletons() // we set this up here regardless in case someone wants to use the verb to generate the config file. if(!length(all_occupations)) - SetupOccupations() + setup_occupations() if(CONFIG_GET(flag/load_jobs_from_txt)) load_jobs_from_config() set_overflow_role(CONFIG_GET(string/overflow_job)) // this must always go after load_jobs_from_config() due to how the legacy systems operate, this always takes precedent. @@ -108,9 +108,9 @@ SUBSYSTEM_DEF(job) return overflow_jobs /datum/controller/subsystem/job/proc/set_overflow_role(new_overflow_role) - var/datum/job/new_overflow = ispath(new_overflow_role) ? GetJobType(new_overflow_role) : GetJob(new_overflow_role) + var/datum/job/new_overflow = ispath(new_overflow_role) ? get_job_type(new_overflow_role) : get_job(new_overflow_role) if(!new_overflow) - JobDebug("Failed to set new overflow role: [new_overflow_role]") + job_debug("SET_OVRFLW: Failed to set new overflow role: [new_overflow_role]") CRASH("set_overflow_role failed | new_overflow_role: [isnull(new_overflow_role) ? "null" : new_overflow_role]") var/cap = CONFIG_GET(number/overflow_cap) @@ -121,17 +121,16 @@ SUBSYSTEM_DEF(job) if(new_overflow.type == overflow_role) return - var/datum/job/old_overflow = GetJobType(overflow_role) + var/datum/job/old_overflow = get_job_type(overflow_role) old_overflow.allow_bureaucratic_error = initial(old_overflow.allow_bureaucratic_error) old_overflow.spawn_positions = initial(old_overflow.spawn_positions) old_overflow.total_positions = initial(old_overflow.total_positions) if(!(initial(old_overflow.job_flags) & JOB_CANNOT_OPEN_SLOTS)) old_overflow.job_flags &= ~JOB_CANNOT_OPEN_SLOTS overflow_role = new_overflow.type - JobDebug("Overflow role set to : [new_overflow.type]") + job_debug("SET_OVRFLW: Overflow role set to: [new_overflow.type]") - -/datum/controller/subsystem/job/proc/SetupOccupations() +/datum/controller/subsystem/job/proc/setup_occupations() name_occupations = list() type_occupations = list() @@ -205,20 +204,20 @@ SUBSYSTEM_DEF(job) return TRUE -/datum/controller/subsystem/job/proc/GetJob(rank) +/datum/controller/subsystem/job/proc/get_job(rank) if(!length(all_occupations)) - SetupOccupations() + setup_occupations() return name_occupations[rank] -/datum/controller/subsystem/job/proc/GetJobType(jobtype) +/datum/controller/subsystem/job/proc/get_job_type(jobtype) RETURN_TYPE(/datum/job) if(!length(all_occupations)) - SetupOccupations() + setup_occupations() return type_occupations[jobtype] /datum/controller/subsystem/job/proc/get_department_type(department_type) if(!length(all_occupations)) - SetupOccupations() + setup_occupations() return joinable_departments_by_type[department_type] /** @@ -230,89 +229,92 @@ SUBSYSTEM_DEF(job) * * latejoin - Set to TRUE if this is a latejoin role assignment. * * do_eligibility_checks - Set to TRUE to conduct all job eligibility tests and reject on failure. Set to FALSE if job eligibility has been tested elsewhere and they can be safely skipped. */ -/datum/controller/subsystem/job/proc/AssignRole(mob/dead/new_player/player, datum/job/job, latejoin = FALSE, do_eligibility_checks = TRUE) - JobDebug("Running AR, Player: [player], Job: [isnull(job) ? "null" : job], LateJoin: [latejoin]") +/datum/controller/subsystem/job/proc/assign_role(mob/dead/new_player/player, datum/job/job, latejoin = FALSE, do_eligibility_checks = TRUE) + job_debug("AR: Running, Player: [player], Job: [isnull(job) ? "null" : job], LateJoin: [latejoin]") if(!player?.mind || !job) - JobDebug("AR has failed, player has no mind or job is null, Player: [player], Rank: [isnull(job) ? "null" : job.type]") + job_debug("AR: Failed, player has no mind or job is null. Player: [player], Rank: [isnull(job) ? "null" : job.type]") return FALSE if(do_eligibility_checks && (check_job_eligibility(player, job, "AR", add_job_to_log = TRUE) != JOB_AVAILABLE)) return FALSE - JobDebug("Player: [player] is now Rank: [job.title], JCP:[job.current_positions], JPL:[latejoin ? job.total_positions : job.spawn_positions]") + job_debug("AR: Role now set and assigned - [player] is [job.title], JCP:[job.current_positions], JPL:[latejoin ? job.total_positions : job.spawn_positions]") player.mind.set_assigned_role(job) unassigned -= player job.current_positions++ return TRUE -/datum/controller/subsystem/job/proc/FindOccupationCandidates(datum/job/job, level) - JobDebug("Running FOC, Job: [job], Level: [job_priority_level_to_string(level)]") +/datum/controller/subsystem/job/proc/find_occupation_candidates(datum/job/job, level = 0) + job_debug("FOC: Now running, Job: [job], Level: [job_priority_level_to_string(level)]") var/list/candidates = list() for(var/mob/dead/new_player/player in unassigned) if(!player) - JobDebug("FOC player no longer exists.") + job_debug("FOC: Player no longer exists.") continue + if(!player.client) - JobDebug("FOC player client no longer exists, Player: [player]") + job_debug("FOC: Player client no longer exists, Player: [player]") continue + // Initial screening check. Does the player even have the job enabled, if they do - Is it at the correct priority level? var/player_job_level = player.client?.prefs.job_preferences[job.title] if(isnull(player_job_level)) - JobDebug("FOC player job not enabled, Player: [player]") + job_debug("FOC: Player job not enabled, Player: [player]") continue - else if(player_job_level != level) - JobDebug("FOC player job enabled at wrong level, Player: [player], TheirLevel: [job_priority_level_to_string(player_job_level)], ReqLevel: [job_priority_level_to_string(level)]") + + if(level && (player_job_level != level)) + job_debug("FOC: Player job enabled at wrong level, Player: [player], TheirLevel: [job_priority_level_to_string(player_job_level)], ReqLevel: [job_priority_level_to_string(level)]") continue - // This check handles its own output to JobDebug. + // This check handles its own output to job_debug. if(check_job_eligibility(player, job, "FOC", add_job_to_log = FALSE) != JOB_AVAILABLE) continue // They have the job enabled, at this priority level, with no restrictions applying to them. - JobDebug("FOC pass, Player: [player], Level: [job_priority_level_to_string(level)]") + job_debug("FOC: Player eligible, Player: [player], Level: [job_priority_level_to_string(level)]") candidates += player return candidates -/datum/controller/subsystem/job/proc/GiveRandomJob(mob/dead/new_player/player) - JobDebug("GRJ Giving random job, Player: [player]") +/datum/controller/subsystem/job/proc/give_random_job(mob/dead/new_player/player) + job_debug("GRJ: Giving random job, Player: [player]") . = FALSE for(var/datum/job/job as anything in shuffle(joinable_occupations)) if(QDELETED(player)) - JobDebug("GRJ player is deleted, aborting") + job_debug("GRJ: Player is deleted, aborting") break if((job.current_positions >= job.spawn_positions) && job.spawn_positions != -1) - JobDebug("GRJ job lacks spawn positions to be eligible, Player: [player], Job: [job]") + job_debug("GRJ: Job lacks spawn positions to be eligible, Player: [player], Job: [job]") continue - if(istype(job, GetJobType(overflow_role))) // We don't want to give him assistant, that's boring! - JobDebug("GRJ skipping overflow role, Player: [player], Job: [job]") + if(istype(job, get_job_type(overflow_role))) // We don't want to give him assistant, that's boring! + job_debug("GRJ: Skipping overflow role, Player: [player], Job: [job]") continue if(job.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND) //If you want a command position, select it! - JobDebug("GRJ skipping command role, Player: [player], Job: [job]") + job_debug("GRJ: Skipping command role, Player: [player], Job: [job]") continue - // This check handles its own output to JobDebug. + // This check handles its own output to job_debug. if(check_job_eligibility(player, job, "GRJ", add_job_to_log = TRUE) != JOB_AVAILABLE) continue - if(AssignRole(player, job, do_eligibility_checks = FALSE)) - JobDebug("GRJ Random job given, Player: [player], Job: [job]") + if(assign_role(player, job, do_eligibility_checks = FALSE)) + job_debug("GRJ: Random job given, Player: [player], Job: [job]") return TRUE - JobDebug("GRJ Player eligible but AssignRole failed, Player: [player], Job: [job]") + job_debug("GRJ: Player eligible but assign_role failed, Player: [player], Job: [job]") -/datum/controller/subsystem/job/proc/ResetOccupations() - JobDebug("Occupations reset.") +/datum/controller/subsystem/job/proc/reset_occupations() + job_debug("RO: Occupations reset.") for(var/mob/dead/new_player/player as anything in GLOB.new_player_list) if(!player?.mind) continue - player.mind.set_assigned_role(GetJobType(/datum/job/unassigned)) + player.mind.set_assigned_role(get_job_type(/datum/job/unassigned)) player.mind.special_role = null - SetupOccupations() + setup_occupations() unassigned = list() if(CONFIG_GET(flag/load_jobs_from_txt)) // Any errors with the configs has already been said, we don't need to repeat them here. @@ -321,12 +323,11 @@ SUBSYSTEM_DEF(job) return -/** - * Will try to select a head, ignoring ALL non-head preferences for every level until. - * - * Basically tries to ensure there is at least one head in every shift if anyone has that job preference enabled at all. +/* + * Forces a random Head of Staff role to be assigned to a random eligible player. + * Returns TRUE if a player was selected and assigned the role. FALSE otherwise. */ -/datum/controller/subsystem/job/proc/FillHeadPosition() +/datum/controller/subsystem/job/proc/force_one_head_assignment() var/datum/job_department/command_department = get_department_type(/datum/job_department/command) if(!command_department) return FALSE @@ -334,60 +335,65 @@ SUBSYSTEM_DEF(job) for(var/datum/job/job as anything in command_department.department_jobs) if((job.current_positions >= job.total_positions) && job.total_positions != -1) continue - var/list/candidates = FindOccupationCandidates(job, level) + var/list/candidates = find_occupation_candidates(job, level) if(!candidates.len) continue var/mob/dead/new_player/candidate = pick(candidates) - // Eligibility checks done as part of FindOccupationCandidates. - if(AssignRole(candidate, job, do_eligibility_checks = FALSE)) + // Eligibility checks done as part of find_occupation_candidates. + if(assign_role(candidate, job, do_eligibility_checks = FALSE)) return TRUE return FALSE /** * Attempts to fill out all possible head positions for players with that job at a a given job priority level. + * Returns the number of Head positions assigned. * * Arguments: - * * level - One of the JP_LOW, JP_MEDIUM or JP_HIGH defines. Attempts to find candidates with head jobs at this priority only. + * * level - One of the JP_LOW, JP_MEDIUM, JP_HIGH or JP_ANY defines. Attempts to find candidates with head jobs at that priority only. */ -/datum/controller/subsystem/job/proc/CheckHeadPositions(level) +/datum/controller/subsystem/job/proc/fill_all_head_positions_at_priority(level) + . = 0 var/datum/job_department/command_department = get_department_type(/datum/job_department/command) + if(!command_department) - return + return . + for(var/datum/job/job as anything in command_department.department_jobs) if((job.current_positions >= job.total_positions) && job.total_positions != -1) continue - var/list/candidates = FindOccupationCandidates(job, level) + var/list/candidates = find_occupation_candidates(job, level) if(!candidates.len) continue var/mob/dead/new_player/candidate = pick(candidates) - // Eligibility checks done as part of FindOccupationCandidates - AssignRole(candidate, job, do_eligibility_checks = FALSE) + // Eligibility checks done as part of find_occupation_candidates + if(assign_role(candidate, job, do_eligibility_checks = FALSE)) + .++ /// Attempts to fill out all available AI positions. /datum/controller/subsystem/job/proc/fill_ai_positions() - var/datum/job/ai_job = GetJob(JOB_AI) + var/datum/job/ai_job = get_job(JOB_AI) if(!ai_job) return // In byond for(in to) loops, the iteration is inclusive so we need to stop at ai_job.total_positions - 1 for(var/i in ai_job.current_positions to ai_job.total_positions - 1) for(var/level in level_order) var/list/candidates = list() - candidates = FindOccupationCandidates(ai_job, level) + candidates = find_occupation_candidates(ai_job, level) if(candidates.len) var/mob/dead/new_player/candidate = pick(candidates) - // Eligibility checks done as part of FindOccupationCandidates - if(AssignRole(candidate, GetJobType(/datum/job/ai), do_eligibility_checks = FALSE)) + // Eligibility checks done as part of find_occupation_candidates + if(assign_role(candidate, get_job_type(/datum/job/ai), do_eligibility_checks = FALSE)) break -/** Proc DivideOccupations +/** Proc divide_occupations * fills var "assigned_role" for all ready players. * This proc must not have any side effect besides of modifying "assigned_role". **/ -/datum/controller/subsystem/job/proc/DivideOccupations(pure = FALSE, allow_all = FALSE) +/datum/controller/subsystem/job/proc/divide_occupations(pure = FALSE, allow_all = FALSE) //Setup new player list and get the jobs list - JobDebug("Running DO, allow_all = [allow_all], pure = [pure]") + job_debug("DO: Running, allow_all = [allow_all], pure = [pure]") run_divide_occupation_pure = pure SEND_SIGNAL(src, COMSIG_OCCUPATIONS_DIVIDED, pure, allow_all) @@ -397,162 +403,166 @@ SUBSYSTEM_DEF(job) if(player.ready == PLAYER_READY_TO_PLAY && player.check_preferences() && player.mind && is_unassigned_job(player.mind.assigned_role)) unassigned += player - initial_players_to_assign = unassigned.len + initial_players_to_assign = length(unassigned) - JobDebug("DO, Len: [unassigned.len]") + job_debug("DO: Player count to assign roles to: [initial_players_to_assign]") //Scale number of open security officer slots to population setup_officer_positions() //Jobs will have fewer access permissions if the number of players exceeds the threshold defined in game_options.txt - var/mat = CONFIG_GET(number/minimal_access_threshold) - if(mat) - if(mat > unassigned.len) + var/min_access_threshold = CONFIG_GET(number/minimal_access_threshold) + if(min_access_threshold) + if(min_access_threshold > initial_players_to_assign) CONFIG_SET(flag/jobs_have_minimal_access, FALSE) else CONFIG_SET(flag/jobs_have_minimal_access, TRUE) - //Shuffle players and jobs - unassigned = shuffle(unassigned) + //Shuffle player list. + shuffle_inplace(unassigned) - HandleFeedbackGathering() + handle_feedback_gathering() - // Dynamic has picked a ruleset that requires enforcing some jobs before others. - JobDebug("DO, Assigning Priority Positions: [length(dynamic_forced_occupations)]") + // Assign any priority positions before all other standard job selections. + job_debug("DO: Assigning priority positions") assign_priority_positions() + job_debug("DO: Priority assignment complete") + + // The overflow role has limitless slots, plus having the Overflow box ticked in prefs should (with one exception) set the priority to JP_HIGH. + // So everyone with overflow enabled will get that job. Thus we can assign it immediately to all players that have it enabled. + job_debug("DO: Assigning early overflow roles") + assign_all_overflow_positions() + job_debug("DO: Early overflow roles assigned.") + + // At this point we can assume the following: + // From assign_priority_positions() + // 1. If possible, any necessary job roles to allow Dynamic rulesets to execute (such as an AI for malf AI) are satisfied. + // 2. All Head of Staff roles with any player pref set to JP_HIGH are filled out. + // 3. If any player not selected by the above has any Head of Staff preference enabled at any JP_ level, there is at least one Head of Staff. + // + // From assign_all_overflow_positions() + // 4. Anyone with the overflow role enabled has been given the overflow role. + + // Shuffle the joinable occupation list and filter out ineligible occupations due to above job assignments. + var/list/available_occupations = joinable_occupations.Copy() + for(var/datum/job/job in available_occupations) + // Make sure the job isn't filled. If it is, remove it from the list so it doesn't get checked. + if((job.current_positions >= job.spawn_positions) && job.spawn_positions != -1) + job_debug("DO: Job is now filled, Job: [job], Current: [job.current_positions], Limit: [job.spawn_positions]") + available_occupations -= job - //People who wants to be the overflow role, sure, go on. - JobDebug("DO, Running Overflow Check 1") - var/datum/job/overflow_datum = GetJobType(overflow_role) - var/list/overflow_candidates = FindOccupationCandidates(overflow_datum, JP_LOW) - JobDebug("AC1, Candidates: [overflow_candidates.len]") - for(var/mob/dead/new_player/player in overflow_candidates) - JobDebug("AC1 pass, Player: [player]") - // Eligibility checks done as part of FindOccupationCandidates - AssignRole(player, GetJobType(overflow_role), do_eligibility_checks = FALSE) - overflow_candidates -= player - JobDebug("DO, AC1 end") - - //Select one head - JobDebug("DO, Running Head Check") - FillHeadPosition() - JobDebug("DO, Head Check end") - - // Fill out any remaining AI positions. - JobDebug("DO, Running AI Check") - fill_ai_positions() - JobDebug("DO, AI Check end") - - //Other jobs are now checked - JobDebug("DO, Running standard job assignment") - // New job giving system by Donkie - // This will cause lots of more loops, but since it's only done once it shouldn't really matter much at all. - // Hopefully this will add more randomness and fairness to job giving. + job_debug("DO: Running standard job assignment") - // Loop through all levels from high to low - var/list/shuffledoccupations = shuffle(joinable_occupations) for(var/level in level_order) - //Check the head jobs first each level - CheckHeadPositions(level) + job_debug("JOBS: Filling in head roles, Level: [job_priority_level_to_string(level)]") + // Fill the head jobs first each level + fill_all_head_positions_at_priority(level) // Loop through all unassigned players for(var/mob/dead/new_player/player in unassigned) if(!allow_all) - if(PopcapReached()) - RejectPlayer(player) - - // Loop through all jobs - for(var/datum/job/job in shuffledoccupations) // SHUFFLE ME BABY - if(!job) - JobDebug("FOC invalid/null job in occupations, Player: [player], Job: [job]") - shuffledoccupations -= job - continue + if(popcap_reached()) + job_debug("JOBS: Popcap reached, trying to reject player: [player]") + try_reject_player(player) - // Make sure the job isn't filled. If it is, remove it from the list so it doesn't get checked again. - if((job.current_positions >= job.spawn_positions) && job.spawn_positions != -1) - JobDebug("FOC job filled and not overflow, Player: [player], Job: [job], Current: [job.current_positions], Limit: [job.spawn_positions]") - shuffledoccupations -= job - continue + job_debug("JOBS: Finding a job for player: [player], at job priority pref: [job_priority_level_to_string(level)]") + // Loop through all jobs and build a list of jobs this player could be eligible for. + var/list/possible_jobs = list() + for(var/datum/job/job in available_occupations) // Filter any job that doesn't fit the current level. var/player_job_level = player.client?.prefs.job_preferences[job.title] if(isnull(player_job_level)) - JobDebug("FOC player job not enabled, Player: [player]") + job_debug("JOBS: Job not enabled, Job: [job]") continue - else if(player_job_level != level) - JobDebug("FOC player job enabled but at different level, Player: [player], TheirLevel: [job_priority_level_to_string(player_job_level)], ReqLevel: [job_priority_level_to_string(level)]") + if(player_job_level != level) + job_debug("JOBS: Job enabled at different priority pref, Job: [job], TheirLevel: [job_priority_level_to_string(player_job_level)], ReqLevel: [job_priority_level_to_string(level)]") continue - if(check_job_eligibility(player, job, "DO", add_job_to_log = TRUE) != JOB_AVAILABLE) + if(check_job_eligibility(player, job, "JOBS", add_job_to_log = TRUE) != JOB_AVAILABLE) continue - JobDebug("DO pass, Player: [player], Level:[level], Job:[job.title]") - AssignRole(player, job, do_eligibility_checks = FALSE) - unassigned -= player - break + possible_jobs += job + + // If there are no possible jobs for them at this priority, skip them. + if(!length(possible_jobs)) + job_debug("JOBS: Player not eligible for any available jobs at this priority level: [player]") + continue - JobDebug("DO, Ending standard job assignment") + // Otherwise, pick one of those jobs at random. + var/datum/job/picked_job = pick(possible_jobs) - JobDebug("DO, Handle unassigned.") - // Hand out random jobs to the people who didn't get any in the last check - // Also makes sure that they got their preference correct + job_debug("JOBS: Now assigning role to player: [player], Job:[picked_job.title]") + assign_role(player, picked_job, do_eligibility_checks = FALSE) + if((picked_job.current_positions >= picked_job.spawn_positions) && picked_job.spawn_positions != -1) + job_debug("JOBS: Job is now full, Job: [picked_job], Positions: [picked_job.current_positions], Limit: [picked_job.spawn_positions]") + available_occupations -= picked_job + + job_debug("DO: Ending standard job assignment") + + job_debug("DO: Handle unassigned") + // For any players that didn't get a job, fall back on their pref setting for what to do. for(var/mob/dead/new_player/player in unassigned) - HandleUnassigned(player, allow_all) - JobDebug("DO, Ending handle unassigned.") + handle_unassigned(player, allow_all) + job_debug("DO: Ending handle unassigned") - JobDebug("DO, Handle unrejectable unassigned") + job_debug("DO: Handle unrejectable unassigned") //Mop up people who can't leave. for(var/mob/dead/new_player/player in unassigned) //Players that wanted to back out but couldn't because they're antags (can you feel the edge case?) - if(!GiveRandomJob(player)) - if(!AssignRole(player, GetJobType(overflow_role))) //If everything is already filled, make them an assistant - JobDebug("DO, Forced antagonist could not be assigned any random job or the overflow role. DivideOccupations failed.") - JobDebug("---------------------------------------------------") + if(!give_random_job(player)) + if(!assign_role(player, get_job_type(overflow_role))) //If everything is already filled, make them an assistant + job_debug("DO: Forced antagonist could not be assigned any random job or the overflow role. divide_occupations failed.") + job_debug("---------------------------------------------------") run_divide_occupation_pure = FALSE return FALSE //Living on the edge, the forced antagonist couldn't be assigned to overflow role (bans, client age) - just reroll - JobDebug("DO, Ending handle unrejectable unassigned") + job_debug("DO: Ending handle unrejectable unassigned") - JobDebug("All divide occupations tasks completed.") - JobDebug("---------------------------------------------------") + job_debug("All divide occupations tasks completed.") + job_debug("---------------------------------------------------") run_divide_occupation_pure = FALSE return TRUE //We couldn't find a job from prefs for this guy. -/datum/controller/subsystem/job/proc/HandleUnassigned(mob/dead/new_player/player, allow_all = FALSE) +/datum/controller/subsystem/job/proc/handle_unassigned(mob/dead/new_player/player, allow_all = FALSE) var/jobless_role = player.client.prefs.read_preference(/datum/preference/choiced/jobless_role) if(!allow_all) - if(PopcapReached()) - RejectPlayer(player) + if(popcap_reached()) + job_debug("HU: Popcap reached, trying to reject player: [player]") + try_reject_player(player) return switch (jobless_role) if (BEOVERFLOW) - var/datum/job/overflow_role_datum = GetJobType(overflow_role) + var/datum/job/overflow_role_datum = get_job_type(overflow_role) if(check_job_eligibility(player, overflow_role_datum, debug_prefix = "HU", add_job_to_log = TRUE) != JOB_AVAILABLE) - RejectPlayer(player) + job_debug("HU: Player cannot be overflow, trying to reject: [player]") + try_reject_player(player) return - if(!AssignRole(player, overflow_role_datum, do_eligibility_checks = FALSE)) - RejectPlayer(player) + if(!assign_role(player, overflow_role_datum, do_eligibility_checks = FALSE)) + job_debug("HU: Player could not be assigned overflow role, trying to reject: [player]") + try_reject_player(player) return if (BERANDOMJOB) - if(!GiveRandomJob(player)) - RejectPlayer(player) + if(!give_random_job(player)) + job_debug("HU: Player cannot be given a random job, trying to reject: [player]") + try_reject_player(player) return if (RETURNTOLOBBY) - RejectPlayer(player) + job_debug("HU: Player unable to be assigned job, return to lobby enabled: [player]") + try_reject_player(player) return else //Something gone wrong if we got here. - var/message = "HU: [player] fell through handling unassigned" - JobDebug(message) - log_game(message) - message_admins(message) - RejectPlayer(player) + job_debug("HU: [player] has an invalid jobless_role var: [jobless_role]") + log_game("[player] has an invalid jobless_role var: [jobless_role]") + message_admins("[player] has an invalid jobless_role, this shouldn't happen.") + try_reject_player(player) //Gives the player the stuff he should have with his rank -/datum/controller/subsystem/job/proc/EquipRank(mob/living/equipping, datum/job/job, client/player_client) +/datum/controller/subsystem/job/proc/equip_rank(mob/living/equipping, datum/job/job, client/player_client) equipping.job = job.title SEND_SIGNAL(equipping, COMSIG_JOB_RECEIVED, job) @@ -572,7 +582,7 @@ SUBSYSTEM_DEF(job) /datum/controller/subsystem/job/proc/handle_auto_deadmin_roles(client/C, rank) if(!C?.holder) return TRUE - var/datum/job/job = GetJob(rank) + var/datum/job/job = get_job(rank) var/timegate_expired = FALSE // allow only forcing deadminning in the first X seconds of the round if auto_deadmin_timegate is set in config @@ -590,7 +600,7 @@ SUBSYSTEM_DEF(job) return C.holder.auto_deadmin() /datum/controller/subsystem/job/proc/setup_officer_positions() - var/datum/job/J = SSjob.GetJob(JOB_SECURITY_OFFICER) + var/datum/job/J = SSjob.get_job(JOB_SECURITY_OFFICER) if(!J) CRASH("setup_officer_positions(): Security officer job is missing") @@ -598,7 +608,7 @@ SUBSYSTEM_DEF(job) if(ssc > 0) if(J.spawn_positions > 0) var/officer_positions = min(12, max(J.spawn_positions, round(unassigned.len / ssc))) //Scale between configured minimum and 12 officers - JobDebug("Setting open security officer positions to [officer_positions]") + job_debug("SOP: Setting open security officer positions to [officer_positions]") J.total_positions = officer_positions J.spawn_positions = officer_positions @@ -614,7 +624,7 @@ SUBSYSTEM_DEF(job) else //We ran out of spare locker spawns! break -/datum/controller/subsystem/job/proc/HandleFeedbackGathering() +/datum/controller/subsystem/job/proc/handle_feedback_gathering() for(var/datum/job/job as anything in joinable_occupations) var/high = 0 //high var/medium = 0 //medium @@ -653,7 +663,7 @@ SUBSYSTEM_DEF(job) SSblackbox.record_feedback("nested tally", "job_preferences", young, list("[job.title]", "young")) SSblackbox.record_feedback("nested tally", "job_preferences", newbie, list("[job.title]", "newbie")) -/datum/controller/subsystem/job/proc/PopcapReached() +/datum/controller/subsystem/job/proc/popcap_reached() var/hpc = CONFIG_GET(number/hard_popcap) var/epc = CONFIG_GET(number/extreme_popcap) if(hpc || epc) @@ -662,12 +672,12 @@ SUBSYSTEM_DEF(job) return 1 return 0 -/datum/controller/subsystem/job/proc/RejectPlayer(mob/dead/new_player/player) +/datum/controller/subsystem/job/proc/try_reject_player(mob/dead/new_player/player) if(player.mind && player.mind.special_role) - return - if(PopcapReached()) - JobDebug("Popcap overflow Check observer located, Player: [player]") - JobDebug("Player rejected :[player]") + job_debug("RJCT: Player unable to be rejected due to special_role, Player: [player], SpecialRole: [player.mind.special_role]") + return FALSE + + job_debug("RJCT: Player rejected, Player: [player]") unassigned -= player if(!run_divide_occupation_pure) to_chat(player, "You have failed to qualify for any job you desired.") @@ -679,10 +689,10 @@ SUBSYSTEM_DEF(job) var/oldjobs = SSjob.all_occupations sleep(2 SECONDS) for (var/datum/job/job as anything in oldjobs) - INVOKE_ASYNC(src, PROC_REF(RecoverJob), job) + INVOKE_ASYNC(src, PROC_REF(recover_job), job) -/datum/controller/subsystem/job/proc/RecoverJob(datum/job/J) - var/datum/job/newjob = GetJob(J.title) +/datum/controller/subsystem/job/proc/recover_job(datum/job/J) + var/datum/job/newjob = get_job(J.title) if (!istype(newjob)) return newjob.total_positions = J.total_positions @@ -699,7 +709,7 @@ SUBSYSTEM_DEF(job) if(buckle && isliving(joining_mob)) buckle_mob(joining_mob, FALSE, FALSE) -/datum/controller/subsystem/job/proc/SendToLateJoin(mob/M, buckle = TRUE) +/datum/controller/subsystem/job/proc/send_to_late_join(mob/M, buckle = TRUE) var/atom/destination if(M.mind && !is_unassigned_job(M.mind.assigned_role) && length(GLOB.jobspawn_overrides[M.mind.assigned_role.title])) //We're doing something special today. destination = pick(GLOB.jobspawn_overrides[M.mind.assigned_role.title]) @@ -734,19 +744,6 @@ SUBSYSTEM_DEF(job) stack_trace("Unable to find last resort spawn point.") return GET_ERROR_ROOM -///Lands specified mob at a random spot in the hallways -/datum/controller/subsystem/job/proc/DropLandAtRandomHallwayPoint(mob/living/living_mob) - var/turf/spawn_turf = get_safe_random_station_turf(typesof(/area/station/hallway)) - - if(!spawn_turf) - SendToLateJoin(living_mob) - else - podspawn(list( - "target" = spawn_turf, - "path" = /obj/structure/closet/supplypod/centcompod, - "spawn" = living_mob - )) - /// Returns a list of minds of all heads of staff who are alive /datum/controller/subsystem/job/proc/get_living_heads() . = list() @@ -781,7 +778,7 @@ SUBSYSTEM_DEF(job) if(sec.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_SECURITY) . += sec -/datum/controller/subsystem/job/proc/JobDebug(message) +/datum/controller/subsystem/job/proc/job_debug(message) log_job_debug(message) /// Builds various lists of jobs based on station, centcom and additional jobs with icons associated with them. @@ -846,12 +843,47 @@ SUBSYSTEM_DEF(job) safe_code_timer_id = null safe_code_request_loc = null -/// Blindly assigns the required roles to every player in the dynamic_forced_occupations list. +/// Assigns roles that are considered high priority, either due to dynamic needing to force a specific role for a specific ruleset +/// or making sure roles critical to round progression exist where possible every shift. /datum/controller/subsystem/job/proc/assign_priority_positions() + job_debug("APP: Assigning Dynamic ruleset forced occupations: [length(dynamic_forced_occupations)]") for(var/mob/new_player in dynamic_forced_occupations) - // Eligibility checks already carried out as part of the dynamic ruleset trim_candidates proc.area - // However no guarantee of game state between then and now, so don't skip eligibility checks on AssignRole. - AssignRole(new_player, GetJob(dynamic_forced_occupations[new_player])) + // Eligibility checks already carried out as part of the dynamic ruleset trim_candidates proc. + // However no guarantee of game state between then and now, so don't skip eligibility checks on assign_role. + assign_role(new_player, get_job(dynamic_forced_occupations[new_player])) + + // Get JP_HIGH department Heads of Staff in place. Indirectly useful for the Revolution ruleset to have as many Heads as possible. + job_debug("APP: Assigning all JP_HIGH head of staff roles.") + var/head_count = fill_all_head_positions_at_priority(JP_HIGH) + + // If nobody has JP_HIGH on a Head role, try to force at least one Head of Staff so every shift has the best chance + // of having at least one leadership role. + if(head_count == 0) + force_one_head_assignment() + + // Fill out all AI positions. + job_debug("APP: Filling all AI positions") + fill_ai_positions() + +/datum/controller/subsystem/job/proc/assign_all_overflow_positions() + job_debug("OVRFLW: Assigning all overflow roles.") + job_debug("OVRFLW: This shift's overflow role: [overflow_role]") + var/datum/job/overflow_datum = get_job_type(overflow_role) + + // When the Overflow role changes for any reason, this allows players to set otherwise invalid job priority pref states. + // So if Assistant is the "usual" Overflow but it gets changed to Clown for a shift, players can set the Assistant role's priorities + // to JP_MEDIUM and JP_LOW. When the "usual" Overflow role comes back, it returns to an On option in the prefs menu but still + // keeps its old JP_MEDIUM or JP_LOW value in the background. + + // Due to this prefs quirk, we actually don't want to find JP_HIGH candidates as it may exclude people with abnormal pref states that + // appear normal from the UI. By passing in JP_ANY, it will return all players that have the overflow job pref (which should be a toggle) + // set to any level. + var/list/overflow_candidates = find_occupation_candidates(overflow_datum, JP_ANY) + for(var/mob/dead/new_player/player in overflow_candidates) + // Eligibility checks done as part of find_occupation_candidates, so skip them. + assign_role(player, get_job_type(overflow_role), do_eligibility_checks = FALSE) + job_debug("OVRFLW: Assigned overflow to player: [player]") + job_debug("OVRFLW: All overflow roles assigned.") /// Takes a job priority #define such as JP_LOW and gets its string representation for logging. /datum/controller/subsystem/job/proc/job_priority_level_to_string(priority) @@ -869,40 +901,40 @@ SUBSYSTEM_DEF(job) * Arguments: * * player - The player to check for job eligibility. * * possible_job - The job to check for eligibility against. - * * debug_prefix - Logging prefix for the JobDebug log entries. For example, GRJ during GiveRandomJob or DO during DivideOccupations. + * * debug_prefix - Logging prefix for the job_debug log entries. For example, GRJ during give_random_job or DO during divide_occupations. * * add_job_to_log - If TRUE, appends the job type to the log entry. If FALSE, does not. Set to FALSE when check is part of iterating over players for a specific job, set to TRUE when check is part of iterating over jobs for a specific player and you don't want extra log entry spam. */ /datum/controller/subsystem/job/proc/check_job_eligibility(mob/dead/new_player/player, datum/job/possible_job, debug_prefix = "", add_job_to_log = FALSE) if(!player.mind) - JobDebug("[debug_prefix] player has no mind, Player: [player][add_job_to_log ? ", Job: [possible_job]" : ""]") + job_debug("[debug_prefix]: Player has no mind, Player: [player][add_job_to_log ? ", Job: [possible_job]" : ""]") return JOB_UNAVAILABLE_GENERIC if(possible_job.title in player.mind.restricted_roles) - JobDebug("[debug_prefix] Error: [get_job_unavailable_error_message(JOB_UNAVAILABLE_ANTAG_INCOMPAT, possible_job.title)], Player: [player][add_job_to_log ? ", Job: [possible_job]" : ""]") + job_debug("[debug_prefix] Error: [get_job_unavailable_error_message(JOB_UNAVAILABLE_ANTAG_INCOMPAT, possible_job.title)], Player: [player][add_job_to_log ? ", Job: [possible_job]" : ""]") return JOB_UNAVAILABLE_ANTAG_INCOMPAT if(!possible_job.player_old_enough(player.client)) - JobDebug("[debug_prefix] Error: [get_job_unavailable_error_message(JOB_UNAVAILABLE_ACCOUNTAGE, possible_job.title)], Player: [player][add_job_to_log ? ", Job: [possible_job]" : ""]") + job_debug("[debug_prefix] Error: [get_job_unavailable_error_message(JOB_UNAVAILABLE_ACCOUNTAGE, possible_job.title)], Player: [player][add_job_to_log ? ", Job: [possible_job]" : ""]") return JOB_UNAVAILABLE_ACCOUNTAGE var/required_playtime_remaining = possible_job.required_playtime_remaining(player.client) if(required_playtime_remaining) - JobDebug("[debug_prefix] Error: [get_job_unavailable_error_message(JOB_UNAVAILABLE_PLAYTIME, possible_job.title)], Player: [player], MissingTime: [required_playtime_remaining][add_job_to_log ? ", Job: [possible_job]" : ""]") + job_debug("[debug_prefix] Error: [get_job_unavailable_error_message(JOB_UNAVAILABLE_PLAYTIME, possible_job.title)], Player: [player], MissingTime: [required_playtime_remaining][add_job_to_log ? ", Job: [possible_job]" : ""]") return JOB_UNAVAILABLE_PLAYTIME // Run the banned check last since it should be the rarest check to fail and can access the database. if(is_banned_from(player.ckey, possible_job.title)) - JobDebug("[debug_prefix] Error: [get_job_unavailable_error_message(JOB_UNAVAILABLE_BANNED, possible_job.title)], Player: [player][add_job_to_log ? ", Job: [possible_job]" : ""]") + job_debug("[debug_prefix] Error: [get_job_unavailable_error_message(JOB_UNAVAILABLE_BANNED, possible_job.title)], Player: [player][add_job_to_log ? ", Job: [possible_job]" : ""]") return JOB_UNAVAILABLE_BANNED // Check for character age if(possible_job.required_character_age > player.client.prefs.read_preference(/datum/preference/numeric/age) && possible_job.required_character_age != null) - JobDebug("[debug_prefix] Error: [get_job_unavailable_error_message(JOB_UNAVAILABLE_AGE)], Player: [player][add_job_to_log ? ", Job: [possible_job]" : ""]") + job_debug("[debug_prefix] Error: [get_job_unavailable_error_message(JOB_UNAVAILABLE_AGE)], Player: [player][add_job_to_log ? ", Job: [possible_job]" : ""]") return JOB_UNAVAILABLE_AGE // Need to recheck the player exists after is_banned_from since it can query the DB which may sleep. if(QDELETED(player)) - JobDebug("[debug_prefix] player is qdeleted, Player: [player][add_job_to_log ? ", Job: [possible_job]" : ""]") + job_debug("[debug_prefix]: Player is qdeleted, Player: [player][add_job_to_log ? ", Job: [possible_job]" : ""]") return JOB_UNAVAILABLE_GENERIC return JOB_AVAILABLE diff --git a/code/controllers/subsystem/processing/ai_idle_behaviors.dm b/code/controllers/subsystem/processing/ai_idle_behaviors.dm index cda3d354882f4..8875d971ad87c 100644 --- a/code/controllers/subsystem/processing/ai_idle_behaviors.dm +++ b/code/controllers/subsystem/processing/ai_idle_behaviors.dm @@ -1,6 +1,17 @@ PROCESSING_SUBSYSTEM_DEF(idle_ai_behaviors) - name = "idle_ai_behaviors" - flags = SS_NO_INIT | SS_BACKGROUND + name = "AI Idle Behaviors" + flags = SS_BACKGROUND wait = 1.5 SECONDS priority = FIRE_PRIORITY_IDLE_NPC init_order = INIT_ORDER_AI_IDLE_CONTROLLERS //must execute only after ai behaviors are initialized + ///List of all the idle ai behaviors + var/list/idle_behaviors = list() + +/datum/controller/subsystem/processing/idle_ai_behaviors/Initialize() + setup_idle_behaviors() + return SS_INIT_SUCCESS + +/datum/controller/subsystem/processing/idle_ai_behaviors/proc/setup_idle_behaviors() + for(var/behavior_type in subtypesof(/datum/idle_behavior)) + var/datum/idle_behavior/behavior = new behavior_type + idle_behaviors[behavior_type] = behavior diff --git a/code/controllers/subsystem/processing/fishing.dm b/code/controllers/subsystem/processing/fishing.dm index a81ff0dec6783..0e8c126fe9330 100644 --- a/code/controllers/subsystem/processing/fishing.dm +++ b/code/controllers/subsystem/processing/fishing.dm @@ -13,10 +13,38 @@ PROCESSING_SUBSYSTEM_DEF(fishing) fish_properties = list() for(var/fish_type in subtypesof(/obj/item/fish)) var/obj/item/fish/fish = new fish_type(null, FALSE) - fish_properties[fish_type] = list() - fish_properties[fish_type][FISH_PROPERTIES_FAV_BAIT] = fish.favorite_bait.Copy() - fish_properties[fish_type][FISH_PROPERTIES_BAD_BAIT] = fish.disliked_bait.Copy() - fish_properties[fish_type][FISH_PROPERTIES_TRAITS] = fish.fish_traits.Copy() + var/list/properties = list() + fish_properties[fish_type] = properties + properties[FISH_PROPERTIES_FAV_BAIT] = fish.favorite_bait.Copy() + properties[FISH_PROPERTIES_BAD_BAIT] = fish.disliked_bait.Copy() + properties[FISH_PROPERTIES_TRAITS] = fish.fish_traits.Copy() + + var/list/evo_types = fish.evolution_types?.Copy() + properties[FISH_PROPERTIES_EVOLUTIONS] = evo_types + for(var/type in evo_types) + LAZYADD(GLOB.fishes_by_fish_evolution[type], fish_type) + + var/beauty_score = "???" + switch(fish.beauty) + if(-INFINITY to FISH_BEAUTY_DISGUSTING) + beauty_score = "OH HELL NAW!" + if(FISH_BEAUTY_DISGUSTING to FISH_BEAUTY_UGLY) + beauty_score = "☆☆☆☆☆" + if(FISH_BEAUTY_UGLY to FISH_BEAUTY_BAD) + beauty_score = "★☆☆☆☆" + if(FISH_BEAUTY_BAD to FISH_BEAUTY_NULL) + beauty_score = "★★☆☆☆" + if(FISH_BEAUTY_NULL to FISH_BEAUTY_GENERIC) + beauty_score = "★★★☆☆" + if(FISH_BEAUTY_GENERIC to FISH_BEAUTY_GOOD) + beauty_score = "★★★★☆" + if(FISH_BEAUTY_GOOD to FISH_BEAUTY_GREAT) + beauty_score = "★★★★★" + if(FISH_BEAUTY_GREAT to INFINITY) + beauty_score = "★★★★★★" + + properties[FISH_PROPERTIES_BEAUTY_SCORE] = beauty_score + qdel(fish) ///init the list of things lures can catch diff --git a/code/controllers/subsystem/processing/station.dm b/code/controllers/subsystem/processing/station.dm index 883ab37456d2c..c58840cfa7ad1 100644 --- a/code/controllers/subsystem/processing/station.dm +++ b/code/controllers/subsystem/processing/station.dm @@ -164,6 +164,8 @@ PROCESSING_SUBSYSTEM_DEF(station) ///Creates a given trait of a specific type, while also removing any blacklisted ones from the future pool. /datum/controller/subsystem/processing/station/proc/setup_trait(datum/station_trait/trait_type) + if(locate(trait_type) in station_traits) + return var/datum/station_trait/trait_instance = new trait_type() station_traits += trait_instance log_game("Station Trait: [trait_instance.name] chosen for this round.") @@ -179,5 +181,4 @@ PROCESSING_SUBSYSTEM_DEF(station) var/datum/hud/new_player/observer_hud = player.hud_used if (!istype(observer_hud)) continue - observer_hud.add_station_trait_buttons() - observer_hud.show_hud(observer_hud.hud_version) + observer_hud.show_station_trait_buttons() diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index baca9a1235486..f5a9309457246 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -236,14 +236,14 @@ SUBSYSTEM_DEF(ticker) can_continue = SSdynamic.pre_setup() //Choose antagonists CHECK_TICK SEND_GLOBAL_SIGNAL(COMSIG_GLOB_PRE_JOBS_ASSIGNED, src) - can_continue = can_continue && SSjob.DivideOccupations() //Distribute jobs + can_continue = can_continue && SSjob.divide_occupations() //Distribute jobs CHECK_TICK if(!GLOB.Debug2) if(!can_continue) log_game("Game failed pre_setup") to_chat(world, "Error setting up game. Reverting to pre-game lobby.") - SSjob.ResetOccupations() + SSjob.reset_occupations() return FALSE else message_admins(span_notice("DEBUG: Bypassing prestart checks...")) @@ -416,7 +416,7 @@ SUBSYSTEM_DEF(ticker) continue var/datum/job/player_assigned_role = new_player_living.mind.assigned_role if(player_assigned_role.job_flags & JOB_EQUIP_RANK) - SSjob.EquipRank(new_player_living, player_assigned_role, new_player_mob.client) + SSjob.equip_rank(new_player_living, player_assigned_role, new_player_mob.client) player_assigned_role.after_roundstart_spawn(new_player_living, new_player_mob.client) if(picked_spare_id_candidate == new_player_mob) captainless = FALSE diff --git a/code/datums/actions/action.dm b/code/datums/actions/action.dm index 39e69ba9fa8fd..d8247d3e92a5e 100644 --- a/code/datums/actions/action.dm +++ b/code/datums/actions/action.dm @@ -52,6 +52,8 @@ /// Toggles whether this action is usable or not var/action_disabled = FALSE + /// Can this action be shared with our rider? + var/can_be_shared = TRUE /datum/action/New(Target) link_to(Target) diff --git a/code/datums/actions/mobs/lava_swoop.dm b/code/datums/actions/mobs/lava_swoop.dm index aa512b2d28e8d..2b07734b4a852 100644 --- a/code/datums/actions/mobs/lava_swoop.dm +++ b/code/datums/actions/mobs/lava_swoop.dm @@ -39,7 +39,7 @@ return // stop swooped target movement swooping = TRUE - ADD_TRAIT(owner, TRAIT_UNDENSE, SWOOPING_TRAIT) + owner.add_traits(list(TRAIT_GODMODE, TRAIT_UNDENSE), SWOOPING_TRAIT) owner.visible_message(span_boldwarning("[owner] swoops up high!")) var/negative @@ -66,7 +66,6 @@ animate(owner, alpha = 255, transform = oldtransform, time = 0, flags = ANIMATION_END_NOW) //reset immediately return animate(owner, alpha = 100, transform = matrix()*0.7, time = 7) - owner.status_flags |= GODMODE SEND_SIGNAL(owner, COMSIG_SWOOP_INVULNERABILITY_STARTED) owner.mouse_opacity = MOUSE_OPACITY_TRANSPARENT @@ -112,12 +111,11 @@ for(var/mob/observer in range(7, owner)) shake_camera(observer, 15, 1) - REMOVE_TRAIT(owner, TRAIT_UNDENSE, SWOOPING_TRAIT) + owner.remove_traits(list(TRAIT_GODMODE, TRAIT_UNDENSE), SWOOPING_TRAIT) SLEEP_CHECK_DEATH(1, owner) swooping = FALSE if(!lava_success) SEND_SIGNAL(owner, COMSIG_LAVA_ARENA_FAILED) - owner.status_flags &= ~GODMODE /datum/action/cooldown/mob_cooldown/lava_swoop/proc/lava_pools(atom/target, amount = 30, delay = 0.8) if(!target) diff --git a/code/datums/actions/mobs/personality_commune.dm b/code/datums/actions/mobs/personality_commune.dm index 26cf483449204..8481d451fb1dd 100644 --- a/code/datums/actions/mobs/personality_commune.dm +++ b/code/datums/actions/mobs/personality_commune.dm @@ -31,7 +31,7 @@ var/mob/living/split_personality/non_controller = usr var/client/non_controller_client = non_controller.client - var/to_send = tgui_input_text(non_controller, "What would you like to tell your other self?", "Commune") + var/to_send = tgui_input_text(non_controller, "What would you like to tell your other self?", "Commune", max_length = MAX_MESSAGE_LEN) if(QDELETED(src) || QDELETED(trauma) || !to_send) return FALSE diff --git a/code/datums/ai/_ai_controller.dm b/code/datums/ai/_ai_controller.dm index 499da54b1b1eb..4d5b660044322 100644 --- a/code/datums/ai/_ai_controller.dm +++ b/code/datums/ai/_ai_controller.dm @@ -39,8 +39,6 @@ multiple modular subtrees with behaviors var/continue_processing_when_client = FALSE ///distance to give up on target var/max_target_distance = 14 - ///Cooldown for new plans, to prevent AI from going nuts if it can't think of new plans and looping on end - COOLDOWN_DECLARE(failed_planning_cooldown) ///All subtrees this AI has available, will run them in order, so make sure they're in the order you want them to run. On initialization of this type, it will start as a typepath(s) and get converted to references of ai_subtrees found in SSai_controllers when init_subtrees() is called var/list/planning_subtrees @@ -69,14 +67,15 @@ multiple modular subtrees with behaviors var/able_to_run = FALSE /// are we even able to plan? var/able_to_plan = TRUE + /// are we currently on failed planning timeout? + var/on_failed_planning_timeout = FALSE /datum/ai_controller/New(atom/new_pawn) change_ai_movement_type(ai_movement) init_subtrees() - if(idle_behavior) - idle_behavior = new idle_behavior() + idle_behavior = SSidle_ai_behaviors.idle_behaviors[idle_behavior] if(!isnull(new_pawn)) // unit tests need the ai_controller to exist in isolation due to list schenanigans i hate it here PossessPawn(new_pawn) @@ -240,7 +239,7 @@ multiple modular subtrees with behaviors if(!pawn_turf) CRASH("AI controller [src] controlling pawn ([pawn]) is not on a turf.") #endif - if(!length(SSmobs.clients_by_zlevel[pawn_turf.z])) + if(!length(SSmobs.clients_by_zlevel[pawn_turf.z]) || on_failed_planning_timeout || !able_to_run) return AI_STATUS_OFF if(should_idle()) return AI_STATUS_IDLE @@ -300,6 +299,9 @@ multiple modular subtrees with behaviors /datum/ai_controller/proc/update_able_to_run() SIGNAL_HANDLER able_to_run = get_able_to_run() + if(!able_to_run) + GLOB.move_manager.stop_looping(pawn) //stop moving + set_ai_status(get_expected_ai_status()) ///Returns TRUE if the ai controller can actually run at the moment, FALSE otherwise /datum/ai_controller/proc/get_able_to_run() @@ -312,10 +314,6 @@ multiple modular subtrees with behaviors ///Runs any actions that are currently running /datum/ai_controller/process(seconds_per_tick) - if(!able_to_run) - GLOB.move_manager.stop_looping(pawn) //stop moving - return //this should remove them from processing in the future through event-based stuff. - if(!length(current_behaviors) && idle_behavior) idle_behavior.perform_idle_behavior(seconds_per_tick, src) //Do some stupid shit while we have nothing to do return @@ -491,6 +489,7 @@ multiple modular subtrees with behaviors /datum/ai_controller/proc/on_stat_changed(mob/living/source, new_stat) SIGNAL_HANDLER reset_ai_status() + update_able_to_run() /datum/ai_controller/proc/on_sentience_gained() SIGNAL_HANDLER @@ -531,6 +530,15 @@ multiple modular subtrees with behaviors minimum_distance = iter_behavior.required_distance return minimum_distance +/datum/ai_controller/proc/planning_failed() + on_failed_planning_timeout = TRUE + set_ai_status(get_expected_ai_status()) + addtimer(CALLBACK(src, PROC_REF(resume_planning)), AI_FAILED_PLANNING_COOLDOWN) + +/datum/ai_controller/proc/resume_planning() + on_failed_planning_timeout = FALSE + set_ai_status(get_expected_ai_status()) + /// Returns true if we have a blackboard key with the provided key and it is not qdeleting /datum/ai_controller/proc/blackboard_key_exists(key) var/datum/key_value = blackboard[key] diff --git a/code/datums/ai/basic_mobs/base_basic_controller.dm b/code/datums/ai/basic_mobs/base_basic_controller.dm index a14630fa0e83a..f21d31b05000c 100644 --- a/code/datums/ai/basic_mobs/base_basic_controller.dm +++ b/code/datums/ai/basic_mobs/base_basic_controller.dm @@ -19,9 +19,12 @@ /datum/ai_controller/basic_controller/setup_able_to_run() . = ..() RegisterSignal(pawn, COMSIG_MOB_INCAPACITATE_CHANGED, PROC_REF(update_able_to_run)) + if(ai_traits & PAUSE_DURING_DO_AFTER) + RegisterSignals(pawn, list(COMSIG_DO_AFTER_BEGAN, COMSIG_DO_AFTER_ENDED), PROC_REF(update_able_to_run)) + /datum/ai_controller/basic_controller/clear_able_to_run() - UnregisterSignal(pawn, list(COMSIG_MOB_INCAPACITATE_CHANGED, COMSIG_MOB_STATCHANGE)) + UnregisterSignal(pawn, list(COMSIG_MOB_INCAPACITATE_CHANGED, COMSIG_MOB_STATCHANGE, COMSIG_DO_AFTER_BEGAN, COMSIG_DO_AFTER_ENDED)) return ..() /datum/ai_controller/basic_controller/get_able_to_run() diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/emote_with_target.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/emote_with_target.dm index 8f4483d4dafdd..7960301d70440 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/emote_with_target.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/emote_with_target.dm @@ -14,7 +14,7 @@ var/atom/target = controller.blackboard[target_key] if(!length(emote_list) || isnull(target)) return AI_BEHAVIOR_FAILED | AI_BEHAVIOR_DELAY - run_emote(controller.pawn, target_key, emote_list) + run_emote(controller.pawn, target, emote_list) return AI_BEHAVIOR_SUCCEEDED | AI_BEHAVIOR_DELAY diff --git a/code/datums/ai/basic_mobs/targeting_strategies/basic_targeting_strategy.dm b/code/datums/ai/basic_mobs/targeting_strategies/basic_targeting_strategy.dm index 709acb8d5e892..d552b69c142dc 100644 --- a/code/datums/ai/basic_mobs/targeting_strategies/basic_targeting_strategy.dm +++ b/code/datums/ai/basic_mobs/targeting_strategies/basic_targeting_strategy.dm @@ -25,8 +25,7 @@ if(ismob(the_target)) //Target is in godmode, ignore it. if(living_mob.loc == the_target) return FALSE // We've either been eaten or are shapeshifted, let's assume the latter because we're still alive - var/mob/M = the_target - if(M.status_flags & GODMODE) + if(HAS_TRAIT(the_target, TRAIT_GODMODE)) return FALSE if (vision_range && get_dist(living_mob, the_target) > vision_range) diff --git a/code/datums/ai/movement/_ai_movement.dm b/code/datums/ai/movement/_ai_movement.dm index c1b3aae5bd60f..33b7e4e214f6b 100644 --- a/code/datums/ai/movement/_ai_movement.dm +++ b/code/datums/ai/movement/_ai_movement.dm @@ -11,6 +11,7 @@ controller.consecutive_pathing_attempts = 0 controller.set_blackboard_key(BB_CURRENT_MIN_MOVE_DISTANCE, min_distance) moving_controllers[controller] = current_movement_target + SEND_SIGNAL(controller.pawn, COMSIG_MOB_AI_MOVEMENT_STARTED, current_movement_target) /datum/ai_movement/proc/stop_moving_towards(datum/ai_controller/controller) controller.consecutive_pathing_attempts = 0 diff --git a/code/datums/ai_laws/ai_laws.dm b/code/datums/ai_laws/ai_laws.dm index 0dbc6839430ba..a0d1d629fc8d3 100644 --- a/code/datums/ai_laws/ai_laws.dm +++ b/code/datums/ai_laws/ai_laws.dm @@ -192,7 +192,7 @@ GLOBAL_VAR(round_default_lawset) var/datum/ai_laws/default_laws = get_round_default_lawset() default_laws = new default_laws() inherent = default_laws.inherent - var/datum/job/human_ai_job = SSjob.GetJob(JOB_HUMAN_AI) + var/datum/job/human_ai_job = SSjob.get_job(JOB_HUMAN_AI) if(human_ai_job && human_ai_job.current_positions && !zeroth) //there is a human AI so we "slave" to that. zeroth = "Follow the orders of Big Brother." protected_zeroth = TRUE diff --git a/code/datums/brain_damage/creepy_trauma.dm b/code/datums/brain_damage/creepy_trauma.dm index 742f1fe57e9db..d908dfc0e613c 100644 --- a/code/datums/brain_damage/creepy_trauma.dm +++ b/code/datums/brain_damage/creepy_trauma.dm @@ -66,7 +66,8 @@ /datum/brain_trauma/special/obsessed/on_lose() ..() - owner.mind.remove_antag_datum(/datum/antagonist/obsessed) + if (owner.mind.remove_antag_datum(/datum/antagonist/obsessed)) + owner.mind.add_antag_datum(/datum/antagonist/former_obsessed) owner.clear_mood_event("creeping") if(obsession) log_game("[key_name(owner)] is no longer obsessed with [key_name(obsession)].") diff --git a/code/datums/brain_damage/imaginary_friend.dm b/code/datums/brain_damage/imaginary_friend.dm index f4c78bc9007e6..99467c570990f 100644 --- a/code/datums/brain_damage/imaginary_friend.dm +++ b/code/datums/brain_damage/imaginary_friend.dm @@ -156,11 +156,11 @@ for(var/job in appearance_from_prefs.job_preferences) var/this_pref = appearance_from_prefs.job_preferences[job] if(this_pref > highest_pref) - appearance_job = SSjob.GetJob(job) + appearance_job = SSjob.get_job(job) highest_pref = this_pref if(!appearance_job) - appearance_job = SSjob.GetJob(JOB_ASSISTANT) + appearance_job = SSjob.get_job(JOB_ASSISTANT) if(istype(appearance_job, /datum/job/ai)) human_image = icon('icons/mob/silicon/ai.dmi', icon_state = resolve_ai_icon(appearance_from_prefs.read_preference(/datum/preference/choiced/ai_core_display)), dir = SOUTH) diff --git a/code/datums/components/adjust_fishing_difficulty.dm b/code/datums/components/adjust_fishing_difficulty.dm new file mode 100644 index 0000000000000..b2f5f71a757d8 --- /dev/null +++ b/code/datums/components/adjust_fishing_difficulty.dm @@ -0,0 +1,110 @@ +///Influences the difficulty of the minigame when worn or if buckled to. +/datum/component/adjust_fishing_difficulty + ///The additive numerical modifier to the difficulty of the minigame + var/modifier + ///For items, in which slot it has to be worn to influence the difficulty of the minigame + var/slots + +/datum/component/adjust_fishing_difficulty/Initialize(modifier, slots = NONE) + if(!ismovable(parent) || !modifier) + return COMPONENT_INCOMPATIBLE + + if(!isitem(parent)) + var/atom/movable/movable_parent = parent + if(!movable_parent.can_buckle) + return COMPONENT_INCOMPATIBLE + + src.modifier = modifier + src.slots = slots + +/datum/component/adjust_fishing_difficulty/RegisterWithParent() + if(isitem(parent)) + RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equipped)) + RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(on_dropped)) + RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_item_examine)) + else + RegisterSignal(parent, COMSIG_MOVABLE_BUCKLE, PROC_REF(on_buckle)) + RegisterSignal(parent, COMSIG_MOVABLE_UNBUCKLE, PROC_REF(on_unbuckle)) + RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_buckle_examine)) + + update_check() + +/datum/component/adjust_fishing_difficulty/UnregisterFromParent() + UnregisterSignal(parent, list( + COMSIG_ATOM_EXAMINE, + COMSIG_MOVABLE_BUCKLE, + COMSIG_MOVABLE_UNBUCKLE, + COMSIG_ITEM_EQUIPPED, + COMSIG_ITEM_DROPPED, + )) + + update_check(TRUE) + +/datum/component/adjust_fishing_difficulty/proc/update_check(removing = FALSE) + var/atom/movable/movable_parent = parent + for(var/mob/living/buckled_mob as anything in movable_parent.buckled_mobs) + update_user(buckled_mob, removing) + if(!isitem(movable_parent) || !isliving(movable_parent.loc)) + return + var/mob/living/holder = movable_parent.loc + var/obj/item/item = parent + if(holder.get_slot_by_item(movable_parent) & (slots || item.slot_flags)) + update_user(holder, removing) + +/datum/component/adjust_fishing_difficulty/proc/on_item_examine(obj/item/item, mob/user, list/examine_text) + SIGNAL_HANDLER + if(!HAS_MIND_TRAIT(user, TRAIT_EXAMINE_FISH)) + return + var/method = "[(slots || item.slot_flags) & ITEM_SLOT_HANDS ? "Holding" : "Wearing"] [item.p_them()]" + add_examine_line(user, examine_text, method) + +/datum/component/adjust_fishing_difficulty/proc/on_buckle_examine(atom/movable/source, mob/user, list/examine_text) + SIGNAL_HANDLER + if(!HAS_MIND_TRAIT(user, TRAIT_EXAMINE_FISH)) + return + add_examine_line(user, examine_text, "Buckling to [source.p_them()]") + +/datum/component/adjust_fishing_difficulty/proc/add_examine_line(mob/user, list/examine_text, method) + var/percent = HAS_MIND_TRAIT(user, TRAIT_EXAMINE_DEEPER_FISH) ? "[modifier]% " : "" + var/text = "[method] will make fishing [percent][modifier > 0 ? "easier" : "harder"]." + if(modifier > 0) + examine_text += span_nicegreen(text) + else + examine_text += span_danger(text) + +/datum/component/adjust_fishing_difficulty/proc/on_buckle(atom/movable/source, mob/living/buckled_mob, forced) + SIGNAL_HANDLER + update_user(buckled_mob) + +/datum/component/adjust_fishing_difficulty/proc/on_unbuckle(atom/movable/source, mob/living/buckled_mob, forced) + SIGNAL_HANDLER + update_user(buckled_mob, TRUE) + +/datum/component/adjust_fishing_difficulty/proc/on_equipped(obj/item/source, mob/living/wearer, slot) + SIGNAL_HANDLER + if(slot & (slots || source.slot_flags)) + update_user(wearer) + +/datum/component/adjust_fishing_difficulty/proc/on_dropped(obj/item/source, mob/living/dropper) + SIGNAL_HANDLER + update_user(dropper, TRUE) + +/datum/component/adjust_fishing_difficulty/proc/update_user(mob/living/user, removing = FALSE) + var/datum/fishing_challenge/challenge = GLOB.fishing_challenges_by_user[user] + if(removing) + UnregisterSignal(user, COMSIG_MOB_BEGIN_FISHING) + if(challenge) + UnregisterSignal(challenge, COMSIG_FISHING_CHALLENGE_GET_DIFFICULTY) + else + RegisterSignal(user, COMSIG_MOB_BEGIN_FISHING, PROC_REF(on_minigame_started)) + if(challenge) + RegisterSignal(challenge, COMSIG_FISHING_CHALLENGE_GET_DIFFICULTY, PROC_REF(adjust_difficulty)) + challenge?.update_difficulty() + +/datum/component/adjust_fishing_difficulty/proc/on_minigame_started(mob/living/source, datum/fishing_challenge/challenge) + SIGNAL_HANDLER + RegisterSignal(challenge, COMSIG_FISHING_CHALLENGE_GET_DIFFICULTY, PROC_REF(adjust_difficulty), TRUE) + +/datum/component/adjust_fishing_difficulty/proc/adjust_difficulty(datum/fishing_challenge/challenge, reward_path, obj/item/fishing_rod/rod, mob/living/user, list/holder) + SIGNAL_HANDLER + holder[1] += modifier diff --git a/code/datums/components/aquarium_content.dm b/code/datums/components/aquarium_content.dm index 57d62cdb0ee26..d956b39928a47 100644 --- a/code/datums/components/aquarium_content.dm +++ b/code/datums/components/aquarium_content.dm @@ -15,14 +15,7 @@ var/obj/structure/aquarium/current_aquarium //This is visual effect holder that will end up in aquarium's vis_contents - var/obj/effect/vc_obj - - /// Base px offset of the visual object in current aquarium aka current base position - var/base_px = 0 - /// Base px offset of the visual object in current aquarium aka current base position - var/base_py = 0 - //Current layer for the visual object - var/base_layer + var/obj/effect/aquarium/vc_obj /** * Fish sprite how to: @@ -33,37 +26,12 @@ * cover the extra pixels anyway. */ - /// Icon used for in aquarium sprite - var/icon = 'icons/obj/aquarium/fish.dmi' - /// If this is set this icon state will be used for the holder while icon_state will only be used for item/catalog. Transformation from source_width/height WON'T be applied. - var/icon_state - /// Applied to vc object only for use with greyscaled icons. - var/aquarium_vc_color - /// Transformation applied to the visual holder - used when scaled down sprites are used as in aquarium visual - var/matrix/base_transform - - /// How the thing will be layered - var/layer_mode = AQUARIUM_LAYER_MODE_AUTO - - /// If the starting position is randomised within bounds when inserted into aquarium. - var/randomize_position = FALSE - - //Target sprite size for path/position calculations. - var/sprite_height = 3 - var/sprite_width = 3 - /// Currently playing animation var/current_animation /// Does this behviour need additional processing in aquarium, will be added to SSobj processing on insertion var/processing = FALSE - /// TODO: Change this into trait checked on aquarium insertion - var/unique = FALSE - - /// Proc used to retrieve current animation state from the parent, optional - var/animation_getter - /// Signals of the parent that will trigger animation update var/animation_update_signals @@ -73,50 +41,27 @@ /// The original value of the beauty this component had when initialized var/original_beauty -/datum/component/aquarium_content/Initialize(icon, animation_getter, animation_update_signals, beauty) +/datum/component/aquarium_content/Initialize(animation_update_signals, beauty) if(!ismovable(parent)) return COMPONENT_INCOMPATIBLE - src.animation_getter = animation_getter src.animation_update_signals = animation_update_signals src.beauty = original_beauty = beauty if(animation_update_signals) RegisterSignals(parent, animation_update_signals, PROC_REF(generate_animation)) - if(istype(parent,/obj/item/fish)) - InitializeFromFish() - else if(istype(parent,/obj/item/aquarium_prop)) - InitializeFromProp() - else - InitializeOther() - ADD_TRAIT(parent, TRAIT_FISH_CASE_COMPATIBILE, REF(src)) RegisterSignal(parent, COMSIG_TRY_INSERTING_IN_AQUARIUM, PROC_REF(is_ready_to_insert)) RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(enter_aquarium)) - RegisterSignal(parent, COMSIG_FISH_PETTED, PROC_REF(on_fish_petted)) + + if(isfish(parent)) + RegisterSignal(parent, COMSIG_FISH_STATUS_CHANGED, PROC_REF(on_fish_status_changed)) //If component is added to something already in aquarium at the time initialize it properly. var/atom/movable/movable_parent = parent if(istype(movable_parent.loc, /obj/structure/aquarium)) on_inserted(movable_parent.loc) -/// Sets visuals properties for fish -/datum/component/aquarium_content/proc/InitializeFromFish() - var/obj/item/fish/fish = parent - - icon = fish.icon - sprite_height = fish.sprite_height - sprite_width = fish.sprite_width - aquarium_vc_color = fish.aquarium_vc_color - - icon = fish.dedicated_in_aquarium_icon - icon_state = fish.dedicated_in_aquarium_icon_state - base_transform = matrix() - - randomize_position = TRUE - - RegisterSignal(fish, COMSIG_FISH_STATUS_CHANGED, PROC_REF(on_fish_status_changed)) - /datum/component/aquarium_content/proc/on_fish_status_changed(obj/item/fish/source) SIGNAL_HANDLER var/old_beauty = beauty @@ -127,31 +72,6 @@ change_aquarium_beauty(beauty - old_beauty) generate_animation() -/// Sets visuals properties for fish -/datum/component/aquarium_content/proc/InitializeFromProp() - var/obj/item/aquarium_prop/prop = parent - - icon = prop.icon - icon_state = prop.icon_state - layer_mode = prop.layer_mode - sprite_height = 32 - sprite_width = 32 - base_transform = matrix() - - unique = TRUE - -/// Mostly for admin abuse -/datum/component/aquarium_content/proc/InitializeOther() - sprite_width = 8 - sprite_height = 8 - - var/matrix/matrix = matrix() - var/x_scale = sprite_width / 32 - var/y_scale = sprite_height / 32 - matrix.Scale(x_scale, y_scale) - base_transform = matrix - - /datum/component/aquarium_content/PreTransfer() . = ..() REMOVE_TRAIT(parent, TRAIT_FISH_CASE_COMPATIBILE, REF(src)) @@ -170,12 +90,11 @@ /datum/component/aquarium_content/proc/is_ready_to_insert(datum/source, obj/structure/aquarium/aquarium) SIGNAL_HANDLER - //This is kinda awful but we're unaware of other fish - if(unique) - for(var/atom/movable/fish_or_prop in aquarium) - if(fish_or_prop == parent) + if(HAS_TRAIT(parent, TRAIT_UNIQUE_AQUARIUM_CONTENT)) + for(var/atom/movable/content as anything in aquarium) + if(content == parent) continue - if(fish_or_prop.type == parent.type) + if(content.type == parent.type) return COMSIG_CANNOT_INSERT_IN_AQUARIUM return COMSIG_CAN_INSERT_IN_AQUARIUM @@ -190,7 +109,7 @@ //If we don't have vc object yet build it if(!vc_obj) - vc_obj = generate_base_vc() + generate_base_vc() //Set default position and layer set_vc_base_position() @@ -225,112 +144,28 @@ SIGNAL_HANDLER generate_animation() +///Sends a signal to the parent to get them to update the aquarium animation of the visual object +/datum/component/aquarium_content/proc/generate_animation(reset=FALSE) + if(!current_aquarium) + return + SEND_SIGNAL(parent, COMSIG_AQUARIUM_CONTENT_DO_ANIMATION, reset ? null : current_animation, current_aquarium, vc_obj) + /datum/component/aquarium_content/proc/remove_visual_from_aquarium() current_aquarium.vis_contents -= vc_obj - if(base_layer) - current_aquarium.free_layer(base_layer) + if(vc_obj.layer) + current_aquarium.free_layer(vc_obj.layer) /// Generates common visual object, propeties that don't depend on aquarium surface /datum/component/aquarium_content/proc/generate_base_vc() - var/obj/effect/visual = new - apply_appearance(visual) - visual.vis_flags |= VIS_INHERIT_ID | VIS_INHERIT_PLANE //plane so it shows properly in containers on inventory ui for handheld cases - return visual - -/// Applies icon,color and base scaling to our visual holder -/datum/component/aquarium_content/proc/apply_appearance(obj/effect/holder) - holder.icon = icon - holder.icon_state = icon_state - holder.transform = matrix(base_transform) - if(aquarium_vc_color) - holder.color = aquarium_vc_color - - -/// Actually animates the vc holder -/datum/component/aquarium_content/proc/generate_animation(reset=FALSE) - if(!current_aquarium) - return - var/next_animation = animation_getter ? call(parent,animation_getter)() : null - if(current_animation == next_animation && !reset) - return - current_animation = next_animation - switch(current_animation) - if(AQUARIUM_ANIMATION_FISH_SWIM) - swim_animation() - return - if(AQUARIUM_ANIMATION_FISH_DEAD) - dead_animation() - return - -/// Create looping random path animation, pixel offsets parameters include offsets already -/datum/component/aquarium_content/proc/swim_animation() - var/avg_width = round(sprite_width / 2) - var/avg_height = round(sprite_height / 2) - - var/list/aq_properties = current_aquarium.get_surface_properties() - var/px_min = aq_properties[AQUARIUM_PROPERTIES_PX_MIN] + avg_width - 16 - var/px_max = aq_properties[AQUARIUM_PROPERTIES_PX_MAX] - avg_width - 16 - var/py_min = aq_properties[AQUARIUM_PROPERTIES_PY_MIN] + avg_height - 16 - var/py_max = aq_properties[AQUARIUM_PROPERTIES_PY_MAX] - avg_width - 16 - - var/origin_x = base_px - var/origin_y = base_py - var/prev_x = origin_x - var/prev_y = origin_y - animate(vc_obj, pixel_x = origin_x, time = 0, loop = -1) //Just to start the animation - var/move_number = rand(3, 5) //maybe unhardcode this - for(var/i in 1 to move_number) - //If it's last movement, move back to start otherwise move to some random point - var/target_x = i == move_number ? origin_x : rand(px_min,px_max) //could do with enforcing minimal delta for prettier zigzags - var/target_y = i == move_number ? origin_y : rand(py_min,py_max) - var/dx = prev_x - target_x - var/dy = prev_y - target_y - prev_x = target_x - prev_y = target_y - var/dist = abs(dx) + abs(dy) - var/eyeballed_time = dist * 2 //2ds per px - //Face the direction we're going - var/matrix/dir_mx = matrix(base_transform) - if(dx <= 0) //assuming default sprite is facing left here - dir_mx.Scale(-1, 1) - animate(transform = dir_mx, time = 0, loop = -1) - animate(pixel_x = target_x, pixel_y = target_y, time = eyeballed_time, loop = -1) - -/datum/component/aquarium_content/proc/dead_animation() - //Set base_py to lowest possible value - var/avg_height = round(sprite_height / 2) - var/list/aq_properties = current_aquarium.get_surface_properties() - var/py_min = aq_properties[AQUARIUM_PROPERTIES_PY_MIN] + avg_height - 16 - base_py = py_min - animate(vc_obj, pixel_y = py_min, time = 1) //flop to bottom and end current animation. + vc_obj = new + vc_obj.vis_flags |= VIS_INHERIT_ID | VIS_INHERIT_PLANE //plane so it shows properly in containers on inventory ui for handheld cases + SEND_SIGNAL(parent, COMSIG_AQUARIUM_CONTENT_GENERATE_APPEARANCE, vc_obj) /datum/component/aquarium_content/proc/set_vc_base_position() - if(randomize_position) - randomize_base_position() - if(base_layer) - current_aquarium.free_layer(base_layer) - base_layer = current_aquarium.request_layer(layer_mode) - vc_obj.layer = base_layer - -/datum/component/aquarium_content/proc/on_fish_petted() - SIGNAL_HANDLER - - new /obj/effect/temp_visual/heart(get_turf(parent)) - -/datum/component/aquarium_content/proc/randomize_base_position() - var/list/aq_properties = current_aquarium.get_surface_properties() - var/avg_width = round(sprite_width / 2) - var/avg_height = round(sprite_height / 2) - var/px_min = aq_properties[AQUARIUM_PROPERTIES_PX_MIN] + avg_width - 16 - var/px_max = aq_properties[AQUARIUM_PROPERTIES_PX_MAX] - avg_width - 16 - var/py_min = aq_properties[AQUARIUM_PROPERTIES_PY_MIN] + avg_height - 16 - var/py_max = aq_properties[AQUARIUM_PROPERTIES_PY_MAX] - avg_width - 16 - - base_px = rand(px_min,px_max) - base_py = rand(py_min,py_max) - - vc_obj.pixel_x = base_px - vc_obj.pixel_y = base_py + SEND_SIGNAL(parent, AQUARIUM_CONTENT_RANDOMIZE_POSITION, current_aquarium, vc_obj) + if(vc_obj.layer) + current_aquarium.free_layer(vc_obj.layer) + vc_obj.layer = current_aquarium.request_layer(vc_obj.layer_mode) /datum/component/aquarium_content/proc/on_removed(obj/structure/aquarium/source, atom/movable/gone, direction) SIGNAL_HANDLER @@ -344,6 +179,16 @@ remove_visual_from_aquarium() current_aquarium = null +///The visual overlay of the aquarium content. It holds a few vars that we can modity them during signals. +/obj/effect/aquarium + layer = 0 //set on set_vc_base_position + /// Base px offset of the visual object in current aquarium aka current base position + var/base_px = 0 + /// Base px offset of the visual object in current aquarium aka current base position + var/base_py = 0 + /// How the visual will be layered + var/layer_mode = AQUARIUM_LAYER_MODE_AUTO + #undef DEAD_FISH_BEAUTY #undef MIN_DEAD_FISH_BEAUTY #undef MAX_DEAD_FISH_BEAUTY diff --git a/code/datums/components/area_based_godmode.dm b/code/datums/components/area_based_godmode.dm index 4f03ae57794c8..b9447efbafbf8 100644 --- a/code/datums/components/area_based_godmode.dm +++ b/code/datums/components/area_based_godmode.dm @@ -34,8 +34,6 @@ var/mob/mob_target = parent if(!istype(mob_target)) return COMPONENT_INCOMPATIBLE - if(initial(mob_target.status_flags) & GODMODE) - return COMPONENT_INCOMPATIBLE sources_to_area_type = list() src.gain_message = gain_message @@ -102,11 +100,11 @@ /datum/component/area_based_godmode/proc/check_area(mob/source) SIGNAL_HANDLER - var/has_godmode = source.status_flags & GODMODE + var/has_godmode = HAS_TRAIT(source, TRAIT_GODMODE) if(!check_in_valid_area(source)) if(has_godmode) to_chat(source, lose_message) - source.status_flags ^= GODMODE + REMOVE_TRAIT(source, TRAIT_GODMODE, REF(src)) check_area_cached_state = FALSE return @@ -115,7 +113,7 @@ return to_chat(source, gain_message) - source.status_flags ^= GODMODE + ADD_TRAIT(source, TRAIT_GODMODE, REF(src)) #undef MAP_AREA_TYPE #undef MAP_ALLOW_AREA_SUBTYPES diff --git a/code/datums/components/chuunibyou.dm b/code/datums/components/chuunibyou.dm index 4e06f0fd47486..5724b93488f49 100644 --- a/code/datums/components/chuunibyou.dm +++ b/code/datums/components/chuunibyou.dm @@ -64,7 +64,7 @@ /datum/component/chuunibyou/proc/on_try_speech(datum/source, message, ignore_spam, forced) SIGNAL_HANDLER - if(casting_spell) + if(casting_spell && !HAS_TRAIT(src, TRAIT_MUTE)) return COMPONENT_IGNORE_CAN_SPEAK ///signal sent when the parent casts a spell that has a projectile diff --git a/code/datums/components/cleaner.dm b/code/datums/components/cleaner.dm index 3001fde9837fb..75319a7133f4d 100644 --- a/code/datums/components/cleaner.dm +++ b/code/datums/components/cleaner.dm @@ -62,6 +62,9 @@ /datum/component/cleaner/proc/on_interaction(datum/source, mob/living/user, atom/target, list/modifiers) SIGNAL_HANDLER + if(isitem(source) && SHOULD_SKIP_INTERACTION(target, source, user)) + return NONE + // By default, give XP var/give_xp = TRUE if(pre_clean_callback) diff --git a/code/datums/components/crafting/crafting.dm b/code/datums/components/crafting/crafting.dm index ec6df83b8042f..54f77d4579e23 100644 --- a/code/datums/components/crafting/crafting.dm +++ b/code/datums/components/crafting/crafting.dm @@ -268,9 +268,11 @@ qdel(thing) var/datum/reagents/holder = locate() in parts if(holder) //transfer reagents from ingredients to result - if(!ispath(recipe.result, /obj/item/reagent_containers) && result.reagents) - result.reagents.clear_reagents() - holder.trans_to(result.reagents, holder.total_volume, no_react = TRUE) + if(!ispath(recipe.result, /obj/item/reagent_containers) && result.reagents) + if(recipe.crafting_flags & CRAFT_CLEARS_REAGENTS) + result.reagents.clear_reagents() + if(recipe.crafting_flags & CRAFT_TRANSFERS_REAGENTS) + holder.trans_to(result.reagents, holder.total_volume, no_react = TRUE) parts -= holder qdel(holder) result.CheckParts(parts, recipe) diff --git a/code/datums/components/crafting/ranged_weapon.dm b/code/datums/components/crafting/ranged_weapon.dm index 174c0226a423e..bfd2385f89e01 100644 --- a/code/datums/components/crafting/ranged_weapon.dm +++ b/code/datums/components/crafting/ranged_weapon.dm @@ -300,6 +300,22 @@ category = CAT_WEAPON_RANGED crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_MUST_BE_LEARNED +/datum/crafting_recipe/pipe_organ_gun + name = "Pipe Organ Gun" + tool_behaviors = list(TOOL_WELDER, TOOL_SCREWDRIVER) + result = /obj/structure/mounted_gun/pipe + reqs = list( + /obj/item/pipe = 8, + /obj/item/stack/sheet/mineral/wood = 15, + /obj/item/stack/sheet/iron = 10, + /obj/item/storage/toolbox = 1, + /obj/item/stack/rods = 10, + /obj/item/assembly/igniter = 2, + ) + time = 15 SECONDS + category = CAT_WEAPON_RANGED + crafting_flags = CRAFT_CHECK_DENSITY + /datum/crafting_recipe/trash_cannon name = "Trash Cannon" tool_behaviors = list(TOOL_WELDER, TOOL_SCREWDRIVER) diff --git a/code/datums/components/echolocation.dm b/code/datums/components/echolocation.dm index 51ab89a2be564..4fda54ac0f50e 100644 --- a/code/datums/components/echolocation.dm +++ b/code/datums/components/echolocation.dm @@ -156,7 +156,7 @@ copied_appearance.pixel_x = 0 copied_appearance.pixel_y = 0 copied_appearance.transform = matrix() - if(!iscarbon(input)) //wacky overlay people get generated everytime + if(input.icon && input.icon_state) saved_appearances["[input.icon]-[input.icon_state]"] = copied_appearance return copied_appearance diff --git a/code/datums/components/engraved.dm b/code/datums/components/engraved.dm index 60bfa5f617729..5db43b8076cd2 100644 --- a/code/datums/components/engraved.dm +++ b/code/datums/components/engraved.dm @@ -67,13 +67,13 @@ RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) //supporting component transfer means putting these here instead of initialize SSpersistence.wall_engravings += src - ADD_TRAIT(parent, TRAIT_NOT_ENGRAVABLE, TRAIT_GENERIC) + ADD_TRAIT(parent, TRAIT_NOT_ENGRAVABLE, ENGRAVED_TRAIT) /datum/component/engraved/UnregisterFromParent() UnregisterSignal(parent, COMSIG_ATOM_EXAMINE) //supporting component transfer means putting these here instead of destroy SSpersistence.wall_engravings -= src - REMOVE_TRAIT(parent, TRAIT_NOT_ENGRAVABLE, TRAIT_GENERIC) + REMOVE_TRAIT(parent, TRAIT_NOT_ENGRAVABLE, ENGRAVED_TRAIT) /// Used to maintain the acid overlay on the parent [/atom]. /datum/component/engraved/proc/on_update_overlays(atom/parent_atom, list/overlays) diff --git a/code/datums/components/fishing_spot.dm b/code/datums/components/fishing_spot.dm index b825354d7bebc..982b0da2df71a 100644 --- a/code/datums/components/fishing_spot.dm +++ b/code/datums/components/fishing_spot.dm @@ -19,11 +19,15 @@ RegisterSignal(parent, COMSIG_ATOM_EXAMINE_MORE, PROC_REF(on_examined_more)) RegisterSignal(parent, COMSIG_NPC_FISHING, PROC_REF(return_fishing_spot)) RegisterSignal(parent, COMSIG_ATOM_EX_ACT, PROC_REF(explosive_fishing)) + RegisterSignal(parent, COMSIG_FISH_RELEASED_INTO, PROC_REF(fish_released)) + RegisterSignal(parent, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), PROC_REF(link_to_fish_porter)) ADD_TRAIT(parent, TRAIT_FISHING_SPOT, REF(src)) /datum/component/fishing_spot/Destroy() + REMOVE_TRAIT(parent, TRAIT_FISHING_SPOT, REF(src)) fish_source.on_fishing_spot_del(src) fish_source = null + REMOVE_TRAIT(parent, TRAIT_FISHING_SPOT, REF(src)) return ..() /datum/component/fishing_spot/proc/handle_cast(datum/source, obj/item/fishing_rod/rod, mob/user) @@ -61,7 +65,7 @@ var/obj/item/fishing_rod/rod = possibly_rod if(!istype(rod)) return - if(HAS_TRAIT(user,TRAIT_GONE_FISHING) || rod.fishing_line) + if(GLOB.fishing_challenges_by_user[user] || rod.fishing_line) user.balloon_alert(user, "already fishing") return COMPONENT_NO_AFTERATTACK var/denial_reason = fish_source.reason_we_cant_fish(rod, user, parent) @@ -70,15 +74,10 @@ return COMPONENT_NO_AFTERATTACK // In case the fishing source has anything else to do before beginning to fish. fish_source.on_start_fishing(rod, user, parent) - start_fishing_challenge(rod, user) - return COMPONENT_NO_AFTERATTACK - -/datum/component/fishing_spot/proc/start_fishing_challenge(obj/item/fishing_rod/rod, mob/user) - /// Roll what we caught based on modified table - var/result = fish_source.roll_reward(rod, user, parent) - var/datum/fishing_challenge/challenge = new(src, result, rod, user) + var/datum/fishing_challenge/challenge = new(src, rod, user) fish_source.pre_challenge_started(rod, user, challenge) challenge.start(user) + return COMPONENT_NO_AFTERATTACK /datum/component/fishing_spot/proc/return_fishing_spot(datum/source, list/fish_spot_container) fish_spot_container[NPC_FISHING_SPOT] = fish_source @@ -86,3 +85,13 @@ /datum/component/fishing_spot/proc/explosive_fishing(atom/location, severity) SIGNAL_HANDLER fish_source.spawn_reward_from_explosion(location, severity) + +/datum/component/fishing_spot/proc/link_to_fish_porter(atom/source, mob/user, obj/item/multitool/tool) + SIGNAL_HANDLER + if(istype(tool.buffer, /obj/machinery/fishing_portal_generator)) + var/obj/machinery/fishing_portal_generator/portal = tool.buffer + return portal.link_fishing_spot(fish_source, source, user) + +/datum/component/fishing_spot/proc/fish_released(datum/source, obj/item/fish/fish, mob/living/releaser) + SIGNAL_HANDLER + fish_source.readd_fish(fish, releaser) diff --git a/code/datums/components/food/edible.dm b/code/datums/components/food/edible.dm index c034300f982fe..9e2964273fd48 100644 --- a/code/datums/components/food/edible.dm +++ b/code/datums/components/food/edible.dm @@ -40,8 +40,6 @@ Behavior that's still missing from this component that original food items had t var/volume = 50 ///The flavortext for taste (haha get it flavor text) var/list/tastes - ///Whether to tell the examiner that this is edible or not. - var/show_examine = TRUE /datum/component/edible/Initialize( list/initial_reagents, @@ -57,7 +55,6 @@ Behavior that's still missing from this component that original food items had t datum/callback/on_consume, datum/callback/check_liked, reagent_purity = 0.5, - show_examine = TRUE, ) if(!isatom(parent)) return COMPONENT_INCOMPATIBLE @@ -73,7 +70,6 @@ Behavior that's still missing from this component that original food items had t src.on_consume = on_consume src.tastes = string_assoc_list(tastes) src.check_liked = check_liked - src.show_examine = show_examine setup_initial_reagents(initial_reagents, reagent_purity) @@ -81,9 +77,9 @@ Behavior that's still missing from this component that original food items had t RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(examine)) RegisterSignal(parent, COMSIG_ATOM_ATTACK_ANIMAL, PROC_REF(UseByAnimal)) RegisterSignal(parent, COMSIG_ATOM_CHECKPARTS, PROC_REF(OnCraft)) - RegisterSignal(parent, COMSIG_ATOM_CREATEDBY_PROCESSING, PROC_REF(OnProcessed)) - RegisterSignal(parent, COMSIG_FOOD_INGREDIENT_ADDED, PROC_REF(edible_ingredient_added)) RegisterSignal(parent, COMSIG_OOZE_EAT_ATOM, PROC_REF(on_ooze_eat)) + RegisterSignal(parent, COMSIG_FOOD_INGREDIENT_ADDED, PROC_REF(edible_ingredient_added)) + RegisterSignal(parent, COMSIG_ATOM_CREATEDBY_PROCESSING, PROC_REF(OnProcessed)) if(isturf(parent)) RegisterSignal(parent, COMSIG_ATOM_ENTERED, PROC_REF(on_entered)) @@ -216,7 +212,7 @@ Behavior that's still missing from this component that original food items had t SIGNAL_HANDLER var/atom/owner = parent - if(!show_examine) + if(food_flags & FOOD_NO_EXAMINE) return if(foodtypes) var/list/types = bitfield_to_list(foodtypes, FOOD_FLAGS) @@ -316,7 +312,6 @@ Behavior that's still missing from this component that original food items had t SIGNAL_HANDLER var/atom/this_food = parent - for(var/obj/item/food/crafted_part in parts_list) if(!crafted_part.reagents) continue @@ -325,7 +320,7 @@ Behavior that's still missing from this component that original food items had t this_food.reagents.maximum_volume = ROUND_UP(this_food.reagents.maximum_volume) // Just because I like whole numbers for this. - BLACKBOX_LOG_FOOD_MADE(this_food.type) + BLACKBOX_LOG_FOOD_MADE(parent.type) ///Makes sure the thing hasn't been destroyed or fully eaten to prevent eating phantom edibles /datum/component/edible/proc/IsFoodGone(atom/owner, mob/living/feeder) @@ -462,7 +457,7 @@ Behavior that's still missing from this component that original food items had t var/atom/owner = parent - if(!owner?.reagents) + if(!owner.reagents) stack_trace("[eater] failed to bite [owner], because [owner] had no reagents.") return FALSE if(eater.satiety > -200) @@ -479,7 +474,8 @@ Behavior that's still missing from this component that original food items had t if(bitecount == 0) apply_buff(eater) - var/fraction = min(bite_consumption / owner.reagents.total_volume, 1) + var/fraction = 0.3 + fraction = min(bite_consumption / owner.reagents.total_volume, 1) owner.reagents.trans_to(eater, bite_consumption, transferred_by = feeder, methods = INGEST) bitecount++ @@ -489,8 +485,7 @@ Behavior that's still missing from this component that original food items had t On_Consume(eater, feeder) //Invoke our after eat callback if it is valid - if(after_eat) - after_eat.Invoke(eater, feeder, bitecount) + after_eat?.Invoke(eater, feeder, bitecount) //Invoke the eater's stomach's after_eat callback if valid if(iscarbon(eater)) @@ -531,7 +526,7 @@ Behavior that's still missing from this component that original food items had t if(recipe_complexity <= 0) return var/obj/item/food/food = parent - if(!isnull(food.crafted_food_buff)) + if(istype(food) && !isnull(food.crafted_food_buff)) buff = food.crafted_food_buff else buff = pick_weight(GLOB.food_buffs[min(recipe_complexity, FOOD_COMPLEXITY_5)]) @@ -666,7 +661,7 @@ Behavior that's still missing from this component that original food items had t /datum/component/edible/proc/UseByAnimal(datum/source, mob/living/basic/pet/dog/doggy) SIGNAL_HANDLER - if(!isdog(doggy)) + if(!isdog(doggy) || (food_flags & FOOD_NO_BITECOUNT)) //this entirely relies on bitecounts alas return var/atom/food = parent diff --git a/code/datums/components/gps.dm b/code/datums/components/gps.dm index 7e52f00def752..0b3751856b8a2 100644 --- a/code/datums/components/gps.dm +++ b/code/datums/components/gps.dm @@ -162,7 +162,7 @@ GLOBAL_LIST_EMPTY(GPS_list) switch(action) if("rename") var/atom/parentasatom = parent - var/a = tgui_input_text(usr, "Enter the desired tag", "GPS Tag", gpstag, 20) + var/a = tgui_input_text(usr, "Enter the desired tag", "GPS Tag", gpstag, max_length = 20) if (QDELETED(ui) || ui.status != UI_INTERACTIVE) return if (!a) diff --git a/code/datums/components/infective.dm b/code/datums/components/infective.dm index bc7cc2e6af3c4..5163ca69dacd9 100644 --- a/code/datums/components/infective.dm +++ b/code/datums/components/infective.dm @@ -8,43 +8,78 @@ var/weak_infection_chance = 10 -/datum/component/infective/Initialize(list/datum/disease/_diseases, expire_in, weak = FALSE) - if(islist(_diseases)) - diseases = _diseases - else - diseases = list(_diseases) +/datum/component/infective/Initialize(list/datum/disease/diseases, expire_in, weak = FALSE, weak_infection_chance = 10) + if(!ismovable(parent)) + return COMPONENT_INCOMPATIBLE + + if(!islist(diseases)) + diseases = islist(diseases) + + ///Make sure the diseases list is populated with instances of diseases so that it doesn't have to be for each AddComponent call. + for(var/datum/disease/disease as anything in diseases) + if(!disease) //empty entry, remove. + diseases -= disease + if(ispath(disease, /datum/disease)) + var/datum/disease/instance = new disease + diseases -= disease + diseases += instance + else if(!istype(disease)) + stack_trace("found [isdatum(disease) ? "an instance of [disease.type]" : disease] inside the diseases list argument for [type]") + diseases -= disease + + src.diseases = diseases + if(expire_in) expire_time = world.time + expire_in QDEL_IN(src, expire_in) - if(!ismovable(parent)) - return COMPONENT_INCOMPATIBLE - is_weak = weak + src.weak_infection_chance = weak_infection_chance + +/datum/component/infective/Destroy() + QDEL_NULL(diseases) + return ..() +/datum/component/infective/RegisterWithParent() if(is_weak && isitem(parent)) RegisterSignal(parent, COMSIG_FOOD_EATEN, PROC_REF(try_infect_eat)) RegisterSignal(parent, COMSIG_PILL_CONSUMED, PROC_REF(try_infect_eat)) - else - var/static/list/disease_connections = list( - COMSIG_ATOM_ENTERED = PROC_REF(try_infect_crossed), - ) - AddComponent(/datum/component/connect_loc_behalf, parent, disease_connections) - - RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, PROC_REF(clean)) - RegisterSignal(parent, COMSIG_MOVABLE_BUCKLE, PROC_REF(try_infect_buckle)) - RegisterSignal(parent, COMSIG_MOVABLE_BUMP, PROC_REF(try_infect_collide)) - RegisterSignal(parent, COMSIG_MOVABLE_IMPACT_ZONE, PROC_REF(try_infect_impact_zone)) - if(isitem(parent)) - RegisterSignal(parent, COMSIG_ITEM_ATTACK_ZONE, PROC_REF(try_infect_attack_zone)) - RegisterSignal(parent, COMSIG_ITEM_ATTACK, PROC_REF(try_infect_attack)) - RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(try_infect_equipped)) - RegisterSignal(parent, COMSIG_FOOD_EATEN, PROC_REF(try_infect_eat)) - RegisterSignal(parent, COMSIG_PILL_CONSUMED, PROC_REF(try_infect_eat)) - if(istype(parent, /obj/item/reagent_containers/cup)) - RegisterSignal(parent, COMSIG_GLASS_DRANK, PROC_REF(try_infect_drink)) - if(isorgan(parent)) - RegisterSignal(parent, COMSIG_ORGAN_IMPLANTED, PROC_REF(on_organ_insertion)) + return + var/static/list/disease_connections = list( + COMSIG_ATOM_ENTERED = PROC_REF(try_infect_crossed), + ) + AddComponent(/datum/component/connect_loc_behalf, parent, disease_connections) + + RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, PROC_REF(clean)) + RegisterSignal(parent, COMSIG_MOVABLE_BUCKLE, PROC_REF(try_infect_buckle)) + RegisterSignal(parent, COMSIG_MOVABLE_BUMP, PROC_REF(try_infect_collide)) + RegisterSignal(parent, COMSIG_MOVABLE_IMPACT_ZONE, PROC_REF(try_infect_impact_zone)) + if(isitem(parent)) + RegisterSignal(parent, COMSIG_ITEM_ATTACK_ZONE, PROC_REF(try_infect_attack_zone)) + RegisterSignal(parent, COMSIG_ITEM_ATTACK, PROC_REF(try_infect_attack)) + RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(try_infect_equipped)) + RegisterSignal(parent, COMSIG_FOOD_EATEN, PROC_REF(try_infect_eat)) + RegisterSignal(parent, COMSIG_PILL_CONSUMED, PROC_REF(try_infect_eat)) + if(istype(parent, /obj/item/reagent_containers/cup)) + RegisterSignal(parent, COMSIG_GLASS_DRANK, PROC_REF(try_infect_drink)) + if(isorgan(parent)) + RegisterSignal(parent, COMSIG_ORGAN_IMPLANTED, PROC_REF(on_organ_insertion)) + +/datum/component/infective/UnregisterFromParent() + . = ..() + UnregisterSignal(parent, list( + COMSIG_FOOD_EATEN, + COMSIG_PILL_CONSUMED, + COMSIG_COMPONENT_CLEAN_ACT, + COMSIG_MOVABLE_BUMP, + COMSIG_MOVABLE_IMPACT_ZONE, + COMSIG_ITEM_ATTACK_ZONE, + COMSIG_ITEM_ATTACK, + COMSIG_ITEM_EQUIPPED, + COMSIG_GLASS_DRANK, + COMSIG_ORGAN_IMPLANTED, + )) + qdel(GetComponent(/datum/component/connect_loc_behalf)) /datum/component/infective/proc/on_organ_insertion(obj/item/organ/target, mob/living/carbon/receiver) SIGNAL_HANDLER @@ -62,16 +97,16 @@ eater.add_mood_event("disgust", /datum/mood_event/disgust/dirty_food) - if(is_weak && !prob(weak_infection_chance)) - return - - for(var/datum/disease/disease in diseases) + for(var/datum/disease/disease as anything in diseases) + if(is_weak && !prob(weak_infection_chance)) + continue if(!disease.has_required_infectious_organ(eater, ORGAN_SLOT_STOMACH)) continue eater.ForceContractDisease(disease) - try_infect(feeder, BODY_ZONE_L_ARM) + if(!is_weak) + try_infect(feeder, BODY_ZONE_L_ARM) /datum/component/infective/proc/try_infect_drink(datum/source, mob/living/drinker, mob/living/feeder) SIGNAL_HANDLER @@ -79,11 +114,14 @@ if(HAS_TRAIT(drinker, TRAIT_STRONG_STOMACH)) return - var/appendage_zone = feeder.held_items.Find(source) - appendage_zone = appendage_zone == 0 ? BODY_ZONE_CHEST : appendage_zone % 2 ? BODY_ZONE_R_ARM : BODY_ZONE_L_ARM - try_infect(feeder, appendage_zone) + if(!is_weak) + var/appendage_zone = feeder.held_items.Find(source) + appendage_zone = appendage_zone == 0 ? BODY_ZONE_CHEST : (appendage_zone % 2 ? BODY_ZONE_R_ARM : BODY_ZONE_L_ARM) + try_infect(feeder, appendage_zone) - for(var/datum/disease/disease in diseases) + for(var/datum/disease/disease as anything in diseases) + if(is_weak && !prob(weak_infection_chance)) + continue if(!disease.has_required_infectious_organ(drinker, ORGAN_SLOT_STOMACH)) continue @@ -163,19 +201,3 @@ /datum/component/infective/proc/try_infect(mob/living/L, target_zone) for(var/V in diseases) L.ContactContractDisease(V, target_zone) - -/datum/component/infective/UnregisterFromParent() - . = ..() - UnregisterSignal(parent, list( - COMSIG_FOOD_EATEN, - COMSIG_PILL_CONSUMED, - COMSIG_COMPONENT_CLEAN_ACT, - COMSIG_MOVABLE_BUMP, - COMSIG_MOVABLE_IMPACT_ZONE, - COMSIG_ITEM_ATTACK_ZONE, - COMSIG_ITEM_ATTACK, - COMSIG_ITEM_EQUIPPED, - COMSIG_GLASS_DRANK, - COMSIG_ORGAN_IMPLANTED, - )) - qdel(GetComponent(/datum/component/connect_loc_behalf)) diff --git a/code/datums/components/irradiated.dm b/code/datums/components/irradiated.dm index 077539f49db8e..9562f161fb4a8 100644 --- a/code/datums/components/irradiated.dm +++ b/code/datums/components/irradiated.dm @@ -138,7 +138,7 @@ if(human_parent.is_blind()) to_chat(human_parent, span_boldwarning("Your [affected_limb.plaintext_zone] feels like it's bubbling, then burns like hell!")) - human_parent.apply_damage(RADIATION_BURN_SPLOTCH_DAMAGE, BURN, affected_limb) + human_parent.apply_damage(RADIATION_BURN_SPLOTCH_DAMAGE, BURN, affected_limb, wound_clothing = FALSE) playsound( human_parent, pick('sound/effects/wounds/sizzle1.ogg', 'sound/effects/wounds/sizzle2.ogg'), diff --git a/code/datums/components/itempicky.dm b/code/datums/components/itempicky.dm index 74fbdff1caa91..bda8b1ae13881 100644 --- a/code/datums/components/itempicky.dm +++ b/code/datums/components/itempicky.dm @@ -5,13 +5,21 @@ var/whitelist /// Message shown if you try to pick up an item not in the whitelist var/message = "You don't like %TARGET, why would you hold it?" + /// An optional callback we check for overriding our whitelist + var/datum/callback/tertiary_condition = null -/datum/component/itempicky/Initialize(whitelist, message) +/datum/component/itempicky/Initialize(whitelist, message, tertiary_condition) if(!ismob(parent)) return COMPONENT_INCOMPATIBLE src.whitelist = whitelist if(message) src.message = message + if(tertiary_condition) + src.tertiary_condition = tertiary_condition + +/datum/component/itempicky/Destroy(force) + tertiary_condition = null + return ..() /datum/component/itempicky/RegisterWithParent() RegisterSignal(parent, COMSIG_LIVING_TRY_PUT_IN_HAND, PROC_REF(particularly)) @@ -30,6 +38,7 @@ /datum/component/itempicky/proc/particularly(datum/source, obj/item/pickingup) SIGNAL_HANDLER - if(!is_type_in_typecache(pickingup, whitelist)) + // if we were passed the output of a callback, check against that + if(!tertiary_condition?.Invoke() && !is_type_in_typecache(pickingup, whitelist)) to_chat(source, span_warning("[replacetext(message, "%TARGET", pickingup)]")) return COMPONENT_LIVING_CANT_PUT_IN_HAND diff --git a/code/datums/components/lockable_storage.dm b/code/datums/components/lockable_storage.dm index 482cb134159e0..ca058cb3fbfab 100644 --- a/code/datums/components/lockable_storage.dm +++ b/code/datums/components/lockable_storage.dm @@ -62,7 +62,6 @@ UnregisterSignal(parent, list( COMSIG_ATOM_TOOL_ACT(TOOL_SCREWDRIVER), COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), - COMSIG_ATOM_STORAGE_ITEM_INTERACT_INSERT, )) UnregisterSignal(parent, list( COMSIG_ATOM_EXAMINE, diff --git a/code/datums/components/mind_linker.dm b/code/datums/components/mind_linker.dm index 4449a8fe36e8e..f6b2af5329716 100644 --- a/code/datums/components/mind_linker.dm +++ b/code/datums/components/mind_linker.dm @@ -242,7 +242,7 @@ var/datum/component/mind_linker/linker = target var/mob/living/linker_parent = linker.parent - var/message = tgui_input_text(owner, "Enter a message to transmit.", "[linker.network_name] Telepathy") + var/message = tgui_input_text(owner, "Enter a message to transmit.", "[linker.network_name] Telepathy", max_length = MAX_MESSAGE_LEN) if(!message || QDELETED(src) || QDELETED(owner) || owner.stat == DEAD) return diff --git a/code/datums/components/profound_fisher.dm b/code/datums/components/profound_fisher.dm index 5bd5af12943a5..61f6543bd12bf 100644 --- a/code/datums/components/profound_fisher.dm +++ b/code/datums/components/profound_fisher.dm @@ -64,9 +64,12 @@ /datum/component/profound_fisher/proc/on_unarmed_attack(mob/living/source, atom/attack_target, proximity_flag, list/modifiers) SIGNAL_HANDLER - if(!source.client || !should_fish_on(source, attack_target)) + if(!should_fish_on(source, attack_target)) return - INVOKE_ASYNC(src, PROC_REF(begin_fishing), source, attack_target) + if(source.client) + INVOKE_ASYNC(src, PROC_REF(begin_fishing), source, attack_target) + else + INVOKE_ASYNC(src, PROC_REF(pretend_fish), source, attack_target) return COMPONENT_CANCEL_ATTACK_CHAIN /datum/component/profound_fisher/proc/pre_attack(mob/living/source, atom/target) @@ -77,34 +80,33 @@ if(source.client) INVOKE_ASYNC(src, PROC_REF(begin_fishing), source, target) else - INVOKE_ASYNC(src, PROC_REF(pretend_fish), target) + INVOKE_ASYNC(src, PROC_REF(pretend_fish), source, target) return COMPONENT_HOSTILE_NO_ATTACK /datum/component/profound_fisher/proc/should_fish_on(mob/living/user, atom/target) - if(!HAS_TRAIT(target, TRAIT_FISHING_SPOT) || HAS_TRAIT(user, TRAIT_GONE_FISHING)) + if(!HAS_TRAIT(target, TRAIT_FISHING_SPOT) || GLOB.fishing_challenges_by_user[user]) return FALSE if(user.combat_mode || !user.CanReach(target)) return FALSE return TRUE /datum/component/profound_fisher/proc/begin_fishing(mob/living/user, atom/target) - RegisterSignal(user, SIGNAL_ADDTRAIT(TRAIT_GONE_FISHING), PROC_REF(actually_fishing_with_internal_rod)) + RegisterSignal(user, COMSIG_MOB_BEGIN_FISHING, PROC_REF(actually_fishing_with_internal_rod)) our_rod.melee_attack_chain(user, target) - UnregisterSignal(user, SIGNAL_ADDTRAIT(TRAIT_GONE_FISHING)) + UnregisterSignal(user, COMSIG_MOB_BEGIN_FISHING) /datum/component/profound_fisher/proc/actually_fishing_with_internal_rod(datum/source) SIGNAL_HANDLER ADD_TRAIT(source, TRAIT_PROFOUND_FISHER, REF(parent)) - RegisterSignal(source, SIGNAL_REMOVETRAIT(TRAIT_GONE_FISHING), PROC_REF(remove_profound_fisher)) + RegisterSignal(source, COMSIG_MOB_COMPLETE_FISHING, PROC_REF(remove_profound_fisher)) /datum/component/profound_fisher/proc/remove_profound_fisher(datum/source) SIGNAL_HANDLER REMOVE_TRAIT(source, TRAIT_PROFOUND_FISHER, TRAIT_GENERIC) - UnregisterSignal(source, SIGNAL_REMOVETRAIT(TRAIT_GONE_FISHING)) + UnregisterSignal(source, COMSIG_MOB_COMPLETE_FISHING) -/datum/component/profound_fisher/proc/pretend_fish(atom/target) - var/mob/living/living_parent = parent - if(DOING_INTERACTION_WITH_TARGET(living_parent, target)) +/datum/component/profound_fisher/proc/pretend_fish(mob/living/source, atom/target) + if(DOING_INTERACTION_WITH_TARGET(source, target)) return var/list/fish_spot_container[NPC_FISHING_SPOT] SEND_SIGNAL(target, COMSIG_NPC_FISHING, fish_spot_container) @@ -113,13 +115,14 @@ return null var/obj/effect/fishing_float/float = new(get_turf(target), target) playsound(float, 'sound/effects/splash.ogg', 100) - var/happiness_percentage = living_parent.ai_controller?.blackboard[BB_BASIC_HAPPINESS] / 100 - var/fishing_speed = 10 SECONDS - round(4 SECONDS * happiness_percentage) - if(!do_after(living_parent, fishing_speed, target = target) && !QDELETED(fish_spot)) - qdel(float) - return - var/reward_loot = fish_spot.roll_reward(our_rod, parent) - fish_spot.dispense_reward(reward_loot, parent, target) + if(!PERFORM_ALL_TESTS(fish_sources)) + var/happiness_percentage = source.ai_controller?.blackboard[BB_BASIC_HAPPINESS] * 0.01 + var/fishing_speed = 10 SECONDS - round(4 SECONDS * happiness_percentage) + if(!do_after(source, fishing_speed, target = target) && !QDELETED(fish_spot)) + qdel(float) + return + var/reward_loot = fish_spot.roll_reward(our_rod, source) + fish_spot.dispense_reward(reward_loot, source, target) playsound(float, 'sound/effects/bigsplash.ogg', 100) qdel(float) @@ -127,3 +130,5 @@ line = /obj/item/fishing_line/reinforced bait = /obj/item/food/bait/doughball/synthetic/unconsumable resistance_flags = INDESTRUCTIBLE + reel_overlay = null + show_in_wiki = FALSE //abstract fishing rod diff --git a/code/datums/components/riding/riding_mob.dm b/code/datums/components/riding/riding_mob.dm index 1e3c94d84c6a3..ae4d29e22f5f9 100644 --- a/code/datums/components/riding/riding_mob.dm +++ b/code/datums/components/riding/riding_mob.dm @@ -7,7 +7,9 @@ var/can_use_abilities = FALSE /// shall we require riders to go through the riding minigame if they arent in our friends list var/require_minigame = FALSE - /// list of blacklisted abilities that cant be shared + /// unsharable abilities that we will force to be shared anyway + var/list/override_unsharable_abilities = list() + /// abilities that are always blacklisted from sharing var/list/blacklist_abilities = list() /datum/component/riding/creature/Initialize(mob/living/riding_mob, force = FALSE, ride_check_flags = NONE, potion_boost = FALSE) @@ -168,6 +170,8 @@ for(var/datum/action/action as anything in ridden_creature.actions) if(is_type_in_list(action, blacklist_abilities)) continue + if(!action.can_be_shared && !is_type_in_list(action, override_unsharable_abilities)) + continue action.GiveAction(rider) /// Takes away the riding parent's abilities from the rider @@ -504,7 +508,6 @@ /datum/component/riding/creature/leaper can_force_unbuckle = FALSE can_use_abilities = TRUE - blacklist_abilities = list(/datum/action/cooldown/toggle_seethrough) ride_check_flags = JUST_FRIEND_RIDERS /datum/component/riding/creature/leaper/handle_specials() diff --git a/code/datums/components/seclight_attachable.dm b/code/datums/components/seclight_attachable.dm index b1d4aebc93f83..6b3991c9c5e3c 100644 --- a/code/datums/components/seclight_attachable.dm +++ b/code/datums/components/seclight_attachable.dm @@ -97,8 +97,8 @@ RegisterSignal(parent, COMSIG_ITEM_UI_ACTION_CLICK, PROC_REF(on_action_click)) RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(on_attackby)) RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) + RegisterSignal(parent, COMSIG_ATOM_SABOTEUR_ACT, PROC_REF(on_hit_by_saboteur)) RegisterSignal(parent, COMSIG_QDELETING, PROC_REF(on_parent_deleted)) - RegisterSignal(parent, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) /datum/component/seclite_attachable/UnregisterFromParent() UnregisterSignal(parent, list( @@ -110,6 +110,7 @@ COMSIG_ITEM_UI_ACTION_CLICK, COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_EXAMINE, + COMSIG_ATOM_SABOTEUR_ACT, COMSIG_QDELETING, )) @@ -296,8 +297,8 @@ // but that's the downside of using icon states over overlays. source.icon_state = base_state -/// Signal proc for [COMSIG_HIT_BY_SABOTEUR] that turns the light off for a few seconds. -/datum/component/seclite_attachable/proc/on_saboteur(datum/source, disrupt_duration) - SIGNAL_HANDLER +//turns the light off for a few seconds. +/datum/component/seclite_attachable/proc/on_hit_by_saboteur(datum/source, disrupt_duration) . = light.on_saboteur(source, disrupt_duration) update_light() + return . diff --git a/code/datums/components/seethrough_mob.dm b/code/datums/components/seethrough_mob.dm index bae87faf61583..b6951c5489b6d 100644 --- a/code/datums/components/seethrough_mob.dm +++ b/code/datums/components/seethrough_mob.dm @@ -122,6 +122,7 @@ background_icon_state = "bg_alien" cooldown_time = 1 SECONDS melee_cooldown_time = 0 + can_be_shared = FALSE /datum/action/cooldown/toggle_seethrough/Remove(mob/remove_from) var/datum/component/seethrough_mob/transparency = target diff --git a/code/datums/components/singularity.dm b/code/datums/components/singularity.dm index 14aaedff7172a..0cd64d829a2fd 100644 --- a/code/datums/components/singularity.dm +++ b/code/datums/components/singularity.dm @@ -373,7 +373,7 @@ for(var/mob/living/target as anything in GLOB.mob_living_list) if(target.z != atom_parent.z) continue - if(target.status_effects & GODMODE) + if(HAS_TRAIT(target, TRAIT_GODMODE)) continue var/distance_from_target = get_dist(target, atom_parent) if(distance_from_target < closest_distance) diff --git a/code/datums/components/soulstoned.dm b/code/datums/components/soulstoned.dm index bb22030c21042..d4e9e0eaf02e1 100644 --- a/code/datums/components/soulstoned.dm +++ b/code/datums/components/soulstoned.dm @@ -11,8 +11,7 @@ stoned.forceMove(container) stoned.fully_heal() - stoned.add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), SOULSTONE_TRAIT) - stoned.status_flags |= GODMODE + stoned.add_traits(list(TRAIT_GODMODE, TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), SOULSTONE_TRAIT) RegisterSignal(stoned, COMSIG_MOVABLE_MOVED, PROC_REF(free_prisoner)) @@ -25,5 +24,4 @@ /datum/component/soulstoned/UnregisterFromParent() var/mob/living/stoned = parent - stoned.status_flags &= ~GODMODE - stoned.remove_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), SOULSTONE_TRAIT) + stoned.remove_traits(list(TRAIT_GODMODE, TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), SOULSTONE_TRAIT) diff --git a/code/datums/components/speechmod.dm b/code/datums/components/speechmod.dm index 8ffa3e8624e49..fc01d8d2d846c 100644 --- a/code/datums/components/speechmod.dm +++ b/code/datums/components/speechmod.dm @@ -60,6 +60,8 @@ var/message = speech_args[SPEECH_MESSAGE] if(message[1] == "*") return + if(SEND_SIGNAL(source, COMSIG_TRY_MODIFY_SPEECH) & PREVENT_MODIFY_SPEECH) + return if(!isnull(should_modify_speech) && !should_modify_speech.Invoke(source, speech_args)) return diff --git a/code/datums/components/supermatter_crystal.dm b/code/datums/components/supermatter_crystal.dm index 81a29b56c6d81..53a0797c2e1c0 100644 --- a/code/datums/components/supermatter_crystal.dm +++ b/code/datums/components/supermatter_crystal.dm @@ -71,7 +71,7 @@ SIGNAL_HANDLER if(isliving(user)) var/mob/living/living_mob = user - if(living_mob.incorporeal_move || living_mob.status_flags & GODMODE) + if(living_mob.incorporeal_move || HAS_TRAIT(living_mob, TRAIT_GODMODE)) return if(isalien(user)) dust_mob(source, user, cause = "alien attack") @@ -80,7 +80,7 @@ /datum/component/supermatter_crystal/proc/animal_hit(datum/source, mob/living/simple_animal/user, list/modifiers) SIGNAL_HANDLER - if(user.incorporeal_move || user.status_flags & GODMODE) + if(user.incorporeal_move || HAS_TRAIT(user, TRAIT_GODMODE)) return var/atom/atom_source = source var/murder @@ -101,7 +101,7 @@ SIGNAL_HANDLER if(isliving(user)) var/mob/living/living_mob = user - if(living_mob.incorporeal_move || living_mob.status_flags & GODMODE) + if(living_mob.incorporeal_move || HAS_TRAIT(living_mob, TRAIT_GODMODE)) return var/atom/atom_source = source if(iscyborg(user) && atom_source.Adjacent(user)) @@ -115,7 +115,7 @@ /datum/component/supermatter_crystal/proc/hand_hit(datum/source, mob/living/user, list/modifiers) SIGNAL_HANDLER - if(user.incorporeal_move || user.status_flags & GODMODE) + if(user.incorporeal_move || HAS_TRAIT(user, TRAIT_GODMODE)) return if(user.zone_selected != BODY_ZONE_PRECISE_MOUTH) dust_mob(source, user, cause = "hand") @@ -202,7 +202,7 @@ return if(atom_source.Adjacent(user)) //if the item is stuck to the person, kill the person too instead of eating just the item. - if(user.incorporeal_move || user.status_flags & GODMODE) + if(user.incorporeal_move || HAS_TRAIT(user, TRAIT_GODMODE)) return var/vis_msg = span_danger("[user] reaches out and touches [atom_source] with [item], inducing a resonance... [item] starts to glow briefly before the light continues up to [user]'s body. [user.p_They()] burst[user.p_s()] into flames before flashing into dust!") var/mob_msg = span_userdanger("You reach out and touch [atom_source] with [item]. Everything starts burning and all you can hear is ringing. Your last thought is \"That was not a wise decision.\"") @@ -219,7 +219,7 @@ SIGNAL_HANDLER if(isliving(hit_object)) var/mob/living/hit_mob = hit_object - if(hit_mob.incorporeal_move || hit_mob.status_flags & GODMODE) + if(hit_mob.incorporeal_move || HAS_TRAIT(hit_mob, TRAIT_GODMODE)) return var/atom/atom_source = source var/obj/machinery/power/supermatter_crystal/our_supermatter = parent // Why is this a component? @@ -272,7 +272,7 @@ span_hear("You hear a loud crack as you are washed with a wave of heat.")) /datum/component/supermatter_crystal/proc/dust_mob(datum/source, mob/living/nom, vis_msg, mob_msg, cause) - if(nom.incorporeal_move || nom.status_flags & GODMODE) //try to keep supermatter sliver's + hemostat's dust conditions in sync with this too + if(nom.incorporeal_move || HAS_TRAIT(nom, TRAIT_GODMODE)) //try to keep supermatter sliver's + hemostat's dust conditions in sync with this too return var/atom/atom_source = source if(!vis_msg) @@ -290,10 +290,8 @@ /datum/component/supermatter_crystal/proc/consume(atom/source, atom/movable/consumed_object) if(consumed_object.flags_1 & SUPERMATTER_IGNORES_1) return - if(isliving(consumed_object)) - var/mob/living/consumed_mob = consumed_object - if(consumed_mob.status_flags & GODMODE) - return + if(HAS_TRAIT(consumed_object, TRAIT_GODMODE)) + return var/atom/atom_source = source SEND_SIGNAL(consumed_object, COMSIG_SUPERMATTER_CONSUMED, atom_source) diff --git a/code/datums/components/tackle.dm b/code/datums/components/tackle.dm index 0c23733ea1658..3d777e888d9fc 100644 --- a/code/datums/components/tackle.dm +++ b/code/datums/components/tackle.dm @@ -71,7 +71,7 @@ /datum/component/tackler/proc/checkTackle(mob/living/carbon/user, atom/clicked_atom, list/modifiers) SIGNAL_HANDLER - if(modifiers[ALT_CLICK] || modifiers[SHIFT_CLICK] || modifiers[CTRL_CLICK] || modifiers[MIDDLE_CLICK]) + if(!modifiers[RIGHT_CLICK] || modifiers[ALT_CLICK] || modifiers[SHIFT_CLICK] || modifiers[CTRL_CLICK] || modifiers[MIDDLE_CLICK]) return if(!user.throw_mode || user.get_active_held_item() || user.pulling || user.buckled || user.incapacitated) diff --git a/code/datums/components/toggle_attached_clothing.dm b/code/datums/components/toggle_attached_clothing.dm index 9ba42fe091732..8321119d85e58 100644 --- a/code/datums/components/toggle_attached_clothing.dm +++ b/code/datums/components/toggle_attached_clothing.dm @@ -198,9 +198,9 @@ on_removed?.Invoke(deployable) var/obj/item/parent_gear = parent - if (destroy_on_removal) + if(destroy_on_removal) QDEL_NULL(deployable) - else if (parent_icon_state_suffix) + if(parent_icon_state_suffix) parent_gear.icon_state = "[initial(parent_gear.icon_state)]" parent_gear.worn_icon_state = parent_gear.icon_state parent_gear.update_slot_icon() diff --git a/code/datums/datum.dm b/code/datums/datum.dm index a4169004fc982..d170aeca8522e 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -419,6 +419,11 @@ filter_data = null atom_cast.filters = null +/// Calls qdel on itself, because signals dont allow callbacks +/datum/proc/selfdelete() + SIGNAL_HANDLER + qdel(src) + /// Return text from this proc to provide extra context to hard deletes that happen to it /// Optional, you should use this for cases where replication is difficult and extra context is required /// Can be called more then once per object, use harddel_deets_dumped to avoid duplicate calls (I am so sorry) diff --git a/code/datums/diseases/advance/floor_diseases/carpellosis.dm b/code/datums/diseases/advance/floor_diseases/carpellosis.dm index a0482215494c4..cdeb6051537e3 100644 --- a/code/datums/diseases/advance/floor_diseases/carpellosis.dm +++ b/code/datums/diseases/advance/floor_diseases/carpellosis.dm @@ -41,7 +41,7 @@ switch(stage) if(2) - if(SPT_PROB(1, seconds_per_tick) && affected_mob.stat == CONSCIOUS) + if(SPT_PROB(1, seconds_per_tick) && affected_mob.stat == CONSCIOUS && affected_mob.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL)) to_chat(affected_mob, span_warning("You want to wag your tail...")) affected_mob.emote("wag") if(3) diff --git a/code/datums/elements/art.dm b/code/datums/elements/art.dm index 81d388aa94af8..d5a642c23d0b6 100644 --- a/code/datums/elements/art.dm +++ b/code/datums/elements/art.dm @@ -74,7 +74,7 @@ var/datum/job_department/hater_department = SSjob.get_department_type(hater_department_type) for(var/datum/job/hater_job as anything in hater_department.department_jobs) haters += hater_job.title - var/datum/job/quartermaster/fucking_quartermaster = SSjob.GetJobType(/datum/job/quartermaster) + var/datum/job/quartermaster/fucking_quartermaster = SSjob.get_job_type(/datum/job/quartermaster) haters += fucking_quartermaster.title if(!(user.mind.assigned_role.title in haters)) diff --git a/code/datums/elements/bed_tucking.dm b/code/datums/elements/bed_tucking.dm index 58f5640c31c75..3b49f2a608f88 100644 --- a/code/datums/elements/bed_tucking.dm +++ b/code/datums/elements/bed_tucking.dm @@ -53,11 +53,11 @@ return COMPONENT_NO_AFTERATTACK /datum/element/bed_tuckable/proc/tuck(obj/item/tucked, obj/structure/bed/target_bed) - tucked.dir = target_bed.dir - tucked.pixel_x = target_bed.dir & EAST ? -x_offset : x_offset + tucked.dir = target_bed.dir & target_bed.left_headrest_dirs ? EAST : WEST + tucked.pixel_x = target_bed.dir & target_bed.left_headrest_dirs ? -x_offset : x_offset tucked.pixel_y = y_offset if(starting_angle) - rotation_degree = target_bed.dir & EAST ? starting_angle + 180 : starting_angle + rotation_degree = target_bed.dir & target_bed.left_headrest_dirs ? starting_angle + 180 : starting_angle tucked.transform = turn(tucked.transform, rotation_degree) RegisterSignal(tucked, COMSIG_ITEM_PICKUP, PROC_REF(untuck)) diff --git a/code/datums/elements/consumable_mob.dm b/code/datums/elements/consumable_mob.dm index 1a7c67a431220..fafdb8cbcab28 100644 --- a/code/datums/elements/consumable_mob.dm +++ b/code/datums/elements/consumable_mob.dm @@ -23,7 +23,7 @@ /datum/element/consumable_mob/proc/on_consume(atom/movable/source, mob/living/consumer) SIGNAL_HANDLER - if(!consumer.combat_mode || !consumer.reagents) + if(!consumer.combat_mode || !consumer.reagents || HAS_TRAIT(consumer, TRAIT_PACIFISM)) return for(var/reagent_type in reagents_list) if(isnull(reagents_list[reagent_type])) diff --git a/code/datums/elements/disarm_attack.dm b/code/datums/elements/disarm_attack.dm index a788cd9f35ed3..8b4b0b3ff8adf 100644 --- a/code/datums/elements/disarm_attack.dm +++ b/code/datums/elements/disarm_attack.dm @@ -6,13 +6,23 @@ if(!isitem(target)) return ELEMENT_INCOMPATIBLE - RegisterSignal(target, COMSIG_ITEM_ATTACK_SECONDARY, PROC_REF(secondary_attack)) - RegisterSignal(target, COMSIG_ATOM_EXAMINE, PROC_REF(examine)) + var/obj/item/item = target + RegisterSignal(item, COMSIG_ITEM_ATTACK_SECONDARY, PROC_REF(secondary_attack)) + RegisterSignal(item, COMSIG_ATOM_EXAMINE, PROC_REF(examine)) + item.item_flags |= ITEM_HAS_CONTEXTUAL_SCREENTIPS + RegisterSignal(item, COMSIG_ITEM_REQUESTING_CONTEXT_FOR_TARGET, PROC_REF(add_item_context)) /datum/element/disarm_attack/Detach(datum/source) - UnregisterSignal(source, list(COMSIG_ATOM_EXAMINE, COMSIG_ITEM_ATTACK_SECONDARY)) + UnregisterSignal(source, list(COMSIG_ATOM_EXAMINE, COMSIG_ITEM_ATTACK_SECONDARY, COMSIG_ITEM_REQUESTING_CONTEXT_FOR_TARGET)) return ..() +/datum/element/disarm_attack/proc/add_item_context(obj/item/source, list/context, atom/target, mob/living/user) + SIGNAL_HANDLER + if(!isliving(target) || !can_disarm_attack(source, target, user, FALSE)) + return NONE + context[SCREENTIP_CONTEXT_RMB] = "Shove" + return CONTEXTUAL_SCREENTIP_SET + /datum/element/disarm_attack/proc/secondary_attack(obj/item/source, mob/living/victim, mob/living/user, params) SIGNAL_HANDLER if(!user.can_disarm(victim) || !can_disarm_attack(source, victim, user)) diff --git a/code/datums/elements/embed.dm b/code/datums/elements/embed.dm index 4a8bda37c3a75..2aae03fb3a4b6 100644 --- a/code/datums/elements/embed.dm +++ b/code/datums/elements/embed.dm @@ -23,7 +23,7 @@ return RegisterSignal(target, COMSIG_MOVABLE_IMPACT_ZONE, PROC_REF(check_embed)) - RegisterSignal(target, COMSIG_ATOM_EXAMINE, PROC_REF(examined)) + RegisterSignal(target, COMSIG_ATOM_EXAMINE_TAGS, PROC_REF(examined_tags)) RegisterSignal(target, COMSIG_EMBED_TRY_FORCE, PROC_REF(try_force_embed)) RegisterSignal(target, COMSIG_ITEM_DISABLE_EMBED, PROC_REF(detach_from_weapon)) @@ -46,7 +46,7 @@ if(blocked || !istype(victim) || HAS_TRAIT(victim, TRAIT_PIERCEIMMUNE)) return FALSE - if(victim.status_flags & GODMODE) + if(HAS_TRAIT(victim, TRAIT_GODMODE)) return FALSE var/flying_speed = throwingdatum?.speed || weapon.throw_speed @@ -82,13 +82,13 @@ Detach(weapon) ///Someone inspected our embeddable item -/datum/element/embed/proc/examined(obj/item/I, mob/user, list/examine_list) +/datum/element/embed/proc/examined_tags(obj/item/I, mob/user, list/examine_list) SIGNAL_HANDLER if(I.is_embed_harmless()) - examine_list += "[I] feels sticky, and could probably get stuck to someone if thrown properly!" + examine_list["sticky"] = "[I] feels sticky, and could probably get stuck to someone if thrown properly!" else - examine_list += "[I] has a fine point, and could probably embed in someone if thrown properly!" + examine_list["embeddable"] = "[I] has a fine point, and could probably embed in someone if thrown properly!" /** * check_embed_projectile() is what we get when a projectile with a defined shrapnel_type impacts a target. diff --git a/code/datums/elements/food/fried_item.dm b/code/datums/elements/food/fried_item.dm index 2afab84d1cb43..bc21e51f24cd7 100644 --- a/code/datums/elements/food/fried_item.dm +++ b/code/datums/elements/food/fried_item.dm @@ -17,28 +17,27 @@ var/atom/this_food = target switch(fry_time) - if(0 to 15) + if(0 to 15 SECONDS) this_food.add_atom_colour(fried_colors[1], FIXED_COLOUR_PRIORITY) this_food.name = "lightly-fried [this_food.name]" this_food.desc += " It's been lightly fried in a deep fryer." - if(15 to 50) + if(15 SECONDS to 50 SECONDS) this_food.add_atom_colour(fried_colors[2], FIXED_COLOUR_PRIORITY) this_food.name = "fried [this_food.name]" this_food.desc += " It's been fried, increasing its tastiness value by [rand(1, 75)]%." - if(50 to 85) + if(50 SECONDS to 85 SECONDS) this_food.add_atom_colour(fried_colors[3], FIXED_COLOUR_PRIORITY) this_food.name = "deep-fried [this_food.name]" this_food.desc += " Deep-fried to perfection." - if(85 to INFINITY) + if(85 SECONDS to INFINITY) this_food.add_atom_colour(fried_colors[4], FIXED_COLOUR_PRIORITY) this_food.name = "\proper the physical manifestation of the very concept of fried foods" this_food.desc = "A heavily-fried... something. Who can tell anymore?" ADD_TRAIT(this_food, TRAIT_FOOD_FRIED, ELEMENT_TRAIT(type)) - SEND_SIGNAL(this_food, COMSIG_ITEM_FRIED, fry_time) // Already edible items will inherent these parameters // Otherwise, we will become edible. this_food.AddComponent( \ @@ -49,6 +48,7 @@ foodtypes = FRIED, \ volume = this_food.reagents?.maximum_volume, \ ) + SEND_SIGNAL(this_food, COMSIG_ITEM_FRIED, fry_time) /datum/element/fried_item/Detach(atom/source, ...) for(var/color in fried_colors) diff --git a/code/datums/elements/food/grilled_item.dm b/code/datums/elements/food/grilled_item.dm index 74e772eb73c92..6899f47faa475 100644 --- a/code/datums/elements/food/grilled_item.dm +++ b/code/datums/elements/food/grilled_item.dm @@ -28,10 +28,12 @@ if(grill_time > 30 SECONDS && isnull(this_food.GetComponent(/datum/component/edible))) this_food.AddComponent(/datum/component/edible, foodtypes = FRIED) - SEND_SIGNAL(this_food, COMSIG_ITEM_BARBEQUE_GRILLED) + SEND_SIGNAL(this_food, COMSIG_ITEM_BARBEQUE_GRILLED, grill_time) + ADD_TRAIT(this_food, TRAIT_FOOD_BBQ_GRILLED, ELEMENT_TRAIT(type)) /datum/element/grilled_item/Detach(atom/source, ...) source.name = initial(source.name) source.desc = initial(source.desc) qdel(source.GetComponent(/datum/component/edible)) // Don't care if it was initially edible + REMOVE_TRAIT(src, TRAIT_FOOD_BBQ_GRILLED, ELEMENT_TRAIT(type)) return ..() diff --git a/code/datums/elements/give_turf_traits.dm b/code/datums/elements/give_turf_traits.dm index 3c53d4a5e7305..7e7c37d86e7ef 100644 --- a/code/datums/elements/give_turf_traits.dm +++ b/code/datums/elements/give_turf_traits.dm @@ -67,7 +67,7 @@ for(var/mob/living/living in location) living.update_turf_movespeed() -/// Signals and components are carried over when the turf is changed, so they've to be readded post-change. +/// Signals are carried over when the turf is changed, but traits aren't, so they've to be readded post-change. /datum/element/give_turf_traits/proc/pre_change_turf(turf/changed, path, list/new_baseturfs, flags, list/post_change_callbacks) SIGNAL_HANDLER post_change_callbacks += CALLBACK(src, PROC_REF(reoccupy_turf)) diff --git a/code/datums/elements/lazy_fishing_spot.dm b/code/datums/elements/lazy_fishing_spot.dm index b84826def1ed8..67edcea2e88ed 100644 --- a/code/datums/elements/lazy_fishing_spot.dm +++ b/code/datums/elements/lazy_fishing_spot.dm @@ -20,10 +20,19 @@ RegisterSignal(target, COMSIG_ATOM_EXAMINE, PROC_REF(on_examined)) RegisterSignal(target, COMSIG_ATOM_EXAMINE_MORE, PROC_REF(on_examined_more)) RegisterSignal(target, COMSIG_ATOM_EX_ACT, PROC_REF(explosive_fishing)) + RegisterSignal(target, COMSIG_FISH_RELEASED_INTO, PROC_REF(fish_released)) + RegisterSignal(target, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), PROC_REF(link_to_fish_porter)) /datum/element/lazy_fishing_spot/Detach(datum/target) - UnregisterSignal(target, list(COMSIG_PRE_FISHING, COMSIG_ATOM_EXAMINE, COMSIG_ATOM_EXAMINE_MORE, COMSIG_ATOM_EX_ACT)) - UnregisterSignal(target, list(COMSIG_PRE_FISHING, COMSIG_NPC_FISHING)) + UnregisterSignal(target, list( + COMSIG_FISH_RELEASED_INTO, + COMSIG_PRE_FISHING, + COMSIG_NPC_FISHING, + COMSIG_ATOM_EXAMINE, + COMSIG_ATOM_EXAMINE_MORE, + COMSIG_ATOM_EX_ACT, + COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), + )) REMOVE_TRAIT(target, TRAIT_FISHING_SPOT, REF(src)) return ..() @@ -61,3 +70,16 @@ /datum/element/lazy_fishing_spot/proc/return_glob_fishing_spot(datum/source, list/fish_spot_container) fish_spot_container[NPC_FISHING_SPOT] = GLOB.preset_fish_sources[configuration] + +/datum/element/lazy_fishing_spot/proc/link_to_fish_porter(atom/source, mob/user, obj/item/multitool/tool) + SIGNAL_HANDLER + if(!istype(tool.buffer, /obj/machinery/fishing_portal_generator)) + return + var/datum/fish_source/fish_source = GLOB.preset_fish_sources[configuration] + var/obj/machinery/fishing_portal_generator/portal = tool.buffer + return portal.link_fishing_spot(fish_source, source, user) + +/datum/element/lazy_fishing_spot/proc/fish_released(datum/source, obj/item/fish/fish, mob/living/releaser) + SIGNAL_HANDLER + var/datum/fish_source/fish_source = GLOB.preset_fish_sources[configuration] + fish_source.readd_fish(fish, releaser) diff --git a/code/datums/elements/lube_walking.dm b/code/datums/elements/lube_walking.dm index 8ab6b2b760285..816f0702a20a3 100644 --- a/code/datums/elements/lube_walking.dm +++ b/code/datums/elements/lube_walking.dm @@ -47,9 +47,19 @@ if(new_resting && lubricate(snail)) snail.add_movespeed_modifier(/datum/movespeed_modifier/snail_crawl) RegisterSignal(snail, COMSIG_MOVABLE_MOVED, PROC_REF(lubricate)) + //DOPPLER EDIT ADDITION BEGIN - This is to prevent snails from achieving FTL speeds without gravity, think of it like snails affixing to walls irl. + ADD_TRAIT(snail, TRAIT_NEGATES_GRAVITY, TRAIT_GENERIC) + snail.AddElement(/datum/element/forced_gravity, 0) + if(HAS_TRAIT(snail, TRAIT_SETTLER)) //This is to keep settlers from reaching FTL speeds too. + snail.remove_movespeed_modifier(/datum/movespeed_modifier/snail_crawl) + //DOPPLER EDIT ADDITION END else snail.remove_movespeed_modifier(/datum/movespeed_modifier/snail_crawl) UnregisterSignal(snail, COMSIG_MOVABLE_MOVED) + //DOPPLER EDIT ADDITION BEGIN - This clears the forced gravity so they're affected by it while standing. + REMOVE_TRAIT(snail, TRAIT_NEGATES_GRAVITY, TRAIT_GENERIC) + snail.RemoveElement(/datum/element/forced_gravity, 0) + //DOPPLER EDIT ADDITION END /datum/element/lube_walking/proc/lubricate(atom/movable/snail) SIGNAL_HANDLER @@ -57,5 +67,6 @@ var/turf/open/turf_standing_on = get_turf(snail) if(!istype(turf_standing_on)) return FALSE - turf_standing_on.MakeSlippery(wet_flags, min_wet_time = min_time_wet_for) + turf_standing_on.MakeSlippery(TURF_WET_WATER, min_wet_time = 1 SECONDS) //DOPPLER EDIT CHANGE: Roundstart Snails - No more lube - ORIGINAL: turf_standing_on.MakeSlippery(wet_flags, min_wet_time = min_time_wet_for) + turf_standing_on.wash(CLEAN_WASH) //DOPPLER EDIT ADDITION: Roundstart Snails - Snails Keep Clean return TRUE diff --git a/code/datums/elements/pet_collar.dm b/code/datums/elements/pet_collar.dm index 5c49de2eceb5b..f98767629e7e7 100644 --- a/code/datums/elements/pet_collar.dm +++ b/code/datums/elements/pet_collar.dm @@ -54,7 +54,7 @@ /datum/element/wears_collar/proc/on_content_enter(mob/living/source, obj/item/clothing/neck/petcollar/new_collar) SIGNAL_HANDLER - if(!istype(new_collar)) + if(!istype(new_collar) || !new_collar.tagname) return source.fully_replace_character_name(null, "\proper [new_collar.tagname]") diff --git a/code/datums/elements/slapcrafting.dm b/code/datums/elements/slapcrafting.dm index 42776bf31f773..4b58bddd2a0f4 100644 --- a/code/datums/elements/slapcrafting.dm +++ b/code/datums/elements/slapcrafting.dm @@ -26,7 +26,7 @@ return //Don't do anything, it just shouldn't be used in crafting. RegisterSignal(target, COMSIG_ATOM_ATTACKBY, PROC_REF(attempt_slapcraft)) - RegisterSignal(target, COMSIG_ATOM_EXAMINE, PROC_REF(get_examine_info)) + RegisterSignal(target, COMSIG_ATOM_EXAMINE_TAGS, PROC_REF(get_examine_info)) RegisterSignal(target, COMSIG_ATOM_EXAMINE_MORE, PROC_REF(get_examine_more_info)) RegisterSignal(target, COMSIG_TOPIC, PROC_REF(topic_handler)) @@ -126,7 +126,7 @@ already_used_names += initial(result.name) string_results += list("\a [initial(result.name)]") - examine_list += span_notice("You think [source] could be used to make [english_list(string_results)]! Examine again to look at the details...") + examine_list["crafting component"] = "You think [source] could be used to make [english_list(string_results)]! Examine again to look at the details..." /// Alerts any examiners to the details of the recipe. /datum/element/slapcrafting/proc/get_examine_more_info(atom/source, mob/user, list/examine_list) diff --git a/code/datums/elements/wall_engraver.dm b/code/datums/elements/wall_engraver.dm index 7204d8cacef5e..2b319b0609a28 100644 --- a/code/datums/elements/wall_engraver.dm +++ b/code/datums/elements/wall_engraver.dm @@ -31,12 +31,12 @@ /datum/element/wall_engraver/proc/try_chisel(obj/item/item, turf/closed/wall, mob/living/user) if(!istype(wall) || !user.mind) return - if(HAS_TRAIT_FROM(wall, TRAIT_NOT_ENGRAVABLE, INNATE_TRAIT)) - user.balloon_alert(user, "wall cannot be engraved!") - return - if(HAS_TRAIT_FROM(wall, TRAIT_NOT_ENGRAVABLE, TRAIT_GENERIC)) + if(HAS_TRAIT_FROM(wall, TRAIT_NOT_ENGRAVABLE, ENGRAVED_TRAIT)) user.balloon_alert(user, "wall has already been engraved!") return + if(HAS_TRAIT(wall, TRAIT_NOT_ENGRAVABLE)) + user.balloon_alert(user, "wall cannot be engraved!") + return if(!length(user.mind?.memories)) user.balloon_alert(user, "nothing memorable to engrave!") return diff --git a/code/datums/elements/weapon_description.dm b/code/datums/elements/weapon_description.dm index 0897b571159bb..eda7ca59b49e6 100644 --- a/code/datums/elements/weapon_description.dm +++ b/code/datums/elements/weapon_description.dm @@ -73,6 +73,10 @@ // Doesn't show the base notes for items that have the override notes variable set to true if(!source.override_notes) + if (source.sharpness & SHARP_EDGED) + readout += "It's sharp and could cause bleeding wounds." + if (source.sharpness & SHARP_POINTY) + readout += "It's pointy and could cause piercing wounds." // Make sure not to divide by 0 on accident if(source.force > 0) readout += "It takes about [span_warning("[HITS_TO_CRIT(source.force)] melee hit\s")] to take down an enemy." diff --git a/code/datums/id_trim/_id_trim.dm b/code/datums/id_trim/_id_trim.dm index 562232214b3d1..a64b71e357fd0 100644 --- a/code/datums/id_trim/_id_trim.dm +++ b/code/datums/id_trim/_id_trim.dm @@ -29,6 +29,12 @@ ///If set, IDs with this trim will give wearers arrows of different colors when pointing var/pointer_color +/datum/id_trim/proc/find_job() + for (var/datum/job/job as anything in SSjob.all_occupations) + if (job.title == assignment) + return job + return null + /// Returns the SecHUD job icon state for whatever this object's ID card is, if it has one. /obj/item/proc/get_sechud_job_icon_state() var/obj/item/card/id/id_card = GetID() diff --git a/code/datums/id_trim/jobs.dm b/code/datums/id_trim/jobs.dm index a42018406b2a5..0bb7dabe262cc 100644 --- a/code/datums/id_trim/jobs.dm +++ b/code/datums/id_trim/jobs.dm @@ -24,7 +24,7 @@ /datum/id_trim/job/New() if(ispath(job)) - job = SSjob.GetJobType(job) + job = SSjob.get_job_type(job) if(isnull(job_changes)) job_changes = SSmapping.config.job_changes @@ -156,6 +156,29 @@ ) job = /datum/job/bartender +/datum/id_trim/job/pun_pun + assignment = "Busser" + trim_state = "trim_busser" + department_color = COLOR_SERVICE_LIME + subdepartment_color = COLOR_SERVICE_LIME + sechud_icon_state = SECHUD_BUSSER + minimal_access = list( + ACCESS_MINERAL_STOREROOM, + ACCESS_SERVICE, + ACCESS_THEATRE, + ) + extra_access = list( + ACCESS_HYDROPONICS, + ACCESS_KITCHEN, + ACCESS_BAR, + ) + template_access = list( + ACCESS_CAPTAIN, + ACCESS_CHANGE_IDS, + ACCESS_HOP, + ) + job = /datum/job/pun_pun + /datum/id_trim/job/bitrunner assignment = JOB_BITRUNNER trim_state = "trim_bitrunner" @@ -1070,7 +1093,7 @@ if(CONFIG_GET(number/depsec_access_level) == POPULATION_SCALED_ACCESS) var/minimal_security_officers = 3 // We do not spawn in any more lockers if there are 5 or less security officers, so let's keep it lower than that number. - var/datum/job/J = SSjob.GetJob(JOB_SECURITY_OFFICER) + var/datum/job/J = SSjob.get_job(JOB_SECURITY_OFFICER) if((J.spawn_positions - minimal_security_officers) <= 0) access |= elevated_access diff --git a/code/datums/memory/tattoo_kit.dm b/code/datums/memory/tattoo_kit.dm index 98d47eaa285d8..62b4d73be28ba 100644 --- a/code/datums/memory/tattoo_kit.dm +++ b/code/datums/memory/tattoo_kit.dm @@ -46,11 +46,11 @@ if(!tattoo_target) balloon_alert(tattoo_artist, "no limb to tattoo!") return - if(HAS_TRAIT_FROM(tattoo_target, TRAIT_NOT_ENGRAVABLE, INNATE_TRAIT)) - balloon_alert(tattoo_artist, "bodypart cannot be engraved!") + if(HAS_TRAIT_FROM(tattoo_target, TRAIT_NOT_ENGRAVABLE, ENGRAVED_TRAIT)) + balloon_alert(tattoo_artist, "bodypart already tattooed!") return - if(HAS_TRAIT_FROM(tattoo_target, TRAIT_NOT_ENGRAVABLE, TRAIT_GENERIC)) - balloon_alert(tattoo_artist, "bodypart has already been engraved!") + if(HAS_TRAIT(tattoo_target, TRAIT_NOT_ENGRAVABLE)) + balloon_alert(tattoo_artist, "bodypart cannot be tattooed!") return var/datum/memory/memory_to_tattoo = tattoo_artist.mind.select_memory("tattoo") if(!memory_to_tattoo || !tattoo_artist.Adjacent(tattoo_holder) || !tattoo_holder.get_bodypart(selected_zone)) diff --git a/code/datums/mind/_mind.dm b/code/datums/mind/_mind.dm index 36e9d7ba6d024..397a1c5b13afa 100644 --- a/code/datums/mind/_mind.dm +++ b/code/datums/mind/_mind.dm @@ -106,7 +106,7 @@ /datum/mind/New(_key) key = _key init_known_skills() - set_assigned_role(SSjob.GetJobType(/datum/job/unassigned)) // Unassigned by default. + set_assigned_role(SSjob.get_job_type(/datum/job/unassigned)) // Unassigned by default. /datum/mind/Destroy() SSticker.minds -= src @@ -251,7 +251,7 @@ var/new_role = input("Select new role", "Assigned role", assigned_role.title) as null|anything in sort_list(SSjob.name_occupations) if(isnull(new_role)) return - var/datum/job/new_job = SSjob.GetJob(new_role) + var/datum/job/new_job = SSjob.get_job(new_role) if (!new_job) to_chat(usr, span_warning("Job not found.")) return diff --git a/code/datums/mind/antag.dm b/code/datums/mind/antag.dm index 11340ae56a6b4..ca10f3afe2071 100644 --- a/code/datums/mind/antag.dm +++ b/code/datums/mind/antag.dm @@ -286,7 +286,7 @@ /datum/mind/proc/make_wizard() if(has_antag_datum(/datum/antagonist/wizard)) return - set_assigned_role(SSjob.GetJobType(/datum/job/space_wizard)) + set_assigned_role(SSjob.get_job_type(/datum/job/space_wizard)) special_role = ROLE_WIZARD add_antag_datum(/datum/antagonist/wizard) diff --git a/code/datums/mind/initialization.dm b/code/datums/mind/initialization.dm index eb622cc5af549..e3b3e8225dc7a 100644 --- a/code/datums/mind/initialization.dm +++ b/code/datums/mind/initialization.dm @@ -21,17 +21,17 @@ //AI /mob/living/silicon/ai/mind_initialize() . = ..() - mind.set_assigned_role(SSjob.GetJobType(/datum/job/ai)) + mind.set_assigned_role(SSjob.get_job_type(/datum/job/ai)) //BORG /mob/living/silicon/robot/mind_initialize() . = ..() - mind.set_assigned_role(SSjob.GetJobType(/datum/job/cyborg)) + mind.set_assigned_role(SSjob.get_job_type(/datum/job/cyborg)) //PAI /mob/living/silicon/pai/mind_initialize() . = ..() - mind.set_assigned_role(SSjob.GetJobType(/datum/job/personal_ai)) + mind.set_assigned_role(SSjob.get_job_type(/datum/job/personal_ai)) mind.special_role = "" diff --git a/code/datums/mood.dm b/code/datums/mood.dm index 3834ea866b8da..cffd955635817 100644 --- a/code/datums/mood.dm +++ b/code/datums/mood.dm @@ -406,7 +406,7 @@ clear_mood_event(MOOD_CATEGORY_AREA_BEAUTY) return - if(HAS_TRAIT(mob_parent, TRAIT_MORBID)) + if(HAS_MIND_TRAIT(mob_parent, TRAIT_MORBID)) if(HAS_TRAIT(mob_parent, TRAIT_SNOB)) switch(area_to_beautify.beauty) if(BEAUTY_LEVEL_DECENT to BEAUTY_LEVEL_GOOD) diff --git a/code/datums/mood_events/food_events.dm b/code/datums/mood_events/food_events.dm index 7d33e7e57ce06..e64d975902ea7 100644 --- a/code/datums/mood_events/food_events.dm +++ b/code/datums/mood_events/food_events.dm @@ -49,3 +49,8 @@ /datum/mood_event/food/top quality = FOOD_QUALITY_TOP + +/datum/mood_event/pacifist_eating_fish_item + description = "I shouldn't be eating living creatures..." + mood_change = -1 //The disgusting food moodlet already has a pretty big negative value, this is just for context. + timeout = 4 MINUTES diff --git a/code/datums/mood_events/generic_positive_events.dm b/code/datums/mood_events/generic_positive_events.dm index 54b276fa71a3d..cdd28c1855ee8 100644 --- a/code/datums/mood_events/generic_positive_events.dm +++ b/code/datums/mood_events/generic_positive_events.dm @@ -333,9 +333,34 @@ /datum/mood_event/fishing description = "Fishing is relaxing." - mood_change = 5 + mood_change = 4 timeout = 3 MINUTES +/datum/mood_event/fish_released + description = "Go, fish, swim and be free!" + mood_change = 1 + timeout = 2 MINUTES + +/datum/mood_event/fish_released/add_effects(morbid, obj/item/fish/fish) + if(!morbid) + description = "Go, [fish.name], swim and be free!" + return + if(fish.status == FISH_DEAD) + description = "Some scavenger will surely find a use for the remains of [fish.name]. How pragmatic." + else + description = "Returned to the burden of the deep. But is this truly a mercy, [fish.name]? There will always be bigger fish..." + +/datum/mood_event/fish_petting + description = "It felt nice to pet the fish." + mood_change = 2 + timeout = 2 MINUTES + +/datum/mood_event/fish_petting/add_effects(obj/item/fish/fish, morbid) + if(!morbid) + description = "It felt nice to pet \the [fish]." + else + description = "I caress \the [fish] as [fish.p_they()] squirms under my touch, blissfully unaware of how cruel this world is." + /datum/mood_event/kobun description = "You are all loved by the Universe. I’m not alone, and you aren’t either." mood_change = 14 diff --git a/code/datums/proximity_monitor/field.dm b/code/datums/proximity_monitor/field.dm index e3f0ade5e7dba..3ba3017bed0a5 100644 --- a/code/datums/proximity_monitor/field.dm +++ b/code/datums/proximity_monitor/field.dm @@ -40,7 +40,7 @@ var/list/old_edge_turfs = edge_turfs field_turfs = new_turfs[FIELD_TURFS_KEY] edge_turfs = new_turfs[EDGE_TURFS_KEY] - if(!full_recalc) + if(full_recalc) field_turfs = list() edge_turfs = list() @@ -62,12 +62,11 @@ for(var/turf/new_turf as anything in field_turfs - old_field_turfs) if(QDELETED(src)) return - field_turfs += new_turf setup_field_turf(new_turf) + for(var/turf/new_turf as anything in edge_turfs - old_edge_turfs) if(QDELETED(src)) return - edge_turfs += new_turf setup_edge_turf(new_turf) /datum/proximity_monitor/advanced/on_initialized(turf/location, atom/created, init_flags) diff --git a/code/datums/proximity_monitor/fields/void_storm.dm b/code/datums/proximity_monitor/fields/void_storm.dm new file mode 100644 index 0000000000000..c9e3bbbbcff91 --- /dev/null +++ b/code/datums/proximity_monitor/fields/void_storm.dm @@ -0,0 +1,37 @@ +/*! + * Void storm for the void heretic ascension + * + * Follows the heretic around and acts like an aura with damaging effects for non-heretics + */ +/datum/proximity_monitor/advanced/void_storm + edge_is_a_field = TRUE + // lazylist that keeps track of the overlays added + var/list/turf_effects + var/static/image/storm_overlay = image('icons/effects/weather_effects.dmi', "snow_storm") + +/datum/proximity_monitor/advanced/void_storm/New(atom/_host, range, _ignore_if_not_on_turf) + . = ..() + recalculate_field(full_recalc = TRUE) + +/datum/proximity_monitor/advanced/void_storm/recalculate_field(full_recalc) + full_recalc = TRUE // We always perform a full recalc because we need to update ALL the sprites + return ..() + +/datum/proximity_monitor/advanced/void_storm/cleanup_field_turf(turf/target) + . = ..() + var/obj/effect/abstract/effect = LAZYACCESS(turf_effects, target) + LAZYREMOVE(turf_effects, target) + if(effect) + qdel(effect) + +/datum/proximity_monitor/advanced/void_storm/setup_field_turf(turf/target) + . = ..() + var/obj/effect/abstract/effect = new(target) // Makes the field visible to players. + effect.alpha = 255 - get_dist(target, host.loc) * 23 + effect.color = COLOR_BLACK + effect.icon = storm_overlay.icon + effect.icon_state = storm_overlay.icon_state + effect.mouse_opacity = MOUSE_OPACITY_TRANSPARENT + effect.layer = ABOVE_ALL_MOB_LAYER + SET_PLANE(effect, ABOVE_GAME_PLANE, target) + LAZYSET(turf_effects, target, effect) diff --git a/code/datums/quirks/neutral_quirks/vegetarian.dm b/code/datums/quirks/neutral_quirks/vegetarian.dm index 0ade72acafe57..0568e2f1e2293 100644 --- a/code/datums/quirks/neutral_quirks/vegetarian.dm +++ b/code/datums/quirks/neutral_quirks/vegetarian.dm @@ -7,17 +7,4 @@ lose_text = span_notice("You feel like eating meat isn't that bad.") medical_record_text = "Patient reports a vegetarian diet." mail_goodies = list(/obj/effect/spawner/random/food_or_drink/salad) - -/datum/quirk/vegetarian/add(client/client_source) - var/obj/item/organ/internal/tongue/tongue = quirk_holder.get_organ_slot(ORGAN_SLOT_TONGUE) - if(!tongue) - return - tongue.liked_foodtypes &= ~MEAT - tongue.disliked_foodtypes |= MEAT - -/datum/quirk/vegetarian/remove() - var/obj/item/organ/internal/tongue/tongue = quirk_holder.get_organ_slot(ORGAN_SLOT_TONGUE) - if(!tongue) - return - tongue.liked_foodtypes = initial(tongue.liked_foodtypes) - tongue.disliked_foodtypes = initial(tongue.disliked_foodtypes) + mob_trait = TRAIT_VEGETARIAN diff --git a/code/datums/records/manifest.dm b/code/datums/records/manifest.dm index fc2bb30ce8d32..afc5cef6aa4ec 100644 --- a/code/datums/records/manifest.dm +++ b/code/datums/records/manifest.dm @@ -31,7 +31,7 @@ GLOBAL_DATUM_INIT(manifest, /datum/manifest, new) var/name = target.name var/rank = target.rank // user-visible job var/trim = target.trim // internal jobs by trim type - var/datum/job/job = SSjob.GetJob(trim) + var/datum/job/job = SSjob.get_job(trim) if(!job || !(job.job_flags & JOB_CREW_MANIFEST) || !LAZYLEN(job.departments_list)) // In case an unlawful custom rank is added. var/list/misc_list = manifest_out[DEPARTMENT_UNASSIGNED] misc_list[++misc_list.len] = list( diff --git a/code/datums/ruins/icemoon.dm b/code/datums/ruins/icemoon.dm index 2445b4da242e6..d6317b12ab15c 100644 --- a/code/datums/ruins/icemoon.dm +++ b/code/datums/ruins/icemoon.dm @@ -64,7 +64,7 @@ /datum/map_template/ruin/icemoon/frozen_phonebooth name = "Ice-Ruin Frozen Phonebooth" id = "frozen_phonebooth" - description = "A venture by nanotrasen to help popularize the use of holopads. This one was sent to a icemoon." + description = "A venture by Nanotrasen to help popularize the use of holopads. This one was sent to a icemoon." suffix = "icemoon_surface_phonebooth.dmm" /datum/map_template/ruin/icemoon/smoking_room @@ -172,6 +172,12 @@ description = "Radio signals are being detected and the source is this completely innocent pile of snow." suffix = "icemoon_underground_comms_agent.dmm" +/datum/map_template/ruin/icemoon/underground/syndie_lab + name = "Ice-Ruin Syndicate Lab" + id = "syndie_lab" + description = "A small laboratory and living space for Syndicate agents." + suffix = "icemoon_underground_syndielab.dmm" + //TODO: Bottom-Level ONLY Spawns after Refactoring Related Code /datum/map_template/ruin/icemoon/underground/plasma_facility name = "Ice-Ruin Abandoned Plasma Facility" diff --git a/code/datums/ruins/lavaland.dm b/code/datums/ruins/lavaland.dm index bb5f58500e2d1..fb2d1d44c0c08 100644 --- a/code/datums/ruins/lavaland.dm +++ b/code/datums/ruins/lavaland.dm @@ -278,7 +278,7 @@ /datum/map_template/ruin/lavaland/lava_phonebooth name = "Lava-Ruin Phonebooth" id = "lava_phonebooth" - description = "A venture by nanotrasen to help popularize the use of holopads. This one somehow made its way here." + description = "A venture by Nanotrasen to help popularize the use of holopads. This one somehow made its way here." suffix = "lavaland_surface_phonebooth.dmm" allow_duplicates = FALSE cost = 5 diff --git a/code/datums/ruins/space.dm b/code/datums/ruins/space.dm index e3ff61fad6c25..790ae33ade4b1 100644 --- a/code/datums/ruins/space.dm +++ b/code/datums/ruins/space.dm @@ -49,7 +49,7 @@ id = "asteroid6" suffix = "asteroid6.dmm" name = "Space-Ruin Asteroid 6" - description = "This asteroid has brittle bone disease, so it is fortunate asteroids dont have bones." + description = "This asteroid has brittle bone disease, so it is fortunate asteroids don't have bones." /datum/map_template/ruin/space/deep_storage id = "deep-storage" @@ -70,7 +70,7 @@ suffix = "derelict_construction.dmm" name = "Space-Ruin Derelict Construction" description = "Construction supplies are in high demand due to non-trivial damage routinely sustained by most space stations in this sector. \ - Space pirates who dont attempt to rob corporate research stations with only 3 collaborators live long enough to sell captured construction \ + Space pirates who don't attempt to rob corporate research stations with only 3 collaborators live long enough to sell captured construction \ equipment back to the highest bidder." /datum/map_template/ruin/space/derelict_sulaco @@ -181,7 +181,7 @@ id = "spacehotel" suffix = "spacehotel.dmm" name = "Space-Ruin The Twin-Nexus Hotel" - description = "An interstellar hotel, where the weary spaceman can rest their head and relax, assured that the residental staff will not murder them in their sleep. Probably." + description = "An interstellar hotel, where the weary spaceman can rest their head and relax, assured that the residential staff will not murder them in their sleep. Probably." /datum/map_template/ruin/space/turreted_outpost id = "turreted-outpost" @@ -470,7 +470,7 @@ id = "Space_phonebooth" suffix = "phonebooth.dmm" name = "Space-Ruin Phonebooth" - description = "A venture by nanotrasen to help popularize the use of holopads." + description = "A venture by Nanotrasen to help popularize the use of holopads." /datum/map_template/ruin/space/the_outlet id = "the_outlet" @@ -500,7 +500,7 @@ id = "garbagetruck3" suffix = "garbagetruck3.dmm" name = "Space-Ruin Decommissioned Garbage Truck NX3" - description = "An NX-760 interstellar transport barge. At the end of their life cycle, they are often filled with trash and launched into unexplored space to become someone else's problem. This one is full of industrial garbage, and a russian drug den." + description = "An NX-760 interstellar transport barge. At the end of their life cycle, they are often filled with trash and launched into unexplored space to become someone else's problem. This one is full of industrial garbage, and a Russian drug den." /datum/map_template/ruin/space/garbagetruck4 id = "garbagetruck4" diff --git a/code/datums/shuttles/_shuttle.dm b/code/datums/shuttles/_shuttle.dm index 0100a3d85da3d..94c20d41b7365 100644 --- a/code/datums/shuttles/_shuttle.dm +++ b/code/datums/shuttles/_shuttle.dm @@ -14,7 +14,7 @@ var/description /// The recommended occupancy limit for the shuttle (count chairs, beds, and benches then round to 5) var/occupancy_limit - /// Description of the prerequisition that has to be achieved for the shuttle to be purchased + /// Description of the prerequisite that has to be achieved for the shuttle to be purchased var/prerequisites /// Shuttle warnings and hazards to the admin who spawns the shuttle var/admin_notes @@ -40,7 +40,7 @@ . = ..() /datum/map_template/shuttle/preload_size(path, cache) - . = ..(path, TRUE) // Done this way because we still want to know if someone actualy wanted to cache the map + . = ..(path, TRUE) // Done this way because we still want to know if someone actually wanted to cache the map if(!cached_map) return diff --git a/code/datums/shuttles/emergency.dm b/code/datums/shuttles/emergency.dm index 42e3566ccfef1..2af1a238a7258 100644 --- a/code/datums/shuttles/emergency.dm +++ b/code/datums/shuttles/emergency.dm @@ -90,7 +90,7 @@ suffix = "bar" name = "The Emergency Escape Bar" description = "Features include sentient bar staff (a Bardrone and a Barmaid), bathroom, a quality lounge for the heads, and a large gathering table." - admin_notes = "Bardrone and Barmaid are GODMODE, will be automatically sentienced by the fun balloon at 60 seconds before arrival. \ + admin_notes = "Bardrone and Barmaid have TRAIT_GODMODE (basically invincibility), will be automatically sentienced by the fun balloon at 60 seconds before arrival. \ Has medical facilities." credit_cost = CARGO_CRATE_VALUE * 10 occupancy_limit = "30" @@ -164,7 +164,7 @@ /datum/map_template/shuttle/emergency/arena suffix = "arena" name = "The Arena" - description = "The crew must pass through an otherworldy arena to board this shuttle. Expect massive casualties." + description = "The crew must pass through an otherworldly arena to board this shuttle. Expect massive casualties." prerequisites = "The source of the Bloody Signal must be tracked down and eliminated to unlock this shuttle." admin_notes = "RIP AND TEAR." credit_cost = CARGO_CRATE_VALUE * 20 @@ -241,7 +241,7 @@ suffix = "kilo" name = "Kilo Station Emergency Shuttle" credit_cost = CARGO_CRATE_VALUE * 10 - description = "A fully functional shuttle including a complete infirmary, storage facilties and regular amenities." + description = "A fully functional shuttle including a complete infirmary, storage facilities and regular amenities." occupancy_limit = "55" /datum/map_template/shuttle/emergency/mini @@ -400,15 +400,15 @@ /datum/map_template/shuttle/emergency/monkey suffix = "nature" name = "Dynamic Environmental Interaction Shuttle" - description = "A large shuttle with a center biodome that is flourishing with life. Frolick with the monkeys! (Extra monkeys are stored on the bridge.)" - admin_notes = "Pretty freakin' large, almost as big as Raven or Cere. Excercise caution with it." + description = "A large shuttle with a center biodome that is flourishing with life. Frolic with the monkeys! (Extra monkeys are stored on the bridge.)" + admin_notes = "Pretty freakin' large, almost as big as Raven or Cere. Exercise caution with it." credit_cost = CARGO_CRATE_VALUE * 16 occupancy_limit = "45" /datum/map_template/shuttle/emergency/casino suffix = "casino" name = "Lucky Jackpot Casino Shuttle" - description = "A luxurious casino packed to the brim with everything you need to start new gambling addicitions!" + description = "A luxurious casino packed to the brim with everything you need to start new gambling addictions!" admin_notes = "The ship is a bit chunky, so watch where you park it." credit_cost = 7777 occupancy_limit = "85" @@ -424,7 +424,7 @@ /datum/map_template/shuttle/emergency/fish suffix = "fish" name = "Angler's Choice Emergency Shuttle" - description = "Trades such amenities as 'storage space' and 'sufficient seating' for an artifical environment ideal for fishing, plus ample supplies (also for fishing)." + description = "Trades such amenities as 'storage space' and 'sufficient seating' for an artificial environment ideal for fishing, plus ample supplies (also for fishing)." admin_notes = "There's a chasm in it, it has railings but that won't stop determined players." credit_cost = CARGO_CRATE_VALUE * 10 occupancy_limit = "35" diff --git a/code/datums/station_traits/_station_trait.dm b/code/datums/station_traits/_station_trait.dm index ef91a183d9f27..ddd8bc20a9110 100644 --- a/code/datums/station_traits/_station_trait.dm +++ b/code/datums/station_traits/_station_trait.dm @@ -33,10 +33,10 @@ GLOBAL_LIST_EMPTY(lobby_station_traits) var/list/lobby_buttons = list() /// The ID that we look for in dynamic.json. Not synced with 'name' because I can already see this go wrong var/dynamic_threat_id - /// If ran during dynamic, do we reduce the total threat? Will be overriden by config if set + /// If ran during dynamic, do we reduce the total threat? Will be overridden by config if set var/threat_reduction = 0 - /// Which ruleset flags to allow dynamic to use. null to disregard - var/dynamic_category = null + /// Which ruleset flags to allow dynamic to use. NONE to disregard + var/dynamic_category = NONE /// Trait should not be instantiated in a round if its type matches this type var/abstract_type = /datum/station_trait @@ -51,15 +51,19 @@ GLOBAL_LIST_EMPTY(lobby_station_traits) GLOB.dynamic_ruleset_categories = dynamic_category if(sign_up_button) GLOB.lobby_station_traits += src + if(SSstation.initialized) + SSstation.display_lobby_traits() if(trait_processes) START_PROCESSING(SSstation, src) if(trait_to_give) ADD_TRAIT(SSstation, trait_to_give, STATION_TRAIT) /datum/station_trait/Destroy() - SSstation.station_traits -= src - GLOB.dynamic_station_traits.Remove(src) destroy_lobby_buttons() + SSstation.station_traits -= src + GLOB.lobby_station_traits -= src + GLOB.dynamic_station_traits -= src + REMOVE_TRAIT(SSstation, trait_to_give, STATION_TRAIT) return ..() /// Returns the type of info the centcom report has on this trait, if any. @@ -125,13 +129,15 @@ GLOBAL_LIST_EMPTY(lobby_station_traits) /// Remove all of our active lobby buttons /datum/station_trait/proc/destroy_lobby_buttons() for (var/atom/movable/screen/button as anything in lobby_buttons) - var/mob/hud_owner = button.get_mob() - qdel(button) + var/mob/dead/new_player/hud_owner = button.get_mob() if (QDELETED(hud_owner)) + qdel(button) + continue + var/datum/hud/new_player/using_hud = hud_owner.hud_used + if(!using_hud) + qdel(button) continue - var/datum/hud/using_hud = hud_owner.hud_used - using_hud?.show_hud(using_hud?.hud_version) - lobby_buttons = list() + using_hud.remove_station_trait_button(src) /// Called when overriding a pulsar star command report message. /datum/station_trait/proc/get_pulsar_message() diff --git a/code/datums/station_traits/job_traits.dm b/code/datums/station_traits/job_traits.dm index f2bd456aaee77..b23a694cfdec9 100644 --- a/code/datums/station_traits/job_traits.dm +++ b/code/datums/station_traits/job_traits.dm @@ -41,6 +41,10 @@ else LAZYADD(lobby_candidates, user) +/datum/station_trait/job/on_lobby_button_destroyed(atom/movable/screen/lobby/button/sign_up/lobby_button) + . = ..() + LAZYREMOVE(lobby_candidates, lobby_button.get_mob()) + /datum/station_trait/job/on_lobby_button_update_icon(atom/movable/screen/lobby/button/sign_up/lobby_button, updates) if (LAZYFIND(lobby_candidates, lobby_button.get_mob())) lobby_button.base_icon_state = "signup_on" @@ -61,7 +65,7 @@ if (isnull(signee) || !signee.client || !signee.mind || signee.ready != PLAYER_READY_TO_PLAY) LAZYREMOVE(lobby_candidates, signee) - var/datum/job/our_job = SSjob.GetJobType(job_to_add) + var/datum/job/our_job = SSjob.get_job_type(job_to_add) our_job.total_positions = position_amount our_job.spawn_positions = position_amount while(length(lobby_candidates) && position_amount > 0) @@ -73,14 +77,14 @@ lobby_candidates = null /datum/station_trait/job/can_display_lobby_button(client/player) - var/datum/job/our_job = SSjob.GetJobType(job_to_add) + var/datum/job/our_job = SSjob.get_job_type(job_to_add) return our_job.player_old_enough(player) && ..() /// Adds a gorilla to the cargo department, replacing the sloth and the mech /datum/station_trait/job/cargorilla name = "Cargo Gorilla" button_desc = "Sign up to become the Cargo Gorilla, a peaceful shepherd of boxes." - weight = 1 + weight = 0 show_in_report = FALSE // Selective attention test. Did you spot the gorilla? can_roll_antag = CAN_ROLL_NEVER job_to_add = /datum/job/cargo_gorilla @@ -243,6 +247,26 @@ qdel(thing_on_table) new /obj/machinery/fax/auto_name(picked_turf) +/datum/station_trait/job/pun_pun + name = "Pun Pun is a Crewmember" + button_desc = "Ook ook ah ah, sign up to play as the bartender's monkey." + weight = 0 //Unrollable by default, available all day during monkey day. + report_message = "We've evaluated the bartender's monkey to have the mental capacity of the average crewmember. As such, we made them one." + show_in_report = TRUE + can_roll_antag = CAN_ROLL_ALWAYS + job_to_add = /datum/job/pun_pun + +/datum/station_trait/job/pun_pun/New() + . = ..() + if(!SSticker.HasRoundStarted() || !GLOB.the_one_and_only_punpun) //Make sure we don't have two Pun Puns if loaded before the start of the round. + return + new /obj/effect/landmark/start/pun_pun(GLOB.the_one_and_only_punpun.loc) + qdel(GLOB.the_one_and_only_punpun) + +/datum/station_trait/job/pun_pun/on_lobby_button_update_overlays(atom/movable/screen/lobby/button/sign_up/lobby_button, list/overlays) + . = ..() + overlays += LAZYFIND(lobby_candidates, lobby_button.get_mob()) ? "pun_pun_on" : "pun_pun_off" + #undef CAN_ROLL_ALWAYS #undef CAN_ROLL_PROTECTED #undef CAN_ROLL_NEVER diff --git a/code/datums/station_traits/negative_traits.dm b/code/datums/station_traits/negative_traits.dm index 83d1bfa14f4c9..fc7fd4c01ef7f 100644 --- a/code/datums/station_traits/negative_traits.dm +++ b/code/datums/station_traits/negative_traits.dm @@ -26,7 +26,7 @@ report_message = "Due to an ongoing strike announced by the postal workers union, mail won't be delivered this shift." /datum/station_trait/mail_blocked/on_round_start() - //This is either a holiday or sunday... well then, let's flip the situation. + //This is either a holiday or Sunday... well then, let's flip the situation. if(SSeconomy.mail_blocked) name = "Postal system overtime" report_message = "Despite being a day off, the postal system is working overtime today. Mail will be delivered this shift." @@ -343,7 +343,7 @@ /datum/station_trait/random_event_weight_modifier/dust_storms name = "Dust Stormfront" - report_message = "The space around your station is clouded by heavy pockets of space dust. Expect an increased likelyhood of space dust storms damaging the station hull." + report_message = "The space around your station is clouded by heavy pockets of space dust. Expect an increased likelihood of space dust storms damaging the station hull." trait_type = STATION_TRAIT_NEGATIVE weight = 2 cost = STATION_TRAIT_COST_LOW @@ -614,10 +614,10 @@ //Send a nebula shielding unit to engineering var/datum/supply_pack/supply_pack_shielding = new /datum/supply_pack/engineering/rad_nebula_shielding_kit() if(!send_supply_pod_to_area(supply_pack_shielding.generate(null), /area/station/engineering/main, /obj/structure/closet/supplypod/centcompod)) - //if engineering isnt valid, just send it to the bridge + //if engineering isn't valid, just send it to the bridge send_supply_pod_to_area(supply_pack_shielding.generate(null), /area/station/command/bridge, /obj/structure/closet/supplypod/centcompod) - // Let medical know resistence is futile + // Let medical know resistance is futile if (/area/station/medical/virology in GLOB.areas_by_type) send_fax_to_area( new /obj/item/paper/fluff/radiation_nebula_virologist, @@ -656,7 +656,7 @@ if(!istype(get_area(spawned_mob), radioactive_areas)) //only if you're spawned in the radioactive areas return - if(!isliving(spawned_mob)) // Dynamic shouldnt spawn non-living but uhhhhhhh why not + if(!isliving(spawned_mob)) // Dynamic shouldn't spawn non-living but uhhhhhhh why not return var/mob/living/spawnee = spawned_mob @@ -696,7 +696,7 @@ /datum/station_trait/nebula/hostile/radiation/send_instructions() var/obj/machinery/nebula_shielding/shielder = /obj/machinery/nebula_shielding/radiation var/obj/machinery/gravity_generator/main/innate_shielding = /obj/machinery/gravity_generator/main - //How long do we have untill the first shielding unit needs to be up? + //How long do we have until the first shielding unit needs to be up? var/deadline = "[(initial(innate_shielding.radioactive_nebula_shielding) * intensity_increment_time) / (1 MINUTES)] minute\s" //For how long each shielding unit will protect for var/shielder_time = "[(initial(shielder.shielding_strength) * intensity_increment_time) / (1 MINUTES)] minute\s" diff --git a/code/datums/station_traits/positive_traits.dm b/code/datums/station_traits/positive_traits.dm index 945fbe06934bc..052a8177345c7 100644 --- a/code/datums/station_traits/positive_traits.dm +++ b/code/datums/station_traits/positive_traits.dm @@ -285,6 +285,7 @@ /datum/job/paramedic = /obj/item/organ/internal/cyberimp/eyes/hud/medical, /datum/job/prisoner = /obj/item/organ/internal/eyes/robotic/shield, /datum/job/psychologist = /obj/item/organ/internal/ears/cybernetic/whisper, + /datum/job/pun_pun = /obj/item/organ/internal/cyberimp/arm/strongarm, /datum/job/quartermaster = /obj/item/organ/internal/stomach/cybernetic/tier3, /datum/job/research_director = /obj/item/organ/internal/cyberimp/bci, /datum/job/roboticist = /obj/item/organ/internal/cyberimp/eyes/hud/diagnostic, diff --git a/code/datums/status_effects/debuffs/fire_stacks.dm b/code/datums/status_effects/debuffs/fire_stacks.dm index c2ca39b638726..ae7f73d4e0de0 100644 --- a/code/datums/status_effects/debuffs/fire_stacks.dm +++ b/code/datums/status_effects/debuffs/fire_stacks.dm @@ -227,8 +227,9 @@ amount_to_heat = amount_to_heat ** (BODYTEMP_FIRE_TEMP_SOFTCAP / owner.bodytemperature) victim.adjust_bodytemperature(amount_to_heat) - victim.add_mood_event("on_fire", /datum/mood_event/on_fire) - victim.add_mob_memory(/datum/memory/was_burning) + if (!(HAS_TRAIT(victim, TRAIT_RESISTHEAT))) + victim.add_mood_event("on_fire", /datum/mood_event/on_fire) + victim.add_mob_memory(/datum/memory/was_burning) /** * Handles mob ignition, should be the only way to set on_fire to TRUE diff --git a/code/datums/status_effects/debuffs/genetic_damage.dm b/code/datums/status_effects/debuffs/genetic_damage.dm index 9a6944090775e..91cfc593fcc41 100644 --- a/code/datums/status_effects/debuffs/genetic_damage.dm +++ b/code/datums/status_effects/debuffs/genetic_damage.dm @@ -34,7 +34,7 @@ /datum/status_effect/genetic_damage/tick(seconds_between_ticks) if(ismonkey(owner) && total_damage >= GORILLA_MUTATION_MINIMUM_DAMAGE && SPT_PROB(GORILLA_MUTATION_CHANCE_PER_SECOND, seconds_between_ticks)) var/mob/living/carbon/carbon_owner = owner - carbon_owner.gorillize() + carbon_owner.gorillize(genetics_gorilla = TRUE) qdel(src) return diff --git a/code/datums/storage/storage.dm b/code/datums/storage/storage.dm index 4633ffb556616..e5a7f3ee0f5a8 100644 --- a/code/datums/storage/storage.dm +++ b/code/datums/storage/storage.dm @@ -189,20 +189,19 @@ /// Set the passed atom as the parent /datum/storage/proc/set_parent(atom/new_parent) - PRIVATE_PROC(TRUE) + PROTECTED_PROC(TRUE) ASSERT(isnull(parent)) parent = new_parent + ADD_TRAIT(parent, TRAIT_COMBAT_MODE_SKIP_INTERACTION, REF(src)) // a few of theses should probably be on the real_location rather than the parent - RegisterSignal(parent, COMSIG_ATOM_ITEM_INTERACTION, PROC_REF(on_item_interact)) RegisterSignals(parent, list(COMSIG_ATOM_ATTACK_PAW, COMSIG_ATOM_ATTACK_HAND), PROC_REF(on_attack)) RegisterSignal(parent, COMSIG_MOUSEDROP_ONTO, PROC_REF(on_mousedrop_onto)) RegisterSignal(parent, COMSIG_MOUSEDROPPED_ONTO, PROC_REF(on_mousedropped_onto)) RegisterSignal(parent, COMSIG_ITEM_PRE_ATTACK, PROC_REF(on_preattack)) RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, PROC_REF(mass_empty)) RegisterSignals(parent, list(COMSIG_ATOM_ATTACK_GHOST, COMSIG_ATOM_ATTACK_HAND_SECONDARY), PROC_REF(open_storage_on_signal)) - RegisterSignal(parent, COMSIG_ATOM_ITEM_INTERACTION_SECONDARY, PROC_REF(on_item_interact_secondary)) RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(close_distance)) RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(update_actions)) RegisterSignal(parent, COMSIG_TOPIC, PROC_REF(topic_handle)) @@ -827,26 +826,12 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) return if(!iscarbon(user) && !isdrone(user)) return - var/mob/living/user_living = user - if(user_living.incapacitated) - return - attempt_insert(dropping, user) return COMPONENT_CANCEL_MOUSEDROPPED_ONTO -/// Signal handler for whenever we're attacked by an object. -/datum/storage/proc/on_item_interact(datum/source, mob/user, obj/item/thing, params) - SIGNAL_HANDLER - - if(!insert_on_attack) - return NONE - if(!thing.storage_insert_on_interaction(src, parent, user)) - return NONE - if(!parent.storage_insert_on_interacted_with(src, thing, user)) - return NONE - if(SEND_SIGNAL(parent, COMSIG_ATOM_STORAGE_ITEM_INTERACT_INSERT, thing, user) & BLOCK_STORAGE_INSERT) - return NONE - +/// Called directly from the attack chain if [insert_on_attack] is TRUE. +/// Handles inserting an item into the storage when clicked. +/datum/storage/proc/item_interact_insert(mob/living/user, obj/item/thing) if(iscyborg(user)) return ITEM_INTERACT_BLOCKING @@ -897,18 +882,6 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) return toreturn -/// Signal handler for when we get attacked with secondary click by an item. -/datum/storage/proc/on_item_interact_secondary(datum/source, mob/user, atom/weapon) - SIGNAL_HANDLER - - if(istype(weapon, /obj/item/chameleon)) - var/obj/item/chameleon/chameleon_weapon = weapon - chameleon_weapon.make_copy(source, user) - - if(open_storage_on_signal(source, user)) - return ITEM_INTERACT_BLOCKING - return NONE - /// Signal handler to open up the storage when we receive a signal. /datum/storage/proc/open_storage_on_signal(datum/source, mob/to_show) SIGNAL_HANDLER diff --git a/code/datums/weather/weather_types/radiation_storm.dm b/code/datums/weather/weather_types/radiation_storm.dm index 8a1cfff765733..9bf17c7a9dc76 100644 --- a/code/datums/weather/weather_types/radiation_storm.dm +++ b/code/datums/weather/weather_types/radiation_storm.dm @@ -34,28 +34,28 @@ status_alarm(TRUE) -/datum/weather/rad_storm/weather_act(mob/living/L) +/datum/weather/rad_storm/weather_act(mob/living/living) if(!prob(mutate_chance)) return - if(!ishuman(L)) + if(!ishuman(living) || HAS_TRAIT(living, TRAIT_GODMODE)) return - var/mob/living/carbon/human/H = L - if(!H.can_mutate() || H.status_flags & GODMODE) + var/mob/living/carbon/human/human = living + if(!human.can_mutate()) return - if(HAS_TRAIT(H, TRAIT_RADIMMUNE)) + if(HAS_TRAIT(human, TRAIT_RADIMMUNE)) return - if (SSradiation.wearing_rad_protected_clothing(H)) + if (SSradiation.wearing_rad_protected_clothing(human)) return - H.random_mutate_unique_identity() - H.random_mutate_unique_features() + human.random_mutate_unique_identity() + human.random_mutate_unique_features() if(prob(50)) - do_mutate(L) + do_mutate(human) /datum/weather/rad_storm/end() if(..()) diff --git a/code/datums/weather/weather_types/void_storm.dm b/code/datums/weather/weather_types/void_storm.dm index 90cc7d44cfbe1..617e3ff0230fd 100644 --- a/code/datums/weather/weather_types/void_storm.dm +++ b/code/datums/weather/weather_types/void_storm.dm @@ -6,7 +6,7 @@ telegraph_overlay = "light_snow" weather_message = span_hypnophrase("You feel the air around you getting colder... and void's sweet embrace...") - weather_overlay = "snow_storm" + weather_overlay = "light_snow" weather_color = COLOR_BLACK weather_duration_lower = 60 SECONDS weather_duration_upper = 120 SECONDS @@ -19,31 +19,5 @@ protect_indoors = FALSE target_trait = ZTRAIT_VOIDSTORM - immunity_type = TRAIT_VOIDSTORM_IMMUNE - barometer_predictable = FALSE perpetual = TRUE - - /// List of areas that were once impacted areas but are not anymore. Used for updating the weather overlay based whether the ascended heretic is in the area. - var/list/former_impacted_areas = list() - -/datum/weather/void_storm/can_weather_act(mob/living/mob_to_check) - . = ..() - if(IS_HERETIC_OR_MONSTER(mob_to_check)) - return FALSE - -/datum/weather/void_storm/weather_act(mob/living/victim) - var/need_mob_update = FALSE - need_mob_update += victim.adjustFireLoss(1, updating_health = FALSE) - need_mob_update += victim.adjustOxyLoss(rand(1, 3), updating_health = FALSE) - if(need_mob_update) - victim.updatehealth() - victim.adjust_eye_blur(rand(0 SECONDS, 2 SECONDS)) - victim.adjust_bodytemperature(-30 * TEMPERATURE_DAMAGE_COEFFICIENT) - -// Goes through former_impacted_areas and sets the overlay of each back to the telegraph overlay, to indicate the ascended heretic is no longer in that area. -/datum/weather/void_storm/update_areas() - for(var/area/former_area as anything in former_impacted_areas) - former_area.icon_state = telegraph_overlay - former_impacted_areas -= former_area - return ..() diff --git a/code/datums/wounds/_wound_static_data.dm b/code/datums/wounds/_wound_static_data.dm index f8b03d1856b5d..adc0923ee4f0a 100644 --- a/code/datums/wounds/_wound_static_data.dm +++ b/code/datums/wounds/_wound_static_data.dm @@ -95,7 +95,7 @@ if (random_roll && !can_be_randomly_generated) return FALSE - if (HAS_TRAIT(limb.owner, TRAIT_NEVER_WOUNDED) || (limb.owner.status_flags & GODMODE)) + if (HAS_TRAIT(limb.owner, TRAIT_NEVER_WOUNDED) || HAS_TRAIT(limb.owner, TRAIT_GODMODE)) return FALSE if (!wounding_types_valid(suggested_wounding_types)) diff --git a/code/game/area/areas/centcom.dm b/code/game/area/areas/centcom.dm index 012e7a170f726..28b3496c4e18a 100644 --- a/code/game/area/areas/centcom.dm +++ b/code/game/area/areas/centcom.dm @@ -124,6 +124,7 @@ /area/centcom/tdome/arena name = "Thunderdome Arena" icon_state = "thunder" + area_flags = parent_type::area_flags | UNLIMITED_FISHING //for possible testing purposes /area/centcom/tdome/tdome1 name = "Thunderdome (Team 1)" diff --git a/code/game/area/areas/ruins/icemoon.dm b/code/game/area/areas/ruins/icemoon.dm index d0049e7007c49..061bd8f06d209 100644 --- a/code/game/area/areas/ruins/icemoon.dm +++ b/code/game/area/areas/ruins/icemoon.dm @@ -75,3 +75,7 @@ /area/ruin/powered/hermit name = "\improper Hermit's Cabin" +/area/ruin/syndielab + name = "\improper Syndicate Lab" + ambience_index = AMBIENCE_DANGER + sound_environment = SOUND_ENVIRONMENT_CAVE diff --git a/code/game/atom/_atom.dm b/code/game/atom/_atom.dm index 9c1f69af47e23..ca4ae5635797a 100644 --- a/code/game/atom/_atom.dm +++ b/code/game/atom/_atom.dm @@ -690,10 +690,10 @@ 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) + UsedforProcessing(user, process_item, chosen_option, created_atoms) return -/atom/proc/UsedforProcessing(mob/living/user, obj/item/used_item, list/chosen_option) +/atom/proc/UsedforProcessing(mob/living/user, obj/item/used_item, list/chosen_option, list/created_atoms) qdel(src) return diff --git a/code/game/atom/alternate_appearance.dm b/code/game/atom/alternate_appearance.dm index 108b72b95d286..8c50760ea45ea 100644 --- a/code/game/atom/alternate_appearance.dm +++ b/code/game/atom/alternate_appearance.dm @@ -212,3 +212,10 @@ GLOBAL_LIST_EMPTY(active_alternate_appearances) return ..() /datum/atom_hud/alternate_appearance/basic/food_demands + +/datum/atom_hud/alternate_appearance/basic/heretic + +/datum/atom_hud/alternate_appearance/basic/heretic/mobShouldSee(mob/M) + if(IS_HERETIC(M)) + return TRUE + return FALSE diff --git a/code/game/atom/atom_examine.dm b/code/game/atom/atom_examine.dm index 0a2a51dc297d4..fee219f7b4b50 100644 --- a/code/game/atom/atom_examine.dm +++ b/code/game/atom/atom_examine.dm @@ -24,12 +24,15 @@ if(desc) . += "[desc]" - if(custom_materials) - var/list/materials_list = list() - for(var/custom_material in custom_materials) - var/datum/material/current_material = GET_MATERIAL_REF(custom_material) - materials_list += "[current_material.name]" - . += "It is made out of [english_list(materials_list)]." + var/list/tags_list = examine_tags(user) + if (length(tags_list)) + var/tag_string = list() + for (var/atom_tag in tags_list) + tag_string += (isnull(tags_list[atom_tag]) ? atom_tag : span_tooltip(tags_list[atom_tag], atom_tag)) + // Weird bit but ensures that if the final element has its own "and" we don't add another one + tag_string = english_list(tag_string, and_text = (findtext(tag_string[length(tag_string)], " and ")) ? ", " : " and ") + var/post_descriptor = examine_post_descriptor(user) + . += "[p_They()] [p_are()] a [tag_string] [examine_descriptor(user)][length(post_descriptor) ? " [jointext(post_descriptor, " ")]" : ""]." if(reagents) var/user_sees_reagents = user.can_see_reagents() @@ -55,6 +58,34 @@ SEND_SIGNAL(src, COMSIG_ATOM_EXAMINE, user, .) +/* + * A list of "tags" displayed after atom's description in examine. + * This should return an assoc list of tags -> tooltips for them. If item if null, then no tooltip is assigned. + * For example: + * list("small" = "This is a small size class item.", "fireproof" = "This item is impervious to fire.") + * will result in + * This is a small, fireproof item. + * where "item" is pulled from examine_descriptor() proc + */ +/atom/proc/examine_tags(mob/user) + . = list() + SEND_SIGNAL(src, COMSIG_ATOM_EXAMINE_TAGS, user, .) + +/// What this atom should be called in examine tags +/atom/proc/examine_descriptor(mob/user) + return "object" + +/// Returns a list of strings to be displayed after the descriptor +/atom/proc/examine_post_descriptor(mob/user) + . = list() + if(!custom_materials) + return + var/mats_list = list() + for(var/custom_material in custom_materials) + var/datum/material/current_material = GET_MATERIAL_REF(custom_material) + mats_list += span_tooltip("It is made out of [current_material.name].", current_material.name) + . += "made of [english_list(mats_list)]" + /** * Called when a mob examines (shift click or verb) this atom twice (or more) within EXAMINE_MORE_WINDOW (default 1 second) * diff --git a/code/game/atom/atom_tool_acts.dm b/code/game/atom/atom_tool_acts.dm index 8c71fc17c1b6a..94f096abe5236 100644 --- a/code/game/atom/atom_tool_acts.dm +++ b/code/game/atom/atom_tool_acts.dm @@ -1,7 +1,7 @@ /** * ## Item interaction * - * Handles non-combat iteractions of a tool on this atom, + * Handles non-combat interactions of a tool on this atom, * such as using a tool on a wall to deconstruct it, * or scanning someone with a health analyzer */ @@ -14,7 +14,7 @@ if(tool_return) return tool_return - var/is_right_clicking = LAZYACCESS(modifiers, RIGHT_CLICK) + var/is_right_clicking = text2num(LAZYACCESS(modifiers, RIGHT_CLICK)) var/is_left_clicking = !is_right_clicking var/early_sig_return = NONE if(is_left_clicking) @@ -22,10 +22,8 @@ * This is intentionally using `||` instead of `|` to short-circuit the signal calls * This is because we want to return early if ANY of these signals return a value * - * This puts priority on the atom's signals, then the tool's signals, then the user's signals - * So stuff like storage can be handled before stuff the item wants to do like cleaner component - * - * Future idea: Being on combat mode could change/reverse the priority of these signals + * This puts priority on the atom's signals, then the tool's signals, then the user's signals, + * so we can avoid doing two interactions at once */ early_sig_return = SEND_SIGNAL(src, COMSIG_ATOM_ITEM_INTERACTION, user, tool, modifiers) \ || SEND_SIGNAL(tool, COMSIG_ITEM_INTERACTING_WITH_ATOM, user, src, modifiers) \ @@ -50,6 +48,16 @@ if(interact_return) return interact_return + // We have to manually handle storage in item_interaction because storage is blocking in 99% of interactions, which stifles a lot + // Yeah it sucks not being able to signalize this, but the other option is to have a second signal here just for storage which is also not great + if(atom_storage) + if(is_left_clicking) + if(atom_storage.insert_on_attack) + return atom_storage.item_interact_insert(user, tool) + else + if(atom_storage.open_storage(user) && atom_storage.display_contents) + return ITEM_INTERACT_SUCCESS + return NONE /** @@ -61,7 +69,7 @@ * * Handles the tool_acts in particular, such as wrenches and screwdrivers. * - * This can be overriden to handle unique "tool interactions" + * This can be overridden to handle unique "tool interactions" * IE using an item like a tool (when it's not actually one) * This is particularly useful for things that shouldn't be inserted into storage * (because tool acting runs before storage checks) @@ -325,23 +333,3 @@ /// Called on an object when a tool with analyzer capabilities is used to right click an object /atom/proc/analyzer_act_secondary(mob/living/user, obj/item/tool) return - -/** - * Called before this item is placed into a storage container - * via the item clicking on the target atom - * - * Returning FALSE will prevent the item from being stored. - */ -/obj/item/proc/storage_insert_on_interaction(datum/storage, atom/storage_holder, mob/user) - return TRUE - -/** - * Called before an item is put into this atom's storage datum via the item clicking on this atom - * - * This can be used to add item-atom interactions that you want handled before inserting something into storage - * (But it's also fairly snowflakey) - * - * Returning FALSE will block that item from being put into our storage. - */ -/atom/proc/storage_insert_on_interacted_with(datum/storage, obj/item/inserted, mob/living/user) - return TRUE diff --git a/code/game/atom/atoms_initializing_EXPENSIVE.dm b/code/game/atom/atoms_initializing_EXPENSIVE.dm index c603ae5514810..205617fdbc8f9 100644 --- a/code/game/atom/atoms_initializing_EXPENSIVE.dm +++ b/code/game/atom/atoms_initializing_EXPENSIVE.dm @@ -57,14 +57,14 @@ * Called when an atom is created in byond (built in engine proc) * * Not a lot happens here in SS13 code, as we offload most of the work to the - * [Intialization][/atom/proc/Initialize] proc, mostly we run the preloader + * [Initialization][/atom/proc/Initialize] proc, mostly we run the preloader * if the preloader is being used and then call [InitAtom][/datum/controller/subsystem/atoms/proc/InitAtom] of which the ultimate - * result is that the Intialize proc is called. + * result is that the Initialize proc is called. * */ /atom/New(loc, ...) //atom creation method that preloads variables at creation - if(GLOB.use_preloader && src.type == GLOB._preloader_path)//in case the instanciated atom is creating other atoms in New() + if(GLOB.use_preloader && src.type == GLOB._preloader_path)//in case the instantiated atom is creating other atoms in New() world.preloader_load(src) var/do_initialize = SSatoms.initialized @@ -80,17 +80,17 @@ * we don't use New as we have better control over when this is called and we can choose * to delay calls or hook other logic in and so forth * - * During roundstart map parsing, atoms are queued for intialization in the base atom/New(), - * After the map has loaded, then Initalize is called on all atoms one by one. NB: this - * is also true for loading map templates as well, so they don't Initalize until all objects + * During roundstart map parsing, atoms are queued for initialization in the base atom/New(), + * After the map has loaded, then Initialize is called on all atoms one by one. NB: this + * is also true for loading map templates as well, so they don't Initialize until all objects * in the map file are parsed and present in the world * * If you're creating an object at any point after SSInit has run then this proc will be * immediately be called from New. * - * mapload: This parameter is true if the atom being loaded is either being intialized during - * the Atom subsystem intialization, or if the atom is being loaded from the map template. - * If the item is being created at runtime any time after the Atom subsystem is intialized then + * mapload: This parameter is true if the atom being loaded is either being initialized during + * the Atom subsystem initialization, or if the atom is being loaded from the map template. + * If the item is being created at runtime any time after the Atom subsystem is initialized then * it's false. * * The mapload argument occupies the same position as loc when Initialize() is called by New(). @@ -98,7 +98,7 @@ * with mapload at the end of atom/New() before this proc (atom/Initialize()) is called. * * You must always call the parent of this proc, otherwise failures will occur as the item - * will not be seen as initalized (this can lead to all sorts of strange behaviour, like + * will not be seen as initialized (this can lead to all sorts of strange behaviour, like * the item being completely unclickable) * * You must not sleep in this proc, or any subprocs @@ -136,7 +136,7 @@ if(uses_integrity) atom_integrity = max_integrity - TEST_ONLY_ASSERT((!armor || istype(armor)), "[type] has an armor that contains an invalid value at intialize") + TEST_ONLY_ASSERT((!armor || istype(armor)), "[type] has an armor that contains an invalid value at initialize") // apply materials properly from the default custom_materials value // This MUST come after atom_integrity is set above, as if old materials get removed, @@ -150,14 +150,14 @@ return INITIALIZE_HINT_NORMAL /** - * Late Intialization, for code that should run after all atoms have run Intialization + * Late Initialization, for code that should run after all atoms have run Initialization * - * To have your LateIntialize proc be called, your atoms [Initalization][/atom/proc/Initialize] + * To have your LateIntialize proc be called, your atoms [Initialization][/atom/proc/Initialize] * proc must return the hint * [INITIALIZE_HINT_LATELOAD] otherwise it will never be called. * * useful for doing things like finding other machines on GLOB.machines because you can guarantee - * that all atoms will actually exist in the "WORLD" at this time and that all their Intialization + * that all atoms will actually exist in the "WORLD" at this time and that all their Initialization * code has been run */ /atom/proc/LateInitialize() diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 1949f1571cc03..0928ff220df7b 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -17,7 +17,7 @@ var/tk_throw_range = 10 var/mob/pulledby = null /// What language holder type to init as - var/initial_language_holder = /datum/language_holder + var/initial_language_holder = /datum/language_holder/atom_basic /// Holds all languages this mob can speak and understand VAR_PRIVATE/datum/language_holder/language_holder /// The list of factions this atom belongs to diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm index e39ce9bd92d37..58cc789430ae0 100644 --- a/code/game/data_huds.dm +++ b/code/game/data_huds.dm @@ -28,6 +28,8 @@ var/obj/item/clothing/under/U = H.w_uniform if(!istype(U)) return FALSE + if(U.has_sensor < HAS_SENSORS) + return FALSE if(U.sensor_mode <= SENSOR_VITALS) return FALSE return TRUE @@ -227,7 +229,11 @@ Medical HUD! Basic mode needs suit sensors on. holder.icon_state = "hudbuff" if(null) holder.icon_state = "hudhealthy" - + if(ishuman(src)) + var/mob/living/carbon/human/crew = src + var/obj/item/clothing/under/uniform = crew.w_uniform + if(uniform && uniform.has_sensor == BROKEN_SENSORS) + holder.icon_state = "hudnosensor" /*********************************************** FAN HUDs! For identifying other fans on-sight. diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index bce9ed3bb9375..b2df8d7416dde 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -353,7 +353,7 @@ GLOBAL_LIST(admin_objective_list) //Prefilled admin assignable objective list return FALSE if(human_check) brain_target = target.current?.get_organ_slot(ORGAN_SLOT_BRAIN) - //Protect will always suceed when someone suicides + //Protect will always succeed when someone suicides return !target || (target.current && HAS_TRAIT(target.current, TRAIT_SUICIDED)) || considered_alive(target, enforce_human = human_check) || (brain_target && HAS_TRAIT(brain_target, TRAIT_SUICIDED)) /datum/objective/protect/update_explanation_text() diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index 8a7e9846561be..34b8612c2d4be 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -1147,6 +1147,9 @@ if(0 to 25) . += span_warning("It's falling apart!") +/obj/machinery/examine_descriptor(mob/user) + return "machine" + /obj/machinery/examine_more(mob/user) . = ..() if(HAS_TRAIT(user, TRAIT_RESEARCH_SCANNER) && component_parts) diff --git a/code/game/machinery/announcement_system.dm b/code/game/machinery/announcement_system.dm index 1700abb0af1ab..c9e66c89c9576 100644 --- a/code/game/machinery/announcement_system.dm +++ b/code/game/machinery/announcement_system.dm @@ -16,16 +16,26 @@ GLOBAL_LIST_EMPTY(announcement_systems) circuit = /obj/item/circuitboard/machine/announcement_system + ///The headset that we use for broadcasting var/obj/item/radio/headset/radio + ///The message that we send when someone is joining. var/arrival = "%PERSON has signed up as %RANK" - var/arrivalToggle = 1 + ///Whether the arrival message is sent + var/arrival_toggle = TRUE + ///The message that we send when a department head arrives. var/newhead = "%PERSON, %RANK, is the department head." - var/newheadToggle = 1 + ///Whether the newhead message is sent. + var/newhead_toggle = TRUE var/greenlight = "Light_Green" var/pinklight = "Light_Pink" var/errorlight = "Error_Red" + ///If true, researched nodes will be announced to the appropriate channels + var/announce_research_node = TRUE + /// The text that we send when announcing researched nodes. + var/node_message = "The '%NODE' techweb node has been researched" + /obj/machinery/announcement_system/Initialize(mapload) . = ..() GLOB.announcement_systems += src @@ -41,10 +51,10 @@ GLOBAL_LIST_EMPTY(announcement_systems) /obj/machinery/announcement_system/update_overlays() . = ..() - if(arrivalToggle) + if(arrival_toggle) . += greenlight - if(newheadToggle) + if(newhead_toggle) . += pinklight if(machine_stat & BROKEN) @@ -78,18 +88,25 @@ GLOBAL_LIST_EMPTY(announcement_systems) str = replacetext(str, "%RANK", "[rank]") return str -/obj/machinery/announcement_system/proc/announce(message_type, user, rank, list/channels) +/obj/machinery/announcement_system/proc/announce(message_type, target, rank, list/channels) if(!is_operational) return var/message - if(message_type == "ARRIVAL" && arrivalToggle) - message = CompileText(arrival, user, rank) - else if(message_type == "NEWHEAD" && newheadToggle) - message = CompileText(newhead, user, rank) - else if(message_type == "ARRIVALS_BROKEN") - message = "The arrivals shuttle has been damaged. Docking for repairs..." + switch(message_type) + if(AUTO_ANNOUNCE_ARRIVAL) + if(!arrival_toggle) + message = CompileText(arrival, target, rank) + return + if(AUTO_ANNOUNCE_NEWHEAD) + if(!newhead_toggle) + message = CompileText(newhead, target, rank) + return + if(AUTO_ANNOUNCE_ARRIVALS_BROKEN) + message = "The arrivals shuttle has been damaged. Docking for repairs..." + if(AUTO_ANNOUNCE_NODE) + message = replacetext(node_message, "%NODE", target) broadcast(message, channels) @@ -118,9 +135,11 @@ GLOBAL_LIST_EMPTY(announcement_systems) /obj/machinery/announcement_system/ui_data() var/list/data = list() data["arrival"] = arrival - data["arrivalToggle"] = arrivalToggle + data["arrivalToggle"] = arrival_toggle data["newhead"] = newhead - data["newheadToggle"] = newheadToggle + data["newheadToggle"] = newhead_toggle + data["node_message"] = node_message + data["node_toggle"] = announce_research_node return data /obj/machinery/announcement_system/ui_act(action, param) @@ -135,25 +154,28 @@ GLOBAL_LIST_EMPTY(announcement_systems) return switch(action) if("ArrivalText") - var/NewMessage = trim(html_encode(param["newText"]), MAX_MESSAGE_LEN) - if(!usr.can_perform_action(src, ALLOW_SILICON_REACH)) - return - if(NewMessage) - arrival = NewMessage - usr.log_message("updated the arrivals announcement to: [NewMessage]", LOG_GAME) + var/new_message = trim(html_encode(param["newText"]), MAX_MESSAGE_LEN) + if(new_message) + arrival = new_message + usr.log_message("updated the arrivals announcement to: [new_message]", LOG_GAME) if("NewheadText") - var/NewMessage = trim(html_encode(param["newText"]), MAX_MESSAGE_LEN) - if(!usr.can_perform_action(src, ALLOW_SILICON_REACH)) - return - if(NewMessage) - newhead = NewMessage - usr.log_message("updated the head announcement to: [NewMessage]", LOG_GAME) - if("NewheadToggle") - newheadToggle = !newheadToggle + var/new_message = trim(html_encode(param["newText"]), MAX_MESSAGE_LEN) + if(new_message) + newhead = new_message + usr.log_message("updated the head announcement to: [new_message]", LOG_GAME) + if("node_message") + var/new_message = trim(html_encode(param["new_text"]), MAX_MESSAGE_LEN) + if(new_message) + node_message = new_message + usr.log_message("updated the researched node announcement to: [node_message]", LOG_GAME) + if("newhead_toggle") + newhead_toggle = !newhead_toggle update_appearance() - if("ArrivalToggle") - arrivalToggle = !arrivalToggle + if("arrivalToggle") + arrival_toggle = !arrival_toggle update_appearance() + if("node_toggle") + announce_research_node = !announce_research_node add_fingerprint(usr) /obj/machinery/announcement_system/attack_robot(mob/living/silicon/user) @@ -173,6 +195,11 @@ GLOBAL_LIST_EMPTY(announcement_systems) arrival = pick("#!@%ERR-34%2 CANNOT LOCAT@# JO# F*LE!", "CRITICAL ERROR 99.", "ERR)#: DA#AB@#E NOT F(*ND!") newhead = pick("OV#RL()D: \[UNKNOWN??\] DET*#CT)D!", "ER)#R - B*@ TEXT F*O(ND!", "AAS.exe is not responding. NanoOS is searching for a solution to the problem.") + node_message = pick(list( + replacetext(/obj/machinery/announcement_system::node_message, "%NODE", /datum/techweb_node/mech_clown::display_name), + "R/NT1M3 A= ANNOUN-*#nt_SY!?EM.dm, LI%£ 86: N=0DE NULL!", + "BEPIS BEPIS BEPIS", + )) /obj/machinery/announcement_system/emp_act(severity) . = ..() diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 6f21e9303fc5a..e2f5d16cc572f 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -133,8 +133,6 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0) find_and_hang_on_wall(directional = TRUE, \ custom_drop_callback = CALLBACK(src, PROC_REF(deconstruct), FALSE)) - RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) - /obj/machinery/camera/Destroy(force) if(can_use()) toggle_cam(null, 0) //kick anyone viewing out and remove from the camera chunks @@ -235,11 +233,11 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0) M.reset_perspective(null) to_chat(M, span_warning("The screen bursts into static!")) -/obj/machinery/camera/proc/on_saboteur(datum/source, disrupt_duration) - SIGNAL_HANDLER +/obj/machinery/camera/on_saboteur(datum/source, disrupt_duration) + . = ..() //lasts twice as much so we don't have to constantly shoot cameras just to be S T E A L T H Y emp_act(EMP_LIGHT, reset_time = disrupt_duration * 2) - return COMSIG_SABOTEUR_SUCCESS + return TRUE /obj/machinery/camera/proc/post_emp_reset(thisemp, previous_network) if(QDELETED(src)) diff --git a/code/game/machinery/camera/camera_construction.dm b/code/game/machinery/camera/camera_construction.dm index 15f22d02cbe96..d6988617e1f25 100644 --- a/code/game/machinery/camera/camera_construction.dm +++ b/code/game/machinery/camera/camera_construction.dm @@ -30,7 +30,7 @@ switch(camera_construction_state) if(CAMERA_STATE_WIRED) tool.play_tool_sound(src) - var/input = tgui_input_text(user, "Which networks would you like to connect this camera to? Separate networks with a comma. No Spaces!\nFor example: SS13,Security,Secret", "Set Network", "SS13") + var/input = tgui_input_text(user, "Which networks would you like to connect this camera to? Separate networks with a comma. No Spaces!\nFor example: SS13,Security,Secret", "Set Network", "SS13", max_length = MAX_NAME_LEN) if(isnull(input)) return ITEM_INTERACT_BLOCKING var/list/tempnetwork = splittext(input, ",") diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index d48b62977893c..d7b9ac03dae6d 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -721,7 +721,7 @@ if(!GLOB.communications_controller.can_announce(user, is_ai)) to_chat(user, span_alert("Intercomms recharging. Please stand by.")) return - var/input = tgui_input_text(user, "Message to announce to the station crew", "Announcement") + var/input = tgui_input_text(user, "Message to announce to the station crew", "Announcement", max_length = MAX_MESSAGE_LEN) if(!input || !user.can_perform_action(src, ALLOW_SILICON_REACH)) return if(user.try_speak(input)) diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm index b5e5a915ce2bf..adac393d7bedb 100644 --- a/code/game/machinery/computer/crew.dm +++ b/code/game/machinery/computer/crew.dm @@ -223,7 +223,7 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new) continue // Check if their uniform is in a compatible mode. - if((uniform.has_sensor <= NO_SENSORS) || !uniform.sensor_mode) + if((uniform.has_sensor == NO_SENSORS) || !uniform.sensor_mode) stack_trace("Human without active suit sensors is in suit_sensors_list: [tracked_human] ([tracked_human.type]) ([uniform.type])") continue @@ -245,6 +245,19 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new) if (jobs[trim_assignment] != null) entry["ijob"] = jobs[trim_assignment] + // Broken sensors show garbage data + if (uniform.has_sensor == BROKEN_SENSORS) + entry["life_status"] = rand(0,1) + entry["area"] = pick_list (ION_FILE, "ionarea") + entry["oxydam"] = rand(0,175) + entry["toxdam"] = rand(0,175) + entry["burndam"] = rand(0,175) + entry["brutedam"] = rand(0,175) + entry["health"] = -50 + entry["can_track"] = tracked_living_mob.can_track() + results[++results.len] = entry + continue + // Current status if (sensor_mode >= SENSOR_LIVING) entry["life_status"] = tracked_living_mob.stat diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm index e1612ae7ef2e5..da00fc3542197 100644 --- a/code/game/machinery/computer/dna_console.dm +++ b/code/game/machinery/computer/dna_console.dm @@ -683,7 +683,7 @@ var/datum/mutation/human/target_mutation = get_mut_by_ref(bref, search_flags) // Prompt for modifier string - var/new_sequence_input = tgui_input_text(usr, "Enter a replacement sequence", "Inherent Gene Replacement", 32, encode = FALSE) + var/new_sequence_input = tgui_input_text(usr, "Enter a replacement sequence", "Inherent Gene Replacement", max_length = 32, encode = FALSE) // Drop out if the string is the wrong length if(length(new_sequence_input) != 32) return diff --git a/code/game/machinery/computer/records/records.dm b/code/game/machinery/computer/records/records.dm index d53895300438d..7fd47887bc73d 100644 --- a/code/game/machinery/computer/records/records.dm +++ b/code/game/machinery/computer/records/records.dm @@ -148,7 +148,7 @@ return FALSE var/trimmed = copytext(mugshot.name, 9, MAX_NAME_LEN) // Remove "photo - " - var/name = tgui_input_text(user, "Enter the name of the new record.", "New Record", trimmed, MAX_NAME_LEN) + var/name = tgui_input_text(user, "Enter the name of the new record.", "New Record", trimmed, max_length = MAX_NAME_LEN) if(!name || !is_operational || !user.can_perform_action(src, ALLOW_SILICON_REACH) || !mugshot || QDELETED(mugshot) || QDELETED(src)) return FALSE diff --git a/code/game/machinery/computer/telescreen.dm b/code/game/machinery/computer/telescreen.dm index 6058d3bf131ab..6021c954cabfc 100644 --- a/code/game/machinery/computer/telescreen.dm +++ b/code/game/machinery/computer/telescreen.dm @@ -55,7 +55,6 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai /obj/machinery/computer/security/telescreen/entertainment/Initialize(mapload) . = ..() - RegisterSignal(src, COMSIG_CLICK, PROC_REF(BigClick)) find_and_hang_on_wall() speakers = new(src) @@ -63,16 +62,66 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai . = ..() QDEL_NULL(speakers) -/// Bypass clickchain to allow humans to use the telescreen from a distance -/obj/machinery/computer/security/telescreen/entertainment/proc/BigClick() - SIGNAL_HANDLER +/obj/machinery/computer/security/telescreen/entertainment/examine(mob/user) + . = ..() + . += length(network) ? span_notice("The TV is broadcasting something!") : span_notice("There's nothing on TV.") + +/obj/machinery/computer/security/telescreen/entertainment/ui_state(mob/user) + return GLOB.always_state + +// Snowflake ui status to allow mobs to watch TV from across the room, +// but only allow adjacent mobs / tk users / silicon to change the channel +/obj/machinery/computer/security/telescreen/entertainment/ui_status(mob/living/user, datum/ui_state/state) + if(!can_watch_tv(user)) + return UI_CLOSE + if(!isliving(user)) + return isAdminGhostAI(user) ? UI_INTERACTIVE : UI_UPDATE + if(user.stat >= SOFT_CRIT) + return UI_UPDATE + + var/can_range = FALSE + if(iscarbon(user)) + var/mob/living/carbon/carbon_user = user + if(carbon_user.dna?.check_mutation(/datum/mutation/human/telekinesis) && tkMaxRangeCheck(user, src)) + can_range = TRUE + if(HAS_SILICON_ACCESS(user) || (user.interaction_range && user.interaction_range >= get_dist(user, src))) + can_range = TRUE + + if((can_range || user.CanReach(src)) && ISADVANCEDTOOLUSER(user)) + if(user.incapacitated) + return UI_UPDATE + if(!can_range && user.can_hold_items() && (user.usable_hands <= 0 || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED))) + return UI_UPDATE + return UI_INTERACTIVE + return UI_UPDATE + +/obj/machinery/computer/security/telescreen/entertainment/Click(location, control, params) + if(world.time <= usr.next_click + 1) + return // just so someone can't turn an auto clicker on and spam tvs - if(!network.len) - balloon_alert(usr, "nothing on TV!") + . = ..() + if(!can_watch_tv(usr)) return - + if((!length(network) && !Adjacent(usr)) || LAZYACCESS(params2list(params), SHIFT_CLICK)) // let people examine + return + // Lets us see the tv regardless of click results INVOKE_ASYNC(src, TYPE_PROC_REF(/atom, interact), usr) +/obj/machinery/computer/security/telescreen/entertainment/proc/can_watch_tv(mob/living/watcher) + if(!is_operational) + return FALSE + if((watcher.sight & SEE_OBJS) || HAS_SILICON_ACCESS(watcher)) + if(get_dist(watcher, src) > 7) + return FALSE + else + if(!can_see(watcher, src, 7)) + return FALSE + if(watcher.is_blind()) + return FALSE + if(!isobserver(watcher) && watcher.stat >= UNCONSCIOUS) + return FALSE + return TRUE + /// Sets the monitor's icon to the selected state, and says an announcement /obj/machinery/computer/security/telescreen/entertainment/proc/notify(on, announcement) if(on && icon_state == icon_state_off) diff --git a/code/game/machinery/dna_infuser/infuser_entries/infuser_tier_zero_entries.dm b/code/game/machinery/dna_infuser/infuser_entries/infuser_tier_zero_entries.dm index 235986cbd0ddb..670abc2d87bbf 100644 --- a/code/game/machinery/dna_infuser/infuser_entries/infuser_tier_zero_entries.dm +++ b/code/game/machinery/dna_infuser/infuser_entries/infuser_tier_zero_entries.dm @@ -75,7 +75,7 @@ desc = "EVERYONE CALM DOWN! I'm not implying anything with this entry. Are we really so surprised that felinids are humans with mixed feline DNA?" threshold_desc = DNA_INFUSION_NO_THRESHOLD qualities = list( - "oh, let me guess, you're a big fan of those japanese tourist bots", + "oh, let me guess, you're a big fan of those Japanese tourist bots", ) input_obj_or_mob = list( /mob/living/basic/pet/cat, diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index a33895e5569b7..68251b2c1eec3 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1176,10 +1176,10 @@ return TRUE /obj/machinery/door/airlock/try_to_crowbar(obj/item/I, mob/living/user, forced = FALSE) - if(I?.tool_behaviour == TOOL_CROWBAR && should_try_removing_electronics() && !operating) + if(I.tool_behaviour == TOOL_CROWBAR && should_try_removing_electronics() && !operating) user.visible_message(span_notice("[user] removes the electronics from the airlock assembly."), \ span_notice("You start to remove electronics from the airlock assembly...")) - if(I.use_tool(src, user, 40, volume=100)) + if(I.use_tool(src, user, 40, volume = 100)) deconstruct(TRUE, user) return if(seal) @@ -1204,8 +1204,8 @@ var/time_to_open = 50 playsound(src, 'sound/machines/airlock_alien_prying.ogg', 100, TRUE) //is it aliens or just the CE being a dick? prying_so_hard = TRUE - if(do_after(user, time_to_open, src)) - if(check_electrified && shock(user,100)) + if(I.use_tool(src, user, time_to_open, volume = 100)) + if(check_electrified && shock(user, 100)) prying_so_hard = FALSE return open(BYPASS_DOOR_CHECKS) @@ -2228,7 +2228,7 @@ if(!hasPower()) to_chat(user, span_notice("You begin unlocking the airlock safety mechanism...")) if(do_after(user, 15 SECONDS, target = src)) - try_to_crowbar(null, user, TRUE) + try_to_crowbar(src, user, TRUE) return TRUE else // always open from the space side diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index d75b5e17174c5..cd7d8201a9ec8 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -334,7 +334,7 @@ return -/obj/machinery/door/proc/try_to_crowbar(obj/item/acting_object, mob/user) +/obj/machinery/door/proc/try_to_crowbar(obj/item/acting_object, mob/user, forced = FALSE) return /// Called when the user right-clicks on the door with a crowbar. diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 84df989ba0ea3..2e5d909f3e952 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -544,7 +544,7 @@ correct_state() /// We check for adjacency when using the primary attack. -/obj/machinery/door/firedoor/try_to_crowbar(obj/item/acting_object, mob/user) +/obj/machinery/door/firedoor/try_to_crowbar(obj/item/acting_object, mob/user, forced = FALSE) if(welded || operating) return diff --git a/code/game/machinery/doors/passworddoor.dm b/code/game/machinery/doors/passworddoor.dm index bccc243381ba4..bf27dfcffc23b 100644 --- a/code/game/machinery/doors/passworddoor.dm +++ b/code/game/machinery/doors/passworddoor.dm @@ -103,7 +103,7 @@ playsound(src, door_deny, 30, TRUE) /obj/machinery/door/password/proc/ask_for_pass(mob/user) - var/guess = tgui_input_text(user, "Enter the password", "Password") + var/guess = tgui_input_text(user, "Enter the password", "Password", max_length = MAX_MESSAGE_LEN) if(guess == password) return TRUE return FALSE diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 0c897c6809666..a287aefeaa825 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -6,7 +6,7 @@ layer = ABOVE_WINDOW_LAYER closingLayer = ABOVE_WINDOW_LAYER resistance_flags = ACID_PROOF - obj_flags = CAN_BE_HIT | BLOCKS_CONSTRUCTION_DIR + obj_flags = CAN_BE_HIT | IGNORE_DENSITY | BLOCKS_CONSTRUCTION_DIR var/base_state = "left" max_integrity = 150 //If you change this, consider changing ../door/window/brigdoor/ max_integrity at the bottom of this .dm file integrity_failure = 0 diff --git a/code/game/machinery/navbeacon.dm b/code/game/machinery/navbeacon.dm index f6f4270835ca0..98149a8232223 100644 --- a/code/game/machinery/navbeacon.dm +++ b/code/game/machinery/navbeacon.dm @@ -211,7 +211,7 @@ toggle_code(NAVBEACON_DELIVERY_MODE) return TRUE if("set_location") - var/input_text = tgui_input_text(user, "Enter the beacon's location tag", "Beacon Location", location, 20) + var/input_text = tgui_input_text(user, "Enter the beacon's location tag", "Beacon Location", location, max_length = 20) if (!input_text || location == input_text) return glob_lists_deregister() @@ -220,7 +220,7 @@ return TRUE if("set_patrol_next") var/next_patrol = codes[NAVBEACON_PATROL_NEXT] - var/input_text = tgui_input_text(user, "Enter the tag of the next patrol location", "Beacon Location", next_patrol, 20) + var/input_text = tgui_input_text(user, "Enter the tag of the next patrol location", "Beacon Location", next_patrol, max_length = 20) if (!input_text || location == input_text) return codes[NAVBEACON_PATROL_NEXT] = input_text diff --git a/code/game/machinery/newscaster/newscaster_machine.dm b/code/game/machinery/newscaster/newscaster_machine.dm index 3186d2081e5a7..aced87bfe588a 100644 --- a/code/game/machinery/newscaster/newscaster_machine.dm +++ b/code/game/machinery/newscaster/newscaster_machine.dm @@ -405,14 +405,14 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30) return TRUE if("setCriminalName") - var/temp_name = tgui_input_text(usr, "Write the Criminal's Name", "Warrent Alert Handler", "John Doe", MAX_NAME_LEN, multiline = FALSE) + var/temp_name = tgui_input_text(usr, "Write the Criminal's Name", "Warrent Alert Handler", "John Doe", max_length = MAX_NAME_LEN, multiline = FALSE) if(!temp_name) return TRUE criminal_name = temp_name return TRUE if("setCrimeData") - var/temp_desc = tgui_input_text(usr, "Write the Criminal's Crimes", "Warrent Alert Handler", "Unknown", MAX_BROADCAST_LEN, multiline = TRUE) + var/temp_desc = tgui_input_text(usr, "Write the Criminal's Crimes", "Warrent Alert Handler", "Unknown", max_length = MAX_BROADCAST_LEN, multiline = TRUE) if(!temp_desc) return TRUE crime_description = temp_desc @@ -703,7 +703,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30) if(channel_name == potential_channel.channel_ID) current_channel = potential_channel break - var/temp_message = tgui_input_text(usr, "Write your Feed story", "Network Channel Handler", feed_channel_message, multiline = TRUE) + 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 if(temp_message) diff --git a/code/game/machinery/newscaster/newspaper.dm b/code/game/machinery/newscaster/newspaper.dm index c381f2f506304..6bc1e6c77ff14 100644 --- a/code/game/machinery/newscaster/newspaper.dm +++ b/code/game/machinery/newscaster/newspaper.dm @@ -84,7 +84,7 @@ if(scribble_page == current_page) user.balloon_alert(user, "already scribbled!") return - var/new_scribble_text = tgui_input_text(user, "What do you want to scribble?", "Write something") + var/new_scribble_text = tgui_input_text(user, "What do you want to scribble?", "Write something", max_length = MAX_MESSAGE_LEN) if(isnull(new_scribble_text)) return add_fingerprint(user) diff --git a/code/game/machinery/pipe/pipe_dispenser.dm b/code/game/machinery/pipe/pipe_dispenser.dm index 1e90b270c8c8d..de7c6351e38d4 100644 --- a/code/game/machinery/pipe/pipe_dispenser.dm +++ b/code/game/machinery/pipe/pipe_dispenser.dm @@ -187,9 +187,6 @@ //Allow you to drag-drop disposal pipes and transit tubes into it /obj/machinery/pipedispenser/disposal/mouse_drop_receive(obj/structure/pipe, mob/user, params) - if(user.incapacitated) - return - if (!istype(pipe, /obj/structure/disposalconstruct) && !istype(pipe, /obj/structure/c_transit_tube) && !istype(pipe, /obj/structure/c_transit_tube_pod)) return diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index af27a5411cdcd..31fc68b31421f 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -135,8 +135,6 @@ DEFINE_BITFIELD(turret_flags, list( if(!has_cover) INVOKE_ASYNC(src, PROC_REF(popUp)) - RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) - AddElement(/datum/element/hostile_machine) ///Toggles the turret on or off depending on the value of the turn_on arg. @@ -157,10 +155,10 @@ DEFINE_BITFIELD(turret_flags, list( addtimer(CALLBACK(src, PROC_REF(toggle_on), TRUE), duration + 1) //the cooldown isn't over until the tick after its end. toggle_on(FALSE) -/obj/machinery/porta_turret/proc/on_saboteur(datum/source, disrupt_duration) - SIGNAL_HANDLER +/obj/machinery/porta_turret/on_saboteur(datum/source, disrupt_duration) + . = ..() INVOKE_ASYNC(src, PROC_REF(set_disabled), disrupt_duration) - return COMSIG_SABOTEUR_SUCCESS + return TRUE /obj/machinery/porta_turret/proc/check_should_process() if (datum_flags & DF_ISPROCESSING) @@ -575,7 +573,7 @@ DEFINE_BITFIELD(turret_flags, list( // If we aren't shooting heads then return a threatcount of 0 if (!(turret_flags & TURRET_FLAG_SHOOT_HEADS)) - var/datum/job/apparent_job = SSjob.GetJob(perp.get_assignment()) + var/datum/job/apparent_job = SSjob.get_job(perp.get_assignment()) if(apparent_job?.job_flags & JOB_HEAD_OF_STAFF) return 0 diff --git a/code/game/machinery/porta_turret/portable_turret_construct.dm b/code/game/machinery/porta_turret/portable_turret_construct.dm index a8fa4e67b2bf6..0ae7d9699ee26 100644 --- a/code/game/machinery/porta_turret/portable_turret_construct.dm +++ b/code/game/machinery/porta_turret/portable_turret_construct.dm @@ -182,7 +182,7 @@ return if(used.get_writing_implement_details()?["interaction_mode"] == MODE_WRITING) //you can rename turrets like bots! - var/choice = tgui_input_text(user, "Enter a new turret name", "Turret Classification", finish_name, MAX_NAME_LEN) + var/choice = tgui_input_text(user, "Enter a new turret name", "Turret Classification", finish_name, max_length = MAX_NAME_LEN) if(!choice) return if(!user.can_perform_action(src)) diff --git a/code/game/machinery/roulette_machine.dm b/code/game/machinery/roulette_machine.dm index bb43b7a46db9e..3ef023ccb64d7 100644 --- a/code/game/machinery/roulette_machine.dm +++ b/code/game/machinery/roulette_machine.dm @@ -187,7 +187,7 @@ addtimer(CALLBACK(src, PROC_REF(play), user, player_card, chosen_bet_type, chosen_bet_amount, potential_payout), 4) //Animation first return TRUE else - var/msg = tgui_input_text(user, "Name of your roulette wheel", "Roulette Customization", "Roulette Machine", MAX_NAME_LEN) + var/msg = tgui_input_text(user, "Name of your roulette wheel", "Roulette Customization", "Roulette Machine", max_length = MAX_NAME_LEN) if(!msg) return name = msg @@ -456,7 +456,7 @@ "path" = /obj/structure/closet/supplypod/centcompod, "spawn" = /obj/machinery/roulette )) - + qdel(src) #undef ROULETTE_DOZ_COL_PAYOUT diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index 3232dc524ab89..9ff9c562aa04c 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -711,12 +711,12 @@ var/name_set = FALSE var/desc_set = FALSE - var/str = tgui_input_text(user, "Personal Unit Name", "Unit Name") + var/str = tgui_input_text(user, "Personal Unit Name", "Unit Name", max_length = MAX_NAME_LEN) if(!isnull(str)) name = str name_set = TRUE - str = tgui_input_text(user, "Personal Unit Description", "Unit Description") + str = tgui_input_text(user, "Personal Unit Description", "Unit Description", max_length = MAX_DESC_LEN) if(!isnull(str)) desc = str desc_set = TRUE diff --git a/code/game/machinery/telecomms/computers/message.dm b/code/game/machinery/telecomms/computers/message.dm index 05186da8bc08c..1b3197e702da5 100644 --- a/code/game/machinery/telecomms/computers/message.dm +++ b/code/game/machinery/telecomms/computers/message.dm @@ -139,7 +139,7 @@ return TRUE authenticated = TRUE - success_message = "YOU SUCCESFULLY LOGGED IN!" + success_message = "YOU SUCCESSFULLY LOGGED IN!" return TRUE if("link_server") @@ -180,10 +180,10 @@ notice_message = "NOTICE: Logs cleared." return TRUE if("set_key") - var/dkey = tgui_input_text(usr, "Please enter the decryption key", "Telecomms Decryption") + var/dkey = tgui_input_text(usr, "Please enter the decryption key", "Telecomms Decryption", max_length = 16) if(dkey && dkey != "") if(linkedServer.decryptkey == dkey) - var/newkey = tgui_input_text(usr, "Please enter the new key (3 - 16 characters max)", "New Key") + var/newkey = tgui_input_text(usr, "Please enter the new key (3 - 16 characters max)", "New Key", max_length = 16) if(length(newkey) <= 3) notice_message = "NOTICE: Decryption key too short!" else if(newkey && newkey != "") @@ -210,8 +210,8 @@ break return TRUE if("send_fake_message") - var/sender = tgui_input_text(usr, "What is the sender's name?", "Sender") - var/job = tgui_input_text(usr, "What is the sender's job?", "Job") + var/sender = tgui_input_text(usr, "What is the sender's name?", "Sender", max_length = MAX_NAME_LEN) + var/job = tgui_input_text(usr, "What is the sender's job?", "Job", max_length = 60) var/recipient var/list/tablet_to_messenger = list() @@ -229,7 +229,7 @@ else recipient = null - var/message = tgui_input_text(usr, "Please enter your message", "Message") + var/message = tgui_input_text(usr, "Please enter your message", "Message", max_length = MAX_MESSAGE_LEN) if(isnull(sender) || sender == "") sender = "UNKNOWN" diff --git a/code/game/objects/effects/anomalies/anomalies_bioscrambler.dm b/code/game/objects/effects/anomalies/anomalies_bioscrambler.dm index 27c02fb9d1806..d97966160233b 100644 --- a/code/game/objects/effects/anomalies/anomalies_bioscrambler.dm +++ b/code/game/objects/effects/anomalies/anomalies_bioscrambler.dm @@ -62,7 +62,7 @@ for(var/mob/living/carbon/target in GLOB.player_list) if (target.z != z) continue - if (target.status_flags & GODMODE) + if (HAS_TRAIT(target, TRAIT_GODMODE)) continue if (target.stat >= UNCONSCIOUS) continue // Don't just haunt a corpse @@ -89,10 +89,12 @@ duration = 0.5 SECONDS color = COLOR_LIME var/max_alpha = 255 + ///How far the effect would scale in size + var/amount_to_scale = 2 /obj/effect/temp_visual/circle_wave/Initialize(mapload) transform = matrix().Scale(0.1) - animate(src, transform = matrix().Scale(2), time = duration, flags = ANIMATION_PARALLEL) + animate(src, transform = matrix().Scale(amount_to_scale), time = duration, flags = ANIMATION_PARALLEL) animate(src, alpha = max_alpha, time = duration * 0.6, flags = ANIMATION_PARALLEL) animate(alpha = 0, time = duration * 0.4) apply_wibbly_filters(src) @@ -104,3 +106,7 @@ /obj/effect/temp_visual/circle_wave/bioscrambler/light max_alpha = 128 +/obj/effect/temp_visual/circle_wave/void_conduit + color = COLOR_FULL_TONER_BLACK + duration = 12 SECONDS + amount_to_scale = 12 diff --git a/code/game/objects/effects/decals/cleanable/food.dm b/code/game/objects/effects/decals/cleanable/food.dm index 23c266ecb5906..d612bd9e7f53e 100644 --- a/code/game/objects/effects/decals/cleanable/food.dm +++ b/code/game/objects/effects/decals/cleanable/food.dm @@ -10,6 +10,9 @@ icon_state = "tomato_floor1" random_icon_states = list("tomato_floor1", "tomato_floor2", "tomato_floor3") +/obj/effect/decal/cleanable/food/tomato_smudge/can_bloodcrawl_in() + return TRUE // why? why not. + /obj/effect/decal/cleanable/food/plant_smudge name = "plant smudge" desc = "Chlorophyll? More like borophyll!" diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index 64c0afe188a8a..b1a4a75c945d7 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -306,6 +306,11 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player) GLOB.newplayer_start += loc return INITIALIZE_HINT_QDEL +/obj/effect/landmark/start/pun_pun + name = JOB_PUN_PUN + icon = 'icons/mob/human/human.dmi' + icon_state = "monkey" + /obj/effect/landmark/latejoin name = "JoinLate" diff --git a/code/game/objects/effects/spawners/random/trash.dm b/code/game/objects/effects/spawners/random/trash.dm index 9cf00c20ee3ec..6f6f5badc8e7e 100644 --- a/code/game/objects/effects/spawners/random/trash.dm +++ b/code/game/objects/effects/spawners/random/trash.dm @@ -324,3 +324,18 @@ if(istype(crushed_can)) crushed_can.icon_state = pick(soda_icons) return crushed_can + +/obj/effect/spawner/random/trash/ghetto_containers + name = "ghetto container spawner" + loot = list( + /obj/item/reagent_containers/cup/bucket = 5, + /obj/item/reagent_containers/cup/glass/bottle = 5, + /obj/item/reagent_containers/cup/glass/bottle/small = 5, + /obj/item/reagent_containers/cup/glass/mug = 5, + /obj/item/reagent_containers/cup/glass/shaker = 5, + /obj/item/reagent_containers/cup/watering_can/wood = 5, + /obj/item/reagent_containers/cup/mortar = 2, + /obj/item/reagent_containers/cup/soup_pot = 2, + /obj/item/reagent_containers/cup/blastoff_ampoule = 1, + /obj/item/reagent_containers/cup/maunamug = 1, + ) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index fa790eb3e2db6..99266b3787eb6 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -464,27 +464,36 @@ abstract_move(null) forceMove(T) -/obj/item/examine(mob/user) //This might be spammy. Remove? - . = ..() - - . += "[gender == PLURAL ? "They are" : "It is"] a [weight_class_to_text(w_class)] item." +/obj/item/examine_tags(mob/user) + var/list/parent_tags = ..() + parent_tags.Insert(1, weight_class_to_text(w_class)) // To make size display first, otherwise it looks goofy + . = parent_tags + .[weight_class_to_text(w_class)] = "[gender == PLURAL ? "They are" : "It is"] a [weight_class_to_text(w_class)] item." if(item_flags & CRUEL_IMPLEMENT) - . += "[src] seems quite practical for particularly morbid procedures and experiments." + .[span_red("morbid")] = "It seems quite practical for particularly morbid procedures and experiments." + + if (siemens_coefficient == 0) + .["insulated"] = "It is made from a robust electrical insulator and will block any electricity passing through it!" + else if (siemens_coefficient <= 0.5) + .["partially insulated"] = "It is made from a poor insulator that will dampen (but not fully block) electric shocks passing through it." if(resistance_flags & INDESTRUCTIBLE) - . += "[src] seems extremely robust! It'll probably withstand anything that could happen to it!" - else - if(resistance_flags & LAVA_PROOF) - . += "[src] is made of an extremely heat-resistant material, it'd probably be able to withstand lava!" - if(resistance_flags & (ACID_PROOF | UNACIDABLE)) - . += "[src] looks pretty robust! It'd probably be able to withstand acid!" - if(resistance_flags & FREEZE_PROOF) - . += "[src] is made of cold-resistant materials." - if(resistance_flags & FIRE_PROOF) - . += "[src] is made of fire-retardant materials." + .["indestructible"] = "It is extremely robust! It'll probably withstand anything that could happen to it!" return + if(resistance_flags & LAVA_PROOF) + .["lavaproof"] = "It is made of an extremely heat-resistant material, it'd probably be able to withstand lava!" + if(resistance_flags & (ACID_PROOF | UNACIDABLE)) + .["acidproof"] = "It looks pretty robust! It'd probably be able to withstand acid!" + if(resistance_flags & FREEZE_PROOF) + .["freezeproof"] = "It is made of cold-resistant materials." + if(resistance_flags & FIRE_PROOF) + .["fireproof"] = "It is made of fire-retardant materials." + +/obj/item/examine_descriptor(mob/user) + return "item" + /obj/item/examine_more(mob/user) . = ..() if(HAS_TRAIT(user, TRAIT_RESEARCH_SCANNER)) @@ -651,7 +660,7 @@ /obj/item/attack_alien(mob/user, list/modifiers) var/mob/living/carbon/alien/ayy = user - if(!user.can_hold_items(src)) + if(!ayy.can_hold_items(src)) if(src in ayy.contents) // To stop Aliens having items stuck in their pockets ayy.dropItemToGround(src) to_chat(user, span_warning("Your claws aren't capable of such fine manipulation!")) @@ -1202,13 +1211,13 @@ return TRUE /// Called before [obj/item/proc/use_tool] if there is a delay, or by [obj/item/proc/use_tool] if there isn't. Only ever used by welding tools and stacks, so it's not added on any other [obj/item/proc/use_tool] checks. -/obj/item/proc/tool_start_check(mob/living/user, amount=0) - . = tool_use_check(user, amount) +/obj/item/proc/tool_start_check(mob/living/user, amount=0, heat_required=0) + . = tool_use_check(user, amount, heat_required) if(.) SEND_SIGNAL(src, COMSIG_TOOL_START_USE, user) /// A check called by [/obj/item/proc/tool_start_check] once, and by use_tool on every tick of delay. -/obj/item/proc/tool_use_check(mob/living/user, amount) +/obj/item/proc/tool_use_check(mob/living/user, amount, heat_required) return !amount /// Generic use proc. Depending on the item, it uses up fuel, charges, sheets, etc. Returns TRUE on success, FALSE on failure. diff --git a/code/game/objects/items/AI_modules/freeform.dm b/code/game/objects/items/AI_modules/freeform.dm index a0a91f7185e5a..05ef00c946772 100644 --- a/code/game/objects/items/AI_modules/freeform.dm +++ b/code/game/objects/items/AI_modules/freeform.dm @@ -8,7 +8,7 @@ laws = list("") /obj/item/ai_module/core/freeformcore/attack_self(mob/user) - var/targName = tgui_input_text(user, "Enter a new core law for the AI.", "Freeform Law Entry", laws[1], CONFIG_GET(number/max_law_len), TRUE) + var/targName = tgui_input_text(user, "Enter a new core law for the AI.", "Freeform Law Entry", laws[1], max_length = CONFIG_GET(number/max_law_len), multiline = TRUE) if(!targName || !user.is_holding(src)) return if(is_ic_filtered(targName)) @@ -37,7 +37,7 @@ if(!newpos || !user.is_holding(src) || !usr.can_perform_action(src, FORBID_TELEKINESIS_REACH)) return lawpos = newpos - var/targName = tgui_input_text(user, "Enter a new law for the AI.", "Freeform Law Entry", laws[1], CONFIG_GET(number/max_law_len), TRUE) + var/targName = tgui_input_text(user, "Enter a new law for the AI.", "Freeform Law Entry", laws[1], max_length = CONFIG_GET(number/max_law_len), multiline = TRUE) if(!targName || !user.is_holding(src)) return if(is_ic_filtered(targName)) diff --git a/code/game/objects/items/AI_modules/full_lawsets.dm b/code/game/objects/items/AI_modules/full_lawsets.dm index 30e904d45ac84..593bc43f2dcea 100644 --- a/code/game/objects/items/AI_modules/full_lawsets.dm +++ b/code/game/objects/items/AI_modules/full_lawsets.dm @@ -58,7 +58,7 @@ var/subject = "human being" /obj/item/ai_module/core/full/asimov/attack_self(mob/user as mob) - var/targName = tgui_input_text(user, "Enter a new subject that Asimov is concerned with.", "Asimov", subject, MAX_NAME_LEN) + var/targName = tgui_input_text(user, "Enter a new subject that Asimov is concerned with.", "Asimov", subject, max_length = MAX_NAME_LEN) if(!targName || !user.is_holding(src)) return subject = targName @@ -73,7 +73,7 @@ var/subject = "human being" /obj/item/ai_module/core/full/asimovpp/attack_self(mob/user) - var/target_name = tgui_input_text(user, "Enter a new subject that Asimov++ is concerned with.", "Asimov++", subject, MAX_NAME_LEN) + var/target_name = tgui_input_text(user, "Enter a new subject that Asimov++ is concerned with.", "Asimov++", subject, max_length = MAX_NAME_LEN) if(!target_name || !user.is_holding(src)) return laws.Cut() diff --git a/code/game/objects/items/AI_modules/hacked.dm b/code/game/objects/items/AI_modules/hacked.dm index fafde17acb5f3..41a1f38ba891d 100644 --- a/code/game/objects/items/AI_modules/hacked.dm +++ b/code/game/objects/items/AI_modules/hacked.dm @@ -4,7 +4,7 @@ laws = list("") /obj/item/ai_module/syndicate/attack_self(mob/user) - var/targName = tgui_input_text(user, "Enter a new law for the AI", "Freeform Law Entry", laws[1], CONFIG_GET(number/max_law_len), TRUE) + var/targName = tgui_input_text(user, "Enter a new law for the AI", "Freeform Law Entry", laws[1], max_length = CONFIG_GET(number/max_law_len), multiline = TRUE) if(!targName || !user.is_holding(src)) return if(is_ic_filtered(targName)) // not even the syndicate can uwu diff --git a/code/game/objects/items/AI_modules/supplied.dm b/code/game/objects/items/AI_modules/supplied.dm index b53e16a86b0c8..76f4715730620 100644 --- a/code/game/objects/items/AI_modules/supplied.dm +++ b/code/game/objects/items/AI_modules/supplied.dm @@ -27,7 +27,7 @@ lawpos = 4 /obj/item/ai_module/supplied/safeguard/attack_self(mob/user) - var/targName = tgui_input_text(user, "Subject to safeguard.", "Safeguard", user.name, MAX_NAME_LEN) + var/targName = tgui_input_text(user, "Subject to safeguard.", "Safeguard", user.name, max_length = MAX_NAME_LEN) if(!targName || !user.is_holding(src)) return targetName = targName diff --git a/code/game/objects/items/AI_modules/zeroth.dm b/code/game/objects/items/AI_modules/zeroth.dm index 74fc7ab8232ae..480735bfe2fe7 100644 --- a/code/game/objects/items/AI_modules/zeroth.dm +++ b/code/game/objects/items/AI_modules/zeroth.dm @@ -25,7 +25,7 @@ laws = list("Only SUBJECT is human.") /obj/item/ai_module/zeroth/onehuman/attack_self(mob/user) - var/targName = tgui_input_text(user, "Enter the subject who is the only human.", "One Human", user.real_name, MAX_NAME_LEN) + var/targName = tgui_input_text(user, "Enter the subject who is the only human.", "One Human", user.real_name, max_length = MAX_NAME_LEN) if(!targName || !user.is_holding(src)) return targetName = targName diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index 1f20ea9bc3e39..b28acce35d42d 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -125,7 +125,7 @@ /obj/item/card/id/Initialize(mapload) . = ..() - var/datum/bank_account/blank_bank_account = new("Unassigned", SSjob.GetJobType(/datum/job/unassigned), player_account = FALSE) + var/datum/bank_account/blank_bank_account = new("Unassigned", SSjob.get_job_type(/datum/job/unassigned), player_account = FALSE) registered_account = blank_bank_account registered_account.replaceable = TRUE @@ -987,6 +987,11 @@ return ..() +/obj/item/card/id/advanced/proc/after_input_check(mob/user) + if(QDELETED(user) || QDELETED(src) || !user.client || !user.can_perform_action(src, NEED_DEXTERITY|FORBID_TELEKINESIS_REACH)) + return FALSE + return TRUE + /obj/item/card/id/advanced/item_interaction(mob/living/user, obj/item/tool, list/modifiers) . = ..() if(.) @@ -1289,7 +1294,7 @@ . = ..() registered_account = new(player_account = FALSE) registered_account.account_id = ADMIN_ACCOUNT_ID // this is so bank_card_talk() can work. - registered_account.account_job = SSjob.GetJobType(/datum/job/admin) + registered_account.account_job = SSjob.get_job_type(/datum/job/admin) registered_account.account_balance += 999999 // MONEY! We add more money to the account every time we spawn because it's a debug item and infinite money whoopie /obj/item/card/id/advanced/debug/alt_click_can_use_id(mob/living/user) @@ -1442,6 +1447,44 @@ trim = /datum/id_trim/highlander wildcard_slots = WILDCARD_LIMIT_ADMIN +/// An ID that you can flip with attack_self_secondary, overriding the appearance of the ID (useful for plainclothes detectives for example). +/obj/item/card/id/advanced/plainclothes + name = "Plainclothes ID" + ///The trim that we use as plainclothes identity + var/alt_trim = /datum/id_trim/job/assistant + +/obj/item/card/id/advanced/plainclothes/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = ..() + context[SCREENTIP_CONTEXT_LMB] = "Show/Flip ID" + +/obj/item/card/id/advanced/plainclothes/examine(mob/user) + . = ..() + if(trim_assignment_override) + . += span_smallnotice("it's currently under plainclothes identity.") + else + . += span_smallnotice("flip it to switch to the plainclothes identity.") + +/obj/item/card/id/advanced/plainclothes/attack_self(mob/user) + var/popup_input = tgui_input_list(user, "Choose Action", "Two-Sided ID", list("Show", "Flip")) + if(!popup_input || !after_input_check(user)) + return TRUE + if(popup_input == "Show") + return ..() + balloon_alert(user, "flipped") + if(trim_assignment_override) + SSid_access.remove_trim_from_chameleon_card(src) + else + SSid_access.apply_trim_to_chameleon_card(src, alt_trim) + update_label() + update_appearance() + +/obj/item/card/id/advanced/plainclothes/update_label() + if(!trim_assignment_override) + return ..() + var/name_string = registered_name ? "[registered_name]'s ID Card" : initial(name) + var/datum/id_trim/fake = SSid_access.trim_singletons_by_path[alt_trim] + name = "[name_string] ([fake.assignment])" + /obj/item/card/id/advanced/chameleon name = "agent card" desc = "A highly advanced chameleon ID card. Touch this card on another ID card or player to choose which accesses to copy. \ @@ -1656,8 +1699,9 @@ to_chat(user, span_notice("You successfully reset the ID card.")) return - ///forge the ID if not forged. - var/input_name = tgui_input_text(user, "What name would you like to put on this card? Leave blank to randomise.", "Agent card name", registered_name ? registered_name : (ishuman(user) ? user.real_name : user.name), MAX_NAME_LEN) + ///forge the ID if not forged.s + var/input_name = tgui_input_text(user, "What name would you like to put on this card? Leave blank to randomise.", "Agent card name", registered_name ? registered_name : (ishuman(user) ? user.real_name : user.name), max_length = MAX_NAME_LEN, encode = FALSE) + if(!after_input_check(user)) return TRUE if(input_name) @@ -1687,7 +1731,7 @@ if(!after_input_check(user)) return TRUE - var/target_occupation = tgui_input_text(user, "What occupation would you like to put on this card?\nNote: This will not grant any access levels.", "Agent card job assignment", assignment ? assignment : "Assistant", MAX_NAME_LEN) + var/target_occupation = tgui_input_text(user, "What occupation would you like to put on this card?\nNote: This will not grant any access levels.", "Agent card job assignment", assignment ? assignment : "Assistant", max_length = MAX_NAME_LEN) if(!after_input_check(user)) return TRUE @@ -1724,11 +1768,6 @@ registered_account = account to_chat(user, span_notice("Your account number has been automatically assigned.")) -/obj/item/card/id/advanced/chameleon/proc/after_input_check(mob/user) - if(QDELETED(user) || QDELETED(src) || !user.client || !user.can_perform_action(src, NEED_DEXTERITY|FORBID_TELEKINESIS_REACH)) - return FALSE - return TRUE - /obj/item/card/id/advanced/chameleon/add_item_context(obj/item/source, list/context, atom/target, mob/living/user,) . = ..() @@ -1846,15 +1885,15 @@ return switch(popup_input) if("Name") - var/input_name = tgui_input_text(user, "What name would you like to put on this card?", "Cardboard card name", scribbled_name || (ishuman(user) ? user.real_name : user.name), MAX_NAME_LEN) - input_name = sanitize_name(input_name, allow_numbers = TRUE) + var/raw_input = tgui_input_text(user, "What name would you like to put on this card?", "Cardboard card name", scribbled_name || (ishuman(user) ? user.real_name : user.name), max_length = MAX_NAME_LEN) + var/input_name = sanitize_name(raw_input, allow_numbers = TRUE) if(!after_input_check(user, item, input_name, scribbled_name)) return scribbled_name = input_name var/list/details = item.get_writing_implement_details() details_colors[INDEX_NAME_COLOR] = details["color"] || COLOR_BLACK if("Assignment") - var/input_assignment = tgui_input_text(user, "What assignment would you like to put on this card?", "Cardboard card job ssignment", scribbled_assignment || "Assistant", MAX_NAME_LEN) + var/input_assignment = tgui_input_text(user, "What assignment would you like to put on this card?", "Cardboard card job ssignment", scribbled_assignment || "Assistant", max_length = MAX_NAME_LEN) if(!after_input_check(user, item, input_assignment, scribbled_assignment)) return scribbled_assignment = sanitize(input_assignment) diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigarettes.dm similarity index 76% rename from code/game/objects/items/cigs_lighters.dm rename to code/game/objects/items/cigarettes.dm index 35f14640278e4..168817bf1ff9f 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigarettes.dm @@ -6,8 +6,6 @@ MATCHES CIGARETTES CIGARS SMOKING PIPES -CHEAP LIGHTERS -ZIPPO CIGARETTE PACKETS ARE IN FANCY.DM */ @@ -200,7 +198,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM // "It is called a cigarette" AddComponent(/datum/component/edible,\ initial_reagents = list_reagents,\ - food_flags = null,\ + food_flags = FOOD_NO_EXAMINE,\ foodtypes = JUNKFOOD,\ volume = 50,\ eat_time = 0 SECONDS,\ @@ -210,7 +208,6 @@ CIGARETTE PACKETS ARE IN FANCY.DM junkiness = 0,\ reagent_purity = null,\ on_consume = CALLBACK(src, PROC_REF(on_consume)),\ - show_examine = FALSE, \ ) /obj/item/cigarette/Destroy() @@ -820,319 +817,6 @@ CIGARETTE PACKETS ARE IN FANCY.DM inhand_icon_on = null inhand_icon_off = null -///////// -//ZIPPO// -///////// -/obj/item/lighter - name = "\improper Zippo lighter" - desc = "The zippo." - icon = 'icons/obj/cigarettes.dmi' - icon_state = "zippo" - inhand_icon_state = "zippo" - worn_icon_state = "lighter" - w_class = WEIGHT_CLASS_TINY - obj_flags = CONDUCTS_ELECTRICITY - slot_flags = ITEM_SLOT_BELT - heat = 1500 - resistance_flags = FIRE_PROOF - grind_results = list(/datum/reagent/iron = 1, /datum/reagent/fuel = 5, /datum/reagent/fuel/oil = 5) - custom_price = PAYCHECK_CREW * 1.1 - light_system = OVERLAY_LIGHT - light_range = 2 - light_power = 1.3 - light_color = LIGHT_COLOR_FIRE - light_on = FALSE - /// Whether the lighter is lit. - var/lit = FALSE - /// Whether the lighter is fancy. Fancy lighters have fancier flavortext and won't burn thumbs. - var/fancy = TRUE - /// The engraving overlay used by this lighter. - var/overlay_state - /// A list of possible engraving overlays. - var/overlay_list = list( - "plain", - "dame", - "thirteen", - "snake" - ) - -/obj/item/lighter/Initialize(mapload) - . = ..() - if(!overlay_state) - overlay_state = pick(overlay_list) - AddComponent(\ - /datum/component/bullet_intercepting,\ - block_chance = 0.5,\ - active_slots = ITEM_SLOT_SUITSTORE,\ - on_intercepted = CALLBACK(src, PROC_REF(on_intercepted_bullet)),\ - ) - update_appearance() - -/// Destroy the lighter when it's shot by a bullet -/obj/item/lighter/proc/on_intercepted_bullet(mob/living/victim, obj/projectile/bullet) - victim.visible_message(span_warning("\The [bullet] shatters on [victim]'s lighter!")) - playsound(victim, SFX_RICOCHET, 100, TRUE) - new /obj/effect/decal/cleanable/oil(get_turf(src)) - do_sparks(1, TRUE, src) - victim.dropItemToGround(src, force = TRUE, silent = TRUE) - qdel(src) - -/obj/item/lighter/cyborg_unequip(mob/user) - if(!lit) - return - set_lit(FALSE) - -/obj/item/lighter/suicide_act(mob/living/carbon/user) - if (lit) - user.visible_message(span_suicide("[user] begins holding \the [src]'s flame up to [user.p_their()] face! It looks like [user.p_theyre()] trying to commit suicide!")) - playsound(src, 'sound/items/welder.ogg', 50, TRUE) - return FIRELOSS - else - user.visible_message(span_suicide("[user] begins whacking [user.p_them()]self with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")) - return BRUTELOSS - -/obj/item/lighter/update_icon_state() - icon_state = "[initial(icon_state)][lit ? "-on" : ""]" - return ..() - -/obj/item/lighter/update_overlays() - . = ..() - . += create_lighter_overlay() - -/// Generates an overlay used by this lighter. -/obj/item/lighter/proc/create_lighter_overlay() - return mutable_appearance(icon, "lighter_overlay_[overlay_state][lit ? "-on" : ""]") - -/obj/item/lighter/ignition_effect(atom/A, mob/user) - if(get_temperature()) - . = span_infoplain(span_rose("With a single flick of [user.p_their()] wrist, [user] smoothly lights [A] with [src]. Damn [user.p_theyre()] cool.")) - -/obj/item/lighter/proc/set_lit(new_lit) - if(lit == new_lit) - return - - lit = new_lit - if(lit) - force = 5 - damtype = BURN - hitsound = 'sound/items/welder.ogg' - attack_verb_continuous = string_list(list("burns", "singes")) - attack_verb_simple = string_list(list("burn", "singe")) - START_PROCESSING(SSobj, src) - if(isliving(loc)) - var/mob/living/male_model = loc - if(male_model.fire_stacks && !(male_model.on_fire)) - male_model.ignite_mob() - else - hitsound = SFX_SWING_HIT - force = 0 - attack_verb_continuous = null //human_defense.dm takes care of it - attack_verb_simple = null - STOP_PROCESSING(SSobj, src) - set_light_on(lit) - update_appearance() - -/obj/item/lighter/extinguish() - . = ..() - set_lit(FALSE) - -/obj/item/lighter/attack_self(mob/living/user) - if(!user.is_holding(src)) - return ..() - if(lit) - set_lit(FALSE) - if(fancy) - user.visible_message( - span_notice("You hear a quiet click, as [user] shuts off [src] without even looking at what [user.p_theyre()] doing. Wow."), - span_notice("You quietly shut off [src] without even looking at what you're doing. Wow.") - ) - playsound(src.loc , 'sound/items/zippo_off.ogg', 100, 1) - else - user.visible_message( - span_notice("[user] quietly shuts off [src]."), - span_notice("You quietly shut off [src].") - ) - playsound(src.loc , 'sound/items/lighter_off.ogg', 100, 1) - return - - set_lit(TRUE) - if(fancy) - user.visible_message( - span_notice("Without even breaking stride, [user] flips open and lights [src] in one smooth movement."), - span_notice("Without even breaking stride, you flip open and light [src] in one smooth movement.") - ) - playsound(src.loc , 'sound/items/zippo_on.ogg', 100, 1) - return - else - playsound(src.loc, 'sound/items/lighter_on.ogg', 100, 1) - - var/hand_protected = FALSE - var/mob/living/carbon/human/human_user = user - if(!istype(human_user) || HAS_TRAIT(human_user, TRAIT_RESISTHEAT) || HAS_TRAIT(human_user, TRAIT_RESISTHEATHANDS)) - hand_protected = TRUE - else if(!istype(human_user.gloves, /obj/item/clothing/gloves)) - hand_protected = FALSE - else - var/obj/item/clothing/gloves/gloves = human_user.gloves - if(gloves.max_heat_protection_temperature) - hand_protected = (gloves.max_heat_protection_temperature > 360) - - if(hand_protected || prob(75)) - user.visible_message( - span_notice("After a few attempts, [user] manages to light [src]."), - span_notice("After a few attempts, you manage to light [src].") - ) - return - - var/hitzone = user.held_index_to_dir(user.active_hand_index) == "r" ? BODY_ZONE_PRECISE_R_HAND : BODY_ZONE_PRECISE_L_HAND - user.apply_damage(5, BURN, hitzone) - user.visible_message( - span_warning("After a few attempts, [user] manages to light [src] - however, [user.p_they()] burn[user.p_s()] [user.p_their()] finger in the process."), - span_warning("You burn yourself while lighting the lighter!") - ) - user.add_mood_event("burnt_thumb", /datum/mood_event/burnt_thumb) - - -/obj/item/lighter/attack(mob/living/carbon/M, mob/living/carbon/user) - if(lit && M.ignite_mob()) - message_admins("[ADMIN_LOOKUPFLW(user)] set [key_name_admin(M)] on fire with [src] at [AREACOORD(user)]") - log_game("[key_name(user)] set [key_name(M)] on fire with [src] at [AREACOORD(user)]") - var/obj/item/cigarette/cig = help_light_cig(M) - if(!lit || !cig || user.combat_mode) - ..() - return - - if(cig.lit) - to_chat(user, span_warning("The [cig.name] is already lit!")) - if(M == user) - cig.attackby(src, user) - return - - if(fancy) - cig.light(span_rose("[user] whips the [name] out and holds it for [M]. [user.p_Their()] arm is as steady as the unflickering flame [user.p_they()] light[user.p_s()] \the [cig] with.")) - else - cig.light(span_notice("[user] holds the [name] out for [M], and lights [M.p_their()] [cig.name].")) - - -/obj/item/lighter/process() - open_flame(heat) - -/obj/item/lighter/get_temperature() - return lit * heat - - -/obj/item/lighter/greyscale - name = "cheap lighter" - desc = "A cheap lighter." - icon_state = "lighter" - fancy = FALSE - overlay_list = list( - "transp", - "tall", - "matte", - "zoppo" //u cant stoppo th zoppo - ) - - /// The color of the lighter. - var/lighter_color - /// The set of colors this lighter can be autoset as on init. - var/list/color_list = list( //Same 16 color selection as electronic assemblies - COLOR_ASSEMBLY_BLACK, - COLOR_FLOORTILE_GRAY, - COLOR_ASSEMBLY_BGRAY, - COLOR_ASSEMBLY_WHITE, - COLOR_ASSEMBLY_RED, - COLOR_ASSEMBLY_ORANGE, - COLOR_ASSEMBLY_BEIGE, - COLOR_ASSEMBLY_BROWN, - COLOR_ASSEMBLY_GOLD, - COLOR_ASSEMBLY_YELLOW, - COLOR_ASSEMBLY_GURKHA, - COLOR_ASSEMBLY_LGREEN, - COLOR_ASSEMBLY_GREEN, - COLOR_ASSEMBLY_LBLUE, - COLOR_ASSEMBLY_BLUE, - COLOR_ASSEMBLY_PURPLE - ) - -/obj/item/lighter/greyscale/Initialize(mapload) - . = ..() - if(!lighter_color) - lighter_color = pick(color_list) - update_appearance() - -/obj/item/lighter/greyscale/create_lighter_overlay() - var/mutable_appearance/lighter_overlay = ..() - lighter_overlay.color = lighter_color - return lighter_overlay - -/obj/item/lighter/greyscale/ignition_effect(atom/A, mob/user) - if(get_temperature()) - . = span_notice("After some fiddling, [user] manages to light [A] with [src].") - - -/obj/item/lighter/slime - name = "slime zippo" - desc = "A specialty zippo made from slimes and industry. Has a much hotter flame than normal." - icon_state = "slighter" - heat = 3000 //Blue flame! - light_color = LIGHT_COLOR_CYAN - overlay_state = "slime" - grind_results = list(/datum/reagent/iron = 1, /datum/reagent/fuel = 5, /datum/reagent/medicine/pyroxadone = 5) - -/obj/item/lighter/skull - name = "badass zippo" - desc = "An absolutely badass zippo lighter. Just look at that skull!" - overlay_state = "skull" - -/obj/item/lighter/mime - name = "pale zippo" - desc = "In lieu of fuel, performative spirit can be used to light cigarettes." - icon_state = "mlighter" //These ones don't show a flame. - light_color = LIGHT_COLOR_HALOGEN - heat = 0 //I swear it's a real lighter dude you just can't see the flame dude I promise - overlay_state = "mime" - grind_results = list(/datum/reagent/iron = 1, /datum/reagent/toxin/mutetoxin = 5, /datum/reagent/consumable/nothing = 10) - light_range = 0 - light_power = 0 - fancy = FALSE - -/obj/item/lighter/mime/ignition_effect(atom/A, mob/user) - . = span_infoplain("[user] lifts the [name] to the [A], which miraculously lights!") - -/obj/item/lighter/bright - name = "illuminative zippo" - desc = "Sustains an incredibly bright chemical reaction when you spark it. Avoid looking directly at the igniter when lit." - icon_state = "slighter" - light_color = LIGHT_COLOR_ELECTRIC_CYAN - overlay_state = "bright" - grind_results = list(/datum/reagent/iron = 1, /datum/reagent/flash_powder = 10) - light_range = 8 - light_power = 3 //Irritatingly bright and large enough to cover a small room. - fancy = FALSE - -/obj/item/lighter/bright/examine(mob/user) - . = ..() - - if(lit && isliving(user)) - var/mob/living/current_viewer = user - current_viewer.flash_act(4) - -/obj/item/lighter/bright/ignition_effect(atom/A, mob/user) - if(get_temperature()) - . = span_infoplain(span_rose("[user] lifts the [src] to the [A], igniting it with a brilliant flash of light!")) - var/mob/living/current_viewer = user - current_viewer.flash_act(4) - -/obj/effect/spawner/random/special_lighter - name = "special lighter spawner" - icon_state = "lighter" - loot = list( - /obj/item/lighter/skull, - /obj/item/lighter/mime, - /obj/item/lighter/bright, - ) - /////////// //ROLLING// /////////// diff --git a/code/game/objects/items/circuitboards/circuitboard.dm b/code/game/objects/items/circuitboards/circuitboard.dm index 236b6ed402c4a..6439ef9ccbe94 100644 --- a/code/game/objects/items/circuitboards/circuitboard.dm +++ b/code/game/objects/items/circuitboards/circuitboard.dm @@ -17,8 +17,8 @@ grind_results = list(/datum/reagent/silicon = 20) greyscale_colors = CIRCUIT_COLOR_GENERIC var/build_path = null - ///determines if the circuit board originated from a vendor off station or not. - var/onstation = TRUE + /// whether or not the circuit board will build into a vendor whose products cost nothing (used for offstation vending machines mostly) + var/all_products_free = FALSE ///determines if the board requires specific levels of parts. (ie specifically a femto menipulator vs generic manipulator) var/specific_parts = FALSE diff --git a/code/game/objects/items/circuitboards/computer_circuitboards.dm b/code/game/objects/items/circuitboards/computer_circuitboards.dm index 41950561571d6..9c3cde9f725a5 100644 --- a/code/game/objects/items/circuitboards/computer_circuitboards.dm +++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm @@ -403,6 +403,29 @@ name = "R&D Console" greyscale_colors = CIRCUIT_COLOR_SCIENCE build_path = /obj/machinery/computer/rdconsole + var/silence_announcements = FALSE + +/obj/item/circuitboard/computer/rdconsole/examine(mob/user) + . = ..() + . += span_info("The board is configured to [silence_announcements ? "silence" : "announce"] researched nodes on radio.") + . += span_notice("The board mode can be changed with a [EXAMINE_HINT("multitool")].") + +/obj/item/circuitboard/computer/rdconsole/multitool_act(mob/living/user) + . = ..() + if(obj_flags & EMAGGED) + balloon_alert(user, "board mode is broken!") + return + silence_announcements = !silence_announcements + balloon_alert(user, "announcements [silence_announcements ? "enabled" : "disabled"]") + +/obj/item/circuitboard/computer/rdconsole/emag_act(mob/user, obj/item/card/emag/emag_card) + if (obj_flags & EMAGGED) + return FALSE + + obj_flags |= EMAGGED + silence_announcements = FALSE + to_chat(user, span_notice("You overload the node announcement chip, forcing every node to be announced on the common channel.")) + return TRUE /obj/item/circuitboard/computer/rdservercontrol name = "R&D Server Control" diff --git a/code/game/objects/items/climbingrope.dm b/code/game/objects/items/climbingrope.dm index e68e508771248..552b5d5885011 100644 --- a/code/game/objects/items/climbingrope.dm +++ b/code/game/objects/items/climbingrope.dm @@ -27,6 +27,8 @@ . += span_notice("The rope looks like you could use it [uses] times before it falls apart.") /obj/item/climbing_hook/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(HAS_TRAIT(interacting_with, TRAIT_COMBAT_MODE_SKIP_INTERACTION)) + return NONE return ranged_interact_with_atom(interacting_with, user, modifiers) /obj/item/climbing_hook/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) diff --git a/code/game/objects/items/clown_items.dm b/code/game/objects/items/clown_items.dm index 6565bcae44f5b..58f2cb49a130a 100644 --- a/code/game/objects/items/clown_items.dm +++ b/code/game/objects/items/clown_items.dm @@ -161,9 +161,6 @@ return CLEAN_BLOCKED return ..() -/obj/item/soap/storage_insert_on_interaction(datum/storage, atom/storage_holder, mob/living/user) - return !user.combat_mode // only cleans a storage item if on combat - /* * Bike Horns */ diff --git a/code/game/objects/items/control_wand.dm b/code/game/objects/items/control_wand.dm index abad07f96d844..9734661e88f63 100644 --- a/code/game/objects/items/control_wand.dm +++ b/code/game/objects/items/control_wand.dm @@ -35,10 +35,12 @@ update_icon_state() balloon_alert(user, "mode: [desc[mode]]") -/obj/item/door_remote/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) - return interact_with_atom(interacting_with, user, modifiers) - /obj/item/door_remote/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!istype(interacting_with, /obj/machinery/door) && !isturf(interacting_with)) + return NONE + return ranged_interact_with_atom(interacting_with, user, modifiers) + +/obj/item/door_remote/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) var/obj/machinery/door/door if (istype(interacting_with, /obj/machinery/door)) diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index 3b2d9d196a190..03c79049b3087 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -402,7 +402,7 @@ set_painting_tool_color(paint_color) . = TRUE if("enter_text") - var/txt = tgui_input_text(usr, "Choose what to write", "Scribbles", text_buffer) + var/txt = tgui_input_text(usr, "Choose what to write", "Scribbles", text_buffer, max_length = MAX_MESSAGE_LEN) if(isnull(txt)) return txt = crayon_text_strip(txt) @@ -865,7 +865,10 @@ /obj/item/toy/crayon/spraycan/can_use_on(atom/target, mob/user, list/modifiers) if(iscarbon(target)) return TRUE - if(ismob(target) && (HAS_TRAIT(target, TRAIT_SPRAY_PAINTABLE))) + if(is_capped && HAS_TRAIT(target, TRAIT_COMBAT_MODE_SKIP_INTERACTION)) + // specifically don't try to use a capped spraycan on stuff like bags and tables, just place it + return FALSE + if(ismob(target) && HAS_TRAIT(target, TRAIT_SPRAY_PAINTABLE)) return TRUE if(isobj(target) && !(target.flags_1 & UNPAINTABLE_1)) return TRUE @@ -967,6 +970,10 @@ /obj/item/toy/crayon/spraycan/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) if(is_capped) + if(!interacting_with.color) + // let's be generous and assume if they're trying to match something with no color, while capped, + // we shouldn't be blocking further interactions + return NONE balloon_alert(user, "take the cap off first!") return ITEM_INTERACT_BLOCKING if(check_empty(user)) @@ -1003,9 +1010,6 @@ update_appearance() return CLICK_ACTION_SUCCESS -/obj/item/toy/crayon/spraycan/storage_insert_on_interaction(datum/storage, atom/storage_holder, mob/user) - return is_capped - /obj/item/toy/crayon/spraycan/update_icon_state() icon_state = is_capped ? icon_capped : icon_uncapped return ..() diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm index b1e01e5a6cebc..491d48a66d392 100644 --- a/code/game/objects/items/defib.dm +++ b/code/game/objects/items/defib.dm @@ -493,7 +493,7 @@ do_help(H, user) -/// Called whenever the paddles successfuly shock something +/// Called whenever the paddles successfully shock something /obj/item/shockpaddles/proc/do_success() if(busy) busy = FALSE @@ -708,7 +708,7 @@ base_icon_state = "syndiepaddles" /obj/item/shockpaddles/syndicate/nanotrasen - name = "elite nanotrasen defibrillator paddles" + name = "elite Nanotrasen defibrillator paddles" desc = "A pair of paddles used to revive deceased ERT members. They possess both the ability to penetrate armor and to deliver powerful or disabling shocks offensively." icon_state = "ntpaddles0" inhand_icon_state = "ntpaddles0" diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm index c619f7d7018e0..77eefa8a1507b 100644 --- a/code/game/objects/items/devices/aicard.dm +++ b/code/game/objects/items/devices/aicard.dm @@ -43,17 +43,15 @@ user.visible_message(span_suicide("[user] is trying to upload [user.p_them()]self into [src]! That's not going to work out well!")) return BRUTELOSS -/obj/item/aicard/pre_attack(atom/target, mob/living/user, params) - . = ..() - if(.) - return - +/obj/item/aicard/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(AI) - if(upload_ai(target, user)) - return TRUE + if(upload_ai(interacting_with, user)) + return ITEM_INTERACT_SUCCESS else - if(capture_ai(target, user)) - return TRUE + if(capture_ai(interacting_with, user)) + return ITEM_INTERACT_SUCCESS + + return NONE /// Tries to get an AI from the atom clicked /obj/item/aicard/proc/capture_ai(atom/from_what, mob/living/user) diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm index 1920e47f97f66..f0a934fc198cc 100644 --- a/code/game/objects/items/devices/chameleonproj.dm +++ b/code/game/objects/items/devices/chameleonproj.dm @@ -36,25 +36,36 @@ else to_chat(user, span_warning("You can't use [src] while inside something!")) -/obj/item/chameleon/interact_with_atom(atom/target, mob/living/user, list/modifiers) +/obj/item/chameleon/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!can_copy(interacting_with) || SHOULD_SKIP_INTERACTION(interacting_with, src, user)) + return NONE + make_copy(interacting_with, user) + return ITEM_INTERACT_SUCCESS + +/obj/item/chameleon/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + if(!can_copy(interacting_with)) // RMB scan works on storage items, LMB scan does not + return NONE + make_copy(interacting_with, user) + return ITEM_INTERACT_SUCCESS + +/obj/item/chameleon/proc/can_copy(atom/target) if(!check_sprite(target)) - return ITEM_INTERACT_BLOCKING + return FALSE if(active_dummy)//I now present you the blackli(f)st - return ITEM_INTERACT_BLOCKING + return FALSE if(isturf(target)) - return ITEM_INTERACT_BLOCKING + return FALSE if(ismob(target)) - return ITEM_INTERACT_BLOCKING + return FALSE if(istype(target, /obj/structure/falsewall)) - return ITEM_INTERACT_BLOCKING + return FALSE if(target.alpha != 255) - return ITEM_INTERACT_BLOCKING + return FALSE if(target.invisibility != 0) - return ITEM_INTERACT_BLOCKING + return FALSE if(iseffect(target) && !istype(target, /obj/effect/decal)) //be a footprint - return ITEM_INTERACT_BLOCKING - make_copy(target, user) - return ITEM_INTERACT_SUCCESS + return FALSE + return TRUE /obj/item/chameleon/proc/make_copy(atom/target, mob/user) playsound(get_turf(src), 'sound/weapons/flash.ogg', 100, TRUE, -6) diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 8db7652d5a07e..5e59ee700c6aa 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -41,8 +41,6 @@ set_light_on(TRUE) update_brightness() register_context() - if(toggle_context) - RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) var/static/list/slapcraft_recipe_list = list(/datum/crafting_recipe/flashlight_eyes) @@ -256,7 +254,7 @@ if(!scanning.get_bodypart(BODY_ZONE_HEAD)) to_chat(user, span_warning("[scanning] doesn't have a head!")) return - if(light_power < 1) + if(light_power < 0.5) to_chat(user, span_warning("[src] isn't bright enough to see anything!")) return @@ -286,12 +284,12 @@ setDir(user.dir) /// when hit by a light disruptor - turns the light off, forces the light to be disabled for a few seconds -/obj/item/flashlight/proc/on_saboteur(datum/source, disrupt_duration) - SIGNAL_HANDLER +/obj/item/flashlight/on_saboteur(datum/source, disrupt_duration) + . = ..() if(light_on) toggle_light() COOLDOWN_START(src, disabled_time, disrupt_duration) - return COMSIG_SABOTEUR_SUCCESS + return TRUE /obj/item/flashlight/pen name = "penlight" diff --git a/code/game/objects/items/devices/forcefieldprojector.dm b/code/game/objects/items/devices/forcefieldprojector.dm index 5d40d40a4d925..91bd3040832e4 100644 --- a/code/game/objects/items/devices/forcefieldprojector.dm +++ b/code/game/objects/items/devices/forcefieldprojector.dm @@ -21,10 +21,10 @@ /// Checks to make sure the projector isn't busy with making another forcefield. var/force_proj_busy = FALSE -/obj/item/forcefield_projector/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) - return interact_with_atom(interacting_with, user, modifiers) - /obj/item/forcefield_projector/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return ranged_interact_with_atom(interacting_with, user, modifiers) + +/obj/item/forcefield_projector/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!check_allowed_items(interacting_with, not_inside = TRUE)) return NONE if(istype(interacting_with, /obj/structure/projected_forcefield)) diff --git a/code/game/objects/items/devices/geiger_counter.dm b/code/game/objects/items/devices/geiger_counter.dm index 1d5ef17a90c4a..25bae4306091f 100644 --- a/code/game/objects/items/devices/geiger_counter.dm +++ b/code/game/objects/items/devices/geiger_counter.dm @@ -67,13 +67,13 @@ update_appearance(UPDATE_ICON) balloon_alert(user, "switch [scanning ? "on" : "off"]") -/obj/item/geiger_counter/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) - return interact_with_atom(interacting_with, user, modifiers) - /obj/item/geiger_counter/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) - if (user.combat_mode) + if(SHOULD_SKIP_INTERACTION(interacting_with, src, user)) return NONE - if (!CAN_IRRADIATE(interacting_with)) + return ranged_interact_with_atom(interacting_with, user, modifiers) + +/obj/item/geiger_counter/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!CAN_IRRADIATE(interacting_with)) return NONE user.visible_message(span_notice("[user] scans [interacting_with] with [src]."), span_notice("You scan [interacting_with]'s radiation levels with [src]...")) diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm index 3fe16fdb3fd96..dae54ce9e7816 100644 --- a/code/game/objects/items/devices/laserpointer.dm +++ b/code/game/objects/items/devices/laserpointer.dm @@ -183,12 +183,14 @@ and the wide margin between it and the focus lens could probably house a crystal of some sort." /obj/item/laser_pointer/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) - return interact_with_atom(interacting_with, user, modifiers) - -/obj/item/laser_pointer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) laser_act(interacting_with, user, modifiers) return ITEM_INTERACT_BLOCKING +/obj/item/laser_pointer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(HAS_TRAIT(interacting_with, TRAIT_COMBAT_MODE_SKIP_INTERACTION)) + return NONE + return ranged_interact_with_atom(interacting_with, user, modifiers) + ///Handles shining the clicked atom, /obj/item/laser_pointer/proc/laser_act(atom/target, mob/living/user, list/modifiers) if(isnull(diode)) @@ -233,9 +235,12 @@ else if(user.zone_selected == BODY_ZONE_PRECISE_EYES) //Intensity of the laser dot to pass to flash_act var/severity = pick(0, 1, 2) + var/always_fail = FALSE + if(istype(target_humanoid.glasses, /obj/item/clothing/glasses/eyepatch) && prob(50)) + always_fail = TRUE //chance to actually hit the eyes depends on internal component - if(prob(effectchance * diode.rating) && target_humanoid.flash_act(severity)) + if(prob(effectchance * diode.rating) && !always_fail && target_humanoid.flash_act(severity)) outmsg = span_notice("You blind [target_humanoid] by shining [src] in [target_humanoid.p_their()] eyes.") log_combat(user, target_humanoid, "blinded with a laser pointer", src) else diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm index 03ed7f927b0f7..8e29be708db6e 100644 --- a/code/game/objects/items/devices/multitool.dm +++ b/code/game/objects/items/devices/multitool.dm @@ -35,6 +35,11 @@ var/apc_scanner = TRUE COOLDOWN_DECLARE(next_apc_scan) +/obj/item/multitool/Destroy() + if(buffer) + remove_buffer(buffer) + return ..() + /obj/item/multitool/examine(mob/user) . = ..() . += span_notice("Its buffer [buffer ? "contains [buffer]." : "is empty."]") @@ -70,9 +75,10 @@ /obj/item/multitool/proc/set_buffer(datum/buffer) if(src.buffer) UnregisterSignal(src.buffer, COMSIG_QDELETING) + remove_buffer(src.buffer) src.buffer = buffer if(!QDELETED(buffer)) - RegisterSignal(buffer, COMSIG_QDELETING, PROC_REF(on_buffer_del)) + RegisterSignal(buffer, COMSIG_QDELETING, PROC_REF(remove_buffer)) /** * Called when the buffer's stored object is deleted @@ -80,8 +86,9 @@ * This proc does not clear the buffer of the multitool, it is here to * handle the deletion of the object the buffer references */ -/obj/item/multitool/proc/on_buffer_del(datum/source) +/obj/item/multitool/proc/remove_buffer(datum/source) SIGNAL_HANDLER + SEND_SIGNAL(src, COMSIG_MULTITOOL_REMOVE_BUFFER, source) buffer = null // Syndicate device disguised as a multitool; it will turn red when an AI camera is nearby. diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index 5673afc678a41..6ce325034e3ac 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -462,9 +462,7 @@ GLOBAL_LIST_INIT(channel_tokens, list( grant_headset_languages(mob_loc) /obj/item/radio/headset/click_alt(mob/living/user) - if(!istype(user) || !Adjacent(user) || user.incapacitated) - return CLICK_ACTION_BLOCKING - if (!command) + if(!istype(user) || !command) return CLICK_ACTION_BLOCKING use_command = !use_command to_chat(user, span_notice("You toggle high-volume mode [use_command ? "on" : "off"].")) diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 2b7a9bad7602a..7303eaf873803 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -121,19 +121,17 @@ return AddElement(/datum/element/slapcrafting, string_list(list(/datum/crafting_recipe/improv_explosive))) - RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) - /obj/item/radio/Destroy() remove_radio_all(src) //Just to be sure if(istype(keyslot)) QDEL_NULL(keyslot) return ..() -/obj/item/radio/proc/on_saboteur(datum/source, disrupt_duration) - SIGNAL_HANDLER +/obj/item/radio/on_saboteur(datum/source, disrupt_duration) + . = ..() if(broadcasting) //no broadcasting but it can still be used to send radio messages. set_broadcasting(FALSE) - return COMSIG_SABOTEUR_SUCCESS + return TRUE /obj/item/radio/proc/set_frequency(new_frequency) SEND_SIGNAL(src, COMSIG_RADIO_NEW_FREQUENCY, args) diff --git a/code/game/objects/items/devices/scanners/health_analyzer.dm b/code/game/objects/items/devices/scanners/health_analyzer.dm index 40ca839cb9a15..7374254885251 100644 --- a/code/game/objects/items/devices/scanners/health_analyzer.dm +++ b/code/game/objects/items/devices/scanners/health_analyzer.dm @@ -30,6 +30,8 @@ custom_price = PAYCHECK_COMMAND /// If this analyzer will give a bonus to wound treatments apon woundscan. var/give_wound_treatment_bonus = FALSE + var/last_scan_text + var/scanner_busy = FALSE /obj/item/healthanalyzer/Initialize(mapload) . = ..() @@ -38,7 +40,7 @@ /obj/item/healthanalyzer/examine(mob/user) . = ..() if(src.mode != SCANNER_NO_MODE) - . += span_notice("Alt-click [src] to toggle the limb damage readout.") + . += span_notice("Alt-click [src] to toggle the limb damage readout. Ctrl-shift-click to print readout report.") /obj/item/healthanalyzer/suicide_act(mob/living/carbon/user) user.visible_message(span_suicide("[user] begins to analyze [user.p_them()]self with [src]! The display shows that [user.p_theyre()] dead!")) @@ -71,10 +73,10 @@ if ((HAS_TRAIT(user, TRAIT_CLUMSY) || HAS_TRAIT(user, TRAIT_DUMB)) && prob(50)) user.visible_message(span_warning("[user] analyzes the floor's vitals!"), \ span_notice("You stupidly try to analyze the floor's vitals!")) - to_chat(user, "[span_info("Analyzing results for The floor:\n\tOverall status: Healthy")]\ - \n[span_info("Key: Suffocation/Toxin/Burn/Brute")]\ - \n[span_info("\tDamage specifics: 0-0-0-0")]\ - \n[span_info("Body temperature: ???")]") + to_chat(user, "[span_info("Analyzing results for The floor:
\tOverall status: Healthy")]\ +
[span_info("Key: Suffocation/Toxin/Burn/Brute")]\ +
[span_info("\tDamage specifics: 0-0-0-0")]\ +
[span_info("Body temperature: ???")]") return if(ispodperson(M) && !advanced) @@ -88,6 +90,7 @@ switch (scanmode) if (SCANMODE_HEALTH) healthscan(user, M, mode, advanced) + last_scan_text = healthscan(user, M, mode, advanced, tochat = FALSE) if (SCANMODE_WOUND) woundscan(user, M, src) @@ -149,12 +152,12 @@ mob_status = span_alert("Deceased") oxy_loss = max(rand(1, 40), oxy_loss, (300 - (tox_loss + fire_loss + brute_loss))) // Random oxygen loss - render_list += "[span_info("Analyzing results for [target]:")]\nOverall status: [mob_status]\n" + render_list += "[span_info("Analyzing results for [target]:")]
Overall status: [mob_status]
" if(ishuman(target)) var/mob/living/carbon/human/humantarget = target if(humantarget.undergoing_cardiac_arrest() && humantarget.stat != DEAD) - render_list += "Subject suffering from heart attack: Apply defibrillation or other electric shock immediately!\n" + render_list += "Subject suffering from heart attack: Apply defibrillation or other electric shock immediately!
" if(humantarget.has_reagent(/datum/reagent/inverse/technetium)) advanced = TRUE @@ -164,22 +167,22 @@ if(HAS_TRAIT(target, TRAIT_HUSK)) if(advanced) if(HAS_TRAIT_FROM(target, TRAIT_HUSK, BURN)) - render_list += "Subject has been husked by severe burns.\n" + render_list += "Subject has been husked by severe burns.
" else if (HAS_TRAIT_FROM(target, TRAIT_HUSK, CHANGELING_DRAIN)) - render_list += "Subject has been husked by dessication.\n" + render_list += "Subject has been husked by dessication.
" else - render_list += "Subject has been husked by mysterious causes.\n" + render_list += "Subject has been husked by mysterious causes.
" else - render_list += "Subject has been husked.\n" + render_list += "Subject has been husked.
" if(target.getStaminaLoss()) if(advanced) - render_list += "Fatigue level: [target.getStaminaLoss()]%.\n" + render_list += "Fatigue level: [target.getStaminaLoss()]%.
" else - render_list += "Subject appears to be suffering from fatigue.\n" + render_list += "Subject appears to be suffering from fatigue.
" if (!target.get_organ_slot(ORGAN_SLOT_BRAIN)) // kept exclusively for soul purposes - render_list += "Subject lacks a brain.\n" + render_list += "Subject lacks a brain.
" if(iscarbon(target)) var/mob/living/carbon/carbontarget = target @@ -198,14 +201,14 @@ trauma_desc += "permanent " trauma_desc += trauma.scan_desc trauma_text += trauma_desc - render_list += "Cerebral traumas detected: subject appears to be suffering from [english_list(trauma_text)].\n" + render_list += "Cerebral traumas detected: subject appears to be suffering from [english_list(trauma_text)].
" if(carbontarget.quirks.len) - render_list += "Subject Major Disabilities: [carbontarget.get_quirk_string(FALSE, CAT_QUIRK_MAJOR_DISABILITY, from_scan = TRUE)].\n" + render_list += "Subject Major Disabilities: [carbontarget.get_quirk_string(FALSE, CAT_QUIRK_MAJOR_DISABILITY, from_scan = TRUE)].
" if(advanced) - render_list += "Subject Minor Disabilities: [carbontarget.get_quirk_string(FALSE, CAT_QUIRK_MINOR_DISABILITY, TRUE)].\n" + render_list += "Subject Minor Disabilities: [carbontarget.get_quirk_string(FALSE, CAT_QUIRK_MINOR_DISABILITY, TRUE)].
" if (HAS_TRAIT(target, TRAIT_IRRADIATED)) - render_list += "Subject is irradiated. Supply toxin healing.\n" + render_list += "Subject is irradiated. Supply toxin healing.
" //Eyes and ears if(advanced && iscarbon(target)) @@ -215,24 +218,24 @@ var/obj/item/organ/internal/ears/ears = carbontarget.get_organ_slot(ORGAN_SLOT_EARS) if(istype(ears)) if(HAS_TRAIT_FROM(carbontarget, TRAIT_DEAF, GENETIC_MUTATION)) - render_list += "Subject is genetically deaf.\n" + render_list += "Subject is genetically deaf.
" else if(HAS_TRAIT_FROM(carbontarget, TRAIT_DEAF, EAR_DAMAGE)) - render_list += "Subject is deaf from ear damage.\n" + render_list += "Subject is deaf from ear damage.
" else if(HAS_TRAIT(carbontarget, TRAIT_DEAF)) - render_list += "Subject is deaf.\n" + render_list += "Subject is deaf.
" else if(ears.damage) - render_list += "Subject has [ears.damage > ears.maxHealth ? "permanent ": "temporary "]hearing damage.\n" + render_list += "Subject has [ears.damage > ears.maxHealth ? "permanent ": "temporary "]hearing damage.
" if(ears.deaf) - render_list += "Subject is [ears.damage > ears.maxHealth ? "permanently": "temporarily"] deaf.\n" + render_list += "Subject is [ears.damage > ears.maxHealth ? "permanently": "temporarily"] deaf.
" // Eye status var/obj/item/organ/internal/eyes/eyes = carbontarget.get_organ_slot(ORGAN_SLOT_EYES) if(istype(eyes)) if(carbontarget.is_blind()) - render_list += "Subject is blind.\n" + render_list += "Subject is blind.
" else if(carbontarget.is_nearsighted()) - render_list += "Subject is nearsighted.\n" + render_list += "Subject is nearsighted.
" // Body part damage report if(iscarbon(target)) @@ -264,7 +267,7 @@ render_list += dmgreport // tables do not need extra linebreak for(var/obj/item/bodypart/limb as anything in carbontarget.bodyparts) for(var/obj/item/embed as anything in limb.embedded_objects) - render_list += "Embedded object: [embed] located in \the [limb.plaintext_zone]\n" + render_list += "Embedded object: [embed] located in \the [limb.plaintext_zone]
" if(ishuman(target)) var/mob/living/carbon/human/humantarget = target @@ -316,34 +319,34 @@ //Genetic stability if(advanced && humantarget.has_dna()) - render_list += "Genetic Stability: [humantarget.dna.stability]%.\n" + render_list += "Genetic Stability: [humantarget.dna.stability]%.
" // Hulk and body temperature var/datum/species/targetspecies = humantarget.dna.species var/mutant = HAS_TRAIT(humantarget, TRAIT_HULK) - render_list += "Species: [targetspecies.name][mutant ? "-derived mutant" : ""]\n" + render_list += "Species: [targetspecies.name][mutant ? "-derived mutant" : ""]
" var/core_temperature_message = "Core temperature: [round(humantarget.coretemperature-T0C, 0.1)] °C ([round(humantarget.coretemperature*1.8-459.67,0.1)] °F)" if(humantarget.coretemperature >= humantarget.get_body_temp_heat_damage_limit()) - render_list += "☼ [core_temperature_message] ☼\n" + render_list += "☼ [core_temperature_message] ☼
" else if(humantarget.coretemperature <= humantarget.get_body_temp_cold_damage_limit()) - render_list += "❄ [core_temperature_message] ❄\n" + render_list += "❄ [core_temperature_message] ❄
" else - render_list += "[core_temperature_message]\n" + render_list += "[core_temperature_message]
" var/body_temperature_message = "Body temperature: [round(target.bodytemperature-T0C, 0.1)] °C ([round(target.bodytemperature*1.8-459.67,0.1)] °F)" if(target.bodytemperature >= target.get_body_temp_heat_damage_limit()) - render_list += "☼ [body_temperature_message] ☼\n" + render_list += "☼ [body_temperature_message] ☼
" else if(target.bodytemperature <= target.get_body_temp_cold_damage_limit()) - render_list += "❄ [body_temperature_message] ❄\n" + render_list += "❄ [body_temperature_message] ❄
" else - render_list += "[body_temperature_message]\n" + render_list += "[body_temperature_message]
" // Time of death if(target.station_timestamp_timeofdeath && (target.stat == DEAD || ((HAS_TRAIT(target, TRAIT_FAKEDEATH)) && !advanced))) - render_list += "Time of Death: [target.station_timestamp_timeofdeath]\n" + render_list += "Time of Death: [target.station_timestamp_timeofdeath]
" var/tdelta = round(world.time - target.timeofdeath) - render_list += "Subject died [DisplayTimeText(tdelta)] ago.\n" + render_list += "Subject died [DisplayTimeText(tdelta)] ago.
" // Wounds if(iscarbon(target)) @@ -354,14 +357,14 @@ render_list += "Physical trauma[LAZYLEN(wounded_part.wounds) > 1 ? "s" : ""] detected in [wounded_part.name]" for(var/k in wounded_part.wounds) var/datum/wound/W = k - render_list += "
[W.name] ([W.severity_text()])\nRecommended treatment: [W.treat_text]
" // less lines than in woundscan() so we don't overload people trying to get basic med info + render_list += "
[W.name] ([W.severity_text()])
Recommended treatment: [W.treat_text]
" // less lines than in woundscan() so we don't overload people trying to get basic med info render_list += "
" //Diseases for(var/datum/disease/disease as anything in target.diseases) if(!(disease.visibility_flags & HIDDEN_SCANNER)) - render_list += "Warning: [disease.form] detected\n\ -
Name: [disease.name].\nType: [disease.spread_text].\nStage: [disease.stage]/[disease.max_stages].\nPossible Cure: [disease.cure_text]
\ + render_list += "Warning: [disease.form] detected
\ +
Name: [disease.name].
Type: [disease.spread_text].
Stage: [disease.stage]/[disease.max_stages].
Possible Cure: [disease.cure_text]
\
" // divs do not need extra linebreak // Blood Level @@ -370,26 +373,26 @@ var/blood_id = carbontarget.get_blood_id() if(blood_id) if(carbontarget.is_bleeding()) - render_list += "Subject is bleeding!\n" + render_list += "Subject is bleeding!
" var/blood_percent = round((carbontarget.blood_volume / BLOOD_VOLUME_NORMAL) * 100) var/blood_type = carbontarget.dna.blood_type if(blood_id != /datum/reagent/blood) // special blood substance var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id] blood_type = R ? R.name : blood_id if(carbontarget.blood_volume <= BLOOD_VOLUME_SAFE && carbontarget.blood_volume > BLOOD_VOLUME_OKAY) - render_list += "Blood level: LOW [blood_percent]%, [carbontarget.blood_volume] cl, [span_info("type: [blood_type]")]\n" + render_list += "Blood level: LOW [blood_percent]%, [carbontarget.blood_volume] cl, [span_info("type: [blood_type]")]
" else if(carbontarget.blood_volume <= BLOOD_VOLUME_OKAY) - render_list += "Blood level: CRITICAL [blood_percent]%, [carbontarget.blood_volume] cl, [span_info("type: [blood_type]")]\n" + render_list += "Blood level: CRITICAL [blood_percent]%, [carbontarget.blood_volume] cl, [span_info("type: [blood_type]")]
" else - render_list += "Blood level: [blood_percent]%, [carbontarget.blood_volume] cl, type: [blood_type]\n" + render_list += "Blood level: [blood_percent]%, [carbontarget.blood_volume] cl, type: [blood_type]
" // Blood Alcohol Content var/blood_alcohol_content = target.get_blood_alcohol_content() if(blood_alcohol_content > 0) if(blood_alcohol_content >= 0.24) - render_list += "Blood alcohol content: CRITICAL [blood_alcohol_content]%\n" + render_list += "Blood alcohol content: CRITICAL [blood_alcohol_content]%
" else - render_list += "Blood alcohol content: [blood_alcohol_content]%\n" + render_list += "Blood alcohol content: [blood_alcohol_content]%
" // Cybernetics if(iscarbon(target)) @@ -399,8 +402,8 @@ if(IS_ROBOTIC_ORGAN(cyberimp) && !(cyberimp.organ_flags & ORGAN_HIDDEN)) cyberimp_detect += "[!cyberimp_detect ? "[cyberimp.examine_title(user)]" : ", [cyberimp.examine_title(user)]"]" if(cyberimp_detect) - render_list += "Detected cybernetic modifications:\n" - render_list += "[cyberimp_detect]\n" + render_list += "Detected cybernetic modifications:
" + render_list += "[cyberimp_detect]
" // we handled the last
so we don't need handholding if(tochat) @@ -408,6 +411,37 @@ else return(jointext(render_list, "")) +/obj/item/healthanalyzer/click_ctrl_shift(mob/user) + . = ..() + if(!LAZYLEN(last_scan_text)) + balloon_alert(user, "no scans!") + return + if(scanner_busy) + balloon_alert(user, "analyzer busy!") + return + scanner_busy = TRUE + balloon_alert(user, "printing report...") + addtimer(CALLBACK(src, PROC_REF(print_report)), 2 SECONDS) + +/obj/item/healthanalyzer/proc/print_report(mob/user) + var/obj/item/paper/report_paper = new(get_turf(src)) + + report_paper.color = COLOR_STARLIGHT + report_paper.name = "Health scan report" + var/report_text = "
Health scan report. Time of scan: [station_time_timestamp()]


" + report_text += last_scan_text + + report_paper.add_raw_text(report_text) + report_paper.update_appearance() + + if(ismob(loc)) + var/mob/printer = loc + printer.put_in_hands(report_paper) + balloon_alert(printer, "logs cleared") + + report_text = list() + scanner_busy = FALSE + /proc/chemscan(mob/living/user, mob/living/target) if(user.incapacitated) return @@ -422,12 +456,12 @@ var/datum/reagent/reagent = r if(reagent.chemical_flags & REAGENT_INVISIBLE) //Don't show hidden chems on scanners continue - render_block += "[round(reagent.volume, 0.001)] units of [reagent.name][reagent.overdosed ? " - [span_boldannounce("OVERDOSING")]" : ".
"]\n" + render_block += "[round(reagent.volume, 0.001)] units of [reagent.name][reagent.overdosed ? " - [span_boldannounce("OVERDOSING")]" : "."]
" if(!length(render_block)) //If no VISIBLY DISPLAYED reagents are present, we report as if there is nothing. - render_list += "Subject contains no reagents in their blood.\n" + render_list += "Subject contains no reagents in their blood.
" else - render_list += "Subject contains the following reagents in their blood:\n" + render_list += "Subject contains the following reagents in their blood:
" render_list += render_block //Otherwise, we add the header, reagent readouts, and clear the readout block for use on the stomach. render_block.Cut() @@ -440,35 +474,35 @@ if(bit.chemical_flags & REAGENT_INVISIBLE) continue if(!belly.food_reagents[bit.type]) - render_block += "[round(bit.volume, 0.001)] units of [bit.name][bit.overdosed ? " - [span_boldannounce("OVERDOSING")]" : "."]\n" + render_block += "[round(bit.volume, 0.001)] units of [bit.name][bit.overdosed ? " - [span_boldannounce("OVERDOSING")]" : "."]
" else var/bit_vol = bit.volume - belly.food_reagents[bit.type] if(bit_vol > 0) - render_block += "[round(bit_vol, 0.001)] units of [bit.name][bit.overdosed ? " - [span_boldannounce("OVERDOSING")]" : "."]\n" + render_block += "[round(bit_vol, 0.001)] units of [bit.name][bit.overdosed ? " - [span_boldannounce("OVERDOSING")]" : "."]
" if(!length(render_block)) - render_list += "Subject contains no reagents in their stomach.\n" + render_list += "Subject contains no reagents in their stomach.
" else - render_list += "Subject contains the following reagents in their stomach:\n" + render_list += "Subject contains the following reagents in their stomach:
" render_list += render_block // Addictions if(LAZYLEN(target.mind?.active_addictions)) - render_list += "Subject is addicted to the following types of drug:\n" + render_list += "Subject is addicted to the following types of drug:
" for(var/datum/addiction/addiction_type as anything in target.mind.active_addictions) - render_list += "[initial(addiction_type.name)]\n" + render_list += "[initial(addiction_type.name)]
" // Special eigenstasium addiction if(target.has_status_effect(/datum/status_effect/eigenstasium)) - render_list += "Subject is temporally unstable. Stabilising agent is recommended to reduce disturbances.\n" + render_list += "Subject is temporally unstable. Stabilising agent is recommended to reduce disturbances.
" // Allergies for(var/datum/quirk/quirky as anything in target.quirks) if(istype(quirky, /datum/quirk/item_quirk/allergic)) var/datum/quirk/item_quirk/allergic/allergies_quirk = quirky var/allergies = allergies_quirk.allergy_string - render_list += "Subject is extremely allergic to the following chemicals:\n" - render_list += "[allergies]\n" + render_list += "Subject is extremely allergic to the following chemicals:
" + render_list += "[allergies]
" // we handled the last
so we don't need handholding to_chat(user, examine_block(jointext(render_list, "")), trailing_newline = FALSE, type = MESSAGE_TYPE_INFO) @@ -505,7 +539,7 @@ render_list += "Warning: Physical trauma[LAZYLEN(wounded_part.wounds) > 1? "s" : ""] detected in [wounded_part.name]" for(var/limb_wound in wounded_part.wounds) var/datum/wound/current_wound = limb_wound - render_list += "
[simple_scan ? current_wound.get_simple_scanner_description() : current_wound.get_scanner_description()]
\n" + render_list += "
[simple_scan ? current_wound.get_simple_scanner_description() : current_wound.get_scanner_description()]

" if (scanner.give_wound_treatment_bonus) ADD_TRAIT(current_wound, TRAIT_WOUND_SCANNED, ANALYZER_TRAIT) if(!advised) @@ -670,8 +704,8 @@ var/list/render = list() for(var/datum/disease/disease as anything in patient.diseases) if(!(disease.visibility_flags & HIDDEN_SCANNER)) - render += "Warning: [disease.form] detected\n\ -
Name: [disease.name].\nType: [disease.spread_text].\nStage: [disease.stage]/[disease.max_stages].\nPossible Cure: [disease.cure_text]
\ + render += "Warning: [disease.form] detected
\ +
Name: [disease.name].
Type: [disease.spread_text].
Stage: [disease.stage]/[disease.max_stages].
Possible Cure: [disease.cure_text]
\
" if(!length(render)) diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm index b86489fae9ea7..9b6328fe682fa 100644 --- a/code/game/objects/items/devices/taperecorder.dm +++ b/code/game/objects/items/devices/taperecorder.dm @@ -162,7 +162,7 @@ if(mytape && recording) mytape.timestamp += mytape.used_capacity - mytape.storedinfo += "\[[time2text(mytape.used_capacity,"mm:ss")]\] [raw_message]" + mytape.storedinfo += "\[[time2text(mytape.used_capacity,"mm:ss")]\] [speaker.GetVoice()]: [raw_message]" /obj/item/taperecorder/verb/record() diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm index 8327e185ea612..ee4a61b935157 100644 --- a/code/game/objects/items/devices/traitordevices.dm +++ b/code/game/objects/items/devices/traitordevices.dm @@ -361,15 +361,6 @@ effective or pretty fucking useless. new /obj/item/analyzer(src) new /obj/item/wirecutters(src) -/obj/item/storage/toolbox/emergency/turret/storage_insert_on_interacted_with(datum/storage, obj/item/inserted, mob/living/user) - if(!istype(inserted, /obj/item/wrench/combat)) - return TRUE - if(!user.combat_mode) - return TRUE - if(!inserted.toolspeed) - return TRUE - return FALSE - /obj/item/storage/toolbox/emergency/turret/item_interaction(mob/living/user, obj/item/tool, list/modifiers) if(!istype(tool, /obj/item/wrench/combat)) return NONE diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm index d17530c801085..4f0c0a84aa317 100644 --- a/code/game/objects/items/devices/transfer_valve.dm +++ b/code/game/objects/items/devices/transfer_valve.dm @@ -25,11 +25,36 @@ /obj/item/transfer_valve/Initialize(mapload) . = ..() RegisterSignal(src, COMSIG_ITEM_FRIED, PROC_REF(on_fried)) + register_context() /obj/item/transfer_valve/Destroy() attached_device = null return ..() +/obj/item/transfer_valve/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = ..() + + if(tank_one || tank_two) + context[SCREENTIP_CONTEXT_ALT_LMB] = "Remove [tank_one || tank_two]" + . = CONTEXTUAL_SCREENTIP_SET + if(istype(held_item) && is_type_in_list(held_item, list(/obj/item/tank, /obj/item/assembly))) + context[SCREENTIP_CONTEXT_LMB] = "Attach [held_item]" + . = CONTEXTUAL_SCREENTIP_SET + + return . || NONE + +/obj/item/transfer_valve/click_alt(mob/user) + if(tank_one) + split_gases() + valve_open = FALSE + tank_one.forceMove(drop_location()) + else if(tank_two) + split_gases() + valve_open = FALSE + tank_two.forceMove(drop_location()) + + return CLICK_ACTION_SUCCESS + /obj/item/transfer_valve/IsAssemblyHolder() return TRUE diff --git a/code/game/objects/items/eightball.dm b/code/game/objects/items/eightball.dm index 4445cdd1b7277..40f08e78ffc77 100644 --- a/code/game/objects/items/eightball.dm +++ b/code/game/objects/items/eightball.dm @@ -153,7 +153,7 @@ /obj/item/toy/eightball/haunted/start_shaking(mob/user) // notify ghosts that someone's shaking a haunted eightball // and inform them of the message, (hopefully a yes/no question) - selected_message = tgui_input_text(user, "What is your question?", "Eightball") || initial(selected_message) + selected_message = tgui_input_text(user, "What is your question?", "Eightball", max_length = MAX_MESSAGE_LEN) || initial(selected_message) if (!(src in user.held_items)) return FALSE notify_ghosts( diff --git a/code/game/objects/items/emags.dm b/code/game/objects/items/emags.dm index ccb52b71bc3bc..f854ba1b90a0c 100644 --- a/code/game/objects/items/emags.dm +++ b/code/game/objects/items/emags.dm @@ -137,16 +137,16 @@ . = ..() type_blacklist = list(typesof(/obj/machinery/door/airlock) + typesof(/obj/machinery/door/window/) + typesof(/obj/machinery/door/firedoor) - typesof(/obj/machinery/door/airlock/tram)) //list of all typepaths that require a specialized emag to hack. -/obj/item/card/emag/storage_insert_on_interaction(datum/storage, atom/storage_holder, mob/living/user) - return !user.combat_mode - /obj/item/card/emag/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(SHOULD_SKIP_INTERACTION(interacting_with, src, user)) + return NONE // lets us put things in bags without trying to emag them if(!can_emag(interacting_with, user)) return ITEM_INTERACT_BLOCKING log_combat(user, interacting_with, "attempted to emag") if(interacting_with.emag_act(user, src)) SSblackbox.record_feedback("tally", "atom_emagged", 1, interacting_with.type) - return ITEM_INTERACT_SUCCESS + return ITEM_INTERACT_SUCCESS + return NONE // In a perfect world this would be blocking, but this is not a perfect world /obj/item/card/emag/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) return prox_check ? NONE : interact_with_atom(interacting_with, user) diff --git a/code/game/objects/items/etherealdiscoball.dm b/code/game/objects/items/etherealdiscoball.dm index fe066bd1bf572..4eca1dc2fc0a7 100644 --- a/code/game/objects/items/etherealdiscoball.dm +++ b/code/game/objects/items/etherealdiscoball.dm @@ -1,5 +1,5 @@ /obj/item/etherealballdeployer - name = "Portable Ethereal Disco Ball" + name = "portable ethereal disco ball" desc = "Press the button for a deployment of slightly-unethical PARTY!" icon = 'icons/obj/devices/remote.dmi' icon_state = "ethdisco" @@ -11,7 +11,7 @@ qdel(src) /obj/structure/etherealball - name = "Ethereal Disco Ball" + name = "ethereal disco ball" desc = "The ethics of this discoball are questionable." icon = 'icons/obj/machines/floor.dmi' icon_state = "ethdisco_head_0" diff --git a/code/game/objects/items/extinguisher.dm b/code/game/objects/items/extinguisher.dm index 764e2fc6173bf..c542048b49d98 100644 --- a/code/game/objects/items/extinguisher.dm +++ b/code/game/objects/items/extinguisher.dm @@ -207,13 +207,15 @@ else return FALSE -/obj/item/extinguisher/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) - return interact_with_atom(interacting_with, user, modifiers) - /obj/item/extinguisher/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) - if (interacting_with.loc == user) + if(interacting_with.loc == user) return NONE + // Always skip interaction if it's a bag or table (that's not on fire) + if(!(interacting_with.resistance_flags & ON_FIRE) && HAS_TRAIT(interacting_with, TRAIT_COMBAT_MODE_SKIP_INTERACTION)) + return NONE + return ranged_interact_with_atom(interacting_with, user, modifiers) +/obj/item/extinguisher/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(refilling) refilling = FALSE return NONE diff --git a/code/game/objects/items/food/bait.dm b/code/game/objects/items/food/bait.dm index f31eb44f308eb..711c6cb1e68ff 100644 --- a/code/game/objects/items/food/bait.dm +++ b/code/game/objects/items/food/bait.dm @@ -6,6 +6,8 @@ var/bait_quality = TRAIT_BASIC_QUALITY_BAIT /// Icon state added to main fishing rod icon when this bait is equipped var/rod_overlay_icon_state + /// Is this included in the autowiki? + var/show_on_wiki = TRUE /obj/item/food/bait/Initialize(mapload) . = ..() @@ -36,9 +38,14 @@ lefthand_file = 'icons/mob/inhands/items_lefthand.dmi' righthand_file = 'icons/mob/inhands/items_righthand.dmi' inhand_icon_state = "pen" + bait_quality = TRAIT_GREAT_QUALITY_BAIT //this is only here for autowiki purposes, it's removed on init. food_reagents = list(/datum/reagent/drug/kronkaine = 2) //The kronkaine is the thing that makes this a great bait. tastes = list("hypocrisy" = 1) +/obj/item/food/bait/natural/Initialize(mapload) + . = ..() + REMOVE_TRAIT(src, bait_quality, INNATE_TRAIT) + /obj/item/food/bait/doughball name = "doughball" desc = "Small piece of dough. Simple but effective fishing bait." @@ -51,17 +58,12 @@ bait_quality = TRAIT_BASIC_QUALITY_BAIT rod_overlay_icon_state = "dough_overlay" -/** - * Bound to the tech fishing rod, from which cannot be removed, - * Bait-related preferences and traits, both negative and positive, - * should be ignored by this bait. - * Otherwise it'd be hard/impossible to cath some fish with it, - * making that rod a shoddy choice in the long run. - */ +///The abstract synthetic doughball type. /obj/item/food/bait/doughball/synthetic name = "synthetic doughball" icon_state = "doughball_blue" preserved_food = TRUE + show_on_wiki = FALSE //It's an abstract item. /obj/item/food/bait/doughball/synthetic/Initialize(mapload) . = ..() @@ -70,10 +72,17 @@ ///Found in the can of omni-baits, only available from the super fishing toolbox, from the fishing mystery box. /obj/item/food/bait/doughball/synthetic/super name = "super-doughball" - desc = "No fish will be able to resist this." + desc = "Be they herbivore or carnivores, no fish will be able to resist this." bait_quality = TRAIT_GREAT_QUALITY_BAIT + show_on_wiki = TRUE -///Used by the advanced fishing rod +/** + * Bound to the tech fishing rod, from which cannot be removed, + * Bait-related preferences and traits, both negative and positive, + * should be ignored by this bait. + * Otherwise it'd be hard/impossible to cath some fish with it, + * making that rod a shoddy choice in the long run. + */ /obj/item/food/bait/doughball/syntethic/unconsumable /obj/item/food/bait/doughball/synthetic/unconsumable/Initialize(mapload) diff --git a/code/game/objects/items/food/donuts.dm b/code/game/objects/items/food/donuts.dm index 0d2e2f91d3008..922ed2eaa6674 100644 --- a/code/game/objects/items/food/donuts.dm +++ b/code/game/objects/items/food/donuts.dm @@ -79,7 +79,7 @@ reagents.add_reagent(extra_reagent, 3) /obj/item/food/donut/meat - name = "Meat Donut" + name = "meat donut" desc = "Tastes as gross as it looks." icon_state = "donut_meat" food_reagents = list( diff --git a/code/game/objects/items/food/meatdish.dm b/code/game/objects/items/food/meatdish.dm index 5ad5cea20fae8..a619be72062af 100644 --- a/code/game/objects/items/food/meatdish.dm +++ b/code/game/objects/items/food/meatdish.dm @@ -57,7 +57,7 @@ food_reagents = list( /datum/reagent/consumable/nutriment/protein = 4, /datum/reagent/consumable/nutriment/vitamin = 3, - /datum/reagent/consumable/nutriment/fat/oil = 2, + /datum/reagent/consumable/nutriment/fat = 2, ) bite_consumption = 4.5 crafting_complexity = FOOD_COMPLEXITY_1 @@ -99,14 +99,20 @@ /obj/item/food/fishmeat/gunner_jellyfish name = "filleted gunner jellyfish" - desc = "A gunner jellyfish with the stingers removed. Mildly hallucinogenic." + desc = "A gunner jellyfish with the stingers removed. Mildly hallucinogenic when raw." icon = 'icons/obj/food/lizard.dmi' icon_state = "jellyfish_fillet" food_reagents = list( - /datum/reagent/consumable/nutriment/protein = 4, - /datum/reagent/toxin/mindbreaker = 2, + /datum/reagent/consumable/nutriment/protein = 4, //The halluginogen comes from the fish trait. ) +///Premade gunner jellyfish fillets from supply orders. Contains the halluginogen that'd be normally from the fish trait. +/obj/item/food/fishmeat/gunner_jellyfish/supply + +/obj/item/food/fishmeat/gunner_jellyfish/supply/Initialize(mapload) + food_reagents[/datum/reagent/toxin/mindbreaker/fish] = 2 + return ..() + /obj/item/food/fishmeat/armorfish name = "cleaned armorfish" desc = "An armorfish with its guts and shell removed, ready for use in cooking." diff --git a/code/game/objects/items/food/misc.dm b/code/game/objects/items/food/misc.dm index b2cf4d132c5fb..54ec5ce019012 100644 --- a/code/game/objects/items/food/misc.dm +++ b/code/game/objects/items/food/misc.dm @@ -339,7 +339,7 @@ crafting_complexity = FOOD_COMPLEXITY_5 /obj/item/food/branrequests - name = "Bran Requests Cereal" + name = "bran requests cereal" desc = "A dry cereal that satiates your requests for bran. Tastes uniquely like raisins and salt." icon_state = "bran_requests" food_reagents = list( @@ -422,7 +422,7 @@ w_class = WEIGHT_CLASS_TINY /obj/item/food/crab_rangoon - name = "Crab Rangoon" + name = "crab rangoon" desc = "Has many names, like crab puffs, cheese won'tons, crab dumplings? Whatever you call them, they're a fabulous blast of cream cheesy crab." icon = 'icons/obj/food/meat.dmi' icon_state = "crabrangoon" diff --git a/code/game/objects/items/grenades/_grenade.dm b/code/game/objects/items/grenades/_grenade.dm index ca7da893bb4b4..cbf604db63d0d 100644 --- a/code/game/objects/items/grenades/_grenade.dm +++ b/code/game/objects/items/grenades/_grenade.dm @@ -51,6 +51,8 @@ var/shrapnel_radius ///Did we add the component responsible for spawning shrapnel to this? var/shrapnel_initialized + ///Possible timers that can be assigned for detonation. Values are strings in SECONDS + var/list/possible_fuse_time = list("Instant", "3", "4", "5") /obj/item/grenade/Initialize(mapload) . = ..() @@ -210,7 +212,10 @@ return FALSE if(change_det_time()) tool.play_tool_sound(src) - to_chat(user, span_notice("You modify the time delay. It's set for [DisplayTimeText(det_time)].")) + if(det_time == 0) + to_chat(user, span_notice("You modify the time delay. It's set to be instantaneous.")) + else + to_chat(user, span_notice("You modify the time delay. It's set for [DisplayTimeText(det_time)].")) return TRUE /obj/item/grenade/multitool_act(mob/living/user, obj/item/tool) @@ -220,7 +225,7 @@ . = TRUE - var/newtime = tgui_input_list(user, "Please enter a new detonation time", "Detonation Timer", list("Instant", 3, 4, 5)) + var/newtime = tgui_input_list(user, "Please enter a new detonation time", "Detonation Timer", possible_fuse_time) if (isnull(newtime)) return if(!user.can_perform_action(src)) @@ -228,25 +233,40 @@ if(newtime == "Instant" && change_det_time(0)) to_chat(user, span_notice("You modify the time delay. It's set to be instantaneous.")) return - newtime = round(newtime) + newtime = round(text2num(newtime)) if(change_det_time(newtime)) to_chat(user, span_notice("You modify the time delay. It's set for [DisplayTimeText(det_time)].")) -/obj/item/grenade/proc/change_det_time(time) //Time uses real time. +/** + * Sets det_time to a number in SECONDS + * + * if time is passed as an argument, `det_time` will be `time SECONDS` + * + * Cycles the duration of the fuse of the grenade `det_time` based on the options provided in list/possible_fuse_time +*/ +/obj/item/grenade/proc/change_det_time(time) . = TRUE + //Multitool if(!isnull(time)) - det_time = round(clamp(time * 10, 0, 5 SECONDS)) + det_time = round(clamp(time SECONDS, 0, 5 SECONDS)) //This is fine for now but consider making this a variable if you want >5s fuse + return + + //Screwdriver + if(det_time == 0) + det_time = "Instant" + else + det_time = num2text(det_time * 0.1) + + var/old_selection = possible_fuse_time.Find(det_time) //Position of det_time in the list + if(old_selection >= possible_fuse_time.len) + det_time = possible_fuse_time[1] else - var/previous_time = det_time - switch(det_time) - if (0) - det_time = 3 SECONDS - if (3 SECONDS) - det_time = 5 SECONDS - if (5 SECONDS) - det_time = 0 - if(det_time == previous_time) - det_time = 5 SECONDS + det_time = possible_fuse_time[old_selection+1] + + if(det_time == "Instant") + det_time = 0 //String to num conversion because I hate coders + return + det_time = text2num(det_time) SECONDS /obj/item/grenade/attack_paw(mob/user, list/modifiers) return attack_hand(user, modifiers) diff --git a/code/game/objects/items/grenades/flashbang.dm b/code/game/objects/items/grenades/flashbang.dm index 98e7a4bab796e..6817610bf76e7 100644 --- a/code/game/objects/items/grenades/flashbang.dm +++ b/code/game/objects/items/grenades/flashbang.dm @@ -4,6 +4,7 @@ inhand_icon_state = "flashbang" lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi' + possible_fuse_time = list("3", "4", "5") var/flashbang_range = 7 //how many tiles away the mob will be stunned. /obj/item/grenade/flashbang/apply_grenade_fantasy_bonuses(quality) diff --git a/code/game/objects/items/implants/security/implant_noteleport.dm b/code/game/objects/items/implants/security/implant_noteleport.dm index b4795a7f797b7..a757e2cc0cd0f 100644 --- a/code/game/objects/items/implants/security/implant_noteleport.dm +++ b/code/game/objects/items/implants/security/implant_noteleport.dm @@ -17,6 +17,7 @@ if(!. || !isliving(target)) return FALSE RegisterSignal(target, COMSIG_MOVABLE_TELEPORTING, PROC_REF(on_teleport)) + RegisterSignal(target, COMSIG_MOB_PRE_JAUNT, PROC_REF(on_jaunt)) return TRUE /obj/item/implant/teleport_blocker/removed(mob/target, silent = FALSE, special = FALSE) @@ -24,6 +25,7 @@ if(!. || !isliving(target)) return FALSE UnregisterSignal(target, COMSIG_MOVABLE_TELEPORTING) + UnregisterSignal(target, COMSIG_MOB_PRE_JAUNT) return TRUE /// Signal for COMSIG_MOVABLE_TELEPORTED that blocks teleports and stuns the would-be-teleportee. @@ -38,6 +40,18 @@ spark_system.start() return COMPONENT_BLOCK_TELEPORT +/// Signal for COMSIG_MOB_PRE_JAUNT that prevents a user from entering a jaunt. +/obj/item/implant/teleport_blocker/proc/on_jaunt(mob/living/jaunter) + SIGNAL_HANDLER + + to_chat(jaunter, span_holoparasite("As you attempt to jaunt, you slam directly into the barrier between realities and are sent crashing back into corporeality!")) + + jaunter.apply_status_effect(/datum/status_effect/incapacitating/paralyzed, 5 SECONDS) + var/datum/effect_system/spark_spread/quantum/spark_system = new() + spark_system.set_up(5, TRUE, jaunter) + spark_system.start() + return COMPONENT_BLOCK_JAUNT + /obj/item/implantcase/teleport_blocker name = "implant case - 'Bluespace Grounding'" desc = "A glass case containing a bluespace grounding implant." diff --git a/code/game/objects/items/implants/security/implant_track.dm b/code/game/objects/items/implants/security/implant_track.dm index b95c0afa7d857..9b8050d7dade2 100644 --- a/code/game/objects/items/implants/security/implant_track.dm +++ b/code/game/objects/items/implants/security/implant_track.dm @@ -48,7 +48,7 @@ return if(params["implant_action"] == "warn") - var/warning = tgui_input_text(user, "What warning do you want to send to [imp_in.name]?", "Messaging") + var/warning = tgui_input_text(user, "What warning do you want to send to [imp_in.name]?", "Messaging", max_length = MAX_MESSAGE_LEN) if(!warning || QDELETED(src) || QDELETED(user) || QDELETED(console) || isnull(imp_in)) return TRUE if(!console.is_operational || !user.can_perform_action(console, NEED_DEXTERITY|ALLOW_SILICON_REACH)) diff --git a/code/game/objects/items/lighter.dm b/code/game/objects/items/lighter.dm new file mode 100644 index 0000000000000..a0613450b28d6 --- /dev/null +++ b/code/game/objects/items/lighter.dm @@ -0,0 +1,362 @@ +/obj/item/lighter + name = "\improper Zippo lighter" + desc = "The zippo." + icon = 'icons/obj/cigarettes.dmi' + icon_state = "zippo" + inhand_icon_state = "zippo" + worn_icon_state = "lighter" + w_class = WEIGHT_CLASS_TINY + obj_flags = CONDUCTS_ELECTRICITY + slot_flags = ITEM_SLOT_BELT + resistance_flags = FIRE_PROOF + grind_results = list(/datum/reagent/iron = 1, /datum/reagent/fuel = 5, /datum/reagent/fuel/oil = 5) + custom_price = PAYCHECK_CREW * 1.1 + light_system = OVERLAY_LIGHT + light_range = 2 + light_power = 1.3 + light_color = LIGHT_COLOR_FIRE + light_on = FALSE + toolspeed = 1.5 + tool_behaviour = TOOL_WELDER + ///The amount of heat a lighter has while it's on. We're using the define to ensure lighters can't do things we don't want them to. + var/heat_while_on = HIGH_TEMPERATURE_REQUIRED - 100 + ///The amount of time the lighter has been on for, for fuel consumption. + var/burned_fuel_for = 0 + ///The max amount of fuel the lighter can hold. + var/maximum_fuel = 6 + /// Whether the lighter is lit. + var/lit = FALSE + /// Whether the lighter is fancy. Fancy lighters have fancier flavortext and won't burn thumbs. + var/fancy = TRUE + /// The engraving overlay used by this lighter. + var/overlay_state + /// A list of possible engraving overlays. + var/list/overlay_list = list( + "plain", + "dame", + "thirteen", + "snake", + ) + +/obj/item/lighter/Initialize(mapload) + . = ..() + create_reagents(maximum_fuel, REFILLABLE | DRAINABLE) + reagents.add_reagent(/datum/reagent/fuel, maximum_fuel) + if(!overlay_state) + overlay_state = pick(overlay_list) + AddComponent(\ + /datum/component/bullet_intercepting,\ + block_chance = 0.5,\ + active_slots = ITEM_SLOT_SUITSTORE,\ + on_intercepted = CALLBACK(src, PROC_REF(on_intercepted_bullet)),\ + ) + update_appearance() + +/// Destroy the lighter when it's shot by a bullet +/obj/item/lighter/proc/on_intercepted_bullet(mob/living/victim, obj/projectile/bullet) + victim.visible_message(span_warning("\The [bullet] shatters on [victim]'s lighter!")) + playsound(victim, SFX_RICOCHET, 100, TRUE) + new /obj/effect/decal/cleanable/oil(get_turf(src)) + do_sparks(1, TRUE, src) + victim.dropItemToGround(src, force = TRUE, silent = TRUE) + qdel(src) + +/obj/item/lighter/cyborg_unequip(mob/user) + if(!lit) + return + set_lit(FALSE) + +/obj/item/lighter/suicide_act(mob/living/carbon/user) + if (lit) + user.visible_message(span_suicide("[user] begins holding \the [src]'s flame up to [user.p_their()] face! It looks like [user.p_theyre()] trying to commit suicide!")) + playsound(src, 'sound/items/welder.ogg', 50, TRUE) + return FIRELOSS + else + user.visible_message(span_suicide("[user] begins whacking [user.p_them()]self with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")) + return BRUTELOSS + +/obj/item/lighter/update_icon_state() + icon_state = "[initial(icon_state)][lit ? "-on" : ""]" + return ..() + +/obj/item/lighter/update_overlays() + . = ..() + . += create_lighter_overlay() + +/// Generates an overlay used by this lighter. +/obj/item/lighter/proc/create_lighter_overlay() + return mutable_appearance(icon, "lighter_overlay_[overlay_state][lit ? "-on" : ""]") + +/obj/item/lighter/ignition_effect(atom/A, mob/user) + if(get_temperature()) + . = span_infoplain(span_rose("With a single flick of [user.p_their()] wrist, [user] smoothly lights [A] with [src]. Damn [user.p_theyre()] cool.")) + +/obj/item/lighter/proc/set_lit(new_lit) + if(lit == new_lit) + return + + lit = new_lit + if(lit) + force = 5 + damtype = BURN + hitsound = 'sound/items/welder.ogg' + attack_verb_continuous = string_list(list("burns", "singes")) + attack_verb_simple = string_list(list("burn", "singe")) + heat = heat_while_on + START_PROCESSING(SSobj, src) + if(fancy) + playsound(src.loc , 'sound/items/zippo_on.ogg', 100, 1) + else + playsound(src.loc, 'sound/items/lighter_on.ogg', 100, 1) + if(isliving(loc)) + var/mob/living/male_model = loc + if(male_model.fire_stacks && !(male_model.on_fire)) + male_model.ignite_mob() + else + hitsound = SFX_SWING_HIT + force = 0 + heat = 0 + attack_verb_continuous = null //human_defense.dm takes care of it + attack_verb_simple = null + STOP_PROCESSING(SSobj, src) + if(fancy) + playsound(src.loc , 'sound/items/zippo_off.ogg', 100, 1) + else + playsound(src.loc , 'sound/items/lighter_off.ogg', 100, 1) + set_light_on(lit) + update_appearance() + +/obj/item/lighter/extinguish() + . = ..() + set_lit(FALSE) + +/obj/item/lighter/attack_self(mob/living/user) + if(!user.is_holding(src)) + return ..() + if(lit) + set_lit(FALSE) + if(fancy) + user.visible_message( + span_notice("You hear a quiet click, as [user] shuts off [src] without even looking at what [user.p_theyre()] doing. Wow."), + span_notice("You quietly shut off [src] without even looking at what you're doing. Wow.") + ) + else + user.visible_message( + span_notice("[user] quietly shuts off [src]."), + span_notice("You quietly shut off [src].") + ) + return + + if(get_fuel() <= 0) + return + + set_lit(TRUE) + + if(fancy) + user.visible_message( + span_notice("Without even breaking stride, [user] flips open and lights [src] in one smooth movement."), + span_notice("Without even breaking stride, you flip open and light [src] in one smooth movement.") + ) + return + + var/hand_protected = FALSE + var/mob/living/carbon/human/human_user = user + if(!istype(human_user) || HAS_TRAIT(human_user, TRAIT_RESISTHEAT) || HAS_TRAIT(human_user, TRAIT_RESISTHEATHANDS)) + hand_protected = TRUE + else if(!istype(human_user.gloves, /obj/item/clothing/gloves)) + hand_protected = FALSE + else + var/obj/item/clothing/gloves/gloves = human_user.gloves + if(gloves.max_heat_protection_temperature) + hand_protected = (gloves.max_heat_protection_temperature > 360) + + if(hand_protected || prob(75)) + user.visible_message( + span_notice("After a few attempts, [user] manages to light [src]."), + span_notice("After a few attempts, you manage to light [src].") + ) + return + + var/hitzone = user.held_index_to_dir(user.active_hand_index) == "r" ? BODY_ZONE_PRECISE_R_HAND : BODY_ZONE_PRECISE_L_HAND + user.apply_damage(5, BURN, hitzone) + user.visible_message( + span_warning("After a few attempts, [user] manages to light [src] - however, [user.p_they()] burn[user.p_s()] [user.p_their()] finger in the process."), + span_warning("You burn yourself while lighting the lighter!") + ) + user.add_mood_event("burnt_thumb", /datum/mood_event/burnt_thumb) + +/obj/item/lighter/attack(mob/living/target_mob, mob/living/user, params) + if(lit) + use(0.5) + if(target_mob.ignite_mob()) + message_admins("[ADMIN_LOOKUPFLW(user)] set [key_name_admin(target_mob)] on fire with [src] at [AREACOORD(user)]") + log_game("[key_name(user)] set [key_name(target_mob)] on fire with [src] at [AREACOORD(user)]") + var/obj/item/cigarette/cig = help_light_cig(target_mob) + if(!lit || !cig || user.combat_mode) + return ..() + + if(cig.lit) + to_chat(user, span_warning("The [cig.name] is already lit!")) + if(target_mob == user) + cig.attackby(src, user) + return + + if(fancy) + cig.light(span_rose("[user] whips the [name] out and holds it for [target_mob]. [user.p_Their()] arm is as steady as the unflickering flame [user.p_they()] light[user.p_s()] \the [cig] with.")) + else + cig.light(span_notice("[user] holds the [name] out for [target_mob], and lights [target_mob.p_their()] [cig.name].")) + +///Checks if the lighter is able to perform a welding task. +/obj/item/lighter/tool_use_check(mob/living/user, amount, heat_required) + if(!lit) + to_chat(user, span_warning("[src] has to be on to complete this task!")) + return FALSE + if(get_fuel() < amount) + to_chat(user, span_warning("You need more welding fuel to complete this task!")) + return FALSE + if(heat < heat_required) + return FALSE + return TRUE + +/obj/item/lighter/process(seconds_per_tick) + if(lit) + burned_fuel_for += seconds_per_tick + if(burned_fuel_for >= TOOL_FUEL_BURN_INTERVAL) + use(used = 0.25) + + open_flame(heat) + +/obj/item/lighter/get_temperature() + return lit * heat + +/// Uses fuel from the lighter. +/obj/item/lighter/use(used = 0) + if(!lit) + return FALSE + + if(used > 0) + burned_fuel_for = 0 + + if(get_fuel() >= used) + reagents.remove_reagent(/datum/reagent/fuel, used) + if(get_fuel() <= 0) + set_lit(FALSE) + return TRUE + return FALSE + +///Returns the amount of fuel +/obj/item/lighter/proc/get_fuel() + return reagents.get_reagent_amount(/datum/reagent/fuel) + +/obj/item/lighter/greyscale + name = "cheap lighter" + desc = "A cheap lighter." + icon_state = "lighter" + maximum_fuel = 3 + fancy = FALSE + overlay_list = list( + "transp", + "tall", + "matte", + "zoppo", //u cant stoppo th zoppo + ) + + /// The color of the lighter. + var/lighter_color + /// The set of colors this lighter can be autoset as on init. + var/static/list/color_list = list( //Same 16 color selection as electronic assemblies + COLOR_ASSEMBLY_BLACK, + COLOR_FLOORTILE_GRAY, + COLOR_ASSEMBLY_BGRAY, + COLOR_ASSEMBLY_WHITE, + COLOR_ASSEMBLY_RED, + COLOR_ASSEMBLY_ORANGE, + COLOR_ASSEMBLY_BEIGE, + COLOR_ASSEMBLY_BROWN, + COLOR_ASSEMBLY_GOLD, + COLOR_ASSEMBLY_YELLOW, + COLOR_ASSEMBLY_GURKHA, + COLOR_ASSEMBLY_LGREEN, + COLOR_ASSEMBLY_GREEN, + COLOR_ASSEMBLY_LBLUE, + COLOR_ASSEMBLY_BLUE, + COLOR_ASSEMBLY_PURPLE + ) + +/obj/item/lighter/greyscale/Initialize(mapload) + . = ..() + if(!lighter_color) + lighter_color = pick(color_list) + update_appearance() + +/obj/item/lighter/greyscale/create_lighter_overlay() + var/mutable_appearance/lighter_overlay = ..() + lighter_overlay.color = lighter_color + return lighter_overlay + +/obj/item/lighter/greyscale/ignition_effect(atom/A, mob/user) + if(get_temperature()) + . = span_notice("After some fiddling, [user] manages to light [A] with [src].") + + +/obj/item/lighter/slime + name = "slime zippo" + desc = "A specialty zippo made from slimes and industry. Has a much hotter flame than normal." + icon_state = "slighter" + heat_while_on = parent_type::heat_while_on + 1000 //Blue flame is hotter, this means this does act as a welding tool. + light_color = LIGHT_COLOR_CYAN + overlay_state = "slime" + grind_results = list(/datum/reagent/iron = 1, /datum/reagent/fuel = 5, /datum/reagent/medicine/pyroxadone = 5) + +/obj/item/lighter/skull + name = "badass zippo" + desc = "An absolutely badass zippo lighter. Just look at that skull!" + overlay_state = "skull" + +/obj/item/lighter/mime + name = "pale zippo" + desc = "In lieu of fuel, performative spirit can be used to light cigarettes." + icon_state = "mlighter" //These ones don't show a flame. + light_color = LIGHT_COLOR_HALOGEN + heat_while_on = 0 //I swear it's a real lighter dude you just can't see the flame dude I promise + overlay_state = "mime" + grind_results = list(/datum/reagent/iron = 1, /datum/reagent/toxin/mutetoxin = 5, /datum/reagent/consumable/nothing = 10) + light_range = 0 + light_power = 0 + fancy = FALSE + +/obj/item/lighter/mime/ignition_effect(atom/A, mob/user) + . = span_infoplain("[user] lifts the [name] to the [A], which miraculously lights!") + +/obj/item/lighter/bright + name = "illuminative zippo" + desc = "Sustains an incredibly bright chemical reaction when you spark it. Avoid looking directly at the igniter when lit." + icon_state = "slighter" + light_color = LIGHT_COLOR_ELECTRIC_CYAN + overlay_state = "bright" + grind_results = list(/datum/reagent/iron = 1, /datum/reagent/flash_powder = 10) + light_range = 8 + light_power = 3 //Irritatingly bright and large enough to cover a small room. + fancy = FALSE + +/obj/item/lighter/bright/examine(mob/user) + . = ..() + + if(lit && isliving(user)) + var/mob/living/current_viewer = user + current_viewer.flash_act(4) + +/obj/item/lighter/bright/ignition_effect(atom/A, mob/user) + if(get_temperature()) + . = span_infoplain(span_rose("[user] lifts the [src] to the [A], igniting it with a brilliant flash of light!")) + var/mob/living/current_viewer = user + current_viewer.flash_act(4) + +/obj/effect/spawner/random/special_lighter + name = "special lighter spawner" + icon_state = "lighter" + loot = list( + /obj/item/lighter/skull, + /obj/item/lighter/mime, + /obj/item/lighter/bright, + ) diff --git a/code/game/objects/items/machine_wand.dm b/code/game/objects/items/machine_wand.dm index 75c765730f78b..7d8b4a0697d67 100644 --- a/code/game/objects/items/machine_wand.dm +++ b/code/game/objects/items/machine_wand.dm @@ -85,10 +85,12 @@ remove_old_machine() return CLICK_ACTION_SUCCESS -/obj/item/machine_remote/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) - return interact_with_atom(interacting_with, user, modifiers) - /obj/item/machine_remote/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(HAS_TRAIT(interacting_with, TRAIT_COMBAT_MODE_SKIP_INTERACTION) || (!ismachinery(interacting_with) && !isbot(interacting_with))) + return NONE + return ranged_interact_with_atom(interacting_with, user, modifiers) + +/obj/item/machine_remote/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!COOLDOWN_FINISHED(src, timeout_time)) playsound(src, 'sound/machines/synth_no.ogg', 30 , TRUE) say("Remote control disabled temporarily. Please try again soon.") diff --git a/code/game/objects/items/mail.dm b/code/game/objects/items/mail.dm index 2aec478162445..26cefd6eeedbd 100644 --- a/code/game/objects/items/mail.dm +++ b/code/game/objects/items/mail.dm @@ -548,10 +548,10 @@ shady_mail.made_by_cached_name = user.mind.name if(index == 1) - var/mail_name = tgui_input_text(user, "Enter mail title, or leave it blank", "Mail Counterfeiting") + var/mail_name = tgui_input_text(user, "Enter mail title, or leave it blank", "Mail Counterfeiting", max_length = MAX_LABEL_LEN) if(!(src in user.contents)) return FALSE - if(reject_bad_text(mail_name, ascii_only = FALSE)) + if(reject_bad_text(mail_name, max_length = MAX_LABEL_LEN, ascii_only = FALSE)) shady_mail.name = mail_name else shady_mail.name = mail_type diff --git a/code/game/objects/items/melee/baton.dm b/code/game/objects/items/melee/baton.dm index 8c1ae33c4c70e..0fd63321519c0 100644 --- a/code/game/objects/items/melee/baton.dm +++ b/code/game/objects/items/melee/baton.dm @@ -479,7 +479,6 @@ else cell = new preload_cell_type(src) RegisterSignal(src, COMSIG_ATOM_ATTACKBY, PROC_REF(convert)) - RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) update_appearance() /obj/item/melee/baton/security/get_cell() @@ -514,13 +513,14 @@ qdel(item) qdel(src) -/obj/item/melee/baton/security/proc/on_saboteur(datum/source, disrupt_duration) - SIGNAL_HANDLER +/obj/item/melee/baton/security/on_saboteur(datum/source, disrupt_duration) + . = ..() if(!active) return turn_off() update_appearance() - return COMSIG_SABOTEUR_SUCCESS + return TRUE + /obj/item/melee/baton/security/Exited(atom/movable/mov_content) . = ..() if(mov_content == cell) diff --git a/code/game/objects/items/rcd/RCD.dm b/code/game/objects/items/rcd/RCD.dm index 5bd0b4c9d39b8..279bc91d622c5 100644 --- a/code/game/objects/items/rcd/RCD.dm +++ b/code/game/objects/items/rcd/RCD.dm @@ -126,7 +126,7 @@ var/atom/movable/rcd_structure = rcd_results["[RCD_DESIGN_PATH]"] /** *For anything that does not go an a wall we have to make sure that turf is clear for us to put the structure on it - *If we are just trying to destory something then this check is not nessassary + *If we are just trying to destroy something then this check is not necessary *RCD_WALLFRAME is also returned as the rcd_mode when upgrading apc, airalarm, firealarm using simple circuits upgrade */ if(rcd_mode != RCD_WALLFRAME && rcd_mode != RCD_DECONSTRUCT) @@ -142,7 +142,7 @@ structures_to_ignore = list(/obj/structure/grille) else //when building directional windows we ignore the grill and other directional windows structures_to_ignore = list(/obj/structure/grille, /obj/structure/window) - else //for directional windows we ignore other directional windows as they can be in diffrent directions on the turf. + else //for directional windows we ignore other directional windows as they can be in different directions on the turf. structures_to_ignore = list(/obj/structure/window) //check if we can build our window on the grill @@ -152,7 +152,7 @@ return FALSE /** - * if we are trying to create plating on turf which is not a proper floor then dont check for objects on top of the turf just allow that turf to be converted into plating. e.g. create plating beneath a player or underneath a machine frame/any dense object + * if we are trying to create plating on turf which is not a proper floor then don't check for objects on top of the turf just allow that turf to be converted into plating. e.g. create plating beneath a player or underneath a machine frame/any dense object * if we are trying to finish a wall girder then let it finish then make sure no one/nothing is stuck in the girder */ else if(rcd_mode == RCD_TURF && rcd_structure == /turf/open/floor/plating/rcd && (!istype(target_turf, /turf/open/floor) || istype(target, /obj/structure/girder))) @@ -184,10 +184,10 @@ ignored_types = list(/obj/structure/window) //if we are trying to create grills/windoors we can go ahead and further ignore other windoors on the turf if(rcd_mode == RCD_WINDOWGRILLE || (rcd_mode == RCD_AIRLOCK && ispath(rcd_structure, /obj/machinery/door/window))) - //only ignore mobs if we are trying to create windoors and not grills. We dont want to drop a grill on top of somebody + //only ignore mobs if we are trying to create windoors and not grills. We don't want to drop a grill on top of somebody ignore_mobs = rcd_mode == RCD_AIRLOCK ignored_types += /obj/machinery/door/window - //if we are trying to create full airlock doors then we do the regular checks and make sure we have the full space for them. i.e. dont ignore anything dense on the turf + //if we are trying to create full airlock doors then we do the regular checks and make sure we have the full space for them. i.e. don't ignore anything dense on the turf else if(rcd_mode == RCD_AIRLOCK) ignored_types = list() @@ -207,15 +207,15 @@ * * [mob][user]- the user building this structure */ /obj/item/construction/rcd/proc/rcd_create(atom/target, mob/user) - //straight up cant touch this + var/list/rcd_results = target.rcd_vals(user, src) // does this atom allow for rcd actions? + if(!rcd_results) // nope + return NONE + + //straight up can't touch this if(mode == RCD_DECONSTRUCT && (target.resistance_flags & INDESTRUCTIBLE)) balloon_alert(user, "too durable!") - return + return ITEM_INTERACT_BLOCKING - //does this atom allow for rcd actions? - var/list/rcd_results = target.rcd_vals(user, src) - if(!rcd_results) - return FALSE rcd_results["[RCD_DESIGN_MODE]"] = mode rcd_results["[RCD_DESIGN_PATH]"] = rcd_design_path @@ -237,6 +237,7 @@ log_tool("[key_name(user)] used [src] to [rcd_results["[RCD_DESIGN_MODE]"] != RCD_DECONSTRUCT ? "construct [initial(design_path.name)]([design_path])" : "deconstruct [target_name]([target_path])"] at [location]") current_active_effects -= 1 + return ITEM_INTERACT_SUCCESS /** * Internal proc which creates the rcd effects & creates the structure @@ -368,10 +369,10 @@ * The advantage of organizing designs into categories is that * You can ignore an complete category if the design disk upgrade for that category isn't installed. */ - //You can't select designs from the Machines category if you dont have the frames upgrade installed. + //You can't select designs from the Machines category if you don't have the frames upgrade installed. if(category == "Machines" && !(upgrade & RCD_UPGRADE_FRAMES)) return TRUE - //You can't select designs from the Furniture category if you dont have the furnishing upgrade installed. + //You can't select designs from the Furniture category if you don't have the furnishing upgrade installed. if(category == "Furniture" && !(upgrade & RCD_UPGRADE_FURNISHING)) return TRUE @@ -401,29 +402,25 @@ return . mode = construction_mode - rcd_create(interacting_with, user) - return ITEM_INTERACT_SUCCESS + return rcd_create(interacting_with, user) /obj/item/construction/rcd/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!ranged || !range_check(interacting_with, user)) return ITEM_INTERACT_BLOCKING mode = construction_mode - rcd_create(interacting_with, user) - return ITEM_INTERACT_SUCCESS + return rcd_create(interacting_with, user) /obj/item/construction/rcd/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) mode = RCD_DECONSTRUCT - rcd_create(interacting_with, user) - return ITEM_INTERACT_SUCCESS + return rcd_create(interacting_with, user) /obj/item/construction/rcd/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) if(!ranged || !range_check(interacting_with, user)) return ITEM_INTERACT_BLOCKING mode = RCD_DECONSTRUCT - rcd_create(interacting_with, user) - return ITEM_INTERACT_SUCCESS + return rcd_create(interacting_with, user) /obj/item/construction/rcd/handle_openspace_click(turf/target, mob/user, list/modifiers) interact_with_atom(target, user, modifiers) diff --git a/code/game/objects/items/rcd/RHD.dm b/code/game/objects/items/rcd/RHD.dm index a212274ce46be..8007fac4dd4c7 100644 --- a/code/game/objects/items/rcd/RHD.dm +++ b/code/game/objects/items/rcd/RHD.dm @@ -71,7 +71,7 @@ return silo_mats.mat_container.get_material_amount(/datum/material/iron) / SILO_USE_AMOUNT return 0 -///returns local matter units available. overriden by rcd borg to return power units available +///returns local matter units available. overridden by rcd borg to return power units available /obj/item/construction/proc/get_matter(mob/user) return matter diff --git a/code/game/objects/items/religion.dm b/code/game/objects/items/religion.dm index 232de4c461930..77b087b8ac53d 100644 --- a/code/game/objects/items/religion.dm +++ b/code/game/objects/items/religion.dm @@ -343,10 +343,12 @@ var/staffcooldown = 0 var/staffwait = 30 -/obj/item/godstaff/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) - return interact_with_atom(interacting_with, user, modifiers) - /obj/item/godstaff/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(SHOULD_SKIP_INTERACTION(interacting_with, src, user)) + return NONE + return ranged_interact_with_atom(interacting_with, user, modifiers) + +/obj/item/godstaff/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(staffcooldown + staffwait > world.time) return ITEM_INTERACT_BLOCKING diff --git a/code/game/objects/items/robot/ai_upgrades.dm b/code/game/objects/items/robot/ai_upgrades.dm index f6357b229efb9..b630a3b8a4231 100644 --- a/code/game/objects/items/robot/ai_upgrades.dm +++ b/code/game/objects/items/robot/ai_upgrades.dm @@ -1,4 +1,45 @@ ///AI Upgrades +/obj/item/aiupgrade + name = "ai upgrade disk" + desc = "You really shouldn't be seeing this" + icon = 'icons/obj/devices/circuitry_n_data.dmi' + icon_state = "datadisk3" + ///The upgrade that will be applied to the AI when installed + var/datum/ai_module/to_gift = /datum/ai_module + +/obj/item/aiupgrade/pre_attack(atom/target, mob/living/user, proximity) + if(!proximity) + return ..() + if(!isAI(target)) + return ..() + var/mob/living/silicon/ai/AI = target + var/datum/action/innate/ai/action = locate(to_gift.power_type) in AI.actions + var/datum/ai_module/gifted_ability = new to_gift + if(!to_gift.upgrade) + if(!action) + var/ability = to_gift.power_type + var/datum/action/gifted_action = new ability + gifted_action.Grant(AI) + else if(gifted_ability.one_purchase) + to_chat(user, "[AI] already has an [src] installed!") + return + else + action.uses += initial(action.uses) + action.desc = "[initial(action.desc)] It has [action.uses] use\s remaining." + action.build_all_button_icons() + else + if(!action) + gifted_ability.upgrade(AI) + if(gifted_ability.unlock_text) + to_chat(AI, gifted_ability.unlock_text) + if(gifted_ability.unlock_sound) + AI.playsound_local(AI, gifted_ability.unlock_sound, 50, 0) + update_static_data(AI) + to_chat(user, span_notice("You install [src], upgrading [AI].")) + to_chat(AI, span_userdanger("[user] has upgraded you with [src]!")) + user.log_message("has upgraded [key_name(AI)] with a [src].", LOG_GAME) + qdel(src) + return TRUE //Malf Picker @@ -34,28 +75,21 @@ //Lipreading -/obj/item/surveillance_upgrade +/obj/item/aiupgrade/surveillance_upgrade name = "surveillance software upgrade" desc = "An illegal software package that will allow an artificial intelligence to 'hear' from its cameras via lip reading and hidden microphones." - icon = 'icons/obj/devices/circuitry_n_data.dmi' - icon_state = "datadisk3" + to_gift = /datum/ai_module/malf/upgrade/eavesdrop -/obj/item/surveillance_upgrade/Initialize(mapload) +/obj/item/aiupgrade/surveillance_upgrade/Initialize(mapload) . = ..() ADD_TRAIT(src, TRAIT_CONTRABAND, INNATE_TRAIT) -/obj/item/surveillance_upgrade/pre_attack(atom/A, mob/living/user, proximity) - if(!proximity) - return ..() - if(!isAI(A)) - return ..() - var/mob/living/silicon/ai/AI = A - if(AI.eyeobj) - AI.eyeobj.relay_speech = TRUE - to_chat(AI, span_userdanger("[user] has upgraded you with surveillance software!")) - to_chat(AI, "Via a combination of hidden microphones and lip reading software, you are able to use your cameras to listen in on conversations.") - to_chat(user, span_notice("You upgrade [AI]. [src] is consumed in the process.")) - user.log_message("has upgraded [key_name(AI)] with a [src].", LOG_GAME) - message_admins("[ADMIN_LOOKUPFLW(user)] has upgraded [ADMIN_LOOKUPFLW(AI)] with a [src].") - qdel(src) - return TRUE + +/obj/item/aiupgrade/power_transfer + name = "power transfer upgrade" + desc = "A legal upgrade that allows an artificial intelligence to directly provide power to APCs from a distance" + to_gift = /datum/ai_module/power_apc + + + + diff --git a/code/game/objects/items/spear.dm b/code/game/objects/items/spear.dm index 53e307e31d6e0..f0548fa66f404 100644 --- a/code/game/objects/items/spear.dm +++ b/code/game/objects/items/spear.dm @@ -177,10 +177,8 @@ return if(target.resistance_flags & INDESTRUCTIBLE) //due to the lich incident of 2021, embedding grenades inside of indestructible structures is forbidden return - if(ismob(target)) - var/mob/mob_target = target - if(mob_target.status_flags & GODMODE) //no embedding grenade phylacteries inside of ghost poly either - return + if(HAS_TRAIT(target, TRAIT_GODMODE)) + return if(iseffect(target)) //and no accidentally wasting your moment of glory on graffiti return user.say("[war_cry]", forced="spear warcry") diff --git a/code/game/objects/items/stacks/sheets/sheets.dm b/code/game/objects/items/stacks/sheets/sheets.dm index 568fd2f49aa29..110713d343612 100644 --- a/code/game/objects/items/stacks/sheets/sheets.dm +++ b/code/game/objects/items/stacks/sheets/sheets.dm @@ -63,7 +63,7 @@ * Facilitates sheets being smacked on the floor * * This is used for crafting by hitting the floor with items. - * The inital use case is glass sheets breaking in to shards when the floor is hit. + * The initial use case is glass sheets breaking in to shards when the floor is hit. * Args: * * user: The user that did the action * * params: paramas passed in from attackby diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 5eb651b2905d4..e2a8e10c4df49 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -177,7 +177,7 @@ /** * use available_amount of sheets/pieces, return TRUE only if all sheets/pieces of this stack were used * we don't delete this stack when it reaches 0 because we expect the all in one grinder, etc to delete - * this stack if grinding was successfull + * this stack if grinding was successful */ use(available_amount, check = FALSE) return available_amount == current_amount @@ -546,7 +546,7 @@ update_weight() return TRUE -/obj/item/stack/tool_use_check(mob/living/user, amount) +/obj/item/stack/tool_use_check(mob/living/user, amount, heat_required) if(get_amount() < amount) // general balloon alert that says they don't have enough user.balloon_alert(user, "not enough material!") diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm index 4b89719998c8f..b4855c52fae35 100644 --- a/code/game/objects/items/stacks/tiles/tile_types.dm +++ b/code/game/objects/items/stacks/tiles/tile_types.dm @@ -68,7 +68,7 @@ * Place our tile on a plating, or replace it. * * Arguments: - * * target_plating - Instance of the plating we want to place on. Replaced during sucessful executions. + * * target_plating - Instance of the plating we want to place on. Replaced during successful executions. * * user - The mob doing the placing. */ /obj/item/stack/tile/proc/place_tile(turf/open/floor/plating/target_plating, mob/user) @@ -1259,7 +1259,7 @@ inhand_icon_state = "tile-catwalk" mats_per_unit = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT) turf_type = /turf/open/floor/catwalk_floor - merge_type = /obj/item/stack/tile/catwalk_tile //Just to be cleaner, these all stack with eachother + merge_type = /obj/item/stack/tile/catwalk_tile //Just to be cleaner, these all stack with each other tile_reskin_types = list( /obj/item/stack/tile/catwalk_tile, /obj/item/stack/tile/catwalk_tile/iron, diff --git a/code/game/objects/items/stacks/wrap.dm b/code/game/objects/items/stacks/wrap.dm index d7fcd17f2950d..d1cbb7f1ce8a3 100644 --- a/code/game/objects/items/stacks/wrap.dm +++ b/code/game/objects/items/stacks/wrap.dm @@ -102,13 +102,6 @@ /obj/item/delivery/can_be_package_wrapped() return FALSE -/obj/item/stack/package_wrap/storage_insert_on_interaction(datum/storage, atom/storage_holder, mob/user) - if(isitem(storage_holder)) - // Don't insert if the target can be wrapped - var/obj/item/item = storage_holder - return !item.can_be_package_wrapped() - return TRUE - /obj/item/stack/package_wrap/interact_with_atom(obj/interacting_with, mob/living/user, list/modifiers) if(!isobj(interacting_with)) return NONE @@ -118,6 +111,8 @@ if(isitem(interacting_with)) var/obj/item/item = interacting_with if(!item.can_be_package_wrapped()) + if(SHOULD_SKIP_INTERACTION(interacting_with, src, user)) + return NONE // put it in the bag instead of yelling balloon_alert(user, "can't be wrapped!") return ITEM_INTERACT_BLOCKING if(user.is_holding(item)) diff --git a/code/game/objects/items/stickers.dm b/code/game/objects/items/stickers.dm index 447e202247367..9924749379573 100644 --- a/code/game/objects/items/stickers.dm +++ b/code/game/objects/items/stickers.dm @@ -25,7 +25,7 @@ throw_range = 3 pressure_resistance = 0 - item_flags = NOBLUDGEON | XENOMORPH_HOLDABLE //funny ~Jimmyl + item_flags = NOBLUDGEON w_class = WEIGHT_CLASS_TINY /// `list` or `null`, contains possible alternate `icon_states`. diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm index 269a6699d3e1c..095250fdcca52 100644 --- a/code/game/objects/items/storage/bags.dm +++ b/code/game/objects/items/storage/bags.dm @@ -155,13 +155,13 @@ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED) listeningTo = null -/obj/item/storage/bag/ore/storage_insert_on_interacted_with(datum/storage, obj/item/inserted, mob/living/user) - if(istype(inserted, /obj/item/boulder)) - to_chat(user, span_warning("You can't fit [inserted] into [src]. \ +/obj/item/storage/bag/ore/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(istype(tool, /obj/item/boulder)) + to_chat(user, span_warning("You can't fit [tool] into [src]. \ Perhaps you should break it down first, or find an ore box.")) - return FALSE + return ITEM_INTERACT_BLOCKING - return TRUE + return NONE /obj/item/storage/bag/ore/proc/pickup_ores(mob/living/user) SIGNAL_HANDLER @@ -274,8 +274,6 @@ . += span_notice("Ctrl-click to activate seed extraction.") /obj/item/storage/bag/plants/portaseeder/item_ctrl_click(mob/user) - if(user.incapacitated) - return for(var/obj/item/plant in contents) seedify(plant, 1) return CLICK_ACTION_SUCCESS @@ -577,7 +575,7 @@ new /obj/item/ammo_casing/harpoon(src) /obj/item/storage/bag/rebar_quiver - name = "Rebar Storage Quiver" + name = "rebar quiver" icon = 'icons/obj/weapons/bows/quivers.dmi' icon_state = "rebar_quiver" worn_icon_state = "rebar_quiver" @@ -607,7 +605,7 @@ desc = "A specialized quiver meant to hold any kind of bolts intended for use with the rebar crossbow. \ Clearly a better design than a cut up oxygen tank..." slot_flags = ITEM_SLOT_NECK - w_class = WEIGHT_CLASS_SMALL + w_class = WEIGHT_CLASS_NORMAL resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF actions_types = list(/datum/action/item_action/reload_rebar) @@ -649,7 +647,7 @@ if(held_crossbow.magazine.contents.len >= held_crossbow.magazine.max_ammo) user.balloon_alert(user, "no more room!") return - if(!do_after(user, 0.8 SECONDS, user, IGNORE_USER_LOC_CHANGE)) + if(!do_after(user, 1.2 SECONDS, user)) return var/obj/item/ammo_casing/rebar/ammo_to_load = contents[1] diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm index 5386718d94718..40d35a334d08f 100644 --- a/code/game/objects/items/storage/belt.dm +++ b/code/game/objects/items/storage/belt.dm @@ -515,6 +515,7 @@ . = ..() atom_storage.max_slots = 1 atom_storage.set_holdable(/obj/item/clothing/mask/luchador) + AddComponent(/datum/component/adjust_fishing_difficulty, -2) /obj/item/storage/belt/military name = "chest rig" diff --git a/code/game/objects/items/storage/boxes/food_boxes.dm b/code/game/objects/items/storage/boxes/food_boxes.dm index 86d59123c72aa..bac558ce3be78 100644 --- a/code/game/objects/items/storage/boxes/food_boxes.dm +++ b/code/game/objects/items/storage/boxes/food_boxes.dm @@ -301,7 +301,7 @@ new /obj/item/food/fishmeat/armorfish(src) new /obj/item/food/fishmeat/carp(src) new /obj/item/food/fishmeat/moonfish(src) - new /obj/item/food/fishmeat/gunner_jellyfish(src) + new /obj/item/food/fishmeat/gunner_jellyfish/supply(src) /obj/item/storage/box/ingredients/salads theme_name = "salads" diff --git a/code/game/objects/items/storage/medkit.dm b/code/game/objects/items/storage/medkit.dm index 368ef9c0b406a..e5db3d75855ea 100644 --- a/code/game/objects/items/storage/medkit.dm +++ b/code/game/objects/items/storage/medkit.dm @@ -818,3 +818,8 @@ /obj/item/storage/test_tube_rack/update_icon_state() icon_state = "[base_icon_state][contents.len > 0 ? contents.len : null]" return ..() + +/obj/item/storage/test_tube_rack/full/PopulateContents() + for(var/i in 1 to atom_storage.max_slots) + new /obj/item/reagent_containers/cup/tube(src) + diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm index d2bb90e69e445..873b45210cdec 100644 --- a/code/game/objects/items/storage/toolbox.dm +++ b/code/game/objects/items/storage/toolbox.dm @@ -410,6 +410,7 @@ desc = "A bandana. It seems to have a little carp embroidered on the inside, as well as the kanji '魚'." icon_state = "snake_eater" inhand_icon_state = null + clothing_traits = list(TRAIT_FISH_EATER) /obj/item/clothing/head/costume/knight name = "fake medieval helmet" diff --git a/code/game/objects/items/taster.dm b/code/game/objects/items/taster.dm index 599b78971db11..cdd67ceae5654 100644 --- a/code/game/objects/items/taster.dm +++ b/code/game/objects/items/taster.dm @@ -16,4 +16,4 @@ else var/message = interacting_with.reagents.generate_taste_message(user, taste_sensitivity) to_chat(user, span_notice("[src] tastes [message] in [interacting_with].")) - return ITEM_INTERACT_SUCCESS + return user.combat_mode ? NONE : ITEM_INTERACT_SUCCESS diff --git a/code/game/objects/items/tcg/tcg.dm b/code/game/objects/items/tcg/tcg.dm index 23204b4809ff8..30650fcd69f7e 100644 --- a/code/game/objects/items/tcg/tcg.dm +++ b/code/game/objects/items/tcg/tcg.dm @@ -3,7 +3,7 @@ /obj/item/tcgcard name = "Coder" - desc = "Wow, a mint condition coder card! Better tell the Github all about this!" + desc = "Wow, a mint condition coder card! Better tell the GitHub all about this!" icon = DEFAULT_TCG_DMI_ICON icon_state = "runtime" w_class = WEIGHT_CLASS_TINY @@ -332,11 +332,11 @@ GLOBAL_LIST_EMPTY(tcgcard_radial_choices) /obj/item/cardpack name = "Trading Card Pack: Coder" - desc = "Contains six complete fuckups by the coders. Report this on github please!" + desc = "Contains six complete fuckups by the coders. Report this on GitHub please!" icon = 'icons/obj/toys/tcgmisc.dmi' icon_state = "error" w_class = WEIGHT_CLASS_TINY - custom_price = PAYCHECK_CREW * 0.75 //Price reduced from * 2 to * 0.75, this is planned as a temporary measure until card persistance is added. + custom_price = PAYCHECK_CREW * 0.75 //Price reduced from * 2 to * 0.75, this is planned as a temporary measure until card persistence is added. ///The card series to look in var/series = "MEME" ///Chance of the pack having a coin in it out of 10 @@ -351,7 +351,7 @@ GLOBAL_LIST_EMPTY(tcgcard_radial_choices) "epic" = 30, "legendary" = 5, "misprint" = 1) - ///The amount of cards to draw from the guarenteed rarity table + ///The amount of cards to draw from the guaranteed rarity table var/guaranteed_count = 1 ///The guaranteed rarity table, acts about the same as the rarity table. it can have as many or as few raritys as you'd like var/list/guar_rarity = list( @@ -434,7 +434,7 @@ GLOBAL_LIST_EMPTY(tcgcard_radial_choices) atom_storage.max_total_storage = 120 atom_storage.max_slots = 60 -///Returns a list of cards ids of card_cnt weighted by rarity from the pack's tables that have matching series, with gnt_cnt of the guarenteed table. +///Returns a list of cards ids of card_cnt weighted by rarity from the pack's tables that have matching series, with gnt_cnt of the guaranteed table. /obj/item/cardpack/proc/buildCardListWithRarity(card_cnt, rarity_cnt) var/list/toReturn = list() //You can always get at least one of some rarity @@ -453,7 +453,7 @@ GLOBAL_LIST_EMPTY(tcgcard_radial_choices) weight += rarity_table[chance] var/random = rand(weight) for(var/bracket in rarity_table) - //Steals blatently from pick_weight(), sorry buddy I need the index + //Steals blatantly from pick_weight(), sorry buddy I need the index random -= rarity_table[bracket] if(random <= 0) rarity = bracket @@ -469,12 +469,12 @@ GLOBAL_LIST_EMPTY(tcgcard_radial_choices) log_runtime("The index [rarity] of rarity_table does not exist in the global cache") return toReturn -//All of these values should be overriden by either a template or a card itself +//All of these values should be overridden by either a template or a card itself /datum/card ///Unique ID, for use in lookups and (eventually) for persistence. MAKE SURE THIS IS UNIQUE FOR EACH CARD IN AS SERIES, OR THE ENTIRE SYSTEM WILL BREAK, AND I WILL BE VERY DISAPPOINTED. var/id = "coder" var/name = "Coder" - var/desc = "Wow, a mint condition coder card! Better tell the Github all about this!" + var/desc = "Wow, a mint condition coder card! Better tell the GitHub all about this!" ///This handles any extra rules for the card, i.e. extra attributes, special effects, etc. If you've played any other card game, you know how this works. var/rules = "There are no rules here. There is no escape. No Recall or Intervention can work in this place." var/icon = DEFAULT_TCG_DMI diff --git a/code/game/objects/items/tcg/tcg_machines.dm b/code/game/objects/items/tcg/tcg_machines.dm index 77b6891e4c17a..7a55e2e9554f7 100644 --- a/code/game/objects/items/tcg/tcg_machines.dm +++ b/code/game/objects/items/tcg/tcg_machines.dm @@ -90,7 +90,7 @@ GLOBAL_LIST_EMPTY(tcgcard_machine_radial_choices) /obj/machinery/trading_card_holder/attack_hand_secondary(mob/user) if(isnull(current_summon)) - var/card_name = tgui_input_text(user, "Insert card name", "Blank Card Naming", "blank card", MAX_NAME_LEN) + var/card_name = tgui_input_text(user, "Insert card name", "Blank Card Naming", "blank card", max_length = MAX_NAME_LEN) if(isnull(card_name) || !user.can_perform_action(src)) return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN current_summon = new /obj/structure/trading_card_summon/blank(locate(x + summon_offset_x, y + summon_offset_y, z)) diff --git a/code/game/objects/items/theft_tools.dm b/code/game/objects/items/theft_tools.dm index e13251fe8e5ea..d51130a4d21d2 100644 --- a/code/game/objects/items/theft_tools.dm +++ b/code/game/objects/items/theft_tools.dm @@ -187,7 +187,7 @@ if(!isliving(hit_atom)) return ..() var/mob/living/victim = hit_atom - if(victim.incorporeal_move || victim.status_flags & GODMODE) //try to keep this in sync with supermatter's consume fail conditions + if(victim.incorporeal_move || HAS_TRAIT(victim, TRAIT_GODMODE)) //try to keep this in sync with supermatter's consume fail conditions return ..() var/mob/thrower = throwingdatum?.get_thrower() if(thrower) @@ -208,7 +208,7 @@ /obj/item/nuke_core/supermatter_sliver/pickup(mob/living/user) ..() - if(!isliving(user) || user.status_flags & GODMODE) //try to keep this in sync with supermatter's consume fail conditions + if(!isliving(user) || HAS_TRAIT(user, TRAIT_GODMODE)) //try to keep this in sync with supermatter's consume fail conditions return FALSE user.visible_message(span_danger("[user] reaches out and tries to pick up [src]. [user.p_their()] body starts to glow and bursts into flames before flashing into dust!"),\ span_userdanger("You reach for [src] with your hands. That was dumb."),\ @@ -311,7 +311,7 @@ if(!isliving(AM)) return var/mob/living/victim = AM - if(victim.incorporeal_move || victim.status_flags & GODMODE) //try to keep this in sync with supermatter's consume fail conditions + if(victim.incorporeal_move || HAS_TRAIT(victim, TRAIT_GODMODE)) //try to keep this in sync with supermatter's consume fail conditions return victim.investigate_log("has been dusted by [src].", INVESTIGATE_DEATHS) victim.dust() diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm index 143b8eab174e6..dfc406437201b 100644 --- a/code/game/objects/items/tools/weldingtool.dm +++ b/code/game/objects/items/tools/weldingtool.dm @@ -1,5 +1,3 @@ -/// How many seconds between each fuel depletion tick ("use" proc) -#define WELDER_FUEL_BURN_INTERVAL 5 /obj/item/weldingtool name = "welding tool" desc = "A standard edition welder provided by Nanotrasen." @@ -89,7 +87,7 @@ force = 15 damtype = BURN burned_fuel_for += seconds_per_tick - if(burned_fuel_for >= WELDER_FUEL_BURN_INTERVAL) + if(burned_fuel_for >= TOOL_FUEL_BURN_INTERVAL) use(TRUE) update_appearance() @@ -276,16 +274,17 @@ return welding /// If welding tool ran out of fuel during a construction task, construction fails. -/obj/item/weldingtool/tool_use_check(mob/living/user, amount) +/obj/item/weldingtool/tool_use_check(mob/living/user, amount, heat_required) if(!isOn() || !check_fuel()) to_chat(user, span_warning("[src] has to be on to complete this task!")) return FALSE - - if(get_fuel() >= amount) - return TRUE - else + if(get_fuel() < amount) to_chat(user, span_warning("You need more welding fuel to complete this task!")) return FALSE + if(heat < heat_required) + to_chat(user, span_warning("[src] is not hot enough to complete this task!")) + return FALSE + return TRUE /// Ran when the welder is attacked by a screwdriver. /obj/item/weldingtool/proc/flamethrower_screwdriver(obj/item/tool, mob/user) @@ -410,5 +409,3 @@ if(get_fuel() < max_fuel && nextrefueltick < world.time) nextrefueltick = world.time + 10 reagents.add_reagent(/datum/reagent/fuel, 1) - -#undef WELDER_FUEL_BURN_INTERVAL diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 1c82bffbf7c7e..139a3fcb216f2 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -1134,7 +1134,6 @@ name = "xenomorph action figure" desc = "MEGA presents the new Xenos Isolated action figure! Comes complete with realistic sounds! Pull back string to use." w_class = WEIGHT_CLASS_SMALL - item_flags = XENOMORPH_HOLDABLE var/cooldown = 0 /obj/item/toy/toy_xeno/attack_self(mob/user) @@ -1405,7 +1404,7 @@ //Add changing looks when i feel suicidal about making 20 inhands for these. /obj/item/toy/dummy/attack_self(mob/user) - var/new_name = tgui_input_text(usr, "What would you like to name the dummy?", "Doll Name", doll_name, MAX_NAME_LEN) + var/new_name = tgui_input_text(usr, "What would you like to name the dummy?", "Doll Name", doll_name, max_length = MAX_NAME_LEN) if(!new_name || !user.is_holding(src)) return doll_name = new_name diff --git a/code/game/objects/items/wall_mounted.dm b/code/game/objects/items/wall_mounted.dm index ef19205cf8063..2db970b556ae1 100644 --- a/code/game/objects/items/wall_mounted.dm +++ b/code/game/objects/items/wall_mounted.dm @@ -61,9 +61,9 @@ /obj/item/wallframe/screwdriver_act(mob/living/user, obj/item/tool) // For camera-building borgs - var/turf/T = get_step(get_turf(user), user.dir) - if(iswallturf(T)) - T.attackby(src, user) + var/turf/wall_turf = get_step(get_turf(user), user.dir) + if(iswallturf(wall_turf)) + wall_turf.item_interaction(user, src) return ITEM_INTERACT_SUCCESS /obj/item/wallframe/wrench_act(mob/living/user, obj/item/tool) diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index ef436e24e8c1a..0a88aade6978f 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -187,8 +187,11 @@ GLOBAL_LIST_EMPTY(objects_by_id_tag) . = ..() if(desc_controls) . += span_notice(desc_controls) + +/obj/examine_tags(mob/user) + . = ..() if(obj_flags & UNIQUE_RENAME) - . += span_notice("Use a pen on it to rename it or change its description.") + .["renameable"] = "Use a pen on it to rename it or change its description." /obj/analyzer_act(mob/living/user, obj/item/analyzer/tool) if(atmos_scan(user=user, target=src, silent=FALSE)) diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm index 701c13bfcf755..e6c9579d67936 100644 --- a/code/game/objects/structures.dm +++ b/code/game/objects/structures.dm @@ -58,6 +58,9 @@ if(!broken) return span_warning("It's falling apart!") +/obj/structure/examine_descriptor(mob/user) + return "structure" + /obj/structure/rust_heretic_act() take_damage(500, BRUTE, "melee", 1) diff --git a/code/game/objects/structures/beds_chairs/bed.dm b/code/game/objects/structures/beds_chairs/bed.dm index 4ade32bdd0e0a..9131a28e6eb06 100644 --- a/code/game/objects/structures/beds_chairs/bed.dm +++ b/code/game/objects/structures/beds_chairs/bed.dm @@ -27,6 +27,8 @@ var/elevation = 8 /// If this bed can be deconstructed using a wrench var/can_deconstruct = TRUE + /// Directions in which the bed has its headrest on the left side. + var/left_headrest_dirs = NORTHEAST /obj/structure/bed/Initialize(mapload) . = ..() @@ -58,7 +60,7 @@ update_buckle_vars(newdir) /obj/structure/bed/proc/update_buckle_vars(newdir) - buckle_lying = newdir & NORTHEAST ? 270 : 90 + buckle_lying = newdir & left_headrest_dirs ? 270 : 90 /obj/structure/bed/atom_deconstruct(disassembled = TRUE) if(build_stack_type) @@ -83,6 +85,8 @@ icon_state = "med_down" base_icon_state = "med" anchored = FALSE + left_headrest_dirs = SOUTHWEST + buckle_lying = 270 resistance_flags = NONE build_stack_type = /obj/item/stack/sheet/mineral/titanium build_stack_amount = 1 diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm index e1581422d0570..73020ba93bbb7 100644 --- a/code/game/objects/structures/beds_chairs/chair.dm +++ b/code/game/objects/structures/beds_chairs/chair.dm @@ -16,7 +16,17 @@ var/buildstacktype = /obj/item/stack/sheet/iron var/buildstackamount = 1 var/item_chair = /obj/item/chair // if null it can't be picked up + ///How much sitting on this chair influences fishing difficulty + var/fishing_modifier = -3 +/obj/structure/chair/Initialize(mapload) + . = ..() + if(prob(0.2)) + name = "tactical [name]" + fishing_modifier -= 4 + MakeRotate() + if(can_buckle && fishing_modifier) + AddComponent(/datum/component/adjust_fishing_difficulty, fishing_modifier) /obj/structure/chair/examine(mob/user) . = ..() @@ -24,12 +34,6 @@ if(!has_buckled_mobs() && can_buckle) . += span_notice("While standing on [src], drag and drop your sprite onto [src] to buckle to it.") -/obj/structure/chair/Initialize(mapload) - . = ..() - if(prob(0.2)) - name = "tactical [name]" - MakeRotate() - ///This proc adds the rotate component, overwrite this if you for some reason want to change some specific args. /obj/structure/chair/proc/MakeRotate() AddComponent(/datum/component/simple_rotation, ROTATION_IGNORE_ANCHORED|ROTATION_GHOSTS_ALLOWED) @@ -134,6 +138,7 @@ buildstacktype = /obj/item/stack/sheet/mineral/wood buildstackamount = 3 item_chair = /obj/item/chair/wood + fishing_modifier = -4 /obj/structure/chair/wood/narsie_act() return @@ -151,6 +156,7 @@ max_integrity = 70 buildstackamount = 2 item_chair = null + fishing_modifier = -5 // The mutable appearance used for the overlay over buckled mobs. var/mutable_appearance/armrest @@ -226,11 +232,13 @@ desc = "A luxurious chair, the many purple scales reflect the light in a most pleasing manner." icon_state = "carp_chair" buildstacktype = /obj/item/stack/sheet/animalhide/carp + fishing_modifier = -10 /obj/structure/chair/office anchored = FALSE buildstackamount = 5 item_chair = null + fishing_modifier = -4 icon_state = "officechair_dark" /obj/structure/chair/office/Initialize(mapload) @@ -245,6 +253,10 @@ /obj/structure/chair/office/tactical name = "tactical swivel chair" +/obj/structure/chair/office/tactical/Initialize(mapload) + . = ..() + AddComponent(/datum/component/adjust_fishing_difficulty, -10) + /obj/structure/chair/office/light icon_state = "officechair_white" @@ -436,6 +448,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/chair/stool/bar, 0) desc = "You sit in this. Either by will or force. Looks REALLY uncomfortable." icon_state = "chairold" item_chair = null + fishing_modifier = 4 /obj/structure/chair/bronze name = "brass chair" @@ -445,6 +458,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/chair/stool/bar, 0) buildstacktype = /obj/item/stack/sheet/bronze buildstackamount = 1 item_chair = null + fishing_modifier = -12 //the pinnacle of Ratvarian technology. /// Total rotations made var/turns = 0 @@ -484,6 +498,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/chair/stool/bar, 0) item_chair = null obj_flags = parent_type::obj_flags | NO_DEBRIS_AFTER_DECONSTRUCTION alpha = 0 + fishing_modifier = -20 //it only lives for 25 seconds, so we make them worth it. /obj/structure/chair/mime/wrench_act_secondary(mob/living/user, obj/item/weapon) return NONE @@ -505,6 +520,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/chair/stool/bar, 0) buildstacktype = /obj/item/stack/sheet/plastic buildstackamount = 2 item_chair = /obj/item/chair/plastic + fishing_modifier = -8 /obj/structure/chair/plastic/post_buckle_mob(mob/living/Mob) Mob.pixel_y += 2 diff --git a/code/game/objects/structures/beds_chairs/sofa.dm b/code/game/objects/structures/beds_chairs/sofa.dm index bf9a221929b67..04bb0b1e25e3f 100644 --- a/code/game/objects/structures/beds_chairs/sofa.dm +++ b/code/game/objects/structures/beds_chairs/sofa.dm @@ -19,6 +19,7 @@ path/corner/color_name {\ icon = 'icons/obj/chairs_wide.dmi' buildstackamount = 1 item_chair = null + fishing_modifier = -4 var/mutable_appearance/armrest /obj/structure/chair/sofa/Initialize(mapload) diff --git a/code/game/objects/structures/cannons/cannon_instructions.dm b/code/game/objects/structures/cannons/cannon_instructions.dm index c259ea0e76f17..34cdcdf1ced68 100644 --- a/code/game/objects/structures/cannons/cannon_instructions.dm +++ b/code/game/objects/structures/cannons/cannon_instructions.dm @@ -17,4 +17,10 @@ REGULAR CANNONBALL: A fine choice for killing landlubbers! Will take off any lim EXPLOSIVE SHELLBALL: The most elegant in breaching (er killin', if you're good at aimin') tools, ye be packing this shell with many scuppering chemicals! Just make sure to not fire it when ye be close to target!
MALFUNCTION SHOT: A very gentle "cannonball" dart at first glance, but make no mistake: This is their worst nightmare! Enjoy an easy boarding process while all their machines are broken and all their weapons unloaded from an EMP!
THE BIGGEST ONE: A shellball, but much bigger. Ye won't be seein' much of these as they were discontinued for sinkin' the firer's ship as often as it sunk the scallywag's ship. Very big boom! If ye have one, ye have been warned! + +
FIRING THAR CANISTER GATLING
+ +THE CANISTER GATLING AIN'T LIKE OTHER CANNONS, AND DOESN'T REQUIRE GUNPOWDER, INSTEAD RELYING ON SPECIAL CANISTER SHOT SHELLS. +ALL YOU HAVE TO DO IS CRAM A SHELL IN THE BREACH, LIGHT HER UP AND YOU'LL BE BLOWING THOSE CORPORATE SODS TO KINGDOM COME! +SHE LACKS THE SHEER WALL-BREAKING PUNCH OF THE HOLEMAKERS, BUT CHEWS THROUGH SOFT TARGETS LIKE A SHARK THROUGH A GROUP OF BEACH THROUGH A GROUP OF BEACHGOERS, YAHAR. "} diff --git a/code/game/objects/structures/cannons/mounted_guns/mounted_gun.dm b/code/game/objects/structures/cannons/mounted_guns/mounted_gun.dm new file mode 100644 index 0000000000000..da27cdbdaf9df --- /dev/null +++ b/code/game/objects/structures/cannons/mounted_guns/mounted_gun.dm @@ -0,0 +1,187 @@ +//Mounted guns are basically a smaller equivalent to cannons, designed to use pre-existing ammo rather than cannonballs. +//Due to using pre-existing ammo, they dont require to be loaded with gunpowder or an equivalent. + +/obj/structure/mounted_gun + name = "Mounted Gun" + desc = "Default mounted gun for inheritance purposes." + density = TRUE + anchored = FALSE + icon = 'icons/obj/weapons/cannons.dmi' + icon_state = "falconet_patina" + var/icon_state_base = "falconet_patina" + var/icon_state_fire = "falconet_patina_fire" + max_integrity = 300 + ///whether the cannon can be unwrenched from the ground. Anchorable_cannon equivalent. + var/anchorable_gun = TRUE + ///Max shots per firing of the gun. + var/max_shots_per_fire = 1 + ///Shots currently loaded. Should never be more than max_shots_per_fire. + var/shots_in_gun = 1 + ///shots added to gun, per piece of ammo loaded. + var/shots_per_load = 1 + ///Accepted "ammo" type + var/obj/item/ammo_type = /obj/item/ammo_casing/strilka310 + ///Projectile from said gun. Doesnt automatically inherit said ammo's projectile in case you wanted to make a gun that shoots floor tiles or something. + var/obj/item/projectile_type = /obj/projectile/bullet/strilka310 + ///If the gun has anything in it. + var/loaded_gun = TRUE + ///If the gun is currently loaded with its maximum capacity. + var/fully_loaded_gun = TRUE + ///delay in firing the gun after lighting + var/fire_delay = 5 + ///Delay between shots + var/shot_delay = 3 + ///If the gun shakes the camera when firing + var/firing_shakes_camera = TRUE + ///sound of firing for all but last shot + var/fire_sound = 'sound/weapons/gun/general/mountedgun.ogg' + ///sound of firing for last shot + var/last_fire_sound = 'sound/weapons/gun/general/mountedgunend.ogg' + +/obj/structure/mounted_gun/wrench_act(mob/living/user, obj/item/tool) + . = ..() + if(!anchorable_gun) /// Can't anchor an unanchorable gun. + return FALSE + default_unfasten_wrench(user, tool) + return ITEM_INTERACT_SUCCESS + +///Covers Reloading and lighting of the gun +/obj/structure/mounted_gun/attackby(obj/item/ammo_casing/used_item, mob/user, params) + var/ignition_message = used_item.ignition_effect(src, user) // Checks if item used can ignite stuff. + if(istype(used_item, ammo_type)) + if(fully_loaded_gun) + balloon_alert(user, "already fully loaded!") + return + else + shots_in_gun = shots_in_gun + shots_per_load //Add one to the shots in the gun + + loaded_gun = TRUE // Make sure it registers theres ammo in there, so it can fire. + QDEL_NULL(used_item) + if(shots_in_gun >= max_shots_per_fire) + shots_in_gun = max_shots_per_fire // in case of somehow firing only some of a guns shots, and reloading, you still cant get above the maximum ammo size. + fully_loaded_gun = TRUE //So you cant load extra. + return + + else if(ignition_message) // if item the player used ignites, light the gun! + visible_message(ignition_message) + user.log_message("fired a cannon", LOG_ATTACK) + log_game("[key_name(user)] fired a cannon in [AREACOORD(src)]") + addtimer(CALLBACK(src, PROC_REF(fire)), fire_delay) //uses fire proc as shown below to shoot the gun + return + ..() + +/obj/structure/mounted_gun/proc/fire() + if (!loaded_gun) + balloon_alert_to_viewers("gun is not loaded!","",2) + return + for(var/times_fired = 1, times_fired <= shots_in_gun, times_fired++) //The normal DM for loop structure since the times it has fired is changing in the loop itself. + for(var/mob/shaken_mob in urange(10, src)) + if(shaken_mob.stat == CONSCIOUS && firing_shakes_camera == TRUE) + shake_camera(shaken_mob, 3, 1) + icon_state = icon_state_fire + if(loaded_gun) + + if (times_fired < shots_in_gun) + playsound(src, fire_sound, 50, FALSE, 5) + else + playsound(src, last_fire_sound, 50, TRUE, 5) + var/obj/projectile/fired_projectile = new projectile_type(get_turf(src)) + fired_projectile.firer = src + fired_projectile.fired_from = src + fired_projectile.fire(dir2angle(dir)) + sleep(shot_delay) + loaded_gun = FALSE + shots_in_gun = 0 + fully_loaded_gun = FALSE + icon_state = icon_state_base + +/obj/structure/mounted_gun/pipe + + name = "Pipe Organ Gun" + desc = "To become master over one who has killed, one must become a better killer. This engine of destruction is one of many things made to that end." + icon_state = "pipeorgangun" + icon_state_base = "pipeorgangun" + icon_state_fire = "pipeorgangun_fire" + anchored = FALSE + anchorable_gun = TRUE + max_shots_per_fire = 8 + shots_in_gun = 8 + shots_per_load = 2 + ammo_type = /obj/item/ammo_casing/junk + projectile_type = /obj/projectile/bullet/junk + loaded_gun = TRUE + fully_loaded_gun = TRUE + fire_delay = 3 + shot_delay = 2 + firing_shakes_camera = FALSE + +/obj/structure/mounted_gun/pipe/examine_more(mob/user) + . = ..() + . += span_notice("Looking down at the [name], you recall a tale told to you in some distant memory...") + + . += span_info("To commit an act of vengeance is not unlike to enter a blood pact with a devil, ending the life of another, at the cost of your own.") + . += span_info("When humanity first spilled the blood of its own kind, with likely nothing more than a rock, the seal was broken. Vengeance was borne unto the world.") + . += span_info("However, vengeance alone is not enough to carry through the grim deed of murder. One must an gain advantage over their adversary.") + . += span_info("As such, the man who ended another's life with a stone, was in turn smote himself by another wielding a spear. After spears, bows. Swords. Guns. Tanks. Missiles. And on and on Vengeance fed. Growing stronger. Growing Worse.") + . += span_info("Vengeance persists to this day. It sometimes may slumber, seemingly content with having gorged itself, but in the end, its ceaseless hunger can be neither numbed nor sated.") + +/obj/structure/mounted_gun/pipe/fire() + if (!loaded_gun) + balloon_alert_to_viewers("Gun is not loaded!","",2) + return + for(var/times_fired = 1, times_fired <= shots_in_gun, times_fired++) //The normal DM for loop structure since the times it has fired is changing in the loop itself. + for(var/mob/shaken_mob in urange(10, src)) + if((shaken_mob.stat == CONSCIOUS)&&(firing_shakes_camera == TRUE)) + shake_camera(shaken_mob, 3, 1) + icon_state = icon_state_fire + if(loaded_gun) + playsound(src, fire_sound, 50, TRUE, 5) + + var/list_of_projectiles = list( + /obj/projectile/bullet/junk = 40, + /obj/projectile/bullet/incendiary/fire/junk = 25, + /obj/projectile/bullet/junk/shock = 25, + /obj/projectile/bullet/junk/hunter = 20, + /obj/projectile/bullet/junk/phasic = 8, + /obj/projectile/bullet/junk/ripper = 8, + /obj/projectile/bullet/junk/reaper = 3, + ) + projectile_type = pick_weight(list_of_projectiles) + + var/obj/projectile/fired_projectile = new projectile_type(get_turf(src)) + fired_projectile.firer = src + fired_projectile.fired_from = src + fired_projectile.fire(dir2angle(dir)) + sleep(shot_delay) + loaded_gun = FALSE + shots_in_gun = 0 + fully_loaded_gun = FALSE + icon_state = icon_state_base + +/obj/structure/mounted_gun/canister_gatling //for the funny skeleton pirates! + + name = "Canister Gatling Gun" + desc = "''Quantity has a quality of its own.''" + icon_state = "canister_gatling" + icon_state_base = "canister_gatling" + icon_state_fire = "canister_gatling_fire" + anchored = FALSE + anchorable_gun = TRUE + max_shots_per_fire = 50 + shots_per_load = 50 + shots_in_gun = 50 + ammo_type = /obj/item/ammo_casing/canister_shot + projectile_type = /obj/projectile/bullet/shrapnel + loaded_gun = TRUE + fully_loaded_gun = TRUE + fire_delay = 3 + shot_delay = 1 + firing_shakes_camera = FALSE + +/obj/item/ammo_casing/canister_shot + name = "Canister Shot" + desc = "A gigantic... well, canister of canister shot. Used for reloading the Canister Gatling Gun." + icon_state = "canister_shot" + obj_flags = CONDUCTS_ELECTRICITY + throwforce = 0 + w_class = WEIGHT_CLASS_BULKY diff --git a/code/game/objects/structures/construction_console/construction_actions.dm b/code/game/objects/structures/construction_console/construction_actions.dm index fc014d14318bd..b9abfe70c3f71 100644 --- a/code/game/objects/structures/construction_console/construction_actions.dm +++ b/code/game/objects/structures/construction_console/construction_actions.dm @@ -91,7 +91,7 @@ if(place_turf.density) to_chat(owner, span_warning("[structure_name] may only be placed on a floor.")) return - //Can't place two dense objects inside eachother + //Can't place two dense objects inside each other if(initial(structure_path.density) && place_turf.is_blocked_turf()) to_chat(owner, span_warning("Location is obstructed by something. Please clear the location and try again.")) return diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index f407dcd82c04f..c4740398d82d2 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -157,8 +157,8 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets) register_context() if(opened) - opened = FALSE //nessassary because open() proc will early return if its true - if(open(special_effects = FALSE)) //closets which are meant to be open by default dont need to be animated open + opened = FALSE //necessary because open() proc will early return if its true + if(open(special_effects = FALSE)) //closets which are meant to be open by default don't need to be animated open return update_appearance() @@ -823,21 +823,24 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets) balloon_alert(user, "unlock first!") return - if(isnull(id_card)) + if(isnull(id_card) && secure) balloon_alert(user, "not yours to rename!") return var/name_set = FALSE var/desc_set = FALSE - var/str = tgui_input_text(user, "Personal Locker Name", "Locker Name") - if(!isnull(str)) - name = str + + var/input_name = tgui_input_text(user, "Locker Name", "Locker Name", max_length = MAX_NAME_LEN) + + if(!isnull(input_name)) + name = input_name name_set = TRUE - str = tgui_input_text(user, "Personal Locker Description", "Locker Description") - if(!isnull(str)) - desc = str + var/input_desc = tgui_input_text(user, "Locker Description", "Locker Description", max_length = MAX_DESC_LEN) + + if(!isnull(input_desc)) + desc = input_desc desc_set = TRUE var/bit_flag = NONE @@ -888,7 +891,7 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets) user.log_message("[welded ? "welded":"unwelded"] closet [src] with [weapon]", LOG_GAME) update_appearance() - else if(!user.combat_mode) + else if(!user.combat_mode || (weapon.item_flags & NOBLUDGEON)) var/item_is_id = weapon.GetID() if(!item_is_id) return FALSE @@ -915,8 +918,6 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets) /obj/structure/closet/mouse_drop_receive(atom/movable/O, mob/living/user, params) if(!istype(O) || O.anchored || istype(O, /atom/movable/screen)) return - if(!istype(user) || user.incapacitated || user.body_position == LYING_DOWN) - return if(user == O) //try to climb onto it return ..() if(!opened) @@ -1068,7 +1069,7 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets) addtimer(CALLBACK(src, PROC_REF(check_if_shake)), next_check_time) return TRUE - // If we reach here, nobody is resisting, so dont shake + // If we reach here, nobody is resisting, so don't shake return FALSE /obj/structure/closet/proc/bust_open() @@ -1191,15 +1192,13 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets) return if(!opened && ((shove_flags & SHOVE_KNOCKDOWN_BLOCKED) || !(shove_flags & SHOVE_BLOCKED))) return - var/was_opened = opened - if(!toggle()) - return - if(was_opened) - if (!target.Move(get_turf(src), get_dir(target, src))) + if(opened) + if (target.loc != loc) return target.forceMove(src) else target.Knockdown(SHOVE_KNOCKDOWN_SOLID) + toggle() update_icon() target.visible_message(span_danger("[shover.name] shoves [target.name] into [src]!"), span_userdanger("You're shoved into [src] by [shover.name]!"), diff --git a/code/game/objects/structures/crates_lockers/closets/bodybag.dm b/code/game/objects/structures/crates_lockers/closets/bodybag.dm index ac8b444e47dc7..66950b0845f1d 100644 --- a/code/game/objects/structures/crates_lockers/closets/bodybag.dm +++ b/code/game/objects/structures/crates_lockers/closets/bodybag.dm @@ -116,8 +116,22 @@ */ /obj/structure/closet/body_bag/proc/perform_fold(mob/living/carbon/human/the_folder) visible_message(span_notice("[the_folder] folds up [src].")) - var/obj/item/bodybag/folding_bodybag = foldedbag_instance || new foldedbag_path - the_folder.put_in_hands(folding_bodybag) + the_folder.put_in_hands(undeploy_bodybag(the_folder.loc)) + +/// Makes the bag into an item, returns that item +/obj/structure/closet/body_bag/proc/undeploy_bodybag(atom/fold_loc) + var/obj/item/bodybag/folding_bodybag = foldedbag_instance || new foldedbag_path() + if(fold_loc) + folding_bodybag.forceMove(fold_loc) + return folding_bodybag + +/obj/structure/closet/body_bag/container_resist_act(mob/living/user, loc_required = TRUE) + // ideally we support this natively but i guess that's for a later time + if(!istype(loc, /obj/machinery/disposal)) + return ..() + for(var/atom/movable/thing as anything in src) + thing.forceMove(loc) + undeploy_bodybag(loc) /obj/structure/closet/body_bag/bluespace name = "bluespace body bag" @@ -152,7 +166,7 @@ /obj/structure/closet/body_bag/bluespace/perform_fold(mob/living/carbon/human/the_folder) visible_message(span_notice("[the_folder] folds up [src].")) - var/obj/item/bodybag/folding_bodybag = foldedbag_instance || new foldedbag_path + var/obj/item/bodybag/folding_bodybag = undeploy_bodybag(the_folder.loc) var/max_weight_of_contents = initial(folding_bodybag.w_class) for(var/am in contents) var/atom/movable/content = am @@ -186,7 +200,7 @@ contents_thermal_insulation = 0.5 foldedbag_path = /obj/item/bodybag/environmental /// The list of weathers we protect from. - var/list/weather_protection = list(TRAIT_ASHSTORM_IMMUNE, TRAIT_RADSTORM_IMMUNE, TRAIT_SNOWSTORM_IMMUNE, TRAIT_VOIDSTORM_IMMUNE) // Does not protect against lava or the The Floor Is Lava spell. + var/list/weather_protection = list(TRAIT_ASHSTORM_IMMUNE, TRAIT_RADSTORM_IMMUNE, TRAIT_SNOWSTORM_IMMUNE) // Does not protect against lava or the The Floor Is Lava spell. /// The contents of the gas to be distributed to an occupant. Set in Initialize() var/datum/gas_mixture/air_contents = null @@ -277,18 +291,9 @@ icon_state = initial(icon_state) /obj/structure/closet/body_bag/environmental/prisoner/container_resist_act(mob/living/user, loc_required = TRUE) - /// copy-pasted with changes because flavor text as well as some other misc stuff - if(opened) - return - if(ismovable(loc)) - user.changeNext_move(CLICK_CD_BREAKOUT) - user.last_special = world.time + CLICK_CD_BREAKOUT - var/atom/movable/location = loc - location.relay_container_resist_act(user, src) - return - if(!sinched) - open(user) - return + // copy-pasted with changes because flavor text as well as some other misc stuff + if(opened || ismovable(loc) || !sinched) + return ..() user.changeNext_move(CLICK_CD_BREAKOUT) user.last_special = world.time + CLICK_CD_BREAKOUT @@ -301,6 +306,8 @@ //we check after a while whether there is a point of resisting anymore and whether the user is capable of resisting user.visible_message(span_danger("[user] successfully broke out of [src]!"), span_notice("You successfully break out of [src]!")) + if(istype(loc, /obj/machinery/disposal)) + return ..() bust_open() else if(user.loc == src) //so we don't get the message if we resisted multiple times and succeeded. @@ -369,7 +376,7 @@ icon_state = "holobag_med" resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF foldedbag_path = null - weather_protection = list(TRAIT_VOIDSTORM_IMMUNE, TRAIT_SNOWSTORM_IMMUNE) + weather_protection = list(TRAIT_SNOWSTORM_IMMUNE) /obj/structure/closet/body_bag/environmental/hardlight/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) if(damage_type in list(BRUTE, BURN)) @@ -381,7 +388,7 @@ icon_state = "holobag_sec" resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF foldedbag_path = null - weather_protection = list(TRAIT_VOIDSTORM_IMMUNE, TRAIT_SNOWSTORM_IMMUNE) + weather_protection = list(TRAIT_SNOWSTORM_IMMUNE) /obj/structure/closet/body_bag/environmental/prisoner/hardlight/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) if(damage_type in list(BRUTE, BURN)) diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index cac9fbaf890bb..2fed72c5bab3b 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -5,7 +5,6 @@ icon_state = "crate" base_icon_state = "crate" req_access = null - can_weld_shut = FALSE horizontal = TRUE allow_objects = TRUE allow_dense = TRUE @@ -95,6 +94,9 @@ else if(secure) . += "securecrateg" + if(welded) + . += icon_welded + if(opened && lid_icon_state) var/mutable_appearance/lid = mutable_appearance(icon = lid_icon, icon_state = lid_icon_state) lid.pixel_x = lid_x @@ -174,6 +176,7 @@ can_install_electronics = FALSE paint_jobs = null elevation_open = 0 + can_weld_shut = FALSE /obj/structure/closet/crate/trashcart //please make this a generic cart path later after things calm down a little desc = "A heavy, metal trashcart with wheels." @@ -190,6 +193,7 @@ base_icon_state = "laundry" elevation = 14 elevation_open = 14 + can_weld_shut = FALSE /obj/structure/closet/crate/trashcart/Initialize(mapload) . = ..() @@ -224,7 +228,7 @@ /obj/structure/closet/crate/deforest name = "deforest medical crate" - desc = "A DeFortest brand crate of medical supplies." + desc = "A DeForest brand crate of medical supplies." icon_state = "deforest" base_icon_state = "deforest" diff --git a/code/game/objects/structures/crates_lockers/crates/bins.dm b/code/game/objects/structures/crates_lockers/crates/bins.dm index a686d53f392c6..8ff1e1aa21da8 100644 --- a/code/game/objects/structures/crates_lockers/crates/bins.dm +++ b/code/game/objects/structures/crates_lockers/crates/bins.dm @@ -12,6 +12,7 @@ paint_jobs = null elevation = 17 elevation_open = 17 + can_weld_shut = FALSE /obj/structure/closet/crate/bin/LateInitialize() . = ..() diff --git a/code/game/objects/structures/crates_lockers/crates/cardboard.dm b/code/game/objects/structures/crates_lockers/crates/cardboard.dm index 7b1e7dc725779..12008cc4022bf 100644 --- a/code/game/objects/structures/crates_lockers/crates/cardboard.dm +++ b/code/game/objects/structures/crates_lockers/crates/cardboard.dm @@ -12,6 +12,7 @@ close_sound_volume = 25 paint_jobs = null cutting_tool = /obj/item/wirecutters + can_weld_shut = FALSE /obj/structure/closet/crate/cardboard/mothic name = "\improper Mothic Fleet box" diff --git a/code/game/objects/structures/crates_lockers/crates/critter.dm b/code/game/objects/structures/crates_lockers/crates/critter.dm index 5e1873d166ab6..d116a33d8ff75 100644 --- a/code/game/objects/structures/crates_lockers/crates/critter.dm +++ b/code/game/objects/structures/crates_lockers/crates/critter.dm @@ -17,6 +17,7 @@ can_install_electronics = FALSE elevation = 21 elevation_open = 0 + can_weld_shut = FALSE var/obj/item/tank/internals/emergency_oxygen/tank diff --git a/code/game/objects/structures/crates_lockers/crates/large.dm b/code/game/objects/structures/crates_lockers/crates/large.dm index 0a08d9c7949a1..667dd9b2ebb8b 100644 --- a/code/game/objects/structures/crates_lockers/crates/large.dm +++ b/code/game/objects/structures/crates_lockers/crates/large.dm @@ -15,6 +15,7 @@ close_sound_volume = 50 can_install_electronics = FALSE elevation = 22 + can_weld_shut = FALSE // Stops people from "diving into" a crate you can't open normally divable = FALSE diff --git a/code/game/objects/structures/deployable_turret.dm b/code/game/objects/structures/deployable_turret.dm index 908d2348db4b3..6abb14294de5b 100644 --- a/code/game/objects/structures/deployable_turret.dm +++ b/code/game/objects/structures/deployable_turret.dm @@ -259,11 +259,11 @@ M.attacked_by(src, user) add_fingerprint(user) -/obj/item/gun_control/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) +/obj/item/gun_control/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) var/obj/machinery/deployable_turret/E = user.buckled E.calculated_projectile_vars = calculate_projectile_angle_and_pixel_offsets(user, interacting_with, modifiers) E.direction_track(user, interacting_with) E.checkfire(interacting_with, user) -/obj/item/gun_control/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) - return interact_with_atom(interacting_with, user, modifiers) +/obj/item/gun_control/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return ranged_interact_with_atom(interacting_with, user, modifiers) diff --git a/code/game/objects/structures/detectiveboard.dm b/code/game/objects/structures/detectiveboard.dm index f9d0560dfdee4..27c11cda5a018 100644 --- a/code/game/objects/structures/detectiveboard.dm +++ b/code/game/objects/structures/detectiveboard.dm @@ -50,11 +50,11 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/detectiveboard, 32) to_chat(user, "You already attaching evidence!") return attaching_evidence = TRUE - var/name = tgui_input_text(user, "Please enter the evidence name", "Detective's Board") + var/name = tgui_input_text(user, "Please enter the evidence name", "Detective's Board", max_length = MAX_NAME_LEN) if(!name) attaching_evidence = FALSE return - var/desc = tgui_input_text(user, "Please enter the evidence description", "Detective's Board") + var/desc = tgui_input_text(user, "Please enter the evidence description", "Detective's Board", max_length = MAX_DESC_LEN) if(!desc) attaching_evidence = FALSE return @@ -146,7 +146,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/detectiveboard, 32) if("add_case") if(cases.len == MAX_CASES) return FALSE - var/new_case = tgui_input_text(user, "Please enter the case name", "Detective's Board") + var/new_case = tgui_input_text(user, "Please enter the case name", "Detective's Board", max_length = MAX_NAME_LEN) if(!new_case) return FALSE var/case_color = tgui_input_list(user, "Please choose case color", "Detective's Board", case_colors) @@ -173,7 +173,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/detectiveboard, 32) update_appearance(UPDATE_ICON) return TRUE if("rename_case") - var/new_name = tgui_input_text(user, "Please ender the case new name", "Detective's Board") + var/new_name = tgui_input_text(user, "Please enter the new name for the case", "Detective's Board", max_length = MAX_NAME_LEN) if(new_name) var/datum/case/case = locate(params["case_ref"]) in cases case.name = new_name diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm index b582d86efde0e..03957e2708bf0 100644 --- a/code/game/objects/structures/displaycase.dm +++ b/code/game/objects/structures/displaycase.dm @@ -159,7 +159,7 @@ toggle_lock(user) else if(open && !showpiece) insert_showpiece(attacking_item, user) - return TRUE //cancel the attack chain, wether we successfully placed an item or not + return TRUE //cancel the attack chain, whether we successfully placed an item or not else if(glass_fix && broken && istype(attacking_item, /obj/item/stack/sheet/glass)) var/obj/item/stack/sheet/glass/glass_sheet = attacking_item if(glass_sheet.get_amount() < 2) @@ -426,7 +426,7 @@ return if("change_message") if(showpiece && !holographic_showpiece) - var/new_trophy_message = tgui_input_text(usr, "Let's make history!", "Trophy Message", trophy_message, MAX_PLAQUE_LEN) + var/new_trophy_message = tgui_input_text(usr, "Let's make history!", "Trophy Message", trophy_message, max_length = MAX_PLAQUE_LEN) if(!new_trophy_message) return trophy_message = new_trophy_message diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm index 9493a7c941407..c2d67e6290145 100644 --- a/code/game/objects/structures/door_assembly.dm +++ b/code/game/objects/structures/door_assembly.dm @@ -83,7 +83,7 @@ /obj/structure/door_assembly/attackby(obj/item/W, mob/living/user, params) if(IS_WRITING_UTENSIL(W) && !user.combat_mode) - var/t = tgui_input_text(user, "Enter the name for the door", "Airlock Renaming", created_name, MAX_NAME_LEN) + var/t = tgui_input_text(user, "Enter the name for the door", "Airlock Renaming", created_name, max_length = MAX_NAME_LEN) if(!t) return if(!in_range(src, usr) && loc != usr) diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index 0f20f87e0b547..389e8dcbd743d 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -500,7 +500,7 @@ /obj/structure/girder/bronze/attackby(obj/item/W, mob/living/user, params) add_fingerprint(user) if(W.tool_behaviour == TOOL_WELDER) - if(!W.tool_start_check(user, amount = 0)) + if(!W.tool_start_check(user, amount = 0, heat_required = HIGH_TEMPERATURE_REQUIRED)) return balloon_alert(user, "slicing apart...") if(W.use_tool(src, user, 40, volume=50)) diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm index 0cc73b9adef9c..57e30d58ef2bd 100644 --- a/code/game/objects/structures/kitchen_spike.dm +++ b/code/game/objects/structures/kitchen_spike.dm @@ -34,7 +34,7 @@ return CONTEXTUAL_SCREENTIP_SET /obj/structure/kitchenspike_frame/welder_act(mob/living/user, obj/item/tool) - if(!tool.tool_start_check(user, amount = 0)) + if(!tool.tool_start_check(user, amount = 0, heat_required = HIGH_TEMPERATURE_REQUIRED)) return FALSE to_chat(user, span_notice("You begin cutting \the [src] apart...")) if(!tool.use_tool(src, user, 5 SECONDS, volume = 50)) diff --git a/code/game/objects/structures/lavaland/ore_vent.dm b/code/game/objects/structures/lavaland/ore_vent.dm index f9214b989b95c..1de24f030bf5e 100644 --- a/code/game/objects/structures/lavaland/ore_vent.dm +++ b/code/game/objects/structures/lavaland/ore_vent.dm @@ -426,7 +426,7 @@ /** * When the ore vent cannot spawn a mob due to being blocked from all sides, we cause some MILD, MILD explosions. - * Explosion matches a gibtonite light explosion, as a way to clear neartby solid structures, with a high likelyhood of breaking the NODE drone. + * Explosion matches a gibtonite light explosion, as a way to clear nearby solid structures, with a high likelihood of breaking the NODE drone. */ /obj/structure/ore_vent/proc/anti_cheese() explosion(src, heavy_impact_range = 1, light_impact_range = 3, flame_range = 0, flash_range = 0, adminlog = FALSE) diff --git a/code/game/objects/structures/maintenance.dm b/code/game/objects/structures/maintenance.dm index 9f88246966f94..a8de16271f36d 100644 --- a/code/game/objects/structures/maintenance.dm +++ b/code/game/objects/structures/maintenance.dm @@ -1,9 +1,9 @@ /** This structure acts as a source of moisture loving cell lines, -as well as a location where a hidden item can somtimes be retrieved +as well as a location where a hidden item can sometimes be retrieved at the cost of risking a vicious bite.**/ /obj/structure/moisture_trap name = "moisture trap" - desc = "A device installed in order to control moisture in poorly ventilated areas.\nThe stagnant water inside basin seems to produce serious biofouling issues when improperly maintained.\nThis unit in particular seems to be teeming with life!\nWho thought mother Gaia could assert herself so vigoriously in this sterile and desolate place?" + desc = "A device installed in order to control moisture in poorly ventilated areas.\nThe stagnant water inside basin seems to produce serious biofouling issues when improperly maintained.\nThis unit in particular seems to be teeming with life!\nWho thought mother Gaia could assert herself so vigorously in this sterile and desolate place?" icon_state = "moisture_trap" anchored = TRUE density = FALSE @@ -58,7 +58,7 @@ at the cost of risking a vicious bite.**/ if(!isliving(user)) return FALSE var/mob/living/living_user = user - if(living_user.body_position == STANDING_UP && ishuman(living_user)) //I dont think monkeys can crawl on command. + if(living_user.body_position == STANDING_UP && ishuman(living_user)) //I don't think monkeys can crawl on command. return FALSE return TRUE diff --git a/code/game/objects/structures/mystery_box.dm b/code/game/objects/structures/mystery_box.dm index 9bb51ba09cbef..cb56cfe8ef120 100644 --- a/code/game/objects/structures/mystery_box.dm +++ b/code/game/objects/structures/mystery_box.dm @@ -142,7 +142,7 @@ GLOBAL_LIST_INIT(mystery_fishing, list( /// Stores the current sound channel we're using so we can cut off our own sounds as needed. Randomized after each roll var/current_sound_channel /// How many time can it still be used? - var/uses_left + var/uses_left = INFINITY /// A list of weakrefs to mind datums of people that opened it and how many times. var/list/datum/weakref/minds_that_opened_us @@ -281,6 +281,7 @@ GLOBAL_LIST_INIT(mystery_fishing, list( max_integrity = 100 damage_deflection = 30 grant_extra_mag = FALSE + anchored = FALSE /obj/structure/mystery_box/handle_deconstruct(disassembled) new /obj/item/stack/sheet/mineral/wood(drop_location(), 2) diff --git a/code/game/objects/structures/petrified_statue.dm b/code/game/objects/structures/petrified_statue.dm index 5383436d4dbff..d27a2e8e1cd8d 100644 --- a/code/game/objects/structures/petrified_statue.dm +++ b/code/game/objects/structures/petrified_statue.dm @@ -13,24 +13,24 @@ /obj/structure/statue/petrified/relaymove() return -/obj/structure/statue/petrified/Initialize(mapload, mob/living/L, statue_timer, save_brain) +/obj/structure/statue/petrified/Initialize(mapload, mob/living/living, statue_timer, save_brain) . = ..() if(statue_timer) timer = statue_timer if(save_brain) brain = save_brain - if(L) - petrified_mob = L - if(L.buckled) - L.buckled.unbuckle_mob(L,force=1) - L.visible_message(span_warning("[L]'s skin rapidly turns to marble!"), span_userdanger("Your body freezes up! Can't... move... can't... think...")) - L.forceMove(src) - ADD_TRAIT(L, TRAIT_MUTE, STATUE_MUTE) - L.faction |= FACTION_MIMIC //Stops mimics from instaqdeling people in statues - L.status_flags |= GODMODE - atom_integrity = L.health + 100 //stoning damaged mobs will result in easier to shatter statues - max_integrity = atom_integrity - START_PROCESSING(SSobj, src) + if(!living) + return + petrified_mob = living + if(living.buckled) + living.buckled.unbuckle_mob(living, force = TRUE) + living.visible_message(span_warning("[living]'s skin rapidly turns to marble!"), span_userdanger("Your body freezes up! Can't... move... can't... think...")) + living.forceMove(src) + living.add_traits(list(TRAIT_GODMODE, TRAIT_MUTE, TRAIT_NOBLOOD), STATUE_MUTE) + living.faction |= FACTION_MIMIC //Stops mimics from instaqdeling people in statues + atom_integrity = living.health + 100 //stoning damaged mobs will result in easier to shatter statues + max_integrity = atom_integrity + START_PROCESSING(SSobj, src) /obj/structure/statue/petrified/process(seconds_per_tick) if(!petrified_mob) @@ -47,6 +47,9 @@ /obj/structure/statue/petrified/Exited(atom/movable/gone, direction) . = ..() if(gone == petrified_mob) + petrified_mob.remove_traits(list(TRAIT_GODMODE, TRAIT_MUTE, TRAIT_NOBLOOD), STATUE_MUTE) + petrified_mob.take_overall_damage((petrified_mob.health - atom_integrity + 100)) //any new damage the statue incurred is transferred to the mob + petrified_mob.faction -= FACTION_MIMIC petrified_mob = null /obj/structure/statue/petrified/Destroy() @@ -64,13 +67,7 @@ for(var/obj/O in src) O.forceMove(loc) - if(petrified_mob) - petrified_mob.status_flags &= ~GODMODE - REMOVE_TRAIT(petrified_mob, TRAIT_MUTE, STATUE_MUTE) - REMOVE_TRAIT(petrified_mob, TRAIT_NOBLOOD, MAGIC_TRAIT) - petrified_mob.take_overall_damage((petrified_mob.health - atom_integrity + 100)) //any new damage the statue incurred is transferred to the mob - petrified_mob.faction -= FACTION_MIMIC - petrified_mob.forceMove(loc) + petrified_mob?.forceMove(loc) return ..() /obj/structure/statue/petrified/atom_deconstruct(disassembled = TRUE) @@ -114,7 +111,6 @@ return FALSE var/obj/structure/statue/petrified/S = new(loc, src, statue_timer, save_brain) S.name = "statue of [name]" - ADD_TRAIT(src, TRAIT_NOBLOOD, MAGIC_TRAIT) S.copy_overlays(src) var/newcolor = list(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(0,0,0)) if(colorlist) diff --git a/code/game/objects/structures/pinatas.dm b/code/game/objects/structures/pinatas.dm index 6483d39b1a26c..44d7a8b021594 100644 --- a/code/game/objects/structures/pinatas.dm +++ b/code/game/objects/structures/pinatas.dm @@ -28,7 +28,7 @@ . = ..() if(get_integrity() < (max_integrity/2)) icon_state = "[base_icon_state]_damaged" - if(damage_amount >= 10) // Swing means minimum damage threshhold for dropping candy is met. + if(damage_amount >= 10) // Swing means minimum damage threshold for dropping candy is met. flick("[icon_state]_swing", src) /obj/structure/pinata/play_attack_sound(damage_amount, damage_type, damage_flag) diff --git a/code/game/objects/structures/plaques/_plaques.dm b/code/game/objects/structures/plaques/_plaques.dm index 1277869dbf67f..951a538e7241a 100644 --- a/code/game/objects/structures/plaques/_plaques.dm +++ b/code/game/objects/structures/plaques/_plaques.dm @@ -88,7 +88,7 @@ var/namechoice = tgui_input_text(user, "Title this plaque. (e.g. 'Best HoP Award', 'Great Ashwalker War Memorial')", "Plaque Customization", max_length = MAX_NAME_LEN) if(!namechoice) return - var/descriptionchoice = tgui_input_text(user, "Engrave this plaque's text", "Plaque Customization") + var/descriptionchoice = tgui_input_text(user, "Engrave this plaque's text", "Plaque Customization", max_length = MAX_PLAQUE_LEN) if(!descriptionchoice) return if(!Adjacent(user)) //Make sure user is adjacent still @@ -161,7 +161,7 @@ var/namechoice = tgui_input_text(user, "Title this plaque. (e.g. 'Best HoP Award', 'Great Ashwalker War Memorial')", "Plaque Customization", max_length = MAX_NAME_LEN) if(!namechoice) return - var/descriptionchoice = tgui_input_text(user, "Engrave this plaque's text", "Plaque Customization") + var/descriptionchoice = tgui_input_text(user, "Engrave this plaque's text", "Plaque Customization", max_length = MAX_PLAQUE_LEN) if(!descriptionchoice) return if(!Adjacent(user)) //Make sure user is adjacent still diff --git a/code/game/objects/structures/railings.dm b/code/game/objects/structures/railings.dm index 06a099ad4f906..fe2e4b06b4f10 100644 --- a/code/game/objects/structures/railings.dm +++ b/code/game/objects/structures/railings.dm @@ -4,7 +4,7 @@ icon = 'icons/obj/railings.dmi' icon_state = "railing" flags_1 = ON_BORDER_1 - obj_flags = CAN_BE_HIT | BLOCKS_CONSTRUCTION_DIR + obj_flags = CAN_BE_HIT | BLOCKS_CONSTRUCTION_DIR | IGNORE_DENSITY density = TRUE anchored = TRUE pass_flags_self = LETPASSTHROW|PASSSTRUCTURE diff --git a/code/game/objects/structures/signs/_signs.dm b/code/game/objects/structures/signs/_signs.dm index 9268cb9c059ce..d3713ca1b2f68 100644 --- a/code/game/objects/structures/signs/_signs.dm +++ b/code/game/objects/structures/signs/_signs.dm @@ -12,7 +12,7 @@ var/buildable_sign = TRUE ///This determines if you can select this sign type when using a pen on a sign backing. False by default, set to true per sign type to override. var/is_editable = FALSE - ///sign_change_name is used to make nice looking, alphebetized and categorized names when you use a pen on any sign item or structure which is_editable. + ///sign_change_name is used to make nice looking, alphabetized and categorized names when you use a pen on any sign item or structure which is_editable. var/sign_change_name ///Callback to the knock down proc for wallmounting behavior. var/knock_down_callback @@ -135,7 +135,7 @@ unwrenched_sign.setDir(dir) qdel(src) //The sign structure on the wall goes poof and only the sign item from unwrenching remains. -/obj/structure/sign/blank //This subtype is necessary for now because some other things (posters, picture frames, paintings) inheret from the parent type. +/obj/structure/sign/blank //This subtype is necessary for now because some other things (posters, picture frames, paintings) inherit from the parent type. icon_state = "backing" name = "sign backing" desc = "A plastic sign backing, use a pen to change the decal. It can be detached from the wall with a wrench." diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 8dc8d82ff5f7d..32e76bb2c83ee 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -55,6 +55,8 @@ AddElement(/datum/element/give_turf_traits, give_turf_traits) register_context() + ADD_TRAIT(src, TRAIT_COMBAT_MODE_SKIP_INTERACTION, INNATE_TRAIT) + ///Adds the element used to make the object climbable, and also the one that shift the mob buckled to it up. /obj/structure/table/proc/make_climbable() AddElement(/datum/element/climbable) @@ -224,36 +226,24 @@ deconstruct(TRUE) return ITEM_INTERACT_SUCCESS -/obj/structure/table/item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers) - if(istype(tool, /obj/item/construction/rcd)) - return NONE +// This extends base item interaction because tables default to blocking 99% of interactions +/obj/structure/table/base_item_interaction(mob/living/user, obj/item/tool, list/modifiers) + . = ..() + if(.) + return . - var/deck_act_value = NONE if(istype(tool, /obj/item/toy/cards/deck)) - deck_act_value = deck_act(user, tool, modifiers, TRUE) - // Continue to placing if we don't do anything else - if(deck_act_value != NONE) - return deck_act_value - - if(!user.combat_mode) - return table_place_act(user, tool, modifiers) - - return NONE - -/obj/structure/table/item_interaction(mob/living/user, obj/item/tool, list/modifiers) - . = NONE + . = deck_act(user, tool, modifiers, !!LAZYACCESS(modifiers, RIGHT_CLICK)) if(istype(tool, /obj/item/storage/bag/tray)) . = tray_act(user, tool) - else if(istype(tool, /obj/item/toy/cards/deck)) - . = deck_act(user, tool, modifiers, FALSE) else if(istype(tool, /obj/item/riding_offhand)) . = riding_offhand_act(user, tool) // Continue to placing if we don't do anything else - if(. != NONE) + if(.) return . - if(!user.combat_mode) + if(!user.combat_mode || (tool.item_flags & NOBLUDGEON)) return table_place_act(user, tool, modifiers) return NONE @@ -865,6 +855,7 @@ AddElement(/datum/element/climbable) AddElement(/datum/element/elevation, pixel_shift = 12) register_context() + ADD_TRAIT(src, TRAIT_COMBAT_MODE_SKIP_INTERACTION, INNATE_TRAIT) /obj/structure/rack/add_context(atom/source, list/context, obj/item/held_item, mob/living/user) if(isnull(held_item)) @@ -892,8 +883,11 @@ deconstruct(TRUE) return ITEM_INTERACT_SUCCESS -/obj/structure/rack/item_interaction(mob/living/user, obj/item/tool, list/modifiers) - if((tool.item_flags & ABSTRACT) || user.combat_mode) +/obj/structure/rack/base_item_interaction(mob/living/user, obj/item/tool, list/modifiers) + . = ..() + if(.) + return . + if((tool.item_flags & ABSTRACT) || (user.combat_mode && !(tool.item_flags & NOBLUDGEON))) return NONE if(user.transferItemToLoc(tool, drop_location(), silent = FALSE)) return ITEM_INTERACT_SUCCESS diff --git a/code/game/objects/structures/tank_dispenser.dm b/code/game/objects/structures/tank_dispenser.dm index 2d16ea30a69e4..46c18d85b407f 100644 --- a/code/game/objects/structures/tank_dispenser.dm +++ b/code/game/objects/structures/tank_dispenser.dm @@ -71,7 +71,7 @@ oxygentanks++ else full = TRUE - else if(!user.combat_mode) + else if(!user.combat_mode || (I.item_flags & NOBLUDGEON)) balloon_alert(user, "can't insert!") return else diff --git a/code/game/objects/structures/votingbox.dm b/code/game/objects/structures/votingbox.dm index 42ccd62509304..55909978fe2f7 100644 --- a/code/game/objects/structures/votingbox.dm +++ b/code/game/objects/structures/votingbox.dm @@ -94,7 +94,7 @@ ui_interact(user) /obj/structure/votebox/proc/set_description(mob/user) - var/new_description = tgui_input_text(user, "Enter a new description", "Vote Description", vote_description, multiline = TRUE) + var/new_description = tgui_input_text(user, "Enter a new description", "Vote Description", vote_description, multiline = TRUE, max_length = MAX_DESC_LEN) if(new_description) vote_description = new_description diff --git a/code/game/objects/structures/water_structures/sink.dm b/code/game/objects/structures/water_structures/sink.dm index 878dab578a52e..1cd3f7d7aaa53 100644 --- a/code/game/objects/structures/water_structures/sink.dm +++ b/code/game/objects/structures/water_structures/sink.dm @@ -204,7 +204,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/sink, (-14)) if(O.item_flags & ABSTRACT) //Abstract items like grabs won't wash. No-drop items will though because it's still technically an item in your hand. return - if(!user.combat_mode) + if(!user.combat_mode || (O.item_flags & NOBLUDGEON)) to_chat(user, span_notice("You start washing [O]...")) busy = TRUE if(!do_after(user, 4 SECONDS, target = src)) diff --git a/code/game/objects/structures/water_structures/water_source.dm b/code/game/objects/structures/water_structures/water_source.dm index 9420156d91805..a59051f92dd50 100644 --- a/code/game/objects/structures/water_structures/water_source.dm +++ b/code/game/objects/structures/water_structures/water_source.dm @@ -114,7 +114,7 @@ attacking_item.use(1) return - if(!user.combat_mode) + if(!user.combat_mode || (attacking_item.item_flags & NOBLUDGEON)) to_chat(user, span_notice("You start washing [attacking_item]...")) busy = TRUE if(!do_after(user, 4 SECONDS, target = src)) diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm index 4c22cbf01b29d..4ff29eb606e8f 100644 --- a/code/game/objects/structures/windoor_assembly.dm +++ b/code/game/objects/structures/windoor_assembly.dm @@ -252,7 +252,7 @@ ae.forceMove(drop_location()) else if(IS_WRITING_UTENSIL(W)) - var/t = tgui_input_text(user, "Enter the name for the door", "Windoor Renaming", created_name, MAX_NAME_LEN) + var/t = tgui_input_text(user, "Enter the name for the door", "Windoor Renaming", created_name, max_length = MAX_NAME_LEN) if(!t) return if(!in_range(src, usr) && loc != usr) diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index f2a90d98dc52d..fdb5193035c84 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -505,7 +505,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/window/unanchored/spawner, 0) switch(state) if(RWINDOW_SECURE) if(tool.tool_behaviour == TOOL_WELDER) - if(tool.tool_start_check(user)) + if(tool.tool_start_check(user, heat_required = HIGH_TEMPERATURE_REQUIRED)) user.visible_message(span_notice("[user] holds \the [tool] to the security screws on \the [src]..."), span_notice("You begin heating the security screws on \the [src]...")) if(tool.use_tool(src, user, 15 SECONDS, volume = 100)) diff --git a/code/game/shuttle_engines.dm b/code/game/shuttle_engines.dm index 8ddae94231d31..52372448616c7 100644 --- a/code/game/shuttle_engines.dm +++ b/code/game/shuttle_engines.dm @@ -113,7 +113,7 @@ if(ENGINE_UNWRENCHED) to_chat(user, span_warning("The [src.name] needs to be wrenched to the floor!")) if(ENGINE_WRENCHED) - if(!tool.tool_start_check(user, amount=round(ENGINE_WELDTIME / 5))) + if(!tool.tool_start_check(user, amount=round(ENGINE_WELDTIME / 5), heat_required = HIGH_TEMPERATURE_REQUIRED)) return TRUE user.visible_message(span_notice("[user.name] starts to weld the [name] to the floor."), \ @@ -126,7 +126,7 @@ alter_engine_power(engine_power) if(ENGINE_WELDED) - if(!tool.tool_start_check(user, amount=round(ENGINE_WELDTIME / 5))) + if(!tool.tool_start_check(user, amount=round(ENGINE_WELDTIME / 5), heat_required = HIGH_TEMPERATURE_REQUIRED)) return TRUE user.visible_message(span_notice("[user.name] starts to cut the [name] free from the floor."), \ diff --git a/code/game/turfs/closed/_closed.dm b/code/game/turfs/closed/_closed.dm index 8ccaabc46c0af..cf287a6eb6d88 100644 --- a/code/game/turfs/closed/_closed.dm +++ b/code/game/turfs/closed/_closed.dm @@ -15,3 +15,6 @@ /turf/closed/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir) return FALSE + +/turf/closed/examine_descriptor(mob/user) + return "wall" diff --git a/code/game/turfs/closed/wall/reinf_walls.dm b/code/game/turfs/closed/wall/reinf_walls.dm index e94a31eeafef4..739ee5aeae0f4 100644 --- a/code/game/turfs/closed/wall/reinf_walls.dm +++ b/code/game/turfs/closed/wall/reinf_walls.dm @@ -76,7 +76,7 @@ if(COVER) if(W.tool_behaviour == TOOL_WELDER) - if(!W.tool_start_check(user, amount=2)) + if(!W.tool_start_check(user, amount=2, heat_required = HIGH_TEMPERATURE_REQUIRED)) return to_chat(user, span_notice("You begin slicing through the metal cover...")) if(W.use_tool(src, user, 60, volume=100)) @@ -109,7 +109,7 @@ return TRUE if(W.tool_behaviour == TOOL_WELDER) - if(!W.tool_start_check(user, amount=2)) + if(!W.tool_start_check(user, amount=2, heat_required = HIGH_TEMPERATURE_REQUIRED)) return to_chat(user, span_notice("You begin welding the metal cover back to the frame...")) if(W.use_tool(src, user, 60, volume=100)) @@ -143,7 +143,7 @@ if(SUPPORT_RODS) if(W.tool_behaviour == TOOL_WELDER) - if(!W.tool_start_check(user, amount=2)) + if(!W.tool_start_check(user, amount=2, heat_required = HIGH_TEMPERATURE_REQUIRED)) return to_chat(user, span_notice("You begin slicing through the support rods...")) if(W.use_tool(src, user, 100, volume=100)) @@ -176,7 +176,7 @@ return TRUE if(W.tool_behaviour == TOOL_WELDER) - if(!W.tool_start_check(user, amount=0)) + if(!W.tool_start_check(user, amount=0, heat_required = HIGH_TEMPERATURE_REQUIRED)) return to_chat(user, span_notice("You begin welding the support rods back together...")) if(W.use_tool(src, user, 100, volume=100)) diff --git a/code/game/turfs/closed/walls.dm b/code/game/turfs/closed/walls.dm index a78579d713e9a..0fbe774a7c5ae 100644 --- a/code/game/turfs/closed/walls.dm +++ b/code/game/turfs/closed/walls.dm @@ -117,7 +117,6 @@ GLOB.station_turfs -= src return ..() - /turf/closed/wall/examine(mob/user) . += ..() . += deconstruction_hints(user) @@ -238,23 +237,18 @@ playsound(src, 'sound/weapons/genhit.ogg', 25, TRUE) add_fingerprint(user) -/turf/closed/wall/attackby(obj/item/W, mob/user, params) - user.changeNext_move(CLICK_CD_MELEE) +/turf/closed/wall/item_interaction(mob/living/user, obj/item/tool, list/modifiers) if (!ISADVANCEDTOOLUSER(user)) to_chat(user, span_warning("You don't have the dexterity to do this!")) - return - - //get the user's location - if(!isturf(user.loc)) - return //can't do this stuff whilst inside objects and such + return ITEM_INTERACT_BLOCKING add_fingerprint(user) //the istype cascade has been spread among various procs for easy overriding - if(try_clean(W, user) || try_wallmount(W, user) || try_decon(W, user)) - return + if(try_clean(tool, user) || try_wallmount(tool, user) || try_decon(tool, user)) + return ITEM_INTERACT_SUCCESS - return ..() + return NONE /turf/closed/wall/proc/try_clean(obj/item/W, mob/living/user) if((user.combat_mode) || !LAZYLEN(dent_decals)) @@ -290,7 +284,7 @@ /turf/closed/wall/proc/try_decon(obj/item/I, mob/user) if(I.tool_behaviour == TOOL_WELDER) - if(!I.tool_start_check(user, amount=round(slicing_duration / 50))) + if(!I.tool_start_check(user, amount=round(slicing_duration / 50), heat_required = HIGH_TEMPERATURE_REQUIRED)) return FALSE to_chat(user, span_notice("You begin slicing through the outer plating...")) diff --git a/code/game/turfs/open/_open.dm b/code/game/turfs/open/_open.dm index f9b374c88cb88..01478f4d9f02b 100644 --- a/code/game/turfs/open/_open.dm +++ b/code/game/turfs/open/_open.dm @@ -74,6 +74,9 @@ . += burnt_appearance +/turf/open/examine_descriptor(mob/user) + return "floor" + //direction is direction of travel of A /turf/open/zPassIn(direction) if(direction != DOWN) diff --git a/code/game/turfs/open/floor.dm b/code/game/turfs/open/floor.dm index 84b9ac26e9b8d..dad46fd8de6b6 100644 --- a/code/game/turfs/open/floor.dm +++ b/code/game/turfs/open/floor.dm @@ -14,8 +14,8 @@ smoothing_groups = SMOOTH_GROUP_TURF_OPEN + SMOOTH_GROUP_OPEN_FLOOR canSmoothWith = SMOOTH_GROUP_TURF_OPEN + SMOOTH_GROUP_OPEN_FLOOR - thermal_conductivity = 0.04 - heat_capacity = 10000 + thermal_conductivity = 0.02 + heat_capacity = 20000 tiled_dirt = TRUE diff --git a/code/game/turfs/open/floor/reinforced_floor.dm b/code/game/turfs/open/floor/reinforced_floor.dm index 0a44c78ceca5e..dcba9ed36673a 100644 --- a/code/game/turfs/open/floor/reinforced_floor.dm +++ b/code/game/turfs/open/floor/reinforced_floor.dm @@ -4,7 +4,7 @@ desc = "Extremely sturdy." icon_state = "engine" holodeck_compatible = TRUE - thermal_conductivity = 0.025 + thermal_conductivity = 0.01 heat_capacity = INFINITY floor_tile = /obj/item/stack/rods footstep = FOOTSTEP_PLATING diff --git a/code/game/turfs/open/ice.dm b/code/game/turfs/open/ice.dm index dbfff2efc8f91..f28bc8dd4b052 100644 --- a/code/game/turfs/open/ice.dm +++ b/code/game/turfs/open/ice.dm @@ -53,6 +53,7 @@ return NONE balloon_alert(user, "dug hole") AddComponent(/datum/component/fishing_spot, GLOB.preset_fish_sources[/datum/fish_source/ice_fishing]) + ADD_TRAIT(src, TRAIT_CATCH_AND_RELEASE, INNATE_TRAIT) add_overlay(mutable_appearance('icons/turf/overlays.dmi', "ice_hole")) can_make_hole = FALSE RemoveElement(/datum/element/contextual_screentip_tools, tool_screentips) diff --git a/code/game/turfs/open/lava.dm b/code/game/turfs/open/lava.dm index 23e2b6b38db84..c080e228438a5 100644 --- a/code/game/turfs/open/lava.dm +++ b/code/game/turfs/open/lava.dm @@ -48,6 +48,8 @@ . = ..() if(fish_source_type) AddElement(/datum/element/lazy_fishing_spot, fish_source_type) + // You can release chrabs and lavaloops and likes in lava, or be an absolute scumbag and drop other fish there too. + ADD_TRAIT(src, TRAIT_CATCH_AND_RELEASE, INNATE_TRAIT) refresh_light() if(!smoothing_flags) update_appearance() diff --git a/code/game/turfs/open/misc.dm b/code/game/turfs/open/misc.dm index 5c5987f656e23..f00e6ed6ded6e 100644 --- a/code/game/turfs/open/misc.dm +++ b/code/game/turfs/open/misc.dm @@ -17,8 +17,8 @@ smoothing_groups = SMOOTH_GROUP_TURF_OPEN canSmoothWith = SMOOTH_GROUP_TURF_OPEN + SMOOTH_GROUP_OPEN_FLOOR - thermal_conductivity = 0.04 - heat_capacity = 10000 + thermal_conductivity = 0.02 + heat_capacity = 20000 tiled_dirt = TRUE /turf/open/misc/attackby(obj/item/W, mob/user, params) diff --git a/code/game/turfs/open/water.dm b/code/game/turfs/open/water.dm index de895754d03ae..835d29089181b 100644 --- a/code/game/turfs/open/water.dm +++ b/code/game/turfs/open/water.dm @@ -1,4 +1,5 @@ /turf/open/water + name = "water" gender = PLURAL desc = "Shallow water." icon = 'icons/turf/floors.dmi' @@ -29,6 +30,7 @@ AddElement(/datum/element/watery_tile) if(!isnull(fishing_datum)) AddElement(/datum/element/lazy_fishing_spot, fishing_datum) + ADD_TRAIT(src, TRAIT_CATCH_AND_RELEASE, INNATE_TRAIT) /turf/open/water/jungle diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index b0493ce0a8ad4..19356c2e32309 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -32,7 +32,7 @@ GLOBAL_LIST_EMPTY(station_turfs) var/temperature = T20C ///Used for fire, if a melting temperature was reached, it will be destroyed var/to_be_destroyed = 0 - ///The max temperature of the fire which it was subjected to + ///The max temperature of the fire which it was subjected to, determines the melting point of turf var/max_fire_temperature_sustained = 0 var/blocks_air = FALSE @@ -231,7 +231,7 @@ GLOBAL_LIST_EMPTY(station_turfs) /// Call to move a turf from its current area to a new one /turf/proc/change_area(area/old_area, area/new_area) - //dont waste our time + //don't waste our time if(old_area == new_area) return @@ -277,7 +277,7 @@ GLOBAL_LIST_EMPTY(station_turfs) // We don't want to block ourselves if((movable_content == source_atom)) continue - // dont consider ignored atoms or their types + // don't consider ignored atoms or their types if(length(ignore_atoms)) if(!type_list && (movable_content in ignore_atoms)) continue @@ -306,7 +306,7 @@ GLOBAL_LIST_EMPTY(station_turfs) return TRUE return FALSE -//The zpass procs exist to be overriden, not directly called +//The zpass procs exist to be overridden, not directly called //use can_z_pass for that ///If we'd allow anything to travel into us /turf/proc/zPassIn(direction) @@ -426,7 +426,7 @@ GLOBAL_LIST_EMPTY(station_turfs) if(thing == mover || thing == mover_loc) // Multi tile objects and moving out of other objects continue if(!thing.Cross(mover)) - if(QDELETED(mover)) //deleted from Cross() (CanPass is pure so it cant delete, Cross shouldnt be doing this either though, but it can happen) + if(QDELETED(mover)) //deleted from Cross() (CanPass is pure so it can't delete, Cross shouldn't be doing this either though, but it can happen) return FALSE if(mover_is_phasing) mover.Bump(thing) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 68096367ef80b..1510783fc7cb8 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -320,7 +320,7 @@ ADMIN_VERB(give_mob_action, R_FUN, "Give Mob Action", ADMIN_VERB_NO_DESCRIPTION, if(isnull(ability_melee_cooldown) || ability_melee_cooldown < 0) ability_melee_cooldown = 2 add_ability.melee_cooldown_time = ability_melee_cooldown * 1 SECONDS - add_ability.name = tgui_input_text(user, "Choose ability name", "Ability name", "Generic Ability") + add_ability.name = tgui_input_text(user, "Choose ability name", "Ability name", "Generic Ability", max_length = MAX_NAME_LEN) add_ability.create_sequence_actions() else add_ability = new ability_type(ability_recipient) @@ -523,7 +523,7 @@ ADMIN_VERB(spawn_debug_full_crew, R_DEBUG, "Spawn Debug Full Crew", "Creates a f // Then, spawn a human and slap a person into it. var/number_made = 0 for(var/rank in SSjob.name_occupations) - var/datum/job/job = SSjob.GetJob(rank) + var/datum/job/job = SSjob.get_job(rank) // JOB_CREW_MEMBER is all jobs that pretty much aren't silicon if(!(job.job_flags & JOB_CREW_MEMBER)) @@ -535,7 +535,7 @@ ADMIN_VERB(spawn_debug_full_crew, R_DEBUG, "Spawn Debug Full Crew", "Creates a f new_guy.mind.name = "[rank] Dummy" // Assign the rank to the new player dummy. - if(!SSjob.AssignRole(new_guy, job, do_eligibility_checks = FALSE)) + if(!SSjob.assign_role(new_guy, job, do_eligibility_checks = FALSE)) qdel(new_guy) to_chat(user, "[rank] wasn't able to be spawned.") continue @@ -547,7 +547,7 @@ ADMIN_VERB(spawn_debug_full_crew, R_DEBUG, "Spawn Debug Full Crew", "Creates a f qdel(new_guy) // Then equip up the human with job gear. - SSjob.EquipRank(character, job) + SSjob.equip_rank(character, job) job.after_latejoin_spawn(character) // Finally, ensure the minds are tracked and in the manifest. diff --git a/code/modules/admin/outfit_editor.dm b/code/modules/admin/outfit_editor.dm index 67196c54bd434..a3bd433f52e40 100644 --- a/code/modules/admin/outfit_editor.dm +++ b/code/modules/admin/outfit_editor.dm @@ -100,7 +100,7 @@ drip.vars[slot] = null if("rename") - var/newname = tgui_input_text(owner, "What do you want to name this outfit?", OUTFIT_EDITOR_NAME) + var/newname = tgui_input_text(owner, "What do you want to name this outfit?", OUTFIT_EDITOR_NAME, max_length = MAX_NAME_LEN) if(newname) drip.name = newname if("save") diff --git a/code/modules/admin/painting_manager.dm b/code/modules/admin/painting_manager.dm index 7a8bd7127a4d3..5ebcdef005904 100644 --- a/code/modules/admin/painting_manager.dm +++ b/code/modules/admin/painting_manager.dm @@ -55,7 +55,7 @@ ADMIN_VERB(painting_manager, R_ADMIN, "Paintings Manager", "View and redact pain if("rename") //Modify the metadata var/old_title = chosen_painting.title - var/new_title = tgui_input_text(user, "New painting title?", "Painting Rename", chosen_painting.title) + var/new_title = tgui_input_text(user, "New painting title?", "Painting Rename", chosen_painting.title, max_length = MAX_NAME_LEN) if(!new_title) return chosen_painting.title = new_title @@ -63,7 +63,7 @@ ADMIN_VERB(painting_manager, R_ADMIN, "Paintings Manager", "View and redact pain return TRUE if("rename_author") var/old_name = chosen_painting.creator_name - var/new_name = tgui_input_text(user, "New painting author name?", "Painting Rename", chosen_painting.creator_name) + var/new_name = tgui_input_text(user, "New painting author name?", "Painting Rename", chosen_painting.creator_name, max_length = MAX_NAME_LEN) if(!new_name) return chosen_painting.creator_name = new_name @@ -83,7 +83,7 @@ ADMIN_VERB(painting_manager, R_ADMIN, "Paintings Manager", "View and redact pain log_admin("[key_name(user)] has removed tag [params["tag"]] from persistent painting made by [chosen_painting.creator_ckey] with id [chosen_painting.md5].") return TRUE if("add_tag") - var/tag_name = tgui_input_text(user, "New tag name?", "Add Tag") + var/tag_name = tgui_input_text(user, "New tag name?", "Add Tag", max_length = MAX_NAME_LEN) if(!tag_name) return if(!chosen_painting.tags) diff --git a/code/modules/admin/sound_emitter.dm b/code/modules/admin/sound_emitter.dm index d697537c6df5f..c68baa32e4ea1 100644 --- a/code/modules/admin/sound_emitter.dm +++ b/code/modules/admin/sound_emitter.dm @@ -81,7 +81,7 @@ return var/mob/user = usr if(href_list["edit_label"]) - var/new_label = tgui_input_text(user, "Choose a new label", "Sound Emitter") + var/new_label = tgui_input_text(user, "Choose a new label", "Sound Emitter", max_length = MAX_NAME_LEN) if(!new_label) return maptext = MAPTEXT(new_label) diff --git a/code/modules/admin/verbs/admin.dm b/code/modules/admin/verbs/admin.dm index 37c50f53225ce..a0d772f665fe1 100644 --- a/code/modules/admin/verbs/admin.dm +++ b/code/modules/admin/verbs/admin.dm @@ -32,7 +32,7 @@ ADMIN_VERB(unprison, R_ADMIN, "UnPrison", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEG tgui_alert(user, "[prisoner.name] is not prisoned.") return - SSjob.SendToLateJoin(prisoner) + SSjob.send_to_late_join(prisoner) message_admins("[key_name_admin(user)] has unprisoned [key_name_admin(prisoner)]") log_admin("[key_name(user)] has unprisoned [key_name(prisoner)]") BLACKBOX_LOG_ADMIN_VERB("Unprison") diff --git a/code/modules/admin/verbs/admin_newscaster.dm b/code/modules/admin/verbs/admin_newscaster.dm index 4cb7b5c3344e2..b1be5560d69d9 100644 --- a/code/modules/admin/verbs/admin_newscaster.dm +++ b/code/modules/admin/verbs/admin_newscaster.dm @@ -234,14 +234,14 @@ ADMIN_VERB(access_news_network, R_ADMIN, "Access Newscaster Network", "Allows yo return TRUE if("setCriminalName") - var/temp_name = tgui_input_text(usr, "Write the Criminal's Name", "Warrent Alert Handler", "John Doe", MAX_NAME_LEN, multiline = FALSE) + var/temp_name = tgui_input_text(usr, "Write the Criminal's Name", "Warrent Alert Handler", "John Doe", max_length = MAX_NAME_LEN, multiline = FALSE) if(!temp_name) return TRUE criminal_name = temp_name return TRUE if("setCrimeData") - var/temp_desc = tgui_input_text(usr, "Write the Criminal's Crimes", "Warrent Alert Handler", "Unknown", MAX_BROADCAST_LEN, multiline = TRUE) + var/temp_desc = tgui_input_text(usr, "Write the Criminal's Crimes", "Warrent Alert Handler", "Unknown", max_length = MAX_BROADCAST_LEN, multiline = TRUE) if(!temp_desc) return TRUE crime_description = temp_desc @@ -339,7 +339,7 @@ ADMIN_VERB(access_news_network, R_ADMIN, "Access Newscaster Network", "Allows yo if(channel_name == potential_channel.channel_ID) current_channel = potential_channel break - var/temp_message = tgui_input_text(usr, "Write your Feed story", "Network Channel Handler", feed_channel_message, multiline = TRUE) + 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 if(temp_message) diff --git a/code/modules/admin/verbs/adminevents.dm b/code/modules/admin/verbs/adminevents.dm index 214cf653d4e1f..d2eeba90262cf 100644 --- a/code/modules/admin/verbs/adminevents.dm +++ b/code/modules/admin/verbs/adminevents.dm @@ -269,13 +269,21 @@ ADMIN_VERB(command_report_footnote, R_ADMIN, "Command Report Footnote", "Adds a var/datum/command_footnote/command_report_footnote = new /datum/command_footnote() GLOB.communications_controller.block_command_report += 1 //Add a blocking condition to the counter until the inputs are done. - command_report_footnote.message = tgui_input_text(user, "This message will be attached to the bottom of the roundstart threat report. Be sure to delay the roundstart report if you need extra time.", "P.S.") + command_report_footnote.message = tgui_input_text( + user, + "This message will be attached to the bottom of the roundstart threat report. Be sure to delay the roundstart report if you need extra time.", + "P.S.", + ) if(!command_report_footnote.message) GLOB.communications_controller.block_command_report -= 1 qdel(command_report_footnote) return - command_report_footnote.signature = tgui_input_text(user, "Whose signature will appear on this footnote?", "Also sign here, here, aaand here.") + command_report_footnote.signature = tgui_input_text( + user, + "Whose signature will appear on this footnote?", + "Also sign here, here, aaand here.", + ) if(!command_report_footnote.signature) command_report_footnote.signature = "Classified" diff --git a/code/modules/admin/verbs/admingame.dm b/code/modules/admin/verbs/admingame.dm index 5982f62e5a904..488c670a19d4b 100644 --- a/code/modules/admin/verbs/admingame.dm +++ b/code/modules/admin/verbs/admingame.dm @@ -153,20 +153,24 @@ ADMIN_VERB_ONLY_CONTEXT_MENU(show_player_panel, R_ADMIN, "Show Player Panel", mo user << browse(body, "window=adminplayeropts-[REF(player)];size=550x515") BLACKBOX_LOG_ADMIN_VERB("Player Panel") -/client/proc/cmd_admin_godmode(mob/M in GLOB.mob_list) +/client/proc/cmd_admin_godmode(mob/mob in GLOB.mob_list) set category = "Admin.Game" set name = "Godmode" if(!check_rights(R_ADMIN)) return - M.status_flags ^= GODMODE - to_chat(usr, span_adminnotice("Toggled [(M.status_flags & GODMODE) ? "ON" : "OFF"]"), confidential = TRUE) + var/had_trait = HAS_TRAIT_FROM(mob, TRAIT_GODMODE, ADMIN_TRAIT) + if(had_trait) + REMOVE_TRAIT(mob, TRAIT_GODMODE, ADMIN_TRAIT) + else + ADD_TRAIT(mob, TRAIT_GODMODE, ADMIN_TRAIT) + to_chat(usr, span_adminnotice("Toggled [had_trait ? "OFF" : "ON"]"), confidential = TRUE) - log_admin("[key_name(usr)] has toggled [key_name(M)]'s nodamage to [(M.status_flags & GODMODE) ? "On" : "Off"]") - var/msg = "[key_name_admin(usr)] has toggled [ADMIN_LOOKUPFLW(M)]'s nodamage to [(M.status_flags & GODMODE) ? "On" : "Off"]" + log_admin("[key_name(usr)] has toggled [key_name(mob)]'s nodamage to [had_trait ? "Off" : "On"]") + var/msg = "[key_name_admin(usr)] has toggled [ADMIN_LOOKUPFLW(mob)]'s nodamage to [had_trait ? "Off" : "On"]" message_admins(msg) - admin_ticket_log(M, msg) - SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Godmode", "[M.status_flags & GODMODE ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! + admin_ticket_log(mob, msg) + SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Godmode", "[had_trait ? "Disabled" : "Enabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! /* If a guy was gibbed and you want to revive him, this is a good way to do so. @@ -193,7 +197,7 @@ ADMIN_VERB(respawn_character, R_ADMIN, "Respawn Character", "Respawn a player th if(findtext(G_found.real_name,"monkey")) if(tgui_alert(user,"This character appears to have been a monkey. Would you like to respawn them as such?",,list("Yes","No")) == "Yes") var/mob/living/carbon/human/species/monkey/new_monkey = new - SSjob.SendToLateJoin(new_monkey) + SSjob.send_to_late_join(new_monkey) G_found.mind.transfer_to(new_monkey) //be careful when doing stuff like this! I've already checked the mind isn't in use new_monkey.key = G_found.key to_chat(new_monkey, "You have been fully respawned. Enjoy the game.", confidential = TRUE) @@ -205,7 +209,7 @@ ADMIN_VERB(respawn_character, R_ADMIN, "Respawn Character", "Respawn a player th //Ok, it's not a monkey. So, spawn a human. var/mob/living/carbon/human/new_character = new//The mob being spawned. - SSjob.SendToLateJoin(new_character) + SSjob.send_to_late_join(new_character) var/datum/record/locked/record_found //Referenced to later to either randomize or not randomize the character. if(G_found.mind && !G_found.mind.active) //mind isn't currently in use by someone/something @@ -228,7 +232,7 @@ ADMIN_VERB(respawn_character, R_ADMIN, "Respawn Character", "Respawn a player th else new_character.mind_initialize() if(is_unassigned_job(new_character.mind.assigned_role)) - new_character.mind.set_assigned_role(SSjob.GetJobType(SSjob.overflow_role)) + new_character.mind.set_assigned_role(SSjob.get_job_type(SSjob.overflow_role)) new_character.key = G_found.key @@ -245,7 +249,7 @@ ADMIN_VERB(respawn_character, R_ADMIN, "Respawn Character", "Respawn a player th //Now for special roles and equipment. var/datum/antagonist/traitor/traitordatum = new_character.mind.has_antag_datum(/datum/antagonist/traitor) if(traitordatum) - SSjob.EquipRank(new_character, new_character.mind.assigned_role, new_character.client) + SSjob.equip_rank(new_character, new_character.mind.assigned_role, new_character.client) new_character.mind.give_uplink(silent = TRUE, antag_datum = traitordatum) switch(new_character.mind.special_role) @@ -274,7 +278,7 @@ ADMIN_VERB(respawn_character, R_ADMIN, "Respawn Character", "Respawn a player th new_character = new_character.AIize() else if(!traitordatum) // Already equipped there. - SSjob.EquipRank(new_character, new_character.mind.assigned_role, new_character.client)//Or we simply equip them. + SSjob.equip_rank(new_character, new_character.mind.assigned_role, new_character.client)//Or we simply equip them. //Announces the character on all the systems, based on the record. if(!record_found && (new_character.mind.assigned_role.job_flags & JOB_CREW_MEMBER)) diff --git a/code/modules/admin/verbs/ai_triumvirate.dm b/code/modules/admin/verbs/ai_triumvirate.dm index d63994a25c319..38c2eba712c60 100644 --- a/code/modules/admin/verbs/ai_triumvirate.dm +++ b/code/modules/admin/verbs/ai_triumvirate.dm @@ -36,7 +36,7 @@ GLOBAL_DATUM(triple_ai_controller, /datum/triple_ai_controller) to_chat(usr, "This option is currently only usable during pregame. This may change at a later date.", confidential = TRUE) return - var/datum/job/job = SSjob.GetJobType(/datum/job/ai) + var/datum/job/job = SSjob.get_job_type(/datum/job/ai) if(!job) to_chat(usr, "Unable to locate the AI job", confidential = TRUE) CRASH("triple_ai() called, no /datum/job/ai to be found.") diff --git a/code/modules/admin/verbs/ert.dm b/code/modules/admin/verbs/ert.dm index 441a5d0dd56fe..23f1627503e06 100644 --- a/code/modules/admin/verbs/ert.dm +++ b/code/modules/admin/verbs/ert.dm @@ -248,7 +248,7 @@ ert_antag.random_names = ertemplate.random_names ert_operative.mind.add_antag_datum(ert_antag,ert_team) - ert_operative.mind.set_assigned_role(SSjob.GetJobType(ert_antag.ert_job_path)) + ert_operative.mind.set_assigned_role(SSjob.get_job_type(ert_antag.ert_job_path)) //Logging and cleanup ert_operative.log_message("has been selected as \a [ert_antag.name].", LOG_GAME) diff --git a/code/modules/admin/verbs/lawpanel.dm b/code/modules/admin/verbs/lawpanel.dm index f1daaf175761f..6de3ff70182b8 100644 --- a/code/modules/admin/verbs/lawpanel.dm +++ b/code/modules/admin/verbs/lawpanel.dm @@ -24,7 +24,7 @@ ADMIN_VERB(law_panel, R_ADMIN, "Law Panel", "View the AI laws.", ADMIN_CATEGORY_ var/lawtype = tgui_input_list(user, "Select law type", "Law type", lawtypes) if(isnull(lawtype)) return FALSE - var/lawtext = tgui_input_text(user, "Input law text", "Law text") + var/lawtext = tgui_input_text(user, "Input law text", "Law text") // admin verb so no max length and also any user-level input is config based already so ehhhh if(!lawtext) return FALSE if(QDELETED(src) || QDELETED(borgo)) diff --git a/code/modules/admin/verbs/secrets.dm b/code/modules/admin/verbs/secrets.dm index bcb89379ef40a..9012a8652bbff 100644 --- a/code/modules/admin/verbs/secrets.dm +++ b/code/modules/admin/verbs/secrets.dm @@ -84,7 +84,7 @@ ADMIN_VERB(secrets, R_NONE, "Secrets", "Abuse harder than you ever have before w if("infinite_sec") if(!is_debugger) return - var/datum/job/sec_job = SSjob.GetJobType(/datum/job/security_officer) + var/datum/job/sec_job = SSjob.get_job_type(/datum/job/security_officer) sec_job.total_positions = -1 sec_job.spawn_positions = -1 message_admins("[key_name_admin(holder)] has removed the cap on security officers.") diff --git a/code/modules/admin/view_variables/debug_variable_appearance.dm b/code/modules/admin/view_variables/debug_variable_appearance.dm index 6d87f6cc85d86..c5a367e83a064 100644 --- a/code/modules/admin/view_variables/debug_variable_appearance.dm +++ b/code/modules/admin/view_variables/debug_variable_appearance.dm @@ -38,6 +38,9 @@ // can't use the name either for byond reasons var/_vis_flags +#if (MIN_COMPILER_VERSION > 515 || MIN_COMPILER_BUILD > 1643) +#warn vis_flags should now be supported by mutable appearances so we can safely remove the weird copying in this code +#endif // all alone at the end of the universe GLOBAL_DATUM_INIT(pluto, /atom/movable, new /atom/movable(null)) @@ -63,6 +66,28 @@ GLOBAL_DATUM_INIT(pluto, /atom/movable, new /atom/movable(null)) return FALSE if(var_name == NAMEOF(src, realized_underlays)) return FALSE + +#if (MIN_COMPILER_VERSION >= 515 && MIN_COMPILER_BUILD >= 1643) +#warn X/Y/Z and contents are now fully unviewable on our supported versions, remove the below check +#endif + +// lummy removed these from the the MA/image type +#if (DM_VERSION <= 515 && DM_BUILD < 1643) + // Filtering out the stuff I know we don't care about + if(var_name == NAMEOF(src, x)) + return FALSE + if(var_name == NAMEOF(src, y)) + return FALSE + if(var_name == NAMEOF(src, z)) + return FALSE + #ifndef SPACEMAN_DMM // Spaceman doesn't believe in contents on appearances, sorry lads + if(var_name == NAMEOF(src, contents)) + return FALSE + #endif + if(var_name == NAMEOF(src, loc)) + return FALSE +#endif + // Could make an argument for this but I think they will just confuse people, so yeeet if(var_name == NAMEOF(src, vis_contents)) return FALSE return ..() diff --git a/code/modules/admin/view_variables/view_variables.dm b/code/modules/admin/view_variables/view_variables.dm index 37bf0911c608f..66ac70f3f62f7 100644 --- a/code/modules/admin/view_variables/view_variables.dm +++ b/code/modules/admin/view_variables/view_variables.dm @@ -3,7 +3,7 @@ ADMIN_VERB_AND_CONTEXT_MENU(debug_variables, R_NONE, "View Variables", "View the variables of a datum.", ADMIN_CATEGORY_DEBUG, datum/thing in world) user.debug_variables(thing) -// This is kept as a seperate proc because admins are able to show VV to non-admins +// This is kept as a separate proc because admins are able to show VV to non-admins /client/proc/debug_variables(datum/thing in world) set category = "Debug" @@ -23,7 +23,7 @@ ADMIN_VERB_AND_CONTEXT_MENU(debug_variables, R_NONE, "View Variables", "View the if(isappearance(thing)) thing = get_vv_appearance(thing) // this is /mutable_appearance/our_bs_subtype - var/islist = islist(thing) || (!isdatum(thing) && hascall(thing, "Cut")) // Some special lists dont count as lists, but can be detected by if they have list procs + var/islist = islist(thing) || (!isdatum(thing) && hascall(thing, "Cut")) // Some special lists don't count as lists, but can be detected by if they have list procs if(!islist && !isdatum(thing)) return diff --git a/code/modules/antagonists/_common/antag_spawner.dm b/code/modules/antagonists/_common/antag_spawner.dm index 5f7a7e579d3ee..da7c7e9e39cac 100644 --- a/code/modules/antagonists/_common/antag_spawner.dm +++ b/code/modules/antagonists/_common/antag_spawner.dm @@ -83,7 +83,7 @@ app.wiz_team = master_wizard.wiz_team master_wizard.wiz_team.add_member(app_mind) app_mind.add_antag_datum(app) - app_mind.set_assigned_role(SSjob.GetJobType(/datum/job/wizard_apprentice)) + app_mind.set_assigned_role(SSjob.get_job_type(/datum/job/wizard_apprentice)) app_mind.special_role = ROLE_WIZARD_APPRENTICE SEND_SOUND(M, sound('sound/effects/magic.ogg')) @@ -424,15 +424,7 @@ monkey_man.fully_replace_character_name(monkey_man.real_name, pick(GLOB.syndicate_monkey_names)) - monkey_man.dna.add_mutation(/datum/mutation/human/clever) - // Can't make them human or nonclever. At least not with the easy and boring way out. - for(var/datum/mutation/human/mutation as anything in monkey_man.dna.mutations) - mutation.mutadone_proof = TRUE - mutation.instability = 0 - - // Extra backup! - ADD_TRAIT(monkey_man, TRAIT_NO_DNA_SCRAMBLE, SPECIES_TRAIT) - // Anything else requires enough effort that they deserve it. + monkey_man.make_clever_and_no_dna_scramble() monkey_man.mind.enslave_mind_to_creator(user) diff --git a/code/modules/antagonists/abductor/abductor.dm b/code/modules/antagonists/abductor/abductor.dm index 7fc0c565ab1df..cd56fcdaa5cdc 100644 --- a/code/modules/antagonists/abductor/abductor.dm +++ b/code/modules/antagonists/abductor/abductor.dm @@ -70,7 +70,7 @@ return team /datum/antagonist/abductor/on_gain() - owner.set_assigned_role(SSjob.GetJobType(role_job)) + owner.set_assigned_role(SSjob.get_job_type(role_job)) owner.special_role = ROLE_ABDUCTOR objectives += team.objectives finalize_abductor() diff --git a/code/modules/antagonists/abductor/equipment/gear/abductor_items.dm b/code/modules/antagonists/abductor/equipment/gear/abductor_items.dm index 25bbea665777c..ab1636b4dedfd 100644 --- a/code/modules/antagonists/abductor/equipment/gear/abductor_items.dm +++ b/code/modules/antagonists/abductor/equipment/gear/abductor_items.dm @@ -48,7 +48,7 @@ icon_state = "gizmo_scan" to_chat(user, span_notice("You switch the device to [mode == GIZMO_SCAN? "SCAN": "MARK"] MODE")) -/obj/item/abductor/gizmo/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) +/obj/item/abductor/gizmo/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!ScientistCheck(user)) return ITEM_INTERACT_SKIP_TO_ATTACK // So you slap them with it if(!console) @@ -63,8 +63,10 @@ return ITEM_INTERACT_SUCCESS -/obj/item/abductor/gizmo/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) - return interact_with_atom(interacting_with, user, modifiers) +/obj/item/abductor/gizmo/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!ismob(interacting_with)) + return NONE + return ranged_interact_with_atom(interacting_with, user, modifiers) /obj/item/abductor/gizmo/proc/scan(atom/target, mob/living/user) if(ishuman(target)) @@ -104,15 +106,17 @@ icon_state = "silencer" inhand_icon_state = "gizmo" -/obj/item/abductor/silencer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) +/obj/item/abductor/silencer/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!AbductorCheck(user)) return ITEM_INTERACT_SKIP_TO_ATTACK // So you slap them with it radio_off(interacting_with, user) return ITEM_INTERACT_SUCCESS -/obj/item/abductor/silencer/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) - return interact_with_atom(interacting_with, user, modifiers) +/obj/item/abductor/silencer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!ismob(interacting_with)) + return NONE + return ranged_interact_with_atom(interacting_with, user, modifiers) /obj/item/abductor/silencer/proc/radio_off(atom/target, mob/living/user) if( !(user in (viewers(7,target))) ) @@ -155,10 +159,12 @@ icon_state = "mind_device_message" to_chat(user, span_notice("You switch the device to [mode == MIND_DEVICE_MESSAGE? "TRANSMISSION": "COMMAND"] MODE")) -/obj/item/abductor/mind_device/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) - return interact_with_atom(interacting_with, user, modifiers) - /obj/item/abductor/mind_device/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!ismob(interacting_with)) + return NONE + return ranged_interact_with_atom(interacting_with, user, modifiers) + +/obj/item/abductor/mind_device/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!ScientistCheck(user)) return ITEM_INTERACT_BLOCKING @@ -183,8 +189,12 @@ to_chat(user, span_warning("Your target is already under a mind-controlling influence!")) return - var/command = tgui_input_text(user, "Enter the command for your target to follow.\ - Uses Left: [target_gland.mind_control_uses], Duration: [DisplayTimeText(target_gland.mind_control_duration)]", "Enter command") + var/command = tgui_input_text( + user, + "Enter the command for your target to follow. Uses Left: [target_gland.mind_control_uses], Duration: [DisplayTimeText(target_gland.mind_control_duration)]", + "Enter command", + max_length = MAX_MESSAGE_LEN, + ) if(!command) return @@ -209,7 +219,7 @@ if(living_target.stat == DEAD) to_chat(user, span_warning("Your target is dead!")) return - var/message = tgui_input_text(user, "Message to send to your target's brain", "Enter message") + var/message = tgui_input_text(user, "Message to send to your target's brain", "Enter message", max_length = MAX_MESSAGE_LEN) if(!message) return if(QDELETED(living_target) || living_target.stat == DEAD) diff --git a/code/modules/antagonists/abductor/machinery/experiment.dm b/code/modules/antagonists/abductor/machinery/experiment.dm index 09790f4ba897e..27093778c3116 100644 --- a/code/modules/antagonists/abductor/machinery/experiment.dm +++ b/code/modules/antagonists/abductor/machinery/experiment.dm @@ -190,7 +190,7 @@ H.forceMove(console.pad.teleport_target) return //Area not chosen / It's not safe area - teleport to arrivals - SSjob.SendToLateJoin(H, FALSE) + SSjob.send_to_late_join(H, FALSE) return /obj/machinery/abductor/experiment/update_icon_state() diff --git a/code/modules/antagonists/blob/blobstrains/_reagent.dm b/code/modules/antagonists/blob/blobstrains/_reagent.dm index 2d7f4c5d34eb8..65a50621b1717 100644 --- a/code/modules/antagonists/blob/blobstrains/_reagent.dm +++ b/code/modules/antagonists/blob/blobstrains/_reagent.dm @@ -26,12 +26,21 @@ // These can only be applied by blobs. They are what (reagent) blobs are made out of. /datum/reagent/blob name = "Unknown" - description = "shouldn't exist and you should adminhelp immediately." + description = "" color = COLOR_WHITE taste_description = "bad code and slime" chemical_flags = NONE penetrates_skin = NONE + +/datum/reagent/blob/New() + ..() + + if(name == "Unknown") + description = "shouldn't exist and you should adminhelp immediately." + else if(description == "") + description = "[name] is the reagent created by that type of blob." + /// Used by blob reagents to calculate the reaction volume they should use when exposing mobs. /datum/reagent/blob/proc/return_mob_expose_reac_volume(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) if(exposed_mob.stat == DEAD || HAS_TRAIT(exposed_mob, TRAIT_BLOB_ALLY)) diff --git a/code/modules/antagonists/blob/blobstrains/cryogenic_poison.dm b/code/modules/antagonists/blob/blobstrains/cryogenic_poison.dm index a18d802ff7dd4..acb4d96c23ad8 100644 --- a/code/modules/antagonists/blob/blobstrains/cryogenic_poison.dm +++ b/code/modules/antagonists/blob/blobstrains/cryogenic_poison.dm @@ -12,7 +12,7 @@ /datum/reagent/blob/cryogenic_poison name = "Cryogenic Poison" - description = "will inject targets with a freezing poison that does high damage over time." + description = "A freezing poison that does high damage over time. Cryogenic poison blobs inject this into their victims." color = "#8BA6E9" taste_description = "brain freeze" diff --git a/code/modules/antagonists/blob/blobstrains/regenerative_materia.dm b/code/modules/antagonists/blob/blobstrains/regenerative_materia.dm index a62895ae6c4b7..d9010a965376e 100644 --- a/code/modules/antagonists/blob/blobstrains/regenerative_materia.dm +++ b/code/modules/antagonists/blob/blobstrains/regenerative_materia.dm @@ -12,6 +12,7 @@ /datum/reagent/blob/regenerative_materia name = "Regenerative Materia" + description = "Chemical that inflicts toxin damage and makes the target believe they are fully healed. Regenerative materia blobs inject this into their victims." taste_description = "heaven" color = "#A88FB7" diff --git a/code/modules/antagonists/blob/structures/_blob.dm b/code/modules/antagonists/blob/structures/_blob.dm index 324c91ea3a529..c7a2fc3a1107f 100644 --- a/code/modules/antagonists/blob/structures/_blob.dm +++ b/code/modules/antagonists/blob/structures/_blob.dm @@ -175,6 +175,7 @@ if(isspaceturf(T) && !(locate(/obj/structure/lattice) in T) && prob(80)) make_blob = FALSE playsound(src.loc, 'sound/effects/splat.ogg', 50, TRUE) //Let's give some feedback that we DID try to spawn in space, since players are used to it + balloon_alert(controller, "failed to expand!") ConsumeTile() //hit the tile we're in, making sure there are no border objects blocking us if(!T.CanPass(src, get_dir(T, src))) //is the target turf impassable diff --git a/code/modules/antagonists/blob/structures/core.dm b/code/modules/antagonists/blob/structures/core.dm index 6eeccc8c361dd..f995dc0b81b03 100644 --- a/code/modules/antagonists/blob/structures/core.dm +++ b/code/modules/antagonists/blob/structures/core.dm @@ -24,7 +24,7 @@ GLOB.blob_cores += src START_PROCESSING(SSobj, src) SSpoints_of_interest.make_point_of_interest(src) - update_appearance() //so it atleast appears + update_appearance() //so it at least appears if(!placed && !overmind) return INITIALIZE_HINT_QDEL if(overmind) diff --git a/code/modules/antagonists/brainwashing/brainwashing.dm b/code/modules/antagonists/brainwashing/brainwashing.dm index 57707688f4daf..5d5cca3cb6de1 100644 --- a/code/modules/antagonists/brainwashing/brainwashing.dm +++ b/code/modules/antagonists/brainwashing/brainwashing.dm @@ -61,7 +61,7 @@ return var/list/objectives = list() do - var/objective = tgui_input_text(admin, "Add an objective", "Brainwashing") + var/objective = tgui_input_text(admin, "Add an objective", "Brainwashing", max_length = MAX_MESSAGE_LEN) if(objective) objectives += objective while(tgui_alert(admin, "Add another objective?", "More Brainwashing", list("Yes","No")) == "Yes") diff --git a/code/modules/antagonists/changeling/powers/absorb.dm b/code/modules/antagonists/changeling/powers/absorb.dm index 7e13612153b49..d5ee0c2fc873a 100644 --- a/code/modules/antagonists/changeling/powers/absorb.dm +++ b/code/modules/antagonists/changeling/powers/absorb.dm @@ -41,9 +41,14 @@ owner.visible_message(span_danger("[owner] sucks the fluids from [target]!"), span_notice("We have absorbed [target].")) to_chat(target, span_userdanger("You are absorbed by the changeling!")) + var/true_absorbtion = (!isnull(target.client) || !isnull(target.mind) || !isnull(target.last_mind)) + if (!true_absorbtion) + to_chat(owner, span_changeling(span_bold("You absorb [target], but their weak DNA is not enough to satisfy your hunger."))) + if(!changeling.has_profile_with_dna(target.dna)) changeling.add_new_profile(target) - changeling.true_absorbs++ + if (true_absorbtion) + changeling.true_absorbs++ if(owner.nutrition < NUTRITION_LEVEL_WELL_FED) owner.set_nutrition(min((owner.nutrition + target.nutrition), NUTRITION_LEVEL_WELL_FED)) @@ -57,7 +62,8 @@ is_absorbing = FALSE changeling.adjust_chemicals(10) - changeling.can_respec = TRUE + if (true_absorbtion) + changeling.can_respec = TRUE if(target.stat != DEAD) target.investigate_log("has died from being changeling absorbed.", INVESTIGATE_DEATHS) diff --git a/code/modules/antagonists/clown_ops/clownop.dm b/code/modules/antagonists/clown_ops/clownop.dm index 07c1cc84ad756..9866ee30ccf13 100644 --- a/code/modules/antagonists/clown_ops/clownop.dm +++ b/code/modules/antagonists/clown_ops/clownop.dm @@ -11,7 +11,7 @@ nuke_icon_state = "bananiumbomb_base" /datum/antagonist/nukeop/clownop/admin_add(datum/mind/new_owner,mob/admin) - new_owner.set_assigned_role(SSjob.GetJobType(/datum/job/clown_operative)) + new_owner.set_assigned_role(SSjob.get_job_type(/datum/job/clown_operative)) new_owner.add_antag_datum(src) message_admins("[key_name_admin(admin)] has clown op'ed [key_name_admin(new_owner)].") log_admin("[key_name(admin)] has clown op'ed [key_name(new_owner)].") diff --git a/code/modules/antagonists/cult/cult_comms.dm b/code/modules/antagonists/cult/cult_comms.dm index 3d5677996502a..45c3aee695574 100644 --- a/code/modules/antagonists/cult/cult_comms.dm +++ b/code/modules/antagonists/cult/cult_comms.dm @@ -27,7 +27,7 @@ return ..() /datum/action/innate/cult/comm/Activate() - var/input = tgui_input_text(usr, "Message to tell to the other acolytes", "Voice of Blood") + var/input = tgui_input_text(usr, "Message to tell to the other acolytes", "Voice of Blood", max_length = MAX_MESSAGE_LEN) if(!input || !IsAvailable(feedback = TRUE)) return diff --git a/code/modules/antagonists/cult/cult_objectives.dm b/code/modules/antagonists/cult/cult_objectives.dm index d290b212ab22f..60542f259bf2a 100644 --- a/code/modules/antagonists/cult/cult_objectives.dm +++ b/code/modules/antagonists/cult/cult_objectives.dm @@ -63,7 +63,7 @@ /datum/objective/sacrifice/proc/on_possible_mindswap(mob/source) SIGNAL_HANDLER UnregisterSignal(target.current, list(COMSIG_QDELETING, COMSIG_MOB_MIND_TRANSFERRED_INTO)) - //we check if the mind is bodyless only after mindswap shenanigeans to avoid issues. + //we check if the mind is bodyless only after mindswap shenanigans to avoid issues. addtimer(CALLBACK(src, PROC_REF(do_we_have_a_body)), 0 SECONDS) /datum/objective/sacrifice/proc/do_we_have_a_body() diff --git a/code/modules/antagonists/cult/cult_structures.dm b/code/modules/antagonists/cult/cult_structures.dm index 773f890d25dbb..511988fb5bcbb 100644 --- a/code/modules/antagonists/cult/cult_structures.dm +++ b/code/modules/antagonists/cult/cult_structures.dm @@ -137,7 +137,7 @@ /* * Set up and populate our list of options. - * Overriden by subtypes. + * Overridden by subtypes. * * The list of options is a associated list of format: * item_name = list( diff --git a/code/modules/antagonists/ert/ert.dm b/code/modules/antagonists/ert/ert.dm index 4b94666abc367..29515e45bb124 100644 --- a/code/modules/antagonists/ert/ert.dm +++ b/code/modules/antagonists/ert/ert.dm @@ -233,9 +233,11 @@ var/mob/living/carbon/human/H = owner.current if(!istype(H)) return + if(isplasmaman(H)) - H.equipOutfit(plasmaman_outfit) - H.open_internals(H.get_item_for_held_index(2)) + H.dna.species.outfit_important_for_life = plasmaman_outfit + + H.dna.species.give_important_for_life(H) H.equipOutfit(outfit) if(isplasmaman(H)) diff --git a/code/modules/antagonists/heretic/influences.dm b/code/modules/antagonists/heretic/influences.dm index abba2c3f1007e..7b316d6cdb984 100644 --- a/code/modules/antagonists/heretic/influences.dm +++ b/code/modules/antagonists/heretic/influences.dm @@ -43,7 +43,7 @@ while((length(smashes) + num_drained) < how_many_can_we_make && location_sanity < 100) var/turf/chosen_location = get_safe_random_station_turf() - // We don't want them close to each other - at least 1 tile of seperation + // We don't want them close to each other - at least 1 tile of separation var/list/nearby_things = range(1, chosen_location) var/obj/effect/heretic_influence/what_if_i_have_one = locate() in nearby_things var/obj/effect/visible_heretic_influence/what_if_i_had_one_but_its_used = locate() in nearby_things diff --git a/code/modules/antagonists/heretic/items/heretic_armor.dm b/code/modules/antagonists/heretic/items/heretic_armor.dm index 0c64e4a227eaf..8375c3ae44334 100644 --- a/code/modules/antagonists/heretic/items/heretic_armor.dm +++ b/code/modules/antagonists/heretic/items/heretic_armor.dm @@ -153,6 +153,7 @@ RemoveElement(/datum/element/heretic_focus) if(isliving(loc)) + REMOVE_TRAIT(loc, TRAIT_RESISTLOWPRESSURE, REF(src)) loc.balloon_alert(loc, "cloak hidden") loc.visible_message(span_notice("Light shifts around [loc], making the cloak around them invisible!")) @@ -163,5 +164,6 @@ AddElement(/datum/element/heretic_focus) if(isliving(loc)) + ADD_TRAIT(loc, TRAIT_RESISTLOWPRESSURE, REF(src)) loc.balloon_alert(loc, "cloak revealed") loc.visible_message(span_notice("A kaleidoscope of colours collapses around [loc], a cloak appearing suddenly around their person!")) diff --git a/code/modules/antagonists/heretic/items/heretic_necks.dm b/code/modules/antagonists/heretic/items/heretic_necks.dm index 5c73c22a4e793..a738b4aae47ea 100644 --- a/code/modules/antagonists/heretic/items/heretic_necks.dm +++ b/code/modules/antagonists/heretic/items/heretic_necks.dm @@ -1,5 +1,5 @@ /obj/item/clothing/neck/heretic_focus - name = "Amber Focus" + name = "amber focus" desc = "An amber focusing glass that provides a link to the world beyond. The necklace seems to twitch, but only when you look at it from the corner of your eye." icon_state = "eldritch_necklace" w_class = WEIGHT_CLASS_SMALL @@ -10,7 +10,7 @@ AddElement(/datum/element/heretic_focus) /obj/item/clothing/neck/heretic_focus/crimson_medallion - name = "Crimson Medallion" + name = "crimson medallion" desc = "A blood-red focusing glass that provides a link to the world beyond, and worse. Its eye is constantly twitching and gazing in all directions. It almost seems to be silently screaming..." icon_state = "crimson_medallion" /// The aura healing component. Used to delete it when taken off. @@ -105,7 +105,7 @@ . += span_red("You can also squeeze it to recover a large amount of health quickly, at a cost...") /obj/item/clothing/neck/eldritch_amulet - name = "Warm Eldritch Medallion" + name = "warm eldritch medallion" desc = "A strange medallion. Peering through the crystalline surface, the world around you melts away. You see your own beating heart, and the pulsing of a thousand others." icon = 'icons/obj/antags/eldritch.dmi' icon_state = "eye_medalion" @@ -134,7 +134,7 @@ user.update_sight() /obj/item/clothing/neck/eldritch_amulet/piercing - name = "Piercing Eldritch Medallion" + name = "piercing eldritch medallion" desc = "A strange medallion. Peering through the crystalline surface, the light refracts into new and terrifying spectrums of color. You see yourself, reflected off cascading mirrors, warped into impossible shapes." heretic_only_trait = TRAIT_XRAY_VISION @@ -149,7 +149,7 @@ // The amulet conversion tool used by moon heretics /obj/item/clothing/neck/heretic_focus/moon_amulet - name = "Moonlight Amulet" + name = "moonlight amulet" desc = "A piece of the mind, the soul and the moon. Gazing into it makes your head spin and hear whispers of laughter and joy." icon = 'icons/obj/antags/eldritch.dmi' icon_state = "moon_amulette" diff --git a/code/modules/antagonists/heretic/items/labyrinth_handbook.dm b/code/modules/antagonists/heretic/items/labyrinth_handbook.dm index 8555b60f0c393..e4f333260a88f 100644 --- a/code/modules/antagonists/heretic/items/labyrinth_handbook.dm +++ b/code/modules/antagonists/heretic/items/labyrinth_handbook.dm @@ -41,10 +41,12 @@ . += span_hypnophrase("Materializes a barrier upon any tile in sight, which only you can pass through. Lasts 8 seconds.") . += span_hypnophrase("It has [uses] uses left.") -/obj/item/heretic_labyrinth_handbook/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) - return interact_with_atom(interacting_with, user, modifiers) - /obj/item/heretic_labyrinth_handbook/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(HAS_TRAIT(interacting_with, TRAIT_COMBAT_MODE_SKIP_INTERACTION)) + return NONE + return ranged_interact_with_atom(interacting_with, user, modifiers) + +/obj/item/heretic_labyrinth_handbook/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!IS_HERETIC(user)) if(ishuman(user)) var/mob/living/carbon/human/human_user = user diff --git a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm index 4b3525c93b044..5919f9a40d12a 100644 --- a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm +++ b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm @@ -501,6 +501,7 @@ sac_target.remove_status_effect(/datum/status_effect/necropolis_curse) sac_target.remove_status_effect(/datum/status_effect/unholy_determination) sac_target.reagents?.del_reagent(/datum/reagent/inverse/helgrasp/heretic) + sac_target.uncuff() sac_target.clear_mood_event("shadow_realm") if(IS_HERETIC(sac_target)) var/datum/antagonist/heretic/victim_heretic = sac_target.mind?.has_antag_datum(/datum/antagonist/heretic) diff --git a/code/modules/antagonists/heretic/knowledge/side_blade_rust.dm b/code/modules/antagonists/heretic/knowledge/side_blade_rust.dm index 3a0f17ed48391..2bae6ed540296 100644 --- a/code/modules/antagonists/heretic/knowledge/side_blade_rust.dm +++ b/code/modules/antagonists/heretic/knowledge/side_blade_rust.dm @@ -47,7 +47,7 @@ desc = "Allows you to transmute any ballistic weapon, such as a pipegun, with hide \ from any animal, a plank of wood, and a camera to create the Lionhunter's rifle. \ The Lionhunter's Rifle is a long ranged ballistic weapon with three shots. \ - These shots function as normal, albeit weak high caliber mutitions when fired from \ + These shots function as normal, albeit weak high-caliber munitions when fired from \ close range or at inanimate objects. You can aim the rifle at distant foes, \ causing the shot to deal massively increased damage and hone in on them." gain_text = "I met an old man in an antique shop who wielded a very unusual weapon. \ diff --git a/code/modules/antagonists/heretic/knowledge/side_flesh_void.dm b/code/modules/antagonists/heretic/knowledge/side_flesh_void.dm index a958ab3f272bb..d54646fe103b2 100644 --- a/code/modules/antagonists/heretic/knowledge/side_flesh_void.dm +++ b/code/modules/antagonists/heretic/knowledge/side_flesh_void.dm @@ -37,6 +37,23 @@ route = PATH_SIDE depth = 8 +/datum/heretic_knowledge/spell/void_prison + name = "Void Prison" + desc = "Grants you Void Prison, a spell that places your victim into ball, making them unable to do anything or speak. \ + Applies void chill afterwards." + gain_text = "At first, I see myself, waltzing along a snow-laden street. \ + I try to yell, grab hold of this fool and tell them to run. \ + But the only welts made are on my own beating fist. \ + My smiling face turns to regard me, reflecting back in glassy eyes the empty path I have been lead down." + next_knowledge = list( + /datum/heretic_knowledge/spell/void_phase, + /datum/heretic_knowledge/summon/raw_prophet, + ) + spell_to_add = /datum/action/cooldown/spell/pointed/void_prison + cost = 1 + route = PATH_SIDE + depth = 8 + /datum/heretic_knowledge/spell/cleave name = "Blood Cleave" desc = "Grants you Cleave, an area-of-effect targeted spell \ diff --git a/code/modules/antagonists/heretic/knowledge/void_lore.dm b/code/modules/antagonists/heretic/knowledge/void_lore.dm index 11031a51aca96..d2fd0efe8b570 100644 --- a/code/modules/antagonists/heretic/knowledge/void_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/void_lore.dm @@ -12,9 +12,10 @@ * * Mark of Void * Ritual of Knowledge - * Cone of Cold + * Void Conduit * Void Phase * > Sidepaths: + * Void Stasis * Carving Knife * Blood Siphon * @@ -78,7 +79,7 @@ var/mob/living/carbon/carbon_target = target carbon_target.adjust_silence(10 SECONDS) - carbon_target.apply_status_effect(/datum/status_effect/void_chill) + carbon_target.apply_status_effect(/datum/status_effect/void_chill, 2) /datum/heretic_knowledge/cold_snap name = "Aristocrat's Way" @@ -96,12 +97,29 @@ research_tree_icon_path = 'icons/effects/effects.dmi' research_tree_icon_state = "the_freezer" depth = 4 + /// Traits we apply to become immune to the environment + var/static/list/gain_traits = list(TRAIT_NO_SLIP_ICE, TRAIT_NO_SLIP_SLIDE) /datum/heretic_knowledge/cold_snap/on_gain(mob/user, datum/antagonist/heretic/our_heretic) user.add_traits(list(TRAIT_NOBREATH, TRAIT_RESISTCOLD), type) + RegisterSignal(user, COMSIG_LIVING_LIFE, PROC_REF(check_environment)) /datum/heretic_knowledge/cold_snap/on_lose(mob/user, datum/antagonist/heretic/our_heretic) user.remove_traits(list(TRAIT_RESISTCOLD, TRAIT_NOBREATH), type) + UnregisterSignal(user, COMSIG_LIVING_LIFE) + +///Checks if our traits should be active +/datum/heretic_knowledge/cold_snap/proc/check_environment(mob/living/user) + SIGNAL_HANDLER + + var/datum/gas_mixture/environment = user.loc?.return_air() + if(!isnull(environment)) + var/affected_temperature = environment.return_temperature() + var/affected_pressure = environment.return_pressure() + if(affected_temperature <= T0C || affected_pressure < ONE_ATMOSPHERE) + user.add_traits(gain_traits, type) + else + user.remove_traits(gain_traits, type) /datum/heretic_knowledge/mark/void_mark name = "Mark of Void" @@ -114,17 +132,17 @@ mark_type = /datum/status_effect/eldritch/void /datum/heretic_knowledge/knowledge_ritual/void - next_knowledge = list(/datum/heretic_knowledge/spell/void_cone) + next_knowledge = list(/datum/heretic_knowledge/spell/void_conduit) route = PATH_VOID -/datum/heretic_knowledge/spell/void_cone - name = "Void Blast" - desc = "Grants you Void Blast, a spell that shoots out a freezing blast in a cone in front of you, \ - freezing the ground and any victims within." - gain_text = "Every door I open racks my body. I am afraid of what is behind them. Someone is expecting me, \ - and my legs start to drag. Is that... snow?" +/datum/heretic_knowledge/spell/void_conduit + name = "Void Conduit" + desc = "Grants you Void Conduit, a spell which summons a pulsing gate to the Void itself. Every pulse breaks windows and airlocks, while afflicting Heathens with an eldritch chill and shielding Heretics against low pressure." + gain_text = "The hum in the still, cold air turns to a cacophonous rattle. \ + Over the noise, there is no distinction to the clattering of window panes and the yawning knowledge that ricochets through my skull. \ + The doors won't close. I can't keep the cold out now." next_knowledge = list(/datum/heretic_knowledge/spell/void_phase) - spell_to_add = /datum/action/cooldown/spell/cone/staggered/cone_of_cold/void + spell_to_add = /datum/action/cooldown/spell/conjure/void_conduit cost = 1 route = PATH_VOID depth = 7 @@ -139,6 +157,7 @@ /datum/heretic_knowledge/blade_upgrade/void, /datum/heretic_knowledge/reroll_targets, /datum/heretic_knowledge/spell/blood_siphon, + /datum/heretic_knowledge/spell/void_prison, /datum/heretic_knowledge/rune_carver, ) spell_to_add = /datum/action/cooldown/spell/pointed/void_phase @@ -149,13 +168,19 @@ /datum/heretic_knowledge/blade_upgrade/void name = "Seeking Blade" - desc = "You can now attack distant marked targets with your Void Blade, teleporting directly next to them." + desc = "Your blade now freezes enemies. Additionally, you can now attack distant marked targets with your Void Blade, teleporting directly next to them." gain_text = "Fleeting memories, fleeting feet. I mark my way with frozen blood upon the snow. Covered and forgotten." next_knowledge = list(/datum/heretic_knowledge/spell/void_pull) route = PATH_VOID research_tree_icon_path = 'icons/ui_icons/antags/heretic/knowledge.dmi' research_tree_icon_state = "blade_upgrade_void" +/datum/heretic_knowledge/blade_upgrade/void/do_melee_effects(mob/living/source, mob/living/target, obj/item/melee/sickly_blade/blade) + if(source == target) + return + + target.apply_status_effect(/datum/status_effect/void_chill, 2) + /datum/heretic_knowledge/blade_upgrade/void/do_ranged_effects(mob/living/user, mob/living/target, obj/item/melee/sickly_blade/blade) if(!target.has_status_effect(/datum/status_effect/eldritch)) return @@ -200,6 +225,8 @@ var/datum/looping_sound/void_loop/sound_loop ///Reference to the ongoing voidstrom that surrounds the heretic var/datum/weather/void_storm/storm + ///The storm where there are actual effects + var/datum/proximity_monitor/advanced/void_storm/heavy_storm /datum/heretic_knowledge/ultimate/void_final/recipe_snowflake_check(mob/living/user, list/atoms, list/selected_atoms, turf/loc) if(!isopenturf(loc)) @@ -221,16 +248,22 @@ sound = 'sound/ambience/antag/heretic/ascend_void.ogg', color_override = "pink", ) - ADD_TRAIT(user, TRAIT_RESISTLOWPRESSURE, MAGIC_TRAIT) + user.add_traits(list(TRAIT_RESISTLOWPRESSURE, TRAIT_NEGATES_GRAVITY, TRAIT_MOVE_FLYING, TRAIT_FREE_HYPERSPACE_MOVEMENT), MAGIC_TRAIT) // Let's get this show on the road! sound_loop = new(user, TRUE, TRUE) RegisterSignal(user, COMSIG_LIVING_LIFE, PROC_REF(on_life)) - RegisterSignal(user, COMSIG_LIVING_DEATH, PROC_REF(on_death)) + RegisterSignal(user, COMSIG_ATOM_PRE_BULLET_ACT, PROC_REF(hit_by_projectile)) + RegisterSignals(user, list(COMSIG_LIVING_DEATH, COMSIG_QDELETING), PROC_REF(on_death)) + heavy_storm = new(user, 10) + if(ishuman(user)) + var/mob/living/carbon/human/ascended_human = user + var/obj/item/organ/internal/eyes/heretic_eyes = ascended_human.get_organ_slot(ORGAN_SLOT_EYES) + heretic_eyes?.color_cutoffs = list(30, 30, 30) + ascended_human.update_sight() /datum/heretic_knowledge/ultimate/void_final/on_lose(mob/user, datum/antagonist/heretic/our_heretic) on_death() // Losing is pretty much dying. I think - RegisterSignals(user, list(COMSIG_LIVING_LIFE, COMSIG_LIVING_DEATH)) /** * Signal proc for [COMSIG_LIVING_LIFE]. @@ -243,10 +276,29 @@ /datum/heretic_knowledge/ultimate/void_final/proc/on_life(mob/living/source, seconds_per_tick, times_fired) SIGNAL_HANDLER - for(var/mob/living/carbon/close_carbon in view(5, source)) - if(IS_HERETIC_OR_MONSTER(close_carbon)) - continue - close_carbon.adjust_silence_up_to(2 SECONDS, 20 SECONDS) + for(var/atom/thing_in_range as anything in range(10, source)) + if(iscarbon(thing_in_range)) + var/mob/living/carbon/close_carbon = thing_in_range + if(IS_HERETIC_OR_MONSTER(close_carbon)) + close_carbon.apply_status_effect(/datum/status_effect/void_conduit) + continue + close_carbon.adjust_silence_up_to(2 SECONDS, 20 SECONDS) + close_carbon.apply_status_effect(/datum/status_effect/void_chill, 1) + close_carbon.adjust_eye_blur(rand(0 SECONDS, 2 SECONDS)) + close_carbon.adjust_bodytemperature(-30 * TEMPERATURE_DAMAGE_COEFFICIENT) + + if(istype(thing_in_range, /obj/machinery/door) || istype(thing_in_range, /obj/structure/door_assembly)) + var/obj/affected_door = thing_in_range + affected_door.take_damage(rand(60, 80)) + + if(istype(thing_in_range, /obj/structure/window) || istype(thing_in_range, /obj/structure/grille)) + var/obj/structure/affected_structure = thing_in_range + affected_structure.take_damage(rand(20, 40)) + + if(isturf(thing_in_range)) + var/turf/affected_turf = thing_in_range + var/datum/gas_mixture/environment = affected_turf.return_air() + environment.temperature *= 0.9 // Telegraph the storm in every area on the station. var/list/station_levels = SSmapping.levels_by_trait(ZTRAIT_STATION) @@ -254,14 +306,6 @@ storm = new /datum/weather/void_storm(station_levels) storm.telegraph() - // When the heretic enters a new area, intensify the storm in the new area, - // and lessen the intensity in the former area. - var/area/source_area = get_area(source) - if(!storm.impacted_areas[source_area]) - storm.former_impacted_areas |= storm.impacted_areas - storm.impacted_areas = list(source_area) - storm.update_areas() - /** * Signal proc for [COMSIG_LIVING_DEATH]. * @@ -275,3 +319,32 @@ if(storm) storm.end() QDEL_NULL(storm) + if(heavy_storm) + QDEL_NULL(heavy_storm) + UnregisterSignal(source, list(COMSIG_LIVING_LIFE, COMSIG_ATOM_PRE_BULLET_ACT, COMSIG_LIVING_DEATH, COMSIG_QDELETING)) + +///Few checks to determine if we can deflect bullets +/datum/heretic_knowledge/ultimate/void_final/proc/can_deflect(mob/living/ascended_heretic) + if(!(ascended_heretic.mobility_flags & MOBILITY_USE)) + return FALSE + if(!isturf(ascended_heretic.loc)) + return FALSE + return TRUE + +/datum/heretic_knowledge/ultimate/void_final/proc/hit_by_projectile(mob/living/ascended_heretic, obj/projectile/hitting_projectile, def_zone) + SIGNAL_HANDLER + + if(!can_deflect(ascended_heretic)) + return NONE + + ascended_heretic.visible_message( + span_danger("The void storm surrounding [ascended_heretic] deflects [hitting_projectile]!"), + span_userdanger("The void storm protects you from [hitting_projectile]!"), + ) + playsound(ascended_heretic, pick('sound/magic/VoidDeflect01.ogg', 'sound/magic/VoidDeflect02.ogg', 'sound/magic/VoidDeflect03.ogg'), 75, TRUE) + hitting_projectile.firer = ascended_heretic + if(prob(75)) + hitting_projectile.set_angle(get_angle(hitting_projectile.firer, hitting_projectile.fired_from)) + else + hitting_projectile.set_angle(rand(0, 360))//SHING + return COMPONENT_BULLET_PIERCED diff --git a/code/modules/antagonists/heretic/magic/void_conduit.dm b/code/modules/antagonists/heretic/magic/void_conduit.dm new file mode 100644 index 0000000000000..07ca0cbe2ab0f --- /dev/null +++ b/code/modules/antagonists/heretic/magic/void_conduit.dm @@ -0,0 +1,122 @@ +/datum/action/cooldown/spell/conjure/void_conduit + name = "Void Conduit" + desc = "Opens a gate to the Void; it releases an intermittent pulse that damages windows and airlocks, \ + while afflicting Heathens with void chill. \ + Affected Heretics instead receive low pressure resistance." + background_icon_state = "bg_heretic" + overlay_icon_state = "bg_heretic_border" + button_icon = 'icons/mob/actions/actions_ecult.dmi' + button_icon_state = "void_rift" + + cooldown_time = 1 MINUTES + + sound = null + school = SCHOOL_FORBIDDEN + invocation = "MBR'C' TH' V''D!" + invocation_type = INVOCATION_SHOUT + spell_requirements = NONE + + summon_radius = 0 + summon_type = list(/obj/structure/void_conduit) + summon_respects_density = TRUE + summon_respects_prev_spawn_points = TRUE + +/obj/structure/void_conduit + name = "Void Conduit" + desc = "An open gate which leads to nothingness. Releases pulses which you do not want to get hit by." + icon = 'icons/effects/effects.dmi' + icon_state = "void_conduit" + anchored = TRUE + density = TRUE + ///Overlay to apply to the tiles in range of the conduit + var/static/image/void_overlay = image(icon = 'icons/turf/overlays.dmi', icon_state = "voidtile") + ///List of tiles that we added an overlay to, so we can clear them when the conduit is deleted + var/list/overlayed_turfs = list() + ///How many tiles far our effect is + var/effect_range = 12 + ///id of the deletion timer + var/timerid + ///Audio loop for the rift being alive + var/datum/looping_sound/void_conduit/soundloop + +/obj/structure/void_conduit/Initialize(mapload) + . = ..() + soundloop = new(src, start_immediately = TRUE) + timerid = QDEL_IN_STOPPABLE(src, 1 MINUTES) + START_PROCESSING(SSobj, src) + for(var/turf/affected_turf as anything in RANGE_TURFS(effect_range, src)) + if(!isopenturf(affected_turf)) + continue + affected_turf.add_overlay(void_overlay) + overlayed_turfs += affected_turf + void_overlay.mouse_opacity = MOUSE_OPACITY_TRANSPARENT + void_overlay.alpha = 180 + +/obj/structure/void_conduit/Destroy(force) + QDEL_NULL(soundloop) + deltimer(timerid) + STOP_PROCESSING(SSobj, src) + for(var/turf/affected_turf as anything in overlayed_turfs) //If the portal is moved, the overlays don't stick around + affected_turf.cut_overlay(void_overlay) + return ..() + +/obj/structure/void_conduit/process(seconds_per_tick) + do_conduit_pulse() + +///Sends out a pulse +/obj/structure/void_conduit/proc/do_conduit_pulse() + var/list/turfs_to_affect = list() + for(var/turf/affected_turf as anything in RANGE_TURFS(effect_range, loc)) + var/distance = get_dist(loc, affected_turf) + if(!turfs_to_affect["[distance]"]) + turfs_to_affect["[distance]"] = list() + turfs_to_affect["[distance]"] += affected_turf + + for(var/distance in 0 to effect_range) + if(!turfs_to_affect["[distance]"]) + continue + addtimer(CALLBACK(src, PROC_REF(handle_effects), turfs_to_affect["[distance]"]), (1 SECONDS) * distance) + + new /obj/effect/temp_visual/circle_wave/void_conduit(get_turf(src)) + +///Applies the effects of the pulse "hitting" something. Freezes non-heretic, destroys airlocks/windows +/obj/structure/void_conduit/proc/handle_effects(list/turfs) + for(var/turf/affected_turf as anything in turfs) + for(var/atom/thing_to_affect as anything in affected_turf.contents) + + if(isliving(thing_to_affect)) + var/mob/living/affected_mob = thing_to_affect + if(affected_mob.can_block_magic(MAGIC_RESISTANCE)) + continue + if(IS_HERETIC(affected_mob)) + affected_mob.apply_status_effect(/datum/status_effect/void_conduit) + else + affected_mob.apply_status_effect(/datum/status_effect/void_chill, 1) + + if(istype(thing_to_affect, /obj/machinery/door) || istype(thing_to_affect, /obj/structure/door_assembly)) + var/obj/affected_door = thing_to_affect + affected_door.take_damage(rand(15, 30)) + + if(istype(thing_to_affect, /obj/structure/window) || istype(thing_to_affect, /obj/structure/grille)) + var/obj/structure/affected_structure = thing_to_affect + affected_structure.take_damage(rand(10, 20)) + +/datum/looping_sound/void_conduit + mid_sounds = 'sound/ambience/ambiatm1.ogg' + mid_length = 1 SECONDS + extra_range = 10 + volume = 40 + falloff_distance = 5 + falloff_exponent = 20 + +/datum/status_effect/void_conduit + duration = 15 SECONDS + status_type = STATUS_EFFECT_REPLACE + alert_type = null + +/datum/status_effect/void_conduit/on_apply() + ADD_TRAIT(owner, TRAIT_RESISTLOWPRESSURE, "void_conduit") + return TRUE + +/datum/status_effect/void_conduit/on_remove() + REMOVE_TRAIT(owner, TRAIT_RESISTLOWPRESSURE, "void_conduit") diff --git a/code/modules/antagonists/heretic/magic/void_phase.dm b/code/modules/antagonists/heretic/magic/void_phase.dm index 350ca0f29c100..c6e367e87608c 100644 --- a/code/modules/antagonists/heretic/magic/void_phase.dm +++ b/code/modules/antagonists/heretic/magic/void_phase.dm @@ -10,7 +10,7 @@ ranged_mousepointer = 'icons/effects/mouse_pointers/throw_target.dmi' school = SCHOOL_FORBIDDEN - cooldown_time = 30 SECONDS + cooldown_time = 25 SECONDS invocation = "RE'L'TY PH'S'E." invocation_type = INVOCATION_WHISPER @@ -57,6 +57,7 @@ if(living_mob.can_block_magic(antimagic_flags)) continue living_mob.apply_damage(40, BRUTE, wound_bonus = CANT_WOUND) + living_mob.apply_status_effect(/datum/status_effect/void_chill, 1) /obj/effect/temp_visual/voidin icon = 'icons/effects/96x96.dmi' diff --git a/code/modules/antagonists/heretic/magic/void_prison.dm b/code/modules/antagonists/heretic/magic/void_prison.dm new file mode 100644 index 0000000000000..211a747c8008e --- /dev/null +++ b/code/modules/antagonists/heretic/magic/void_prison.dm @@ -0,0 +1,101 @@ +/datum/action/cooldown/spell/pointed/void_prison + name = "Void Prison" + desc = "Sends a heathen into the void for 10 seconds. \ + They will be unable to perform any actions for the duration. \ + Afterwards, they will be chilled and returned to the mortal plane." + background_icon_state = "bg_heretic" + overlay_icon_state = "bg_heretic_border" + button_icon = 'icons/mob/actions/actions_ecult.dmi' + button_icon_state = "voidball" + ranged_mousepointer = 'icons/effects/mouse_pointers/throw_target.dmi' + sound = 'sound/magic/voidblink.ogg' + + cooldown_time = 1 MINUTES + cast_range = 3 + + sound = null + school = SCHOOL_FORBIDDEN + invocation = "V''D PR'S'N!" + invocation_type = INVOCATION_SHOUT + spell_requirements = NONE + +/datum/action/cooldown/spell/pointed/void_prison/before_cast(atom/cast_on) + . = ..() + if(. & SPELL_CANCEL_CAST) + return + if(!ismob(cast_on)) + return SPELL_CANCEL_CAST + +/datum/action/cooldown/spell/pointed/void_prison/cast(mob/living/carbon/human/cast_on) + . = ..() + if(cast_on.can_block_magic(antimagic_flags)) + cast_on.visible_message( + span_danger("A swirling, cold void wraps around [cast_on], but they burst free in a wave of heat!"), + span_danger("A yawning void begins to open before you, but a great wave of heat bursts it apart! You are protected!!") + ) + return + cast_on.apply_status_effect(/datum/status_effect/void_prison, "void_stasis") + +/datum/status_effect/void_prison + id = "void_prison" + duration = 10 SECONDS + alert_type = /atom/movable/screen/alert/status_effect/void_prison + ///The overlay that gets applied to whoever has this status active + var/obj/effect/abstract/voidball/stasis_overlay + +/datum/status_effect/void_prison/on_creation(mob/living/new_owner, set_duration) + . = ..() + stasis_overlay = new /obj/effect/abstract/voidball(new_owner) + RegisterSignal(stasis_overlay, COMSIG_QDELETING, PROC_REF(clear_overlay)) + new_owner.vis_contents += stasis_overlay + stasis_overlay.animate_opening() + addtimer(CALLBACK(src, PROC_REF(enter_prison), new_owner), 1 SECONDS) + +/datum/status_effect/void_prison/on_remove() + if(!IS_HERETIC(owner)) + owner.apply_status_effect(/datum/status_effect/void_chill, 3) + if(stasis_overlay) + //Free our prisoner + owner.remove_traits(list(TRAIT_GODMODE, TRAIT_NO_TRANSFORM, TRAIT_SOFTSPOKEN), REF(src)) + owner.forceMove(get_turf(stasis_overlay)) + stasis_overlay.forceMove(owner) + owner.vis_contents += stasis_overlay + //Animate closing the ball + stasis_overlay.animate_closing() + stasis_overlay.icon_state = "voidball_closed" + QDEL_IN(stasis_overlay, 1.1 SECONDS) + stasis_overlay = null + return ..() + +///Freezes our prisoner in place +/datum/status_effect/void_prison/proc/enter_prison(mob/living/prisoner) + stasis_overlay.forceMove(prisoner.loc) + prisoner.forceMove(stasis_overlay) + prisoner.add_traits(list(TRAIT_GODMODE, TRAIT_NO_TRANSFORM, TRAIT_SOFTSPOKEN), REF(src)) + +///Makes sure to clear the ref in case the voidball ever suddenly disappears +/datum/status_effect/void_prison/proc/clear_overlay() + SIGNAL_HANDLER + stasis_overlay = null + +//----Voidball effect +/obj/effect/abstract/voidball + icon = 'icons/mob/actions/actions_ecult.dmi' + icon_state = "voidball_effect" + layer = ABOVE_ALL_MOB_LAYER + vis_flags = VIS_INHERIT_ID + +///Plays a opening animation +/obj/effect/abstract/voidball/proc/animate_opening() + flick("voidball_opening", src) + +///Plays a closing animation +/obj/effect/abstract/voidball/proc/animate_closing() + flick("voidball_closing", src) + +//---- Screen alert +/atom/movable/screen/alert/status_effect/void_prison + name = "Void Prison" + desc = "A Yawning void encases your mortal coil." //Go straight to jail, do not pass GO, do not collect 200$ + icon = 'icons/mob/actions/actions_ecult.dmi' + icon_state = "voidball_effect" diff --git a/code/modules/antagonists/heretic/magic/void_pull.dm b/code/modules/antagonists/heretic/magic/void_pull.dm index 2021bf8a04e4f..1db1c6601718e 100644 --- a/code/modules/antagonists/heretic/magic/void_pull.dm +++ b/code/modules/antagonists/heretic/magic/void_pull.dm @@ -9,7 +9,7 @@ sound = 'sound/magic/voidblink.ogg' school = SCHOOL_FORBIDDEN - cooldown_time = 40 SECONDS + cooldown_time = 30 SECONDS invocation = "BR'NG F'RTH TH'M T' M'." invocation_type = INVOCATION_WHISPER @@ -32,6 +32,7 @@ // Before we cast the actual effects, deal AOE damage to anyone adjacent to us for(var/mob/living/nearby_living as anything in get_things_to_cast_on(cast_on, damage_radius)) nearby_living.apply_damage(30, BRUTE, wound_bonus = CANT_WOUND) + nearby_living.apply_status_effect(/datum/status_effect/void_chill, 1) /datum/action/cooldown/spell/aoe/void_pull/get_things_to_cast_on(atom/center, radius_override = 1) var/list/things = list() diff --git a/code/modules/antagonists/heretic/status_effects/buffs.dm b/code/modules/antagonists/heretic/status_effects/buffs.dm index 1668ea5a11ef7..e4f5990040be4 100644 --- a/code/modules/antagonists/heretic/status_effects/buffs.dm +++ b/code/modules/antagonists/heretic/status_effects/buffs.dm @@ -251,11 +251,10 @@ status_type = STATUS_EFFECT_REFRESH duration = -1 alert_type = null - var/static/list/caretaking_traits = list(TRAIT_HANDS_BLOCKED, TRAIT_IGNORESLOWDOWN, TRAIT_SECLUDED_LOCATION) + var/static/list/caretaking_traits = list(TRAIT_GODMODE, TRAIT_HANDS_BLOCKED, TRAIT_IGNORESLOWDOWN, TRAIT_SECLUDED_LOCATION) /datum/status_effect/caretaker_refuge/on_apply() owner.add_traits(caretaking_traits, TRAIT_STATUS_EFFECT(id)) - owner.status_flags |= GODMODE animate(owner, alpha = 45,time = 0.5 SECONDS) owner.density = FALSE RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_ALLOW_HERETIC_CASTING), PROC_REF(on_focus_lost)) @@ -266,7 +265,6 @@ /datum/status_effect/caretaker_refuge/on_remove() owner.remove_traits(caretaking_traits, TRAIT_STATUS_EFFECT(id)) - owner.status_flags &= ~GODMODE owner.alpha = initial(owner.alpha) owner.density = initial(owner.density) UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_ALLOW_HERETIC_CASTING)) diff --git a/code/modules/antagonists/heretic/status_effects/debuffs.dm b/code/modules/antagonists/heretic/status_effects/debuffs.dm index 7037d1cc3778b..8b1751bccde69 100644 --- a/code/modules/antagonists/heretic/status_effects/debuffs.dm +++ b/code/modules/antagonists/heretic/status_effects/debuffs.dm @@ -1,41 +1,3 @@ -// VOID CHILL -/datum/status_effect/void_chill - id = "void_chill" - alert_type = /atom/movable/screen/alert/status_effect/void_chill - duration = 8 SECONDS - status_type = STATUS_EFFECT_REPLACE - tick_interval = 0.5 SECONDS - /// The amount the victim's body temperature changes each tick() in kelvin. Multiplied by TEMPERATURE_DAMAGE_COEFFICIENT. - var/cooling_per_tick = -14 - -/atom/movable/screen/alert/status_effect/void_chill - name = "Void Chill" - desc = "There's something freezing you from within and without. You've never felt cold this oppressive before..." - icon_state = "void_chill" - -/datum/status_effect/void_chill/on_apply() - owner.add_atom_colour(COLOR_BLUE_LIGHT, TEMPORARY_COLOUR_PRIORITY) - owner.add_movespeed_modifier(/datum/movespeed_modifier/void_chill, update = TRUE) - return TRUE - -/datum/status_effect/void_chill/on_remove() - owner.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, COLOR_BLUE_LIGHT) - owner.remove_movespeed_modifier(/datum/movespeed_modifier/void_chill, update = TRUE) - -/datum/status_effect/void_chill/tick(seconds_between_ticks) - owner.adjust_bodytemperature(cooling_per_tick * TEMPERATURE_DAMAGE_COEFFICIENT) - -/datum/status_effect/void_chill/major - duration = 10 SECONDS - cooling_per_tick = -20 - -/datum/status_effect/void_chill/lasting - id = "lasting_void_chill" - duration = -1 - -/datum/movespeed_modifier/void_chill - multiplicative_slowdown = 0.3 - // AMOK /datum/status_effect/amok id = "amok" diff --git a/code/modules/antagonists/heretic/status_effects/mark_effects.dm b/code/modules/antagonists/heretic/status_effects/mark_effects.dm index b647ba6ca8077..4cbdbdf8c1ce1 100644 --- a/code/modules/antagonists/heretic/status_effects/mark_effects.dm +++ b/code/modules/antagonists/heretic/status_effects/mark_effects.dm @@ -105,7 +105,7 @@ effect_icon_state = "emark4" /datum/status_effect/eldritch/void/on_effect() - owner.apply_status_effect(/datum/status_effect/void_chill/major) + owner.apply_status_effect(/datum/status_effect/void_chill, 3) owner.adjust_silence(10 SECONDS) return ..() diff --git a/code/modules/antagonists/heretic/status_effects/void_chill.dm b/code/modules/antagonists/heretic/status_effects/void_chill.dm new file mode 100644 index 0000000000000..ed4bf1f3cb521 --- /dev/null +++ b/code/modules/antagonists/heretic/status_effects/void_chill.dm @@ -0,0 +1,113 @@ +/*! + * Contains the "Void Chill" status effect. Harmful debuff which freezes and slows down non-heretics + * Cannot affect silicons (How are you gonna freeze a robot?) + */ +/datum/status_effect/void_chill + id = "void_chill" + duration = 30 SECONDS + alert_type = /atom/movable/screen/alert/status_effect/void_chill + status_type = STATUS_EFFECT_REFRESH //Custom code + on_remove_on_mob_delete = TRUE + remove_on_fullheal = TRUE + ///Current amount of stacks we have + var/stacks + ///Maximum of stacks that we could possibly get + var/stack_limit = 5 + ///icon for the overlay + var/image/stacks_overlay + +/datum/status_effect/void_chill/on_creation(mob/living/new_owner, new_stacks, ...) + . = ..() + RegisterSignal(owner, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(update_stacks_overlay)) + set_stacks(new_stacks) + owner.add_atom_colour(COLOR_BLUE_LIGHT, TEMPORARY_COLOUR_PRIORITY) + owner.update_icon(UPDATE_OVERLAYS) + +/datum/status_effect/void_chill/on_apply() + if(issilicon(owner)) + return FALSE + return TRUE + +/datum/status_effect/void_chill/on_remove() + owner.update_icon(UPDATE_OVERLAYS) + owner.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, COLOR_BLUE_LIGHT) + owner.remove_movespeed_modifier(/datum/movespeed_modifier/void_chill) + owner.remove_alt_appearance("heretic_status") + REMOVE_TRAIT(owner, TRAIT_HYPOTHERMIC, REF(src)) + UnregisterSignal(owner, COMSIG_ATOM_UPDATE_OVERLAYS) + +/datum/status_effect/void_chill/tick(seconds_between_ticks) + owner.adjust_bodytemperature(-12 * stacks * seconds_between_ticks) + +/datum/status_effect/void_chill/refresh(mob/living/new_owner, new_stacks, forced = FALSE) + . = ..() + if(forced) + set_stacks(new_stacks) + else + adjust_stacks(new_stacks) + owner.update_icon(UPDATE_OVERLAYS) + +///Updates the overlay that gets applied on our victim +/datum/status_effect/void_chill/proc/update_stacks_overlay(atom/parent_atom, list/overlays) + SIGNAL_HANDLER + + linked_alert?.update_appearance(UPDATE_ICON_STATE|UPDATE_DESC) + owner.remove_alt_appearance("heretic_status") + stacks_overlay = image('icons/effects/effects.dmi', owner, "void_chill_partial") + if(stacks >= 5) + stacks_overlay = image('icons/effects/effects.dmi', owner, "void_chill_oh_fuck") + owner.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/heretic, "heretic_status", stacks_overlay, NONE) + +/** + * Setter and adjuster procs for stacks + * + * Arguments: + * - new_stacks + * + */ + +/datum/status_effect/void_chill/proc/set_stacks(new_stacks) + stacks = max(0, min(stack_limit, new_stacks)) + update_movespeed(stacks) + +/datum/status_effect/void_chill/proc/adjust_stacks(new_stacks) + stacks = max(0, min(stack_limit, stacks + new_stacks)) + update_movespeed(stacks) + if(stacks >= 5) + ADD_TRAIT(owner, TRAIT_HYPOTHERMIC, REF(src)) + +///Updates the movespeed of owner based on the amount of stacks of the debuff +/datum/status_effect/void_chill/proc/update_movespeed(stacks) + owner.add_movespeed_modifier(/datum/movespeed_modifier/void_chill, update = TRUE) + owner.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/void_chill, update = TRUE, multiplicative_slowdown = (0.5 * stacks)) + linked_alert.maptext = MAPTEXT_TINY_UNICODE("[stacks]") + +/datum/status_effect/void_chill/lasting + id = "lasting_void_chill" + duration = -1 + +/datum/movespeed_modifier/void_chill + variable = TRUE + multiplicative_slowdown = 0.1 + +//---- Screen alert +/atom/movable/screen/alert/status_effect/void_chill + name = "Void Chill" + desc = "There's something freezing you from within and without. You've never felt cold this oppressive before..." + icon_state = "void_chill_minor" + +/atom/movable/screen/alert/status_effect/void_chill/update_icon_state() + . = ..() + if(!istype(attached_effect, /datum/status_effect/void_chill)) + return + var/datum/status_effect/void_chill/chill_effect = attached_effect + if(chill_effect.stacks >= 5) + icon_state = "void_chill_oh_fuck" + +/atom/movable/screen/alert/status_effect/void_chill/update_desc(updates) + . = ..() + if(!istype(attached_effect, /datum/status_effect/void_chill)) + return + var/datum/status_effect/void_chill/chill_effect = attached_effect + if(chill_effect.stacks >= 5) + desc = "You had your chance to run, now it's too late. You may never feel warmth again..." diff --git a/code/modules/antagonists/malf_ai/malf_ai.dm b/code/modules/antagonists/malf_ai/malf_ai.dm index 4dc2568fe0e89..dc92289f66bef 100644 --- a/code/modules/antagonists/malf_ai/malf_ai.dm +++ b/code/modules/antagonists/malf_ai/malf_ai.dm @@ -41,6 +41,7 @@ malfunction_flavor = strings(MALFUNCTION_FLAVOR_FILE, employer) add_law_zero() + RegisterSignal(owner.current, COMSIG_SILICON_AI_CORE_STATUS, PROC_REF(core_status)) if(malf_sound) owner.current.playsound_local(get_turf(owner.current), malf_sound, 100, FALSE, pressure_affected = FALSE, use_reverb = FALSE) owner.current.grant_language(/datum/language/codespeak, source = LANGUAGE_MALF) @@ -58,7 +59,7 @@ QDEL_NULL(malf_ai.malf_picker) owner.special_role = null - + UnregisterSignal(owner, COMSIG_SILICON_AI_CORE_STATUS) return ..() /// Generates a complete set of malf AI objectives up to the traitor objective limit. @@ -197,7 +198,7 @@ "name" = category, "items" = (category == malf_ai.malf_picker.selected_cat ? list() : null)) for(var/module in malf_ai.malf_picker.possible_modules[category]) - var/datum/ai_module/mod = malf_ai.malf_picker.possible_modules[category][module] + var/datum/ai_module/malf/mod = malf_ai.malf_picker.possible_modules[category][module] cat["items"] += list(list( "name" = mod.name, "cost" = mod.cost, @@ -222,7 +223,7 @@ for(var/category in malf_ai.malf_picker.possible_modules) buyable_items += malf_ai.malf_picker.possible_modules[category] for(var/key in buyable_items) - var/datum/ai_module/valid_mod = buyable_items[key] + var/datum/ai_module/malf/valid_mod = buyable_items[key] if(valid_mod.name == item_name) malf_ai.malf_picker.purchase_module(malf_ai, valid_mod) return TRUE @@ -271,6 +272,14 @@ return malf_ai_icon +/datum/antagonist/malf_ai/proc/core_status(datum/source) + SIGNAL_HANDLER + + var/mob/living/silicon/ai/malf_owner = owner.current + if(malf_owner.linked_core) + return COMPONENT_CORE_ALL_GOOD + return COMPONENT_CORE_DISCONNECTED + //Subtype of Malf AI datum, used for one of the traitor final objectives /datum/antagonist/malf_ai/infected name = "Infected AI" diff --git a/code/modules/antagonists/malf_ai/malf_ai_modules.dm b/code/modules/antagonists/malf_ai/malf_ai_modules.dm index 90f3b76649230..a9f84c51dad1a 100644 --- a/code/modules/antagonists/malf_ai/malf_ai_modules.dm +++ b/code/modules/antagonists/malf_ai/malf_ai_modules.dm @@ -52,7 +52,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( /obj/machinery/computer/gateway_control, ))) -GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) +GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module/malf)) /// The malf AI action subtype. All malf actions are subtypes of this. /datum/action/innate/ai @@ -137,19 +137,19 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) return /// Modules causing destruction -/datum/ai_module/destructive +/datum/ai_module/malf/destructive category = "Destructive Modules" /// Modules with stealthy and utility uses -/datum/ai_module/utility +/datum/ai_module/malf/utility category = "Utility Modules" /// Modules that are improving AI abilities and assets -/datum/ai_module/upgrade +/datum/ai_module/malf/upgrade category = "Upgrade Modules" /// Doomsday Device: Starts the self-destruct timer. It can only be stopped by killing the AI completely. -/datum/ai_module/destructive/nuke_station +/datum/ai_module/malf/destructive/nuke_station name = "Doomsday Device" description = "Activate a weapon that will disintegrate all organic life on the station after a 450 second delay. \ Can only be used while on the station, will fail if your core is moved off station or destroyed. \ @@ -372,7 +372,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) return TRUE /// Hostile Station Lockdown: Locks, bolts, and electrifies every airlock on the station. After 90 seconds, the doors reset. -/datum/ai_module/destructive/lockdown +/datum/ai_module/malf/destructive/lockdown name = "Hostile Station Lockdown" description = "Overload the airlock, blast door and fire control networks, locking them down. \ Caution! This command also electrifies all airlocks. The networks will automatically reset after 90 seconds, briefly \ @@ -424,7 +424,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) CHECK_TICK /// Override Machine: Allows the AI to override a machine, animating it into an angry, living version of itself. -/datum/ai_module/destructive/override_machine +/datum/ai_module/malf/destructive/override_machine name = "Machine Override" description = "Overrides a machine's programming, causing it to rise up and attack everyone except other machines. Four uses per purchase." cost = 30 @@ -481,7 +481,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) new /mob/living/simple_animal/hostile/mimic/copy/machine(get_turf(to_animate), to_animate, caller, TRUE) /// Destroy RCDs: Detonates all non-cyborg RCDs on the station. -/datum/ai_module/destructive/destroy_rcd +/datum/ai_module/malf/destructive/destroy_rcd name = "Destroy RCDs" description = "Send a specialised pulse to detonate all hand-held and exosuit Rapid Construction Devices on the station." cost = 25 @@ -506,7 +506,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) owner.playsound_local(owner, 'sound/machines/twobeep.ogg', 50, 0) /// Overload Machine: Allows the AI to overload a machine, detonating it after a delay. Two uses per purchase. -/datum/ai_module/destructive/overload_machine +/datum/ai_module/malf/destructive/overload_machine name = "Machine Overload" description = "Overheats an electrical machine, causing a small explosion and destroying it. Two uses per purchase." cost = 20 @@ -567,7 +567,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) return TRUE /// Blackout: Overloads a random number of lights across the station. Three uses. -/datum/ai_module/destructive/blackout +/datum/ai_module/malf/destructive/blackout name = "Blackout" description = "Attempts to overload the lighting circuits on the station, destroying some bulbs. Three uses per purchase." cost = 15 @@ -601,7 +601,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) build_all_button_icons() /// HIGH IMPACT HONKING -/datum/ai_module/destructive/megahonk +/datum/ai_module/malf/destructive/megahonk name = "Percussive Intercomm Interference" description = "Emit a debilitatingly percussive auditory blast through the station intercoms. Does not overpower hearing protection. Two uses per purchase." cost = 20 @@ -632,7 +632,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) to_chat(honk_victim, span_clown("HOOOOONK!")) /// Robotic Factory: Places a large machine that converts humans that go through it into cyborgs. Unlocking this ability removes shunting. -/datum/ai_module/utility/place_cyborg_transformer +/datum/ai_module/malf/utility/place_cyborg_transformer name = "Robotic Factory (Removes Shunting)" description = "Build a machine anywhere, using expensive nanomachines, that can convert a living human into a loyal cyborg slave when placed inside." cost = 100 @@ -707,7 +707,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) return success /// Air Alarm Safety Override: Unlocks the ability to enable dangerous modes on all air alarms. -/datum/ai_module/utility/break_air_alarms +/datum/ai_module/malf/utility/break_air_alarms name = "Air Alarm Safety Override" description = "Gives you the ability to disable safeties on all air alarms. This will allow you to use extremely dangerous environmental modes. \ Anyone can check the air alarm's interface and may be tipped off by their nonfunctionality." @@ -733,7 +733,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) owner.playsound_local(owner, 'sound/machines/terminal_off.ogg', 50, 0) /// Thermal Sensor Override: Unlocks the ability to disable all fire alarms from doing their job. -/datum/ai_module/utility/break_fire_alarms +/datum/ai_module/malf/utility/break_fire_alarms name = "Thermal Sensor Override" description = "Gives you the ability to override the thermal sensors on all fire alarms. \ This will remove their ability to scan for fire and thus their ability to alert." @@ -764,7 +764,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) owner.playsound_local(owner, 'sound/machines/terminal_off.ogg', 50, 0) /// Disable Emergency Lights -/datum/ai_module/utility/emergency_lights +/datum/ai_module/malf/utility/emergency_lights name = "Disable Emergency Lights" description = "Cuts emergency lights across the entire station. If power is lost to light fixtures, \ they will not attempt to fall back on emergency power reserves." @@ -791,7 +791,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) owner.playsound_local(owner, 'sound/effects/light_flicker.ogg', 50, FALSE) /// Reactivate Camera Network: Reactivates up to 30 cameras across the station. -/datum/ai_module/utility/reactivate_cameras +/datum/ai_module/malf/utility/reactivate_cameras name = "Reactivate Camera Network" description = "Runs a network-wide diagnostic on the camera network, resetting focus and re-routing power to failed cameras. \ Can be used to repair up to 30 cameras." @@ -832,7 +832,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) build_all_button_icons() /// Upgrade Camera Network: EMP-proofs all cameras, in addition to giving them X-ray vision. -/datum/ai_module/upgrade/upgrade_cameras +/datum/ai_module/malf/upgrade/upgrade_cameras name = "Upgrade Camera Network" description = "Install broad-spectrum scanning and electrical redundancy firmware to the camera network, enabling EMP-proofing and light-amplified X-ray vision. Upgrade is done immediately upon purchase." //I <3 pointless technobabble //This used to have motion sensing as well, but testing quickly revealed that giving it to the whole cameranet is PURE HORROR. @@ -841,7 +841,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) unlock_text = span_notice("OTA firmware distribution complete! Cameras upgraded: CAMSUPGRADED. Light amplification system online.") unlock_sound = 'sound/items/rped.ogg' -/datum/ai_module/upgrade/upgrade_cameras/upgrade(mob/living/silicon/ai/AI) +/datum/ai_module/malf/upgrade/upgrade_cameras/upgrade(mob/living/silicon/ai/AI) // Sets up nightvision RegisterSignal(AI, COMSIG_MOB_UPDATE_SIGHT, PROC_REF(on_update_sight)) AI.update_sight() @@ -864,13 +864,13 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) upgraded_cameras++ unlock_text = replacetext(unlock_text, "CAMSUPGRADED", "[upgraded_cameras]") //This works, since unlock text is called after upgrade() -/datum/ai_module/upgrade/upgrade_cameras/proc/on_update_sight(mob/source) +/datum/ai_module/malf/upgrade/upgrade_cameras/proc/on_update_sight(mob/source) SIGNAL_HANDLER // Dim blue, pretty source.lighting_color_cutoffs = blend_cutoff_colors(source.lighting_color_cutoffs, list(5, 25, 35)) /// AI Turret Upgrade: Increases the health and damage of all turrets. -/datum/ai_module/upgrade/upgrade_turrets +/datum/ai_module/malf/upgrade/upgrade_turrets name = "AI Turret Upgrade" description = "Improves the power and health of all AI turrets. This effect is permanent. Upgrade is done immediately upon purchase." cost = 30 @@ -878,7 +878,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) unlock_text = span_notice("You establish a power diversion to your turrets, upgrading their health and damage.") unlock_sound = 'sound/items/rped.ogg' -/datum/ai_module/upgrade/upgrade_turrets/upgrade(mob/living/silicon/ai/AI) +/datum/ai_module/malf/upgrade/upgrade_turrets/upgrade(mob/living/silicon/ai/AI) for(var/obj/machinery/porta_turret/ai/turret as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/porta_turret/ai)) turret.AddElement(/datum/element/empprotection, EMP_PROTECT_ALL) turret.max_integrity = 200 @@ -887,7 +887,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) turret.lethal_projectile_sound = 'sound/weapons/lasercannonfire.ogg' /// Enhanced Surveillance: Enables AI to hear conversations going on near its active vision. -/datum/ai_module/upgrade/eavesdrop +/datum/ai_module/malf/upgrade/eavesdrop name = "Enhanced Surveillance" description = "Via a combination of hidden microphones and lip reading software, \ you are able to use your cameras to listen in on conversations. Upgrade is done immediately upon purchase." @@ -896,12 +896,12 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) unlock_text = span_notice("OTA firmware distribution complete! Cameras upgraded: Enhanced surveillance package online.") unlock_sound = 'sound/items/rped.ogg' -/datum/ai_module/upgrade/eavesdrop/upgrade(mob/living/silicon/ai/AI) +/datum/ai_module/malf/upgrade/eavesdrop/upgrade(mob/living/silicon/ai/AI) if(AI.eyeobj) AI.eyeobj.relay_speech = TRUE /// Unlock Mech Domination: Unlocks the ability to dominate mechs. Big shocker, right? -/datum/ai_module/upgrade/mecha_domination +/datum/ai_module/malf/upgrade/mecha_domination name = "Unlock Mech Domination" description = "Allows you to hack into a mech's onboard computer, shunting all processes into it and ejecting any occupants. \ Do not allow the mech to leave the station's vicinity or allow it to be destroyed. \ @@ -912,10 +912,10 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) Loss of signal will result in total system lockout.
") unlock_sound = 'sound/mecha/nominal.ogg' -/datum/ai_module/upgrade/mecha_domination/upgrade(mob/living/silicon/ai/AI) +/datum/ai_module/malf/upgrade/mecha_domination/upgrade(mob/living/silicon/ai/AI) AI.can_dominate_mechs = TRUE //Yep. This is all it does. Honk! -/datum/ai_module/upgrade/voice_changer +/datum/ai_module/malf/upgrade/voice_changer name = "Voice Changer" description = "Allows you to change the AI's voice. Upgrade is active immediately upon purchase." cost = 40 @@ -1053,7 +1053,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) if("name") say_name = strip_html(params["name"], MAX_NAME_LEN) -/datum/ai_module/utility/emag +/datum/ai_module/malf/utility/emag name = "Targeted Safeties Override" description = "Allows you to disable the safeties of any machinery on the station, provided you can access it." cost = 20 @@ -1147,7 +1147,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) return TRUE -/datum/ai_module/utility/core_tilt +/datum/ai_module/malf/utility/core_tilt name = "Rolling Servos" description = "Allows you to slowly roll around, crushing anything in your way with your bulk." cost = 10 @@ -1246,7 +1246,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) stack_trace("non-standard dir entered to get_rotation_from_dir. (got: [dir])") return 0 -/datum/ai_module/utility/remote_vendor_tilt +/datum/ai_module/malf/utility/remote_vendor_tilt name = "Remote vendor tilting" description = "Lets you remotely tip vendors over in any direction." cost = 15 diff --git a/code/modules/antagonists/nukeop/datums/operative.dm b/code/modules/antagonists/nukeop/datums/operative.dm index 9eca88d33852d..c05295e15d32e 100644 --- a/code/modules/antagonists/nukeop/datums/operative.dm +++ b/code/modules/antagonists/nukeop/datums/operative.dm @@ -94,7 +94,7 @@ nuke_team = new_team /datum/antagonist/nukeop/admin_add(datum/mind/new_owner,mob/admin) - new_owner.set_assigned_role(SSjob.GetJobType(/datum/job/nuclear_operative)) + new_owner.set_assigned_role(SSjob.get_job_type(/datum/job/nuclear_operative)) new_owner.add_antag_datum(src) message_admins("[key_name_admin(admin)] has nuke op'ed [key_name_admin(new_owner)].") log_admin("[key_name(admin)] has nuke op'ed [key_name(new_owner)].") diff --git a/code/modules/antagonists/nukeop/datums/operative_leader.dm b/code/modules/antagonists/nukeop/datums/operative_leader.dm index c2995e5575326..1af9f1d28c40e 100644 --- a/code/modules/antagonists/nukeop/datums/operative_leader.dm +++ b/code/modules/antagonists/nukeop/datums/operative_leader.dm @@ -44,7 +44,13 @@ /datum/antagonist/nukeop/leader/proc/ask_name() var/randomname = pick(GLOB.last_names) - var/newname = tgui_input_text(owner.current, "You are the nuclear operative [title]. Please choose a last name for your family.", "Name change", randomname, MAX_NAME_LEN) + var/newname = tgui_input_text( + owner.current, + "You are the nuclear operative [title]. Please choose a last name for your family.", + "Name change", + randomname, + max_length = MAX_NAME_LEN, + ) if (!newname) newname = randomname else diff --git a/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm b/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm index 0160fbd89149c..b59d984238e61 100644 --- a/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm +++ b/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm @@ -43,7 +43,7 @@ GLOBAL_LIST_EMPTY(jam_on_wardec) if(custom_threat == "Yes") declaring_war = TRUE - war_declaration = tgui_input_text(user, "Insert your custom declaration", "Declaration", multiline = TRUE, encode = FALSE) + war_declaration = tgui_input_text(user, "Insert your custom declaration", "Declaration", max_length = MAX_MESSAGE_LEN, multiline = TRUE, encode = FALSE) declaring_war = FALSE if(!check_allowed(user) || !war_declaration) @@ -63,7 +63,7 @@ GLOBAL_LIST_EMPTY(jam_on_wardec) var/custom_threat = tgui_alert(usr, "Do you want to customize the declaration?", "Customize?", list("Yes", "No")) if(custom_threat == "Yes") - war_declaration = tgui_input_text(usr, "Insert your custom declaration", "Declaration", multiline = TRUE, encode = FALSE) + war_declaration = tgui_input_text(usr, "Insert your custom declaration", "Declaration", max_length = MAX_MESSAGE_LEN, multiline = TRUE, encode = FALSE) if(!war_declaration) tgui_alert(usr, "Invalid war declaration.", "Poor Choice of Words") diff --git a/code/modules/antagonists/obsessed/obsessed.dm b/code/modules/antagonists/obsessed/obsessed.dm index 7316102e2ce09..7f9d9614fb1d9 100644 --- a/code/modules/antagonists/obsessed/obsessed.dm +++ b/code/modules/antagonists/obsessed/obsessed.dm @@ -1,3 +1,9 @@ +#define OBSESSED_OBJECTIVE_SPEND_TIME "spend_time" +#define OBSESSED_OBJECTIVE_POLAROID "polaroid" +#define OBSESSED_OBJECTIVE_HUG "hug" +#define OBSESSED_OBJECTIVE_HEIRLOOM "heirloom" +#define OBSESSED_OBJECTIVE_JEALOUS "jealous" + /datum/antagonist/obsessed name = "Obsessed" show_in_antagpanel = TRUE @@ -13,8 +19,23 @@ preview_outfit = /datum/outfit/obsessed hardcore_random_bonus = TRUE stinger_sound = 'sound/ambience/antag/creepalert.ogg' + /// How many objectives should be generated + var/objectives_to_generate = 3 + /// Brain trauma that causes the obsession var/datum/brain_trauma/special/obsessed/trauma +/// Dummy antag datum that will show the cured obsessed to admins +/datum/antagonist/former_obsessed + name = "Former Obsessed" + show_in_antagpanel = FALSE + show_name_in_check_antagonists = TRUE + antagpanel_category = ANTAG_GROUP_CREW + show_in_roundend = FALSE + count_against_dynamic_roll_chance = FALSE + silent = TRUE + can_elimination_hijack = ELIMINATION_PREVENT + antag_flags = FLAG_FAKE_ANTAG + /datum/antagonist/obsessed/admin_add(datum/mind/new_owner,mob/admin) var/mob/living/carbon/C = new_owner.current if(!istype(C)) @@ -72,7 +93,7 @@ H.regenerate_icons() /datum/antagonist/obsessed/forge_objectives(datum/mind/obsessionmind) - var/list/objectives_left = list("spendtime", "polaroid", "hug") + var/list/objectives_left = list(OBSESSED_OBJECTIVE_SPEND_TIME, OBSESSED_OBJECTIVE_POLAROID, OBSESSED_OBJECTIVE_HUG) var/datum/objective/assassinate/obsessed/kill = new kill.owner = owner kill.target = obsessionmind @@ -84,44 +105,44 @@ family_heirloom = heirloom_quirk.heirloom?.resolve() break if(family_heirloom) - objectives_left += "heirloom" + objectives_left += OBSESSED_OBJECTIVE_HEIRLOOM // If they have no coworkers, jealousy will pick someone else on the station. This will never be a free objective. if(!is_captain_job(obsessionmind.assigned_role)) - objectives_left += "jealous" + objectives_left += OBSESSED_OBJECTIVE_JEALOUS - for(var/i in 1 to 3) - var/chosen_objective = pick(objectives_left) - objectives_left.Remove(chosen_objective) + for(var/i in 1 to objectives_to_generate) + var/chosen_objective = pick_n_take(objectives_left) switch(chosen_objective) - if("spendtime") + if(OBSESSED_OBJECTIVE_SPEND_TIME) var/datum/objective/spendtime/spendtime = new spendtime.owner = owner spendtime.target = obsessionmind objectives += spendtime - if("polaroid") + if(OBSESSED_OBJECTIVE_POLAROID) var/datum/objective/polaroid/polaroid = new polaroid.owner = owner polaroid.target = obsessionmind objectives += polaroid - if("hug") + if(OBSESSED_OBJECTIVE_HUG) var/datum/objective/hug/hug = new hug.owner = owner hug.target = obsessionmind objectives += hug - if("heirloom") + if(OBSESSED_OBJECTIVE_HEIRLOOM) var/datum/objective/steal/heirloom_thief/heirloom_thief = new heirloom_thief.owner = owner heirloom_thief.target = obsessionmind//while you usually wouldn't need this for stealing, we need the name of the obsession heirloom_thief.steal_target = family_heirloom objectives += heirloom_thief - if("jealous") + if(OBSESSED_OBJECTIVE_JEALOUS) var/datum/objective/assassinate/jealous/jealous = new jealous.owner = owner jealous.target = obsessionmind//will reroll into a coworker on the objective itself objectives += jealous objectives += kill//finally add the assassinate last, because you'd have to complete it last to greentext. + for(var/datum/objective/O in objectives) O.update_explanation_text() @@ -278,3 +299,9 @@ explanation_text = "Steal [target.name]'s family heirloom, [steal_target] they cherish." else explanation_text = "Free Objective" + +#undef OBSESSED_OBJECTIVE_SPEND_TIME +#undef OBSESSED_OBJECTIVE_POLAROID +#undef OBSESSED_OBJECTIVE_HUG +#undef OBSESSED_OBJECTIVE_HEIRLOOM +#undef OBSESSED_OBJECTIVE_JEALOUS diff --git a/code/modules/antagonists/paradox_clone/paradox_clone.dm b/code/modules/antagonists/paradox_clone/paradox_clone.dm index e809e8cecbf00..bd8eb7cd7d866 100644 --- a/code/modules/antagonists/paradox_clone/paradox_clone.dm +++ b/code/modules/antagonists/paradox_clone/paradox_clone.dm @@ -52,7 +52,7 @@ kill.update_explanation_text() objectives += kill - owner.set_assigned_role(SSjob.GetJobType(/datum/job/paradox_clone)) + owner.set_assigned_role(SSjob.get_job_type(/datum/job/paradox_clone)) //clone doesnt show up on message lists var/obj/item/modular_computer/pda/messenger = locate() in owner.current diff --git a/code/modules/antagonists/space_dragon/space_dragon.dm b/code/modules/antagonists/space_dragon/space_dragon.dm index 0d982dc492d4e..cc82f491c1fcd 100644 --- a/code/modules/antagonists/space_dragon/space_dragon.dm +++ b/code/modules/antagonists/space_dragon/space_dragon.dm @@ -67,12 +67,12 @@ forge_objectives() rift_ability = new() owner.special_role = ROLE_SPACE_DRAGON - owner.set_assigned_role(SSjob.GetJobType(/datum/job/space_dragon)) + owner.set_assigned_role(SSjob.get_job_type(/datum/job/space_dragon)) return ..() /datum/antagonist/space_dragon/on_removal() owner.special_role = null - owner.set_assigned_role(SSjob.GetJobType(/datum/job/unassigned)) + owner.set_assigned_role(SSjob.get_job_type(/datum/job/unassigned)) return ..() /datum/antagonist/space_dragon/apply_innate_effects(mob/living/mob_override) diff --git a/code/modules/antagonists/space_ninja/space_ninja.dm b/code/modules/antagonists/space_ninja/space_ninja.dm index 7f88c687c12d1..37bc2299928da 100644 --- a/code/modules/antagonists/space_ninja/space_ninja.dm +++ b/code/modules/antagonists/space_ninja/space_ninja.dm @@ -114,12 +114,12 @@ equip_space_ninja(owner.current) owner.current.add_quirk(/datum/quirk/freerunning) owner.current.add_quirk(/datum/quirk/light_step) - owner.current.mind.set_assigned_role(SSjob.GetJobType(/datum/job/space_ninja)) + owner.current.mind.set_assigned_role(SSjob.get_job_type(/datum/job/space_ninja)) owner.current.mind.special_role = ROLE_NINJA return ..() /datum/antagonist/ninja/admin_add(datum/mind/new_owner,mob/admin) - new_owner.set_assigned_role(SSjob.GetJobType(/datum/job/space_ninja)) + new_owner.set_assigned_role(SSjob.get_job_type(/datum/job/space_ninja)) new_owner.special_role = ROLE_NINJA new_owner.add_antag_datum(src) message_admins("[key_name_admin(admin)] has ninja'ed [key_name_admin(new_owner)].") diff --git a/code/modules/antagonists/spy/spy_bounty.dm b/code/modules/antagonists/spy/spy_bounty.dm index 42ab0203e5c03..ccab7952a9c2c 100644 --- a/code/modules/antagonists/spy/spy_bounty.dm +++ b/code/modules/antagonists/spy/spy_bounty.dm @@ -132,6 +132,14 @@ /datum/spy_bounty/proc/clean_up_stolen_item(atom/movable/stealing, mob/living/spy) do_sparks(3, FALSE, stealing) + if(isitem(stealing) && stealing.loc == spy) + // get it out of our inventory before we mess with it to prevent any weirdness. + // bypasses nodrop - if you want, add a bespoke check for that higher up the chain + spy.temporarilyRemoveItemFromInventory(stealing, force = TRUE) + // also check for DROPDEL + if(QDELETED(stealing)) + return + // Don't mess with it while it's going away var/had_attack_hand_interaction = stealing.interaction_flags_atom & INTERACT_ATOM_ATTACK_HAND stealing.interaction_flags_atom &= ~INTERACT_ATOM_ATTACK_HAND diff --git a/code/modules/antagonists/spy/spy_uplink.dm b/code/modules/antagonists/spy/spy_uplink.dm index 5de66271fe29c..920076f21b468 100644 --- a/code/modules/antagonists/spy/spy_uplink.dm +++ b/code/modules/antagonists/spy/spy_uplink.dm @@ -23,7 +23,7 @@ /datum/component/spy_uplink/RegisterWithParent() RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, PROC_REF(on_attack_self)) - RegisterSignal(parent, COMSIG_ITEM_PRE_ATTACK_SECONDARY, PROC_REF(on_pre_attack_secondary)) + RegisterSignal(parent, COMSIG_ITEM_INTERACTING_WITH_ATOM, PROC_REF(on_item_atom_interaction)) RegisterSignal(parent, COMSIG_TABLET_CHECK_DETONATE, PROC_REF(block_pda_bombs)) /datum/component/spy_uplink/UnregisterFromParent() @@ -60,13 +60,15 @@ INVOKE_ASYNC(src, TYPE_PROC_REF(/datum, ui_interact), user) return NONE -/datum/component/spy_uplink/proc/on_pre_attack_secondary(obj/item/source, atom/target, mob/living/user, params) +/datum/component/spy_uplink/proc/on_item_atom_interaction(obj/item/source, mob/living/user, atom/target, list/modifiers) SIGNAL_HANDLER if(!ismovable(target)) return NONE if(!IS_SPY(user)) return NONE + if(SHOULD_SKIP_INTERACTION(target, source, user)) + return NONE if(!try_steal(target, user)) return NONE return COMPONENT_CANCEL_ATTACK_CHAIN @@ -94,7 +96,7 @@ /// Wraps the stealing process in a scanning effect. /datum/component/spy_uplink/proc/start_stealing(atom/movable/stealing, mob/living/spy, datum/spy_bounty/bounty) if(!isturf(stealing.loc) && stealing.loc != spy) - to_chat(spy, span_warning("Your uplinks blinks red: [stealing] cannot be extracted from there.")) + to_chat(spy, span_warning("Your uplink blinks red: [stealing] cannot be extracted from there.")) return FALSE log_combat(spy, stealing, "started stealing", parent, "(spy bounty)") @@ -139,10 +141,10 @@ if(!do_after(spy, bounty.theft_time, stealing, interaction_key = REF(src), hidden = TRUE)) return FALSE if(bounty.claimed) - to_chat(spy, span_warning("Your uplinks blinks red: The bounty for [stealing] has been claimed by another spy!")) + to_chat(spy, span_warning("Your uplink blinks red: The bounty for [stealing] has been claimed by another spy!")) return FALSE if(spy.is_holding(stealing) && !spy.dropItemToGround(stealing)) - to_chat(spy, span_warning("Your uplinks blinks red: [stealing] seems stuck to your hand!")) + to_chat(spy, span_warning("Your uplink blinks red: [stealing] seems stuck to your hand!")) return FALSE var/bounty_key = bounty.get_dupe_protection_key(stealing) diff --git a/code/modules/antagonists/traitor/contractor/syndicate_contract.dm b/code/modules/antagonists/traitor/contractor/syndicate_contract.dm index 2c9d45e382dd4..71ae454df72f9 100644 --- a/code/modules/antagonists/traitor/contractor/syndicate_contract.dm +++ b/code/modules/antagonists/traitor/contractor/syndicate_contract.dm @@ -102,14 +102,17 @@ if(traitor_data.uplink_handler.contractor_hub.current_contract == src) traitor_data.uplink_handler.contractor_hub.current_contract = null - for(var/obj/item/person_contents as anything in person_sent.gather_belongings()) + for(var/obj/item/person_contents as anything in person_sent.gather_belongings(FALSE, FALSE)) if(ishuman(person_sent)) var/mob/living/carbon/human/human_sent = person_sent if(person_contents == human_sent.w_uniform) continue //So all they're left with are shoes and uniform. if(person_contents == human_sent.shoes) continue - person_sent.transferItemToLoc(person_contents) + var/unequipped = person_sent.temporarilyRemoveItemFromInventory(person_contents) + if (!unequipped) + continue + person_contents.moveToNullspace() victim_belongings.Add(WEAKREF(person_contents)) var/obj/structure/closet/supplypod/extractionpod/pod = source diff --git a/code/modules/antagonists/traitor/objectives/kidnapping.dm b/code/modules/antagonists/traitor/objectives/kidnapping.dm index ea7fef9b4b607..0d4ff5cfd9971 100644 --- a/code/modules/antagonists/traitor/objectives/kidnapping.dm +++ b/code/modules/antagonists/traitor/objectives/kidnapping.dm @@ -228,13 +228,14 @@ var/mob/living/carbon/human/sent_mob = entered_atom - for(var/obj/item/belonging in sent_mob.gather_belongings()) + for(var/obj/item/belonging in sent_mob.gather_belongings(FALSE, FALSE)) if(belonging == sent_mob.get_item_by_slot(ITEM_SLOT_ICLOTHING) || belonging == sent_mob.get_item_by_slot(ITEM_SLOT_FEET)) continue - var/unequipped = sent_mob.transferItemToLoc(belonging) + var/unequipped = sent_mob.temporarilyRemoveItemFromInventory(belonging) if (!unequipped) continue + belonging.moveToNullspace() target_belongings.Add(WEAKREF(belonging)) var/datum/market_item/hostage/market_item = sent_mob.process_capture(rand(1000, 3000)) diff --git a/code/modules/antagonists/traitor/objectives/steal.dm b/code/modules/antagonists/traitor/objectives/steal.dm index fdcd693fed889..4c697d66d57fc 100644 --- a/code/modules/antagonists/traitor/objectives/steal.dm +++ b/code/modules/antagonists/traitor/objectives/steal.dm @@ -255,7 +255,7 @@ GLOBAL_DATUM_INIT(steal_item_handler, /datum/objective_item_handler, new()) /obj/item/traitor_bug name = "suspicious device" desc = "It looks dangerous." - item_flags = EXAMINE_SKIP + item_flags = EXAMINE_SKIP|NOBLUDGEON icon = 'icons/obj/antags/syndicate_tools.dmi' icon_state = "bug" @@ -280,7 +280,8 @@ GLOBAL_DATUM_INIT(steal_item_handler, /datum/objective_item_handler, new()) /obj/item/traitor_bug/interact_with_atom(atom/movable/target, mob/living/user, list/modifiers) if(!target_object_type || !ismovable(target)) return NONE - + if(SHOULD_SKIP_INTERACTION(target, src, user)) + return NONE var/result = SEND_SIGNAL(src, COMSIG_TRAITOR_BUG_PRE_PLANTED_OBJECT, target) if(!(result & COMPONENT_FORCE_PLACEMENT)) if(result & COMPONENT_FORCE_FAIL_PLACEMENT || !istype(target, target_object_type)) @@ -315,6 +316,3 @@ GLOBAL_DATUM_INIT(steal_item_handler, /datum/objective_item_handler, new()) anchored = FALSE UnregisterSignal(planted_on, COMSIG_QDELETING) planted_on = null - -/obj/item/traitor_bug/storage_insert_on_interaction(datum/storage, atom/storage_holder, mob/user) - return !istype(storage_holder, target_object_type) diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm index 9176558c7a166..bf04c535a56a0 100644 --- a/code/modules/antagonists/wizard/equipment/artefact.dm +++ b/code/modules/antagonists/wizard/equipment/artefact.dm @@ -431,10 +431,10 @@ COMSIG_ITEM_MAGICALLY_CHARGED = PROC_REF(on_magic_charge), ) -/obj/item/runic_vendor_scepter/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) - return interact_with_atom(interacting_with, user, modifiers) - /obj/item/runic_vendor_scepter/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return ranged_interact_with_atom(interacting_with, user, modifiers) + +/obj/item/runic_vendor_scepter/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(scepter_is_busy_recharging) user.balloon_alert(user, "busy!") return ITEM_INTERACT_BLOCKING diff --git a/code/modules/antagonists/wizard/equipment/soulstone.dm b/code/modules/antagonists/wizard/equipment/soulstone.dm index f8f5cf22350a7..eb4df6b6239f2 100644 --- a/code/modules/antagonists/wizard/equipment/soulstone.dm +++ b/code/modules/antagonists/wizard/equipment/soulstone.dm @@ -224,19 +224,19 @@ shade_datum.release_time = world.time on_release_spirits() -/obj/item/soulstone/pre_attack(atom/A, mob/living/user, params) - var/mob/living/basic/shade/occupant = (locate() in src) - var/obj/item/storage/toolbox/mechanical/target_toolbox = A - if(!occupant || !istype(target_toolbox) || target_toolbox.has_soul) - return ..() +/obj/item/soulstone/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + var/mob/living/basic/shade/occupant = locate() in src + var/obj/item/storage/toolbox/mechanical/target_toolbox = interacting_with + if(isnull(occupant) || !istype(target_toolbox) || target_toolbox.has_soul) + return NONE if(theme == THEME_HOLY && IS_CULTIST(user)) hot_potato(user) - return + return ITEM_INTERACT_BLOCKING if(!role_check(user)) user.Unconscious(10 SECONDS) to_chat(user, span_userdanger("Your body is wracked with debilitating pain!")) - return + return ITEM_INTERACT_BLOCKING user.visible_message("[user] holds [src] above [user.p_their()] head and forces it into [target_toolbox] with a flash of light!", \ span_notice("You hold [src] above your head briefly, then force it into [target_toolbox], transferring the [occupant]'s soul!"), ignored_mobs = occupant) @@ -253,6 +253,7 @@ target_toolbox.icon_state = "toolbox_blue_old" target_toolbox.has_soul = TRUE target_toolbox.has_latches = FALSE + return ITEM_INTERACT_SUCCESS ///////////////////////////Transferring to constructs///////////////////////////////////////////////////// /obj/structure/constructshell diff --git a/code/modules/antagonists/wizard/equipment/spellbook_entries/summons.dm b/code/modules/antagonists/wizard/equipment/spellbook_entries/summons.dm index fe5f69fd9fa53..b8bf9a8e3cf25 100644 --- a/code/modules/antagonists/wizard/equipment/spellbook_entries/summons.dm +++ b/code/modules/antagonists/wizard/equipment/spellbook_entries/summons.dm @@ -74,7 +74,7 @@ cost = 4 /datum/spellbook_entry/summon/curse_of_madness/buy_spell(mob/living/carbon/human/user, obj/item/spellbook/book, log_buy = TRUE) - var/message = tgui_input_text(user, "Whisper a secret truth to drive your victims to madness", "Whispers of Madness") + var/message = tgui_input_text(user, "Whisper a secret truth to drive your victims to madness", "Whispers of Madness", max_length = MAX_MESSAGE_LEN) if(!message || QDELETED(user) || QDELETED(book) || !can_buy(user, book)) return FALSE curse_of_madness(user, message) diff --git a/code/modules/antagonists/wizard/grand_ritual/grand_rune.dm b/code/modules/antagonists/wizard/grand_ritual/grand_rune.dm index 15900a6ac0b0a..25883370c0d1b 100644 --- a/code/modules/antagonists/wizard/grand_ritual/grand_rune.dm +++ b/code/modules/antagonists/wizard/grand_ritual/grand_rune.dm @@ -147,7 +147,7 @@ haunt_color = spell_colour, \ haunt_duration = 10 SECONDS, \ aggro_radius = 0, \ - spawn_message = span_revenwarning("[sacrifice] begins to float and twirl into the air as it becomes enveloped in otherworldy energies..."), \ + spawn_message = span_revenwarning("[sacrifice] begins to float and twirl into the air as it becomes enveloped in otherworldly energies..."), \ ) addtimer(CALLBACK(sacrifice, TYPE_PROC_REF(/obj/item/food/cheese/wheel, consume_cheese)), 10 SECONDS) cheese_sacrificed += length(cheese_to_haunt) @@ -253,7 +253,7 @@ while(created < to_create && location_sanity < 100) var/turf/chosen_location = get_safe_random_station_turf() - // We don't want them close to each other - at least 1 tile of seperation + // We don't want them close to each other - at least 1 tile of separation var/list/nearby_things = range(1, chosen_location) var/obj/effect/heretic_influence/what_if_i_have_one = locate() in nearby_things var/obj/effect/visible_heretic_influence/what_if_i_had_one_but_its_used = locate() in nearby_things diff --git a/code/modules/antagonists/wizard/wizard.dm b/code/modules/antagonists/wizard/wizard.dm index 335c934a32052..fa6d9a515b680 100644 --- a/code/modules/antagonists/wizard/wizard.dm +++ b/code/modules/antagonists/wizard/wizard.dm @@ -124,7 +124,7 @@ GLOBAL_LIST_EMPTY(wizard_spellbook_purchases_by_key) if(!owner.current) return if(!GLOB.wizardstart.len) - SSjob.SendToLateJoin(owner.current) + SSjob.send_to_late_join(owner.current) to_chat(owner, "HOT INSERTION, GO GO GO") owner.current.forceMove(pick(GLOB.wizardstart)) diff --git a/code/modules/antagonists/xeno/xeno.dm b/code/modules/antagonists/xeno/xeno.dm index 59c83fd52ed11..5ef26665bf238 100644 --- a/code/modules/antagonists/xeno/xeno.dm +++ b/code/modules/antagonists/xeno/xeno.dm @@ -160,7 +160,7 @@ else mind.add_antag_datum(/datum/antagonist/xeno) - mind.set_assigned_role(SSjob.GetJobType(/datum/job/xenomorph)) + mind.set_assigned_role(SSjob.get_job_type(/datum/job/xenomorph)) mind.special_role = ROLE_ALIEN /mob/living/carbon/alien/on_wabbajacked(mob/living/new_mob) @@ -170,7 +170,7 @@ if(isalien(new_mob)) return mind.remove_antag_datum(/datum/antagonist/xeno) - mind.set_assigned_role(SSjob.GetJobType(/datum/job/unassigned)) + mind.set_assigned_role(SSjob.get_job_type(/datum/job/unassigned)) mind.special_role = null #undef CAPTIVE_XENO_DEAD diff --git a/code/modules/art/paintings.dm b/code/modules/art/paintings.dm index 2e330d31185da..1c11e0f8086cc 100644 --- a/code/modules/art/paintings.dm +++ b/code/modules/art/paintings.dm @@ -417,7 +417,7 @@ /obj/item/canvas/proc/try_rename(mob/user) if(painting_metadata.loaded_from_json) // No renaming old paintings return TRUE - var/new_name = tgui_input_text(user, "What do you want to name the painting?", "Title Your Masterpiece", null, MAX_NAME_LEN) + var/new_name = tgui_input_text(user, "What do you want to name the painting?", "Title Your Masterpiece", max_length = MAX_NAME_LEN) new_name = reject_bad_name(new_name, allow_numbers = TRUE, ascii_only = FALSE, strict = TRUE, cap_after_symbols = FALSE) if(isnull(new_name)) return FALSE diff --git a/code/modules/art/statues.dm b/code/modules/art/statues.dm index fd64d212f3e80..da4a47dd843d8 100644 --- a/code/modules/art/statues.dm +++ b/code/modules/art/statues.dm @@ -36,7 +36,7 @@ /obj/structure/statue/attackby(obj/item/W, mob/living/user, params) add_fingerprint(user) if(W.tool_behaviour == TOOL_WELDER) - if(!W.tool_start_check(user, amount=1)) + if(!W.tool_start_check(user, amount=1, heat_required = HIGH_TEMPERATURE_REQUIRED)) return FALSE user.balloon_alert(user, "slicing apart...") if(W.use_tool(src, user, 40, volume=50)) diff --git a/code/modules/assembly/flash.dm b/code/modules/assembly/flash.dm index b81eb26e7fae9..f20d364759927 100644 --- a/code/modules/assembly/flash.dm +++ b/code/modules/assembly/flash.dm @@ -128,7 +128,7 @@ /** * Handles actual flashing part of the attack * - * This proc is awful in every sense of the way, someone should definately refactor this whole code. + * This proc is awful in every sense of the way, someone should definitely refactor this whole code. * Arguments: * * M - Victim * * user - Attacker @@ -161,7 +161,7 @@ else if(sigreturn & DEVIATION_OVERRIDE_NONE) deviation = DEVIATION_NONE - //If you face away from someone they shouldnt notice any effects. + //If you face away from someone they shouldn't notice any effects. if(deviation == DEVIATION_FULL) return @@ -185,7 +185,7 @@ /** * Handles the directionality of the attack * - * Returns the amount of 'deviation', 0 being facing eachother, 1 being sideways, 2 being facing away from eachother. + * Returns the amount of 'deviation', 0 being facing each other, 1 being sideways, 2 being facing away from each other. * Arguments: * * victim - Victim * * attacker - Attacker diff --git a/code/modules/asset_cache/assets/inventory.dm b/code/modules/asset_cache/assets/inventory.dm index 0883dbd7515e5..5aaab9332a852 100644 --- a/code/modules/asset_cache/assets/inventory.dm +++ b/code/modules/asset_cache/assets/inventory.dm @@ -14,6 +14,7 @@ "inventory-suit_storage.png" = 'icons/ui/inventory/suit_storage.png', "inventory-id.png" = 'icons/ui/inventory/id.png', "inventory-belt.png" = 'icons/ui/inventory/belt.png', + "inventory-tail.png" = 'icons/ui/inventory/tail.png', // DOPPLER ADDITION - tail item slot "inventory-back.png" = 'icons/ui/inventory/back.png', "inventory-pocket.png" = 'icons/ui/inventory/pocket.png', "inventory-collar.png" = 'icons/ui/inventory/collar.png', diff --git a/code/modules/asset_cache/assets/rtd.dm b/code/modules/asset_cache/assets/rtd.dm index 23a3b0d71b2db..66899fcb943f1 100644 --- a/code/modules/asset_cache/assets/rtd.dm +++ b/code/modules/asset_cache/assets/rtd.dm @@ -2,7 +2,7 @@ name = "rtd" /datum/asset/spritesheet/rtd/create_spritesheets() - //some tiles may share the same icon but have diffrent properties to animate that icon + //some tiles may share the same icon but have different properties to animate that icon //so we keep track of what icons we registered var/list/registered = list() diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm index e7c5f5d35c7fa..dc56aa3fda7f7 100644 --- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm +++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm @@ -304,7 +304,7 @@ our_excited_group = excited_group //update our cache if(our_excited_group && enemy_excited_group && enemy_tile.excited) //If you're both excited, no need to compare right? should_share_air = TRUE - else if(our_air.compare(enemy_air)) //Lets see if you're up for it + else if(our_air.compare(enemy_air, ARCHIVE)) //Lets see if you're up for it SSair.add_to_active(enemy_tile) //Add yourself young man var/datum/excited_group/existing_group = our_excited_group || enemy_excited_group || new if(!our_excited_group) @@ -332,7 +332,7 @@ var/datum/gas_mixture/planetary_mix = SSair.planetary[initial_gas_mix] // archive ourself again so we don't accidentally share more gas than we currently have LINDA_CYCLE_ARCHIVE(src) - if(our_air.compare(planetary_mix)) + if(our_air.compare(planetary_mix, ARCHIVE)) if(!our_excited_group) var/datum/excited_group/new_group = new new_group.add_turf(src) diff --git a/code/modules/atmospherics/gasmixtures/gas_mixture.dm b/code/modules/atmospherics/gasmixtures/gas_mixture.dm index db2732be83fad..f329b98bec06a 100644 --- a/code/modules/atmospherics/gasmixtures/gas_mixture.dm +++ b/code/modules/atmospherics/gasmixtures/gas_mixture.dm @@ -451,16 +451,17 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) //thermal energy of the system (self and sharer) is unchanged ///Compares sample to self to see if within acceptable ranges that group processing may be enabled +///Takes the gas index to read from as a second arg (either MOLES or ARCHIVE) ///Returns: a string indicating what check failed, or "" if check passes -/datum/gas_mixture/proc/compare(datum/gas_mixture/sample) +/datum/gas_mixture/proc/compare(datum/gas_mixture/sample, index) var/list/sample_gases = sample.gases //accessing datum vars is slower than proc vars var/list/cached_gases = gases var/moles_sum = 0 for(var/id in cached_gases | sample_gases) // compare gases from either mixture // Yes this is actually fast. I too hate it here - var/gas_moles = cached_gases[id]?[MOLES] || 0 - var/sample_moles = sample_gases[id]?[MOLES] || 0 + var/gas_moles = cached_gases[id]?[index] || 0 + var/sample_moles = sample_gases[id]?[index] || 0 // Brief explanation. We are much more likely to not pass this first check then pass the first and fail the second // Because of this, double calculating the delta is FASTER then inserting it into a var if(abs(gas_moles - sample_moles) > MINIMUM_MOLES_DELTA_TO_MOVE) @@ -470,8 +471,12 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) moles_sum += gas_moles if(moles_sum > MINIMUM_MOLES_DELTA_TO_MOVE) //Don't consider temp if there's not enough mols - if(abs(temperature - sample.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) - return "temp" + if(index == ARCHIVE) + if(abs(temperature_archived - sample.temperature_archived) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) + return "temp" + else + if(abs(temperature - sample.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) + return "temp" return "" @@ -547,7 +552,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) /** * Counts how much pressure will there be if we impart MOLAR_ACCURACY amounts of our gas to the output gasmix. - * We do all of this without actually transferring it so dont worry about it changing the gasmix. + * We do all of this without actually transferring it so don't worry about it changing the gasmix. * Returns: Resulting pressure (number). * Args: * - output_air (gasmix). @@ -562,10 +567,10 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) * Args: * - output_air. The gas mix we want to pump to. * - target_pressure. The target pressure we want. - * - ignore_temperature. Returns a cheaper form of gas calculation, useful if the temperature difference between the two gasmixes is low or nonexistant. + * - ignore_temperature. Returns a cheaper form of gas calculation, useful if the temperature difference between the two gasmixes is low or nonexistent. */ /datum/gas_mixture/proc/gas_pressure_calculate(datum/gas_mixture/output_air, target_pressure, ignore_temperature = FALSE) - // So we dont need to iterate the gaslist multiple times. + // So we don't need to iterate the gaslist multiple times. var/our_moles = total_moles() var/output_moles = output_air.total_moles() var/output_pressure = output_air.return_pressure() diff --git a/code/modules/atmospherics/gasmixtures/gas_types.dm b/code/modules/atmospherics/gasmixtures/gas_types.dm index 7bbfea3dcf253..c040e30db3fcf 100644 --- a/code/modules/atmospherics/gasmixtures/gas_types.dm +++ b/code/modules/atmospherics/gasmixtures/gas_types.dm @@ -85,7 +85,7 @@ rarity = 1000 purchaseable = TRUE base_value = 0.1 - desc = "A very common gas that used to pad artifical atmospheres to habitable pressure." + desc = "A very common gas that used to pad artificial atmospheres to habitable pressure." primary_color = "#ffff00" /datum/gas/carbon_dioxide //what the fuck is this? @@ -133,7 +133,7 @@ fusion_power = 10 rarity = 50 base_value = 2.5 - desc = "The most noble gas of them all. High quantities of hyper-noblium actively prevents reactions from occuring." + desc = "The most noble gas of them all. High quantities of hyper-noblium actively prevents reactions from occurring." primary_color = COLOR_TEAL /datum/gas/nitrous_oxide @@ -173,7 +173,7 @@ fusion_power = 5 rarity = 300 base_value = 2.5 - desc = "A highly flammable and radioctive gas." + desc = "A highly flammable and radioactive gas." primary_color = "#32cd32" /datum/gas/bz @@ -279,7 +279,7 @@ moles_visible = MOLES_GAS_VISIBLE rarity = 300 base_value = 4 - desc = "A potent fire supressant. Removes oxygen from high temperature fires and cools down the area" + desc = "A potent fire suppressant. Removes oxygen from high temperature fires and cools down the area" primary_color = COLOR_PURPLE /datum/gas/helium @@ -314,7 +314,7 @@ appearance_flags = TILE_BOUND vis_flags = NONE // The visual offset we are "on". - // Can't use the tradtional loc because we are stored in nullspace, and we can't set plane before init because of the helping that SET_PLANE_EXPLICIT does IN init + // Can't use the traditional loc because we are stored in nullspace, and we can't set plane before init because of the helping that SET_PLANE_EXPLICIT does IN init var/plane_offset = 0 /obj/effect/overlay/gas/New(state, alph, offset) diff --git a/code/modules/atmospherics/gasmixtures/reaction_factors.dm b/code/modules/atmospherics/gasmixtures/reaction_factors.dm index 5148793179500..af058dc77877f 100644 --- a/code/modules/atmospherics/gasmixtures/reaction_factors.dm +++ b/code/modules/atmospherics/gasmixtures/reaction_factors.dm @@ -50,14 +50,14 @@ /datum/gas/carbon_dioxide = "Carbon Dioxide is formed at 1 mole per mole of freon consumed.", "Temperature" = "Can only occur between [FREON_LOWER_TEMPERATURE] - [FREON_MAXIMUM_BURN_TEMPERATURE] Kelvin", "Energy" = "[FIRE_FREON_ENERGY_CONSUMED] joules of energy is absorbed per mole of freon consumed.", - "Hot Ice" = "This reaction produces hot ice when occuring between [HOT_ICE_FORMATION_MINIMUM_TEMPERATURE]-[HOT_ICE_FORMATION_MAXIMUM_TEMPERATURE] kelvins", + "Hot Ice" = "This reaction produces hot ice when occurring between [HOT_ICE_FORMATION_MINIMUM_TEMPERATURE]-[HOT_ICE_FORMATION_MAXIMUM_TEMPERATURE] kelvins", ) /datum/gas_reaction/nitrousformation/init_factors() factor = list( /datum/gas/oxygen = "10 moles of Oxygen needs to be present for the reaction to occur. Oxygen is consumed at 0.5 moles per mole of nitrous oxide formed.", - /datum/gas/nitrogen = " 20 moles of Nitrogen needs to be present for the reaction to occur. Nitrogen is consumed at 1 mole per mole of nitrous oxife formed.", + /datum/gas/nitrogen = " 20 moles of Nitrogen needs to be present for the reaction to occur. Nitrogen is consumed at 1 mole per mole of nitrous oxide formed.", /datum/gas/bz = "5 moles of BZ needs to be present for the reaction to occur. Not consumed.", /datum/gas/nitrous_oxide = "Nitrous oxide gets produced rapidly.", "Temperature" = "Can only occur between [N2O_FORMATION_MIN_TEMPERATURE] - [N2O_FORMATION_MAX_TEMPERATURE] Kelvin", diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm index 49254d077deae..f6c238c8d0e28 100644 --- a/code/modules/atmospherics/gasmixtures/reactions.dm +++ b/code/modules/atmospherics/gasmixtures/reactions.dm @@ -328,7 +328,7 @@ SET_REACTION_RESULTS(burned_fuel) var/turf/open/location - if(istype(holder, /datum/pipeline)) //Find the tile the reaction is occuring on, or a random part of the network if it's a pipenet. + if(istype(holder, /datum/pipeline)) //Find the tile the reaction is occurring on, or a random part of the network if it's a pipenet. var/datum/pipeline/pipenet = holder location = pick(pipenet.members) else if(isatom(holder)) @@ -686,7 +686,7 @@ var/list/cached_gases = air.gases var/temperature = air.temperature - //This reaction is agressively slow. like, a tenth of a mole per fire slow. Keep that in mind + //This reaction is aggressively slow. like, a tenth of a mole per fire slow. Keep that in mind var/heat_efficiency = min(temperature / NITRIUM_DECOMPOSITION_TEMP_DIVISOR, cached_gases[/datum/gas/nitrium][MOLES]) if (heat_efficiency <= 0 || (cached_gases[/datum/gas/nitrium][MOLES] - heat_efficiency < 0)) //Shouldn't produce gas from nothing. @@ -1091,7 +1091,7 @@ SET_REACTION_RESULTS(produced_amount) var/turf/open/location var/energy_released = produced_amount * PN_TRITIUM_CONVERSION_ENERGY - if(istype(holder,/datum/pipeline)) //Find the tile the reaction is occuring on, or a random part of the network if it's a pipenet. + if(istype(holder,/datum/pipeline)) //Find the tile the reaction is occurring on, or a random part of the network if it's a pipenet. var/datum/pipeline/pipenet = holder location = pick(pipenet.members) else if(isatom(holder)) @@ -1143,7 +1143,7 @@ SET_REACTION_RESULTS(consumed_amount) var/turf/open/location var/energy_released = consumed_amount * PN_BZASE_ENERGY - if(istype(holder,/datum/pipeline)) //Find the tile the reaction is occuring on, or a random part of the network if it's a pipenet. + if(istype(holder,/datum/pipeline)) //Find the tile the reaction is occurring on, or a random part of the network if it's a pipenet. var/datum/pipeline/pipenet = holder location = pick(pipenet.members) else if(isatom(holder)) diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm index 12e6c684079e6..95758c22707c6 100644 --- a/code/modules/atmospherics/machinery/atmosmachinery.dm +++ b/code/modules/atmospherics/machinery/atmosmachinery.dm @@ -34,7 +34,7 @@ ///The flags of the pipe/component (PIPING_ALL_LAYER | PIPING_ONE_PER_TURF | PIPING_DEFAULT_LAYER_ONLY | PIPING_CARDINAL_AUTONORMALIZE) var/pipe_flags = NONE - ///This only works on pipes, because they have 1000 subtypes wich need to be visible and invisible under tiles, so we track this here + ///This only works on pipes, because they have 1000 subtypes which need to be visible and invisible under tiles, so we track this here var/hide = TRUE ///The image of the pipe/device used for ventcrawling @@ -331,7 +331,7 @@ if(isnull(given_layer)) given_layer = piping_layer - // you cant place the machine on the same location as the target cause it blocks + // you can't place the machine on the same location as the target cause it blocks if(target.loc == loc) return FALSE @@ -478,7 +478,7 @@ * Called by wrench_act() before deconstruct() * Arguments: * * mob_user - the mob doing the act - * * pressures - it can be passed on from wrench_act(), it's the pressure difference between the enviroment pressure and the pipe internal pressure + * * pressures - it can be passed on from wrench_act(), it's the pressure difference between the environment pressure and the pipe internal pressure */ /obj/machinery/atmospherics/proc/unsafe_pressure_release(mob/user, pressures = null) if(!user) @@ -569,7 +569,7 @@ // Handles mob movement inside a pipenet /obj/machinery/atmospherics/relaymove(mob/living/user, direction) - if(!direction) //cant go this way. + if(!direction) //can't go this way. return if(user in buckled_mobs)// fixes buckle ventcrawl edgecase fuck bug return diff --git a/code/modules/atmospherics/machinery/components/fusion/hfr_procs.dm b/code/modules/atmospherics/machinery/components/fusion/hfr_procs.dm index 9f2f6a96f4bf8..e3ef70489ac85 100644 --- a/code/modules/atmospherics/machinery/components/fusion/hfr_procs.dm +++ b/code/modules/atmospherics/machinery/components/fusion/hfr_procs.dm @@ -430,7 +430,7 @@ radio.talk_into(src, "[safe_alert] Failsafe has been disengaged.", common_channel) final_countdown = FALSE return - else if((i % 50) != 0 && i > 50) // A message once every 5 seconds until the final 5 seconds which count down individualy + else if((i % 50) != 0 && i > 50) // A message once every 5 seconds until the final 5 seconds which count down individually sleep(1 SECONDS) continue else if(i > 50) diff --git a/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer.dm b/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer.dm index 565ada80b931e..b5cc7c628df29 100644 --- a/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer.dm +++ b/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer.dm @@ -106,7 +106,7 @@ return TRUE return FALSE -///Injects the gases from the input inside the internal gasmix, the amount is dependant on the gas_input var +///Injects the gases from the input inside the internal gasmix, the amount is dependent on the gas_input var /obj/machinery/atmospherics/components/binary/crystallizer/proc/inject_gases() var/datum/gas_mixture/contents = airs[2] for(var/gas_type in selected_recipe.requirements) diff --git a/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer_items.dm b/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer_items.dm index 26cb395113519..6308e1eee611e 100644 --- a/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer_items.dm +++ b/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer_items.dm @@ -1,6 +1,6 @@ /obj/item/hypernoblium_crystal name = "Hypernoblium Crystal" - desc = "Crystalized oxygen and hypernoblium stored in a bottle to pressureproof your clothes or stop reactions occuring in portable atmospheric devices." + desc = "Crystallized oxygen and hypernoblium stored in a bottle to pressureproof your clothes or stop reactions occurring in portable atmospheric devices." icon = 'icons/obj/pipes_n_cables/atmos.dmi' icon_state = "hypernoblium_crystal" var/uses = 1 diff --git a/code/modules/atmospherics/machinery/components/tank.dm b/code/modules/atmospherics/machinery/components/tank.dm index ee1e61428d196..f76f3dc470f57 100644 --- a/code/modules/atmospherics/machinery/components/tank.dm +++ b/code/modules/atmospherics/machinery/components/tank.dm @@ -304,7 +304,7 @@ . = TRUE if(atom_integrity >= max_integrity) return - if(!tool.tool_start_check(user, amount = 0)) + if(!tool.tool_start_check(user, amount = 0, heat_required = HIGH_TEMPERATURE_REQUIRED)) return to_chat(user, span_notice("You begin to repair the cracks in the gas tank...")) var/repair_amount = max_integrity / 10 @@ -562,7 +562,7 @@ if(!anchored) to_chat(user, span_notice("You need to wrench [src] to the floor before finishing.")) return - if(!tool.tool_start_check(user, amount = 0)) + if(!tool.tool_start_check(user, amount = 0, heat_required = HIGH_TEMPERATURE_REQUIRED)) return to_chat(user, span_notice("You begin sealing the outer plating with the welder...")) if(!tool.use_tool(src, user, 2 SECONDS, volume = 60)) diff --git a/code/modules/atmospherics/machinery/portable/canister.dm b/code/modules/atmospherics/machinery/portable/canister.dm index a5a03c3ba1204..e6c60140f3a70 100644 --- a/code/modules/atmospherics/machinery/portable/canister.dm +++ b/code/modules/atmospherics/machinery/portable/canister.dm @@ -397,7 +397,7 @@ return ITEM_INTERACT_SUCCESS /obj/machinery/portable_atmospherics/canister/welder_act_secondary(mob/living/user, obj/item/I) - if(!I.tool_start_check(user, amount=1)) + if(!I.tool_start_check(user, amount=1, heat_required = HIGH_TEMPERATURE_REQUIRED)) return ITEM_INTERACT_BLOCKING var/pressure = air_contents.return_pressure() diff --git a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm index 210eb9b0d9e28..edd8e30eaf8ce 100644 --- a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm +++ b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm @@ -95,7 +95,7 @@ /obj/machinery/portable_atmospherics/welder_act(mob/living/user, obj/item/tool) if(user.combat_mode) return ITEM_INTERACT_SKIP_TO_ATTACK - if(atom_integrity >= max_integrity || (machine_stat & BROKEN) || !tool.tool_start_check(user, amount = 1)) + if(atom_integrity >= max_integrity || (machine_stat & BROKEN) || !tool.tool_start_check(user, amount = 1, heat_required = HIGH_TEMPERATURE_REQUIRED)) return ITEM_INTERACT_BLOCKING balloon_alert(user, "repairing...") while(tool.use_tool(src, user, 2.5 SECONDS, volume=40)) @@ -223,16 +223,17 @@ if(!user.transferItemToLoc(new_tank, src)) return FALSE - investigate_log("had its internal [holding] swapped with [new_tank] by [key_name(user)].", INVESTIGATE_ATMOS) - to_chat(user, span_notice("[holding ? "In one smooth motion you pop [holding] out of [src]'s connector and replace it with [new_tank]" : "You insert [new_tank] into [src]"].")) - if(holding && new_tank)//for when we are actually switching tanks + investigate_log("had its internal [holding] swapped with [new_tank] by [key_name(user)].", INVESTIGATE_ATMOS) + to_chat(user, span_notice("In one smooth motion you pop [holding] out of [src]'s connector and replace it with [new_tank].")) user.put_in_hands(holding) UnregisterSignal(holding, COMSIG_QDELETING) holding = new_tank RegisterSignal(holding, COMSIG_QDELETING, PROC_REF(unregister_holding)) playsound(src, list(insert_sound,remove_sound), sound_vol) else if(holding)//we remove a tank + investigate_log("had its internal [holding] removed by [key_name(user)].", INVESTIGATE_ATMOS) + to_chat(user, span_notice("You remove [holding] from [src].")) if(Adjacent(user)) user.put_in_hands(holding) else @@ -241,6 +242,8 @@ UnregisterSignal(holding, COMSIG_QDELETING) holding = null else if(new_tank)//we insert the tank + investigate_log("had [new_tank] inserted into it by [key_name(user)].", INVESTIGATE_ATMOS) + to_chat(user, span_notice("You insert [new_tank] into [src].")) holding = new_tank playsound(src, insert_sound, sound_vol) RegisterSignal(holding, COMSIG_QDELETING, PROC_REF(unregister_holding)) diff --git a/code/modules/autowiki/pages/base.dm b/code/modules/autowiki/pages/base.dm index 8e745ace61c2d..ce32bfd4032b7 100644 --- a/code/modules/autowiki/pages/base.dm +++ b/code/modules/autowiki/pages/base.dm @@ -46,7 +46,12 @@ if (IsAdminAdvancedProcCall()) return + var/static/uploaded_icons = list() + if(uploaded_icons["[name]"]) + CRASH("We tried uploading an icon, but the name \"[name]\" was already taken!") + fcopy(icon, "data/autowiki_files/[name].png") + uploaded_icons["[name]"] = TRUE /// Escape a parameter such that it can be correctly put inside a wiki output /datum/autowiki/proc/escape_value(parameter) diff --git a/code/modules/autowiki/pages/fishing.dm b/code/modules/autowiki/pages/fishing.dm new file mode 100644 index 0000000000000..b71b8dab33026 --- /dev/null +++ b/code/modules/autowiki/pages/fishing.dm @@ -0,0 +1,445 @@ +/datum/autowiki/fish + page = "Template:Autowiki/Content/Fish" + +/datum/autowiki/fish/generate() + var/output = "" + + var/datum/reagent/def_food = /obj/item/fish::food + var/def_food_name = initial(def_food.name) + var/def_feeding = /obj/item/fish::feeding_frequency + var/def_feeding_text = DisplayTimeText(def_feeding) + var/def_breeding = /obj/item/fish::breeding_timeout + var/def_breeding_text = DisplayTimeText(def_breeding) + + var/list/generated_icons = list() + var/list/fish_types = subtypesof(/obj/item/fish) + sortTim(fish_types, GLOBAL_PROC_REF(cmp_fish_fluid)) + + for (var/obj/item/fish/fish as anything in fish_types) + + var/filename = FISH_AUTOWIKI_FILENAME(fish) + + if(!generated_icons[filename]) + upload_icon(icon(fish:icon, fish::icon_state, frame = 1), filename) + generated_icons[filename] = TRUE + + if(!(fish::fish_flags & FISH_FLAG_SHOW_IN_CATALOG)) + continue + + var/list/properties = SSfishing.fish_properties[fish] + + var/description = escape_value(fish::desc) + var/list/extra_info = list() + if(fish::fillet_type != /obj/item/food/fishmeat) + var/obj/item/fillet = fish::fillet_type + if(!fillet) + extra_info += "Cannot be butchered." + else + extra_info += "When butchered, it'll yield [initial(fillet.name)]." + var/datum/reagent/food = fish::food + if(food != def_food) + extra_info += "It has to be fed [initial(food.name)] instead of [def_food_name]" + if(fish::feeding_frequency != def_feeding) + extra_info += "It has to be fed every [DisplayTimeText(fish::feeding_frequency)] instead of [def_feeding_text]" + if(fish::breeding_timeout != def_breeding) + extra_info += "It takes [DisplayTimeText(fish::breeding_timeout)] to reproduce instead of [def_breeding_text]" + if(length(extra_info)) + description += "
[extra_info.Join(extra_info,"
")]" + + output += "\n\n" + include_template("Autowiki/FishEntry", list( + "name" = full_capitalize(escape_value(fish::name)), + "icon" = filename, + "description" = description, + "size_weight" = "[fish::average_size]cm / [fish::average_weight]g", + "fluid" = escape_value(fish::required_fluid_type), + "temperature" = "[fish::required_temperature_min] - [fish::required_temperature_max] K", + "stable_population" = fish::stable_population, + "traits" = generate_traits(properties[FISH_PROPERTIES_TRAITS]), + "favorite_baits" = generate_baits(properties[FISH_PROPERTIES_FAV_BAIT]), + "disliked_baits" = generate_baits(properties[FISH_PROPERTIES_BAD_BAIT], TRUE), + "beauty_score" = properties[FISH_PROPERTIES_BEAUTY_SCORE], + )) + + return output + +/datum/autowiki/fish/proc/generate_baits(list/baits, bad = FALSE) + var/list/list = list() + if(!length(baits)) + return list("None") + + for (var/identifier in baits) + if(ispath(identifier)) //Just a path + var/obj/item/item = identifier + list += initial(item.name) + continue + var/list/special_identifier = identifier + switch(special_identifier["Type"]) + if("Foodtype") + list += english_list(bitfield_to_list(special_identifier["Value"], FOOD_FLAGS_IC)) + if("Reagent") + var/datum/reagent/reagent = special_identifier["Value"] + list += "[reagent::name][bad ? "" : "(At least [special_identifier["Amount"]] units)"]" + + return list + +/datum/autowiki/fish/proc/generate_traits(list/traits) + var/output = "" + + for(var/trait_type in traits) + var/datum/fish_trait/trait = GLOB.fish_traits[trait_type] + output += include_template("Autowiki/FishTypeTraits", list( + "name" = escape_value(trait.name), + "description" = escape_value(trait.catalog_description), + )) + + return output + +/datum/autowiki/fish_trait + page = "Template:Autowiki/Content/Fish/Trait" + +/datum/autowiki/fish_trait/generate() + var/output = "" + + for(var/trait_type in GLOB.fish_traits) + var/datum/fish_trait/trait = GLOB.fish_traits[trait_type] + var/desc = escape_value(trait.catalog_description) + if(length(trait.incompatible_traits)) + var/incompatible = list() + for(var/datum/fish_trait/bad as anything in trait.incompatible_traits) + incompatible += span_bold(initial(bad.name)) + desc += "
Incompatible with [english_list(incompatible)]." + output += include_template("Autowiki/FishAllTraits", list( + "name" = escape_value(trait.name), + "description" = escape_value(trait.catalog_description), + "inheritability" = trait.inheritability, + "inheritability_diff" = trait.diff_traits_inheritability, + + )) + + return output + +/datum/autowiki/fish_bait + page = "Template:Autowiki/Content/Fish/Bait" + +/datum/autowiki/fish_bait/generate() + var/output = "" + + var/list/generated_icons = list() + for (var/obj/item/food/bait/bait as anything in subtypesof(/obj/item/food/bait)) + if(!bait::show_on_wiki) + continue + + var/filename = SANITIZE_FILENAME("[bait::icon_state]_wiki_bait") + + var/quality = "Bland" + + var/list/foodtypes + if(ispath(bait, /obj/item/food/bait/doughball/synthetic)) + foodtypes = list("Don't worry about it") + else + foodtypes = bitfield_to_list(bait::foodtypes, FOOD_FLAGS_IC) || list("None") + + switch(bait::bait_quality) + if(TRAIT_BASIC_QUALITY_BAIT) + quality = "Basic" + if(TRAIT_GOOD_QUALITY_BAIT) + quality = "Good" + if(TRAIT_GREAT_QUALITY_BAIT) + quality = "Great" + + output += "\n\n" + include_template("Autowiki/FishBait", list( + "name" = full_capitalize(escape_value(bait::name)), + "icon" = filename, + "description" = escape_value(bait::desc), + "foodtypes" = foodtypes, + "quality" = quality, + )) + + if(!generated_icons[filename]) + upload_icon(icon(bait:icon, bait::icon_state, frame = 1), filename) + generated_icons[filename] = TRUE + + var/filename = SANITIZE_FILENAME(/obj/item/stock_parts/power_store/cell/lead::icon_state) + + var/lead_desc = /obj/item/stock_parts/power_store/cell/lead::desc + lead_desc += " You probably shouldn't use it unless you're trying to catch a zipzap." + output += "\n\n" + include_template("Autowiki/FishBait", list( + "name" = full_capitalize(escape_value(/obj/item/stock_parts/power_store/cell/lead::name)), + "icon" = filename, + "description" = lead_desc, + "foodtypes" = "None", + "quality" = "Poisonous", + )) + + upload_icon(icon(/obj/item/stock_parts/power_store/cell/lead::icon, /obj/item/stock_parts/power_store/cell/lead::icon_state), filename) + + var/obj/needletype = /obj/item/fish/needlefish + output += "\n\n" + include_template("Autowiki/FishBait", list( + "name" = "Baitfish", + "icon" = FISH_AUTOWIKI_FILENAME(needletype), + "description" = "Smaller fish such as goldfish, needlefish, armorfish and lavaloops can also be used as bait, It's a fish eat fish world.", + "foodtypes" = "Seafood?", + "quality" = "Good", + )) + + output += "\n\n" + include_template("Autowiki/FishBait", list( + "name" = "Food", + "icon" = "plain_bread", + "description" = "In absence of baits, food can be used as a substitute.", + "foodtypes" = "Depends", + "quality" = "Bland most of the times", + )) + + upload_icon(icon(/obj/item/food/bread/plain::icon, /obj/item/food/bread/plain::icon_state), "plain_bread") + + return output + +/datum/autowiki/fishing_line + page = "Template:Autowiki/Content/Fish/Line" + +/datum/autowiki/fishing_line/generate() + var/output = "" + + var/list/generated_icons = list() + for (var/obj/item/fishing_line/line as anything in typesof(/obj/item/fishing_line)) + var/filename = SANITIZE_FILENAME("[line::icon_state]_wiki_line") + + output += "\n\n" + include_template("Autowiki/FishLine", list( + "name" = full_capitalize(escape_value(line::name)), + "icon" = filename, + "description" = escape_value(line::wiki_desc), + )) + + if(!generated_icons[filename]) + upload_icon(icon(line:icon, line::icon_state), filename) + generated_icons[filename] = TRUE + + return output + +/datum/autowiki/fishing_hook + page = "Template:Autowiki/Content/Fish/Hook" + +/datum/autowiki/fishing_hook/generate() + var/output = "" + + var/list/generated_icons = list() + for (var/obj/item/fishing_hook/hook as anything in typesof(/obj/item/fishing_hook)) + var/filename = SANITIZE_FILENAME("[hook::icon_state]_wiki_hook") + + output += "\n\n" + include_template("Autowiki/FishHook", list( + "name" = full_capitalize(escape_value(hook::name)), + "icon" = filename, + "description" = escape_value(hook::wiki_desc), + )) + + if(!generated_icons[filename]) + upload_icon(icon(hook:icon, hook::icon_state), filename) + generated_icons[filename] = TRUE + + return output + +/datum/autowiki/fishing_rod + page = "Template:Autowiki/Content/Fish/Rod" + +/datum/autowiki/fishing_rod/generate() + var/output = "" + + var/list/generated_icons = list() + for (var/obj/item/fishing_rod/rod as anything in typesof(/obj/item/fishing_rod)) + if(!rod::show_in_wiki) + continue + + var/filename = SANITIZE_FILENAME("[rod::icon_state]_wiki_rod") + + var/desc = escape_value(rod::ui_description) + if(rod::wiki_description) + desc += "
[escape_value(rod::wiki_description)]" + output += "\n\n" + include_template("Autowiki/FishingRod", list( + "name" = full_capitalize(escape_value(rod::name)), + "icon" = filename, + "description" = desc, + )) + + if(!generated_icons[filename]) + var/icon/rod_icon = icon(rod:icon, rod::icon_state) + if(rod::reel_overlay) + var/icon/line = icon(rod::icon, rod::reel_overlay) + line.Blend(rod::default_line_color, ICON_MULTIPLY) + rod_icon.Blend(line, ICON_OVERLAY) + upload_icon(rod_icon, filename) + generated_icons[filename] = TRUE + + return output + +/datum/autowiki/fish_sources + page = "Template:Autowiki/Content/Fish/Source" + +/datum/autowiki/fish_sources/generate() + var/output = "" + + for(var/source_type in GLOB.preset_fish_sources) + var/datum/fish_source/source = GLOB.preset_fish_sources[source_type] + if(!source.catalog_description) + continue + + output += "\n\n" + include_template("Autowiki/FishSource", list( + "name" = full_capitalize(source.catalog_description), + "difficulty" = source.fishing_difficulty, + "contents" = get_contents(source), + )) + + ///Used for stuff that isn't fish by default + upload_icon(icon('icons/effects/random_spawners.dmi', "questionmark"), FISH_SOURCE_AUTOWIKI_QUESTIONMARK) + + return output + +/datum/autowiki/fish_sources/proc/get_contents(datum/fish_source/source) + var/output = "" + var/list/data = source.generate_wiki_contents(src) + sortTim(data, GLOBAL_PROC_REF(cmp_autowiki_fish_sources_content)) + for(var/list/entry in data) + entry[FISH_SOURCE_AUTOWIKI_WEIGHT] = "[round(entry[FISH_SOURCE_AUTOWIKI_WEIGHT], 0.1)]%" + var/weight_suffix = entry[FISH_SOURCE_AUTOWIKI_WEIGHT_SUFFIX] + if(weight_suffix) + entry[FISH_SOURCE_AUTOWIKI_WEIGHT] += " [weight_suffix]" + entry -= FISH_SOURCE_AUTOWIKI_WEIGHT + output += include_template("Autowiki/FishSourceContents", entry) + + return output + +///Sort the autowiki fish entries by their weight. However, duds always come first. +/proc/cmp_autowiki_fish_sources_content(list/A, list/B) + if(A[FISH_SOURCE_AUTOWIKI_NAME] == FISH_SOURCE_AUTOWIKI_DUD) + return -1 + if(B[FISH_SOURCE_AUTOWIKI_NAME] == FISH_SOURCE_AUTOWIKI_DUD) + return 1 + if(A[FISH_SOURCE_AUTOWIKI_NAME] == FISH_SOURCE_AUTOWIKI_OTHER) + return 1 + if(B[FISH_SOURCE_AUTOWIKI_NAME] == FISH_SOURCE_AUTOWIKI_OTHER) + return -1 + return B[FISH_SOURCE_AUTOWIKI_WEIGHT] - A[FISH_SOURCE_AUTOWIKI_WEIGHT] + +/datum/autowiki/fish_scan + page = "Template:Autowiki/Content/Fish/Scan" + +/datum/autowiki/fish_scan/generate() + var/output = "" + + var/list/generated_icons = list() + var/datum/techweb/techweb = locate(/datum/techweb/admin) in SSresearch.techwebs + for(var/scan_type in typesof(/datum/experiment/scanning/fish)) + techweb.add_experiment(scan_type) //Make sure each followup experiment is available + var/datum/experiment/scanning/fish/scan = locate(scan_type) in techweb.available_experiments + if(!scan) //Just to be sure, if the scan was already completed. + scan = locate(scan_type) in techweb.completed_experiments + + output += "\n\n" + include_template("Autowiki/FishScan", list( + "name" = full_capitalize(escape_value(scan.name)), + "description" = escape_value(scan.description), + "requirements" = build_requirements(scan), + "rewards" = build_rewards(scan, generated_icons), + + )) + + return output + +/datum/autowiki/fish_scan/proc/build_requirements(datum/experiment/scanning/fish/scan) + var/output = "" + for(var/obj/item/type as anything in scan.required_atoms) + var/name = initial(type.name) + //snowflake case because the default holographic fish is called goldfish but we don't want to confuse readers. + if(type == /obj/item/fish/holo) + name = "holographic Fish" + output += include_template("Autowiki/FishScanRequirements", list( + "name" = full_capitalize(escape_value(name)), + "amount" = scan.required_atoms[type], + )) + return output + +/datum/autowiki/fish_scan/proc/build_rewards(datum/experiment/scanning/fish/scan, list/generated_icons) + var/output = "" + var/datum/fish_source/portal/reward = GLOB.preset_fish_sources[scan.fish_source_reward] + var/filename = SANITIZE_FILENAME("fishing_portal_[reward.radial_state]") + + var/list/unlocks = list() + for(var/datum/experiment/unlock as anything in scan.next_experiments) + unlocks += initial(unlock.name) + output += include_template("Autowiki/FishScanRewards", list( + "name" = full_capitalize(escape_value("[reward.radial_name] Dimension")), + "icon" = filename, + "points" = scan.get_points_reward_text(), + "unlock" = english_list(unlocks, nothing_text = "Nothing"), + )) + + if(!generated_icons[filename]) + upload_icon(icon(icon = 'icons/hud/radial_fishing.dmi', icon_state = reward.radial_state), filename) + generated_icons[filename] = TRUE + + return output + +/datum/autowiki/fish_evolution + page = "Template:Autowiki/Content/Fish/Evolution" + +/datum/autowiki/fish_evolution/generate() + var/output = "" + + for(var/evo_type in GLOB.fish_evolutions) + var/datum/fish_evolution/evolution = GLOB.fish_evolutions[evo_type] + if(!evolution.show_on_wiki) + continue + + output += "\n\n" + include_template("Autowiki/FishEvolution", list( + "name" = escape_value(evolution.name), + "fish" = get_fish(evo_type), + "min_max_temp" = "[evolution.required_temperature_min] - [evolution.required_temperature_max] K", + "notes" = escape_value(evolution.conditions_note), + "result_icon" = evolution.show_result_on_wiki ? FISH_AUTOWIKI_FILENAME(evolution.new_fish_type) : FISH_SOURCE_AUTOWIKI_QUESTIONMARK, + )) + + return output + +/datum/autowiki/fish_evolution/proc/get_fish(evo_type) + var/output = "" + + for(var/obj/item/fish/fish as anything in GLOB.fishes_by_fish_evolution[evo_type]) + if(!(initial(fish.fish_flags) & FISH_FLAG_SHOW_IN_CATALOG)) + continue + output += include_template("Autowiki/FishEvolutionCandidate", list( + "name" = escape_value(full_capitalize(initial(fish.name))), + "icon" = FISH_AUTOWIKI_FILENAME(fish), + )) + + return output + +/datum/autowiki/fish_lure + page = "Template:Autowiki/Content/Fish/Lure" + +/datum/autowiki/fish_lure/generate() + var/output = "" + + for(var/obj/item/fishing_lure/lure as anything in SSfishing.lure_catchables) + var/state = initial(lure.icon_state) + var/filename = SANITIZE_FILENAME("[state]_wiki_lure") + output += "\n\n" + include_template("Autowiki/FishLure", list( + "name" = escape_value(full_capitalize(initial(lure.name))), + "desc" = escape_value(initial(lure.name)), + "icon" = filename, + "catchables" = build_catchables(SSfishing.lure_catchables[lure]), + )) + + upload_icon(icon(icon = initial(lure.icon), icon_state = state), filename) + + return output + +/datum/autowiki/fish_lure/proc/build_catchables(list/catchables) + var/output = "" + + for(var/obj/item/fish/fish as anything in catchables) + if(!(initial(fish.fish_flags) & FISH_FLAG_SHOW_IN_CATALOG)) + continue + output += include_template("Autowiki/FishLureCatchables", list( + "name" = escape_value(full_capitalize(initial(fish.name))), + "icon" = FISH_AUTOWIKI_FILENAME(fish), + )) + + return output diff --git a/code/modules/autowiki/pages/soup.dm b/code/modules/autowiki/pages/soup.dm index f67d00e97a057..754beb3a82adb 100644 --- a/code/modules/autowiki/pages/soup.dm +++ b/code/modules/autowiki/pages/soup.dm @@ -16,6 +16,7 @@ var/container_for_images = /obj/item/reagent_containers/cup/bowl + var/list/already_generated_icons = list() for(var/soup_recipe_type in subtypesof(/datum/chemical_reaction/food/soup)) var/datum/chemical_reaction/food/soup/soup_recipe = new soup_recipe_type() // Used to determine what icon is displayed on the wiki @@ -123,14 +124,17 @@ template_list["results"] = escape_value(compiled_results) // -- While we're here, generate an icon of the bowl -- - if(!soup_icon_state) - var/obj/item/reagent_containers/cup/bowl/soup_bowl = new() - soup_bowl.reagents.add_reagent(result_soup_type, soup_bowl.reagents.maximum_volume) - upload_icon(getFlatIcon(soup_bowl, no_anim = TRUE), filename) - qdel(soup_bowl) - else - var/image/compiled_image = image(icon = soup_icon, icon_state = soup_icon_state) - upload_icon(getFlatIcon(compiled_image, no_anim = TRUE), filename) + + if(!already_generated_icons[filename]) + if(!soup_icon_state) + var/obj/item/reagent_containers/cup/bowl/soup_bowl = new() + soup_bowl.reagents.add_reagent(result_soup_type, soup_bowl.reagents.maximum_volume) + upload_icon(getFlatIcon(soup_bowl, no_anim = TRUE), filename) + qdel(soup_bowl) + else + var/image/compiled_image = image(icon = soup_icon, icon_state = soup_icon_state) + upload_icon(getFlatIcon(compiled_image, no_anim = TRUE), filename) + already_generated_icons[filename] = TRUE // -- Cleanup -- qdel(soup_recipe) diff --git a/code/modules/autowiki/pages/vending.dm b/code/modules/autowiki/pages/vending.dm index 0a8dd3db0a9d5..e110afa760ea2 100644 --- a/code/modules/autowiki/pages/vending.dm +++ b/code/modules/autowiki/pages/vending.dm @@ -10,7 +10,10 @@ // So we put it inside, something var/obj/parent = new - for (var/vending_type in sort_list(subtypesof(/obj/machinery/vending), GLOBAL_PROC_REF(cmp_typepaths_asc))) + for (var/obj/machinery/vending/vending_type as anything in sort_list(subtypesof(/obj/machinery/vending), GLOBAL_PROC_REF(cmp_typepaths_asc))) + var/obj/machinery/vending/parent_machine = type2parent(vending_type) + if(initial(parent_machine.name) == initial(vending_type.name)) + continue //Same name, likely just a slightly touched up subtype for specific maps. var/obj/machinery/vending/vending_machine = new vending_type(parent) vending_machine.use_power = FALSE vending_machine.update_icon(UPDATE_ICON_STATE) diff --git a/code/modules/awaymissions/cordon.dm b/code/modules/awaymissions/cordon.dm index 285d0d49e1051..738efa1d7c21f 100644 --- a/code/modules/awaymissions/cordon.dm +++ b/code/modules/awaymissions/cordon.dm @@ -49,10 +49,10 @@ /turf/cordon/Bumped(atom/movable/bumped_atom) . = ..() - if(HAS_TRAIT(bumped_atom, TRAIT_FREE_HYPERSPACE_SOFTCORDON_MOVEMENT)) //we could feasibly reach the border, so just dont + if(HAS_TRAIT(bumped_atom, TRAIT_FREE_HYPERSPACE_SOFTCORDON_MOVEMENT)) //we could feasibly reach the border, so just don't dump_in_space(bumped_atom) -/// Area used in conjuction with the cordon turf to create a fully functioning world border. +/// Area used in conjunction with the cordon turf to create a fully functioning world border. /area/misc/cordon name = "CORDON" icon_state = "cordon" diff --git a/code/modules/basketball/basketball.dm b/code/modules/basketball/basketball.dm index 35579dc448282..c69c2fd1f7833 100644 --- a/code/modules/basketball/basketball.dm +++ b/code/modules/basketball/basketball.dm @@ -8,7 +8,6 @@ inhand_icon_state = "basketball" desc = "Here's your chance, do your dance at the Space Jam." w_class = WEIGHT_CLASS_BULKY //Stops people from hiding it in their bags/pockets - item_flags = XENOMORPH_HOLDABLE // playing ball against a xeno is rigged since they cannot be disarmed /// The person dribbling the basketball var/mob/living/wielder /// So the basketball doesn't make sound every step diff --git a/code/modules/bitrunning/areas.dm b/code/modules/bitrunning/areas.dm index 4fcf0a0496e47..0656f9d65b389 100644 --- a/code/modules/bitrunning/areas.dm +++ b/code/modules/bitrunning/areas.dm @@ -14,7 +14,7 @@ name = "Virtual Domain Ruins" icon_state = "bit_ruin" icon = 'icons/area/areas_station.dmi' - area_flags = UNIQUE_AREA | NOTELEPORT | EVENT_PROTECTED | HIDDEN_AREA + area_flags = UNIQUE_AREA | NOTELEPORT | EVENT_PROTECTED | HIDDEN_AREA | UNLIMITED_FISHING has_gravity = STANDARD_GRAVITY requires_power = FALSE @@ -26,7 +26,7 @@ /area/virtual_domain/safehouse name = "Virtual Domain Safehouse" - area_flags = UNIQUE_AREA | NOTELEPORT | EVENT_PROTECTED | VIRTUAL_SAFE_AREA + area_flags = UNIQUE_AREA | NOTELEPORT | EVENT_PROTECTED | VIRTUAL_SAFE_AREA | UNLIMITED_FISHING icon_state = "bit_safe" requires_power = FALSE sound_environment = SOUND_ENVIRONMENT_ROOM @@ -36,30 +36,30 @@ /area/lavaland/surface/outdoors/virtual_domain name = "Virtual Domain Lava Ruins" icon_state = "bit_ruin" - area_flags = UNIQUE_AREA | NOTELEPORT | EVENT_PROTECTED | HIDDEN_AREA + area_flags = UNIQUE_AREA | NOTELEPORT | EVENT_PROTECTED | HIDDEN_AREA | UNLIMITED_FISHING /area/icemoon/underground/explored/virtual_domain name = "Virtual Domain Ice Ruins" icon_state = "bit_ice" - area_flags = UNIQUE_AREA | NOTELEPORT | EVENT_PROTECTED | HIDDEN_AREA + area_flags = UNIQUE_AREA | NOTELEPORT | EVENT_PROTECTED | HIDDEN_AREA | UNLIMITED_FISHING /area/ruin/space/virtual_domain name = "Virtual Domain Unexplored Location" icon = 'icons/area/areas_station.dmi' icon_state = "bit_ruin" - area_flags = UNIQUE_AREA | NOTELEPORT | EVENT_PROTECTED | HIDDEN_AREA + area_flags = UNIQUE_AREA | NOTELEPORT | EVENT_PROTECTED | HIDDEN_AREA | UNLIMITED_FISHING /area/space/virtual_domain name = "Virtual Domain Space" icon = 'icons/area/areas_station.dmi' icon_state = "bit_space" - area_flags = UNIQUE_AREA | NOTELEPORT | EVENT_PROTECTED | HIDDEN_AREA + area_flags = UNIQUE_AREA | NOTELEPORT | EVENT_PROTECTED | HIDDEN_AREA | UNLIMITED_FISHING ///Areas that virtual entities should not be in /area/virtual_domain/protected_space name = "Virtual Domain Safe Zone" - area_flags = UNIQUE_AREA | NOTELEPORT | EVENT_PROTECTED | VIRTUAL_SAFE_AREA + area_flags = UNIQUE_AREA | NOTELEPORT | EVENT_PROTECTED | VIRTUAL_SAFE_AREA | UNLIMITED_FISHING icon_state = "bit_safe" /area/virtual_domain/protected_space/fullbright diff --git a/code/modules/bitrunning/server/threats.dm b/code/modules/bitrunning/server/threats.dm index 6b9a334d9252a..ea612a43efaea 100644 --- a/code/modules/bitrunning/server/threats.dm +++ b/code/modules/bitrunning/server/threats.dm @@ -119,7 +119,7 @@ var/datum/mind/antag_mind = new_mob.mind antag_mind.add_antag_datum(chosen_role) antag_mind.special_role = ROLE_GLITCH - antag_mind.set_assigned_role(SSjob.GetJobType(/datum/job/bitrunning_glitch)) + antag_mind.set_assigned_role(SSjob.get_job_type(/datum/job/bitrunning_glitch)) playsound(new_mob, 'sound/magic/ethereal_exit.ogg', 50, vary = TRUE) message_admins("[ADMIN_LOOKUPFLW(new_mob)] has been made into virtual antagonist by an event.") diff --git a/code/modules/bitrunning/spawners.dm b/code/modules/bitrunning/spawners.dm index 4b5f79a43b186..26288d54a1555 100644 --- a/code/modules/bitrunning/spawners.dm +++ b/code/modules/bitrunning/spawners.dm @@ -1,5 +1,5 @@ /obj/effect/mob_spawn/ghost_role/human/virtual_domain - outfit = /datum/outfit/pirate + outfit = /datum/outfit/virtual_pirate prompt_name = "a virtual domain debug entity" flavour_text = "You probably shouldn't be seeing this, contact a coder!" you_are_text = "You are NOT supposed to be here. How did you let this happen?" @@ -32,6 +32,16 @@ you_are_text = "You are a virtual pirate. Yarrr!" flavour_text = " There's a LANDLUBBER after yer booty. Stop them!" +/datum/outfit/virtual_pirate + name = "Virtual Pirate" + id = /obj/item/card/id/advanced + id_trim = /datum/id_trim/pirate + uniform = /obj/item/clothing/under/costume/pirate + suit = /obj/item/clothing/suit/costume/pirate/armored + glasses = /obj/item/clothing/glasses/eyepatch + head = /obj/item/clothing/head/costume/pirate/bandana/armored + shoes = /obj/item/clothing/shoes/pirate/armored + /obj/effect/mob_spawn/ghost_role/human/virtual_domain/pirate/special(mob/living/spawned_mob, mob/mob_possessor) . = ..() diff --git a/code/modules/bitrunning/virtual_domain/domains/meta_central.dm b/code/modules/bitrunning/virtual_domain/domains/meta_central.dm index 0bc35ceaf40e4..dc1029353c320 100644 --- a/code/modules/bitrunning/virtual_domain/domains/meta_central.dm +++ b/code/modules/bitrunning/virtual_domain/domains/meta_central.dm @@ -10,3 +10,4 @@ map_name = "meta_central" mob_modules = list(/datum/modular_mob_segment/revolutionary) reward_points = BITRUNNER_REWARD_LOW + announce_to_ghosts = TRUE diff --git a/code/modules/capture_the_flag/ctf_controller.dm b/code/modules/capture_the_flag/ctf_controller.dm index b5df4981c9f15..dbc152d6bf467 100644 --- a/code/modules/capture_the_flag/ctf_controller.dm +++ b/code/modules/capture_the_flag/ctf_controller.dm @@ -63,7 +63,7 @@ ///Unloading CTF removes the map entirely and allows for a new map to be loaded in its place. /datum/ctf_controller/proc/unload_ctf() if(game_id != CTF_GHOST_CTF_GAME_ID) - return //At present we only support unloading standard centcom ctf, if we intend to support ctf unloading elsewhere then this proc will need to be ammended. + return //At present we only support unloading standard centcom ctf, if we intend to support ctf unloading elsewhere then this proc will need to be amended. stop_ctf() new /obj/effect/landmark/ctf(get_turf(GLOB.ctf_spawner)) @@ -187,7 +187,7 @@ respawn_cooldown = CTF_DEFAULT_RESPAWN instagib_mode = !instagib_mode -///A datum that holds details about individual CTF teams, any team specific CTF functionality should be implimented here. +///A datum that holds details about individual CTF teams, any team specific CTF functionality should be implemented here. /datum/ctf_team ///Reference to the spawn point that this team uses. var/obj/machinery/ctf/spawner/spawner @@ -206,7 +206,7 @@ team_color = spawner.team team_span = spawner.team_span -///If the team is destroyed all players in that team need their componenet removed. +///If the team is destroyed all players in that team need their component removed. /datum/ctf_team/Destroy(force) for(var/player in team_members) var/datum/component/ctf_player/ctf_player = team_members[player] @@ -217,7 +217,7 @@ /datum/ctf_team/proc/score_points(points_scored) points += points_scored -///Resets this teams score and clears its member list. All members will be dusted and have their player componenet removed. +///Resets this teams score and clears its member list. All members will be dusted and have their player component removed. /datum/ctf_team/proc/reset_team() points = 0 for(var/player in team_members) @@ -231,7 +231,7 @@ var/datum/component/ctf_player/ctf_player = team_members[player] ctf_player.send_message(message) -///Creates a CTF game with the provided teeam ID then returns a reference to the new controller. If a controller already exists provides a reference to it. +///Creates a CTF game with the provided team ID then returns a reference to the new controller. If a controller already exists provides a reference to it. /proc/create_ctf_game(game_id) if(GLOB.ctf_games[game_id]) return GLOB.ctf_games[game_id] diff --git a/code/modules/capture_the_flag/ctf_map_loading.dm b/code/modules/capture_the_flag/ctf_map_loading.dm index 6448533a3c74b..4c2f6b319e036 100644 --- a/code/modules/capture_the_flag/ctf_map_loading.dm +++ b/code/modules/capture_the_flag/ctf_map_loading.dm @@ -100,5 +100,5 @@ GLOBAL_DATUM(ctf_spawner, /obj/effect/landmark/ctf) /datum/map_template/ctf/turbine name = "Turbine" - description = "A CTF map that takes place in a familiar facility. Don't try to hold out mid- Theres no sentries in this version." + description = "A CTF map that takes place in a familiar facility. Don't try to hold out mid- There's no sentries in this version." mappath = "_maps/map_files/CTF/turbine.dmm" diff --git a/code/modules/capture_the_flag/ctf_player_component.dm b/code/modules/capture_the_flag/ctf_player_component.dm index c51b48b918c98..5a02a954aba6a 100644 --- a/code/modules/capture_the_flag/ctf_player_component.dm +++ b/code/modules/capture_the_flag/ctf_player_component.dm @@ -1,4 +1,4 @@ -///A component added to the mind of anyone who is playing in an ongoing CTF match. Any player specific CTF functionality should be implimented here. (someone should impliment score tracking here) +///A component added to the mind of anyone who is playing in an ongoing CTF match. Any player specific CTF functionality should be implemented here. (someone should implement score tracking here) /datum/component/ctf_player ///The team that this player is associated with. var/team diff --git a/code/modules/cargo/bounties/science.dm b/code/modules/cargo/bounties/science.dm index 0206ea41967d6..be0edbe1eb64b 100644 --- a/code/modules/cargo/bounties/science.dm +++ b/code/modules/cargo/bounties/science.dm @@ -55,7 +55,7 @@ //******Modular Computer Bounties****** /datum/bounty/item/science/ntnet name = "Modular Tablets" - description = "Turns out that NTNet wasn't actually a fad afterall, who knew. Send some fully functional PDAs to help get us up to speed on the latest technology." + description = "Turns out that NTNet wasn't actually a fad after all, who knew. Send some fully functional PDAs to help get us up to speed on the latest technology." reward = CARGO_CRATE_VALUE * 6 required_count = 4 wanted_types = list(/obj/item/modular_computer/pda = TRUE) diff --git a/code/modules/cargo/centcom_podlauncher.dm b/code/modules/cargo/centcom_podlauncher.dm index cd86761587680..179ca701adc0c 100644 --- a/code/modules/cargo/centcom_podlauncher.dm +++ b/code/modules/cargo/centcom_podlauncher.dm @@ -343,10 +343,10 @@ ADMIN_VERB(centcom_podlauncher, R_ADMIN, "Config/Launch Supplypod", "Configure a temp_pod.adminNamed = FALSE temp_pod.setStyle(temp_pod.style) //This resets the name of the pod based on its current style (see supplypod/setStyle() proc) return - var/nameInput= tgui_input_text(usr, "Enter a custom name", "Custom name", temp_pod.style::name, MAX_NAME_LEN) //Gather input for name and desc + var/nameInput= tgui_input_text(usr, "Enter a custom name", "Custom name", temp_pod.style::name, max_length = MAX_NAME_LEN) if (isnull(nameInput)) return - var/descInput = tgui_input_text(usr, "Enter a custom desc", "Custom description", temp_pod.style::desc) + var/descInput = tgui_input_text(usr, "Enter a custom desc", "Custom description", temp_pod.style::desc, max_length = MAX_DESC_LEN) if (isnull(descInput)) return temp_pod.name = nameInput diff --git a/code/modules/cargo/order.dm b/code/modules/cargo/order.dm index a10bb3da5c00c..ef6484f21fc1f 100644 --- a/code/modules/cargo/order.dm +++ b/code/modules/cargo/order.dm @@ -140,7 +140,7 @@ manifest_text += "Item: [packname]
" manifest_text += "Contents:
" manifest_text += "