diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b154f5c60cc8..9cf858121b9b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -6,7 +6,7 @@ # If you are added, then you are expected to review PRs in a timely manner. -# This code requires the host/head dev to know of changes, therefore it's places in +# This code requires the host/head dev to know of changes, therefore it's placed in # this dedicated section /code/__defines/master_controller.dm @Arrow768 @NonQueueingMatt /code/controllers/master @Arrow768 @NonQueueingMatt @@ -18,31 +18,38 @@ /code/datums/discord/ @Arrow768 @NonQueueingMatt /code/modules/udp/ @Arrow768 @NonQueueingMatt /code/defines/procs/dbcore.dm @Arrow768 @NonQueueingMatt -/SQL/ @Arrow768 @NonQueueingMatt /code/modules/http/ @Arrow768 @NonQueueingMatt /code/datums/api.dm @Arrow768 @NonQueueingMatt -# Custom items, Matt -/code/modules/customitems/item_defines.dm @NonQueueingMatt +# SQL, heads + fabian +/SQL/ @Arrow768 @NonQueueingMatt @FabianK3 -# Mapping, inform dreamy -/maps/ @DreamySkrell +# Custom items, cybs +/code/modules/customitems/item_defines.dm @CyberSpyXD -# Overmap, away sites and organs (brainmed), matt's expertise +# Mapping, inform matt (for now) +/maps/ @NonQueueingMatt + +# Away sites and exoplanets, let wildkins know +/maps/away/ @JohnWildkins @NonQueueingMatt +/maps/random_ruins/exoplanets/ @JohnWildkins @NonQueueingMatt + +# Overmap, matt's expertise /code/__defines/overmap.dm @NonQueueingMatt /code/_helpers/overmap.dm @NonQueueingMatt /code/modules/overmap/ @NonQueueingMatt -/maps/away/ @NonQueueingMatt @DreamySkrell +# Brainmed, matt's area /code/__defines/organs.dm @NonQueueingMatt /code/modules/organs/ @NonQueueingMatt -# UIs. Wildkins or Matt. -/tgui/ @JohnWildkins -code/__defines/tgui.dm @JohnWildkins -code/modules/tgui @JohnWildkins +# UIs. Wildkins and Bat's area +/tgui/ @JohnWildkins @Batrachophreno +/code/__defines/tgui.dm @JohnWildkins @Batrachophreno +/code/modules/tgui @JohnWildkins @Batrachophreno +/nano/templates/ @JohnWildkins @Batrachophreno -# Tools, often binary in nature, let arrow and alb know +# Tools, often binary in nature, let heads know /tools/ @Arrow768 @NonQueueingMatt # Pipeline/CI stuffs, arrow @@ -52,14 +59,10 @@ code/modules/tgui @JohnWildkins /.drone.yml @Arrow768 /flyway.conf @Arrow768 -# ZAS, the dreaded and esoteric atmos system, since Matt is the last to have touched it and -# all others I can find are long gone... +# ZAS, the dreaded and esoteric atmos system. Notify matt /code/__defines/ZAS.dm @NonQueueingMatt /code/ZAS/ @NonQueueingMatt -# Matt is also the implementer/porter of the observable design pattern -/code/datums/observation/ @NonQueueingMatt - # Spatial gridmap, Wildkins /code/__defines/spatial_gridmap.dm @JohnWildkins /code/_helpers/spatial_info.dm @JohnWildkins @@ -69,17 +72,34 @@ code/modules/tgui @JohnWildkins /code/game/machinery/telecomms/ @JohnWildkins /code/game/objects/items/devices/radio/ @JohnWildkins -# Sprites, wezzy -/icons/ @alsoandanswer +# Components and signals, let TCJ know. +/code/__DEFINES/dcs/ @VMSolidus +/code/datums/components/ @VMSolidus +/code/datums/elements/ @VMSolidus + +# Planes, layers, lighting, and rendering. Let Matt and Camo know +/code/__DEFINES/layers.dm @NonQueueingMatt @GeneralCamo +/code/__HELPERS/emissives.dm @NonQueueingMatt @GeneralCamo +/code/datums/components/overlay_lighting.dm @NonQueueingMatt @GeneralCamo +/code/datums/elements/light_blocking.dm @NonQueueingMatt @GeneralCamo +/code/modules/lighting/ @NonQueueingMatt @GeneralCamo +/code/modules/rendering/ @NonQueueingMatt @GeneralCamo + +# Modular computers, wildkins +/code/modules/modular_computers/ @JohnWildkins + +# Persistence, Fabian's area +**/persistence @Arrow768 @NonQueueingMatt @FabianK3 +/code/__DEFINES/persistence.dm @Arrow768 @NonQueueingMatt @FabianK3 +/code/__HELPERS/logging/subsystems/persistence.dm @Arrow768 @NonQueueingMatt @FabianK3 +/code/controllers/subsystems/persistence.dm @Arrow768 @NonQueueingMatt @FabianK3 + +# Sprites, sammy +/icons/ @nauticall # Whatever else /code/controllers/subsystems/cargo.dm @Arrow768 /code/datums/cargo.dm @Arrow768 /code/modules/client/preference_setup/ @Arrow768 /code/modules/item_worth/ @Arrow768 -/code/modules/modular_computers/ @Arrow768 /code/modules/telesci/ @Arrow768 -/code/modules/cargo/ @Arrow768 -/nano/templates/ @Arrow768 - - diff --git a/.github/workflows/byond.yml b/.github/workflows/byond.yml index 0c0b86b2530a..25f5958370af 100644 --- a/.github/workflows/byond.yml +++ b/.github/workflows/byond.yml @@ -15,7 +15,7 @@ on: env: MACRO_COUNT: 0 GENDER_COUNT: 6 - TO_WORLD_COUNT: 179 + TO_WORLD_COUNT: 176 #These variables are filled from dependencies.sh inside the steps, DO NOT SET THEM HERE BYOND_MAJOR: "" @@ -46,8 +46,10 @@ jobs: ########################################### validate-structure: name: Validate Structure + outputs: + skipci: ${{ steps.check_skipci.outputs.skipci }} + skiput: ${{ steps.check_skiput.outputs.skiput }} runs-on: ubuntu-24.04 - if: ${{ !(contains(github.event.head_commit.message, '[ci skip]')) }} concurrency: group: validate-structure-${{ github.head_ref || github.run_id }} @@ -71,6 +73,53 @@ jobs: bash tools/ci/check_grep.sh $PWD awk -f tools/indentation.awk **/*.dm + - name: "Check if running CI" + id: check_skipci + run: | + if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then + pr_num="${{ github.event.number }}" + echo "fetching pull/$pr_num/head" + git fetch origin "pull/$pr_num/head" || true + target_sha=FETCH_HEAD + else + target_sha=HEAD + fi + echo "target commit: $target_sha" + + COMMIT_MSG=$(git log -1 --pretty=%B "$target_sha") + echo "commit message: $COMMIT_MSG" + + if echo "$COMMIT_MSG" | grep -qi '\[ci ignore\]'; then + echo "skipci=true" >> $GITHUB_OUTPUT + echo "Skipping CI." + else + echo "skipci=false" >> $GITHUB_OUTPUT + echo "Continuing with CI." + fi + + - name: "Check if running UTs" + id: check_skiput + run: | + if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then + pr_num="${{ github.event.number }}" + echo "fetching pull/$pr_num/head" + git fetch origin "pull/$pr_num/head" || true + target_sha=FETCH_HEAD + else + target_sha=HEAD + fi + echo "target commit: $target_sha" + + COMMIT_MSG=$(git log -1 --pretty=%B "$target_sha") + echo "commit message: $COMMIT_MSG" + + if echo "$COMMIT_MSG" | grep -qi '\[ut ignore\]'; then + echo "skipci=true" >> $GITHUB_OUTPUT + echo "Skipping CI." + else + echo "skipci=false" >> $GITHUB_OUTPUT + echo "Continuing with CI." + fi ########################################### ############### EditorConfig ############## @@ -78,7 +127,8 @@ jobs: megalinter: name: Validate EditorConfig Compliance runs-on: ubuntu-24.04 - if: ${{ !(contains(github.event.head_commit.message, '[ci skip]')) }} + needs: validate-structure + if: needs.validate-structure.outputs.skipci != 'true' concurrency: group: megalinter-${{ github.head_ref || github.run_id }} @@ -131,8 +181,8 @@ jobs: lint-spacemandmm: name: Lint SpacemanDMM runs-on: ubuntu-24.04 - if: ${{ !(contains(github.event.head_commit.message, '[ci skip]')) }} needs: validate-structure + if: needs.validate-structure.outputs.skipci != 'true' concurrency: group: lint-spacemandmm-${{ github.head_ref || github.run_id }} @@ -178,8 +228,8 @@ jobs: lint-opendream: name: Lint OpenDream runs-on: ubuntu-24.04 - if: ${{ !(contains(github.event.head_commit.message, '[ci skip]')) }} needs: validate-structure + if: needs.validate-structure.outputs.skipci != 'true' concurrency: group: lint-opendream-${{ github.head_ref || github.run_id }} @@ -219,8 +269,8 @@ jobs: lint-tgui: name: Lint TGUI runs-on: ubuntu-24.04 - if: ${{ !(contains(github.event.head_commit.message, '[ci skip]')) }} needs: validate-structure + if: needs.validate-structure.outputs.skipci != 'true' concurrency: group: lint-tgui-${{ github.head_ref || github.run_id }} @@ -256,8 +306,8 @@ jobs: lint-misc: name: Lint Misc runs-on: ubuntu-24.04 - if: ${{ !(contains(github.event.head_commit.message, '[ci skip]')) }} needs: validate-structure + if: needs.validate-structure.outputs.skipci != 'true' concurrency: group: lint-misc-${{ github.head_ref || github.run_id }} @@ -309,8 +359,7 @@ jobs: generic-tests: name: Generic Tests runs-on: ubuntu-24.04 - - if: ${{ !(contains(github.event.head_commit.message, '[ci skip]')) && !(contains(github.event.head_commit.message, '[ut skip]'))}} + if: ${{ !failure() }} needs: [validate-structure, lint-spacemandmm, lint-opendream, lint-tgui, lint-misc] services: @@ -336,43 +385,55 @@ jobs: steps: + - name: "Check if CI or UT ignored" + id: check + if: ${{ needs.validate-structure.outputs.skipci == 'true' || needs.validate-structure.outputs.skiput == 'true' }} + run: | + echo "skip=true" >> $GITHUB_OUTPUT + #This allows us to SSH into the pod, and it's only enabled if we're running in debug mode - name: Setup TMATE session (Debug only) uses: mxschmitt/action-tmate@v3 - if: ${{ env.RUNNER_DEBUG_SHELL == true }} + if: ${{ steps.check.outputs.skip != 'true' && env.RUNNER_DEBUG_SHELL == true }} with: detached: true timeout-minutes: 5 #Checkout the repository - name: Checkout repository + if: steps.check.outputs.skip != 'true' uses: actions/checkout@v4 #Initialize the environment variables - name: Set ENV variables + if: steps.check.outputs.skip != 'true' run: bash dependencies.sh #Restores BYOND cache - name: Restore BYOND cache + if: steps.check.outputs.skip != 'true' uses: actions/cache@v4 with: path: ~/BYOND/* key: ${{ runner.os }}-byond-${{ env.BYOND_MAJOR }}-${{ env.BYOND_MINOR }} - name: Restore FlyWay cache + if: steps.check.outputs.skip != 'true' uses: actions/cache@v4 with: path: ~/flyway key: ${{ runner.os }}-flyway-${{ env.FLYWAY_BUILD }} #Add the x86 architecture and update apt-get's local indexes - - name: Prepare OS Environtment + - name: Prepare OS Environment + if: steps.check.outputs.skip != 'true' run: | sudo dpkg --add-architecture i386 sudo apt-get update #Installs the packages we need, from a cache - name: Install OS Packages + if: steps.check.outputs.skip != 'true' uses: awalsh128/cache-apt-pkgs-action@latest with: packages: gcc-multilib zlib1g-dev:i386 libssl-dev:i386 libgcc-s1:i386 libc6:i386 @@ -380,22 +441,26 @@ jobs: #And natively, the packages that break from a cache - name: Install OS Packages (Native) + if: steps.check.outputs.skip != 'true' run: | sudo apt-get install libgcc-s1:i386 libssl-dev:i386 libcurl4t64 libcurl4t64:i386 #Install flyway - name: Install Flyway + if: steps.check.outputs.skip != 'true' run: | tools/ci/install_flyway.sh #Apply the database migration - name: Apply Database Migrations (FlyWay) + if: steps.check.outputs.skip != 'true' env: PORT: ${{ job.services.mariadb.ports[3306] }} run: | $HOME/flyway/flyway-$FLYWAY_BUILD/flyway migrate -user=root -password=root -url="jdbc:mariadb://localhost:$PORT/game" -validateMigrationNaming="true" - name: Install BYOND & rust_g + if: steps.check.outputs.skip != 'true' run: | source dependencies.sh bash tools/ci/install_byond.sh @@ -403,6 +468,7 @@ jobs: bash tools/ci/install_rust_g.sh - name: Configure pod, build and run + if: steps.check.outputs.skip != 'true' env: PORT: ${{ job.services.mariadb.ports[3306] }} POD: ${{ matrix.pod }} @@ -420,7 +486,7 @@ jobs: - name: Upload Condensed UT Log uses: actions/upload-artifact@v4 - if: failure() || ${{ runner.debug }} + if: steps.check.outputs.skip != 'true' && (failure() || runner.debug) with: name: condensed-${{ matrix.map }}-${{ matrix.pod }}.log path: ./data/logs/**/condensed.log @@ -432,8 +498,7 @@ jobs: create-and-destroy: name: Create and Destroy Test runs-on: ubuntu-24.04 - - if: ${{ !(contains(github.event.head_commit.message, '[ci skip]')) && !(contains(github.event.head_commit.message, '[ut skip]'))}} + if: ${{ !failure() }} needs: [validate-structure, lint-spacemandmm, lint-opendream, lint-tgui, lint-misc] services: @@ -459,43 +524,55 @@ jobs: steps: + - name: "Check if CI or UT ignored" + id: check + if: ${{ needs.validate-structure.outputs.skipci == 'true' || needs.validate-structure.outputs.skiput == 'true' }} + run: | + echo "skip=true" >> $GITHUB_OUTPUT + #This allows us to SSH into the pod, and it's only enabled if we're running in debug mode - name: Setup TMATE session (Debug only) uses: mxschmitt/action-tmate@v3 - if: ${{ env.RUNNER_DEBUG_SHELL == true }} + if: ${{ steps.check.outputs.skip != 'true' && env.RUNNER_DEBUG_SHELL == true }} with: detached: true timeout-minutes: 5 #Checkout the repository - name: Checkout repository + if: steps.check.outputs.skip != 'true' uses: actions/checkout@v4 #Initialize the environment variables - name: Set ENV variables + if: steps.check.outputs.skip != 'true' run: bash dependencies.sh #Restores BYOND cache - name: Restore BYOND cache + if: steps.check.outputs.skip != 'true' uses: actions/cache@v4 with: path: ~/BYOND/* key: ${{ runner.os }}-byond-${{ env.BYOND_MAJOR }}-${{ env.BYOND_MINOR }} - name: Restore FlyWay cache + if: steps.check.outputs.skip != 'true' uses: actions/cache@v4 with: path: ~/flyway key: ${{ runner.os }}-flyway-${{ env.FLYWAY_BUILD }} #Add the x86 architecture and update apt-get's local indexes - - name: Prepare OS Environtment + - name: Prepare OS Environment + if: steps.check.outputs.skip != 'true' run: | sudo dpkg --add-architecture i386 sudo apt-get update #Installs the packages we need, from a cache - name: Install OS Packages + if: steps.check.outputs.skip != 'true' uses: awalsh128/cache-apt-pkgs-action@latest with: packages: gcc-multilib zlib1g-dev:i386 libssl-dev:i386 libgcc-s1:i386 libc6:i386 @@ -503,22 +580,26 @@ jobs: #And natively, the packages that break from a cache - name: Install OS Packages (Native) + if: steps.check.outputs.skip != 'true' run: | sudo apt-get install libgcc-s1:i386 libssl-dev:i386 libcurl4t64 libcurl4t64:i386 #Install flyway - name: Install Flyway + if: steps.check.outputs.skip != 'true' run: | tools/ci/install_flyway.sh #Apply the database migration - name: Apply Database Migrations (FlyWay) + if: steps.check.outputs.skip != 'true' env: PORT: ${{ job.services.mariadb.ports[3306] }} run: | $HOME/flyway/flyway-$FLYWAY_BUILD/flyway migrate -user=root -password=root -url="jdbc:mariadb://localhost:$PORT/game" -validateMigrationNaming="true" - name: Install BYOND & rust_g + if: steps.check.outputs.skip != 'true' run: | source dependencies.sh bash tools/ci/install_byond.sh @@ -526,6 +607,7 @@ jobs: bash tools/ci/install_rust_g.sh - name: Configure pod, build and run + if: steps.check.outputs.skip != 'true' env: PORT: ${{ job.services.mariadb.ports[3306] }} POD: ${{ matrix.pod }} @@ -543,7 +625,7 @@ jobs: - name: Upload Condensed UT Log uses: actions/upload-artifact@v4 - if: failure() || ${{ runner.debug }} + if: steps.check.outputs.skip != 'true' && (failure() || runner.debug) with: name: condensed-${{ matrix.map }}-${{ matrix.pod }}.log path: ./data/logs/**/condensed.log @@ -557,8 +639,7 @@ jobs: map-tests: name: Run Map Tests runs-on: ubuntu-24.04 - - if: ${{ !(contains(github.event.head_commit.message, '[ci skip]')) && !(contains(github.event.head_commit.message, '[ut skip]'))}} + if: ${{ !failure() }} needs: [validate-structure, lint-spacemandmm, lint-opendream, lint-tgui, lint-misc] services: @@ -584,10 +665,16 @@ jobs: steps: + - name: "Check if CI or UT ignored" + id: check + if: ${{ needs.validate-structure.outputs.skipci == 'true' || needs.validate-structure.outputs.skiput == 'true' }} + run: | + echo "skip=true" >> $GITHUB_OUTPUT + #This allows us to SSH into the pod, and it's only enabled if we're running in debug mode - name: Setup TMATE session (Debug only) uses: mxschmitt/action-tmate@v3 - if: ${{ env.RUNNER_DEBUG_SHELL == true }} + if: ${{ steps.check.outputs.skip != 'true' && env.RUNNER_DEBUG_SHELL == true }} with: detached: true timeout-minutes: 5 @@ -595,32 +682,38 @@ jobs: #Checkout the repository - name: Checkout repository uses: actions/checkout@v4 + if: steps.check.outputs.skip != 'true' #Initialize the environment variables - name: Set ENV variables run: bash dependencies.sh + if: steps.check.outputs.skip != 'true' #Restores BYOND cache - name: Restore BYOND cache uses: actions/cache@v4 + if: steps.check.outputs.skip != 'true' with: path: ~/BYOND/* key: ${{ runner.os }}-byond-${{ env.BYOND_MAJOR }}-${{ env.BYOND_MINOR }} - name: Restore FlyWay cache uses: actions/cache@v4 + if: steps.check.outputs.skip != 'true' with: path: ~/flyway key: ${{ runner.os }}-flyway-${{ env.FLYWAY_BUILD }} #Add the x86 architecture and update apt-get's local indexes - - name: Prepare OS Environtment + - name: Prepare OS Environment + if: steps.check.outputs.skip != 'true' run: | sudo dpkg --add-architecture i386 sudo apt-get update #Installs the packages we need, from a cache - name: Install OS Packages + if: steps.check.outputs.skip != 'true' uses: awalsh128/cache-apt-pkgs-action@latest with: packages: gcc-multilib zlib1g-dev:i386 libssl-dev:i386 libgcc-s1:i386 libc6:i386 @@ -628,22 +721,26 @@ jobs: #And natively, the packages that break from a cache - name: Install OS Packages (Native) + if: steps.check.outputs.skip != 'true' run: | sudo apt-get install libgcc-s1:i386 libssl-dev:i386 libcurl4t64 libcurl4t64:i386 #Install flyway - name: Install Flyway + if: steps.check.outputs.skip != 'true' run: | tools/ci/install_flyway.sh #Apply the database migration - name: Apply Database Migrations (FlyWay) + if: steps.check.outputs.skip != 'true' env: PORT: ${{ job.services.mariadb.ports[3306] }} run: | $HOME/flyway/flyway-$FLYWAY_BUILD/flyway migrate -user=root -password=root -url="jdbc:mariadb://localhost:$PORT/game" -validateMigrationNaming="true" - name: Install BYOND & rust_g + if: steps.check.outputs.skip != 'true' run: | source dependencies.sh bash tools/ci/install_byond.sh @@ -651,6 +748,7 @@ jobs: bash tools/ci/install_rust_g.sh - name: Configure pod, build and run + if: steps.check.outputs.skip != 'true' env: PORT: ${{ job.services.mariadb.ports[3306] }} POD: ${{ matrix.pod }} @@ -668,7 +766,7 @@ jobs: - name: Upload Condensed UT Log uses: actions/upload-artifact@v4 - if: failure() || ${{ runner.debug }} + if: steps.check.outputs.skip != 'true' && (failure() || runner.debug) with: name: condensed-${{ matrix.map }}-${{ matrix.pod }}.log path: ./data/logs/**/condensed.log @@ -682,8 +780,7 @@ jobs: exoplanet_testing: name: Run Exoplanet Tests runs-on: ubuntu-24.04 - - if: ${{ !(contains(github.event.head_commit.message, '[ci skip]')) && !(contains(github.event.head_commit.message, '[ut skip]'))}} + if: ${{ !failure() }} needs: [validate-structure, lint-spacemandmm, lint-opendream, lint-tgui, lint-misc] services: @@ -709,43 +806,55 @@ jobs: steps: + - name: "Check if CI or UT ignored" + id: check + if: ${{ needs.validate-structure.outputs.skipci == 'true' || needs.validate-structure.outputs.skiput == 'true' }} + run: | + echo "skip=true" >> $GITHUB_OUTPUT + #This allows us to SSH into the pod, and it's only enabled if we're running in debug mode - name: Setup TMATE session (Debug only) uses: mxschmitt/action-tmate@v3 - if: ${{ env.RUNNER_DEBUG_SHELL == true }} + if: ${{ steps.check.outputs.skip != 'true' && env.RUNNER_DEBUG_SHELL == true }} with: detached: true timeout-minutes: 5 #Checkout the repository - name: Checkout repository + if: steps.check.outputs.skip != 'true' uses: actions/checkout@v4 #Initialize the environment variables - name: Set ENV variables + if: steps.check.outputs.skip != 'true' run: bash dependencies.sh #Restores BYOND cache - name: Restore BYOND cache + if: steps.check.outputs.skip != 'true' uses: actions/cache@v4 with: path: ~/BYOND/* key: ${{ runner.os }}-byond-${{ env.BYOND_MAJOR }}-${{ env.BYOND_MINOR }} - name: Restore FlyWay cache + if: steps.check.outputs.skip != 'true' uses: actions/cache@v4 with: path: ~/flyway key: ${{ runner.os }}-flyway-${{ env.FLYWAY_BUILD }} #Add the x86 architecture and update apt-get's local indexes - - name: Prepare OS Environtment + - name: Prepare OS Environment + if: steps.check.outputs.skip != 'true' run: | sudo dpkg --add-architecture i386 sudo apt-get update #Installs the packages we need, from a cache - name: Install OS Packages + if: steps.check.outputs.skip != 'true' uses: awalsh128/cache-apt-pkgs-action@latest with: packages: gcc-multilib zlib1g-dev:i386 libssl-dev:i386 libgcc-s1:i386 libc6:i386 @@ -753,22 +862,26 @@ jobs: #And natively, the packages that break from a cache - name: Install OS Packages (Native) + if: steps.check.outputs.skip != 'true' run: | sudo apt-get install libgcc-s1:i386 libssl-dev:i386 libcurl4t64 libcurl4t64:i386 #Install flyway - name: Install Flyway + if: steps.check.outputs.skip != 'true' run: | tools/ci/install_flyway.sh #Apply the database migration - name: Apply Database Migrations (FlyWay) + if: steps.check.outputs.skip != 'true' env: PORT: ${{ job.services.mariadb.ports[3306] }} run: | $HOME/flyway/flyway-$FLYWAY_BUILD/flyway migrate -user=root -password=root -url="jdbc:mariadb://localhost:$PORT/game" -validateMigrationNaming="true" - name: Install BYOND & rust_g + if: steps.check.outputs.skip != 'true' run: | source dependencies.sh bash tools/ci/install_byond.sh @@ -776,6 +889,7 @@ jobs: bash tools/ci/install_rust_g.sh - name: Configure pod, build and run + if: steps.check.outputs.skip != 'true' env: PORT: ${{ job.services.mariadb.ports[3306] }} POD: ${{ matrix.pod }} @@ -793,7 +907,7 @@ jobs: - name: Upload Condensed UT Log uses: actions/upload-artifact@v4 - if: failure() || ${{ runner.debug }} + if: steps.check.outputs.skip != 'true' && (failure() || runner.debug) with: name: condensed-${{ matrix.map }}-${{ matrix.pod }}.log path: ./data/logs/**/condensed.log @@ -806,8 +920,7 @@ jobs: away-sites-tests: name: Run Map Tests runs-on: ubuntu-24.04 - - if: ${{ !(contains(github.event.head_commit.message, '[ci skip]')) && !(contains(github.event.head_commit.message, '[ut skip]'))}} + if: ${{ !failure() }} needs: [validate-structure, lint-spacemandmm, lint-opendream, lint-tgui, lint-misc] services: @@ -833,43 +946,55 @@ jobs: steps: + - name: "Check if CI or UT ignored" + id: check + if: ${{ needs.validate-structure.outputs.skipci == 'true' || needs.validate-structure.outputs.skiput == 'true' }} + run: | + echo "skip=true" >> $GITHUB_OUTPUT + #This allows us to SSH into the pod, and it's only enabled if we're running in debug mode - name: Setup TMATE session (Debug only) uses: mxschmitt/action-tmate@v3 - if: ${{ env.RUNNER_DEBUG_SHELL == true }} + if: ${{ steps.check.outputs.skip != 'true' && env.RUNNER_DEBUG_SHELL == true }} with: detached: true timeout-minutes: 5 #Checkout the repository - name: Checkout repository + if: steps.check.outputs.skip != 'true' uses: actions/checkout@v4 #Initialize the environment variables - name: Set ENV variables + if: steps.check.outputs.skip != 'true' run: bash dependencies.sh #Restores BYOND cache - name: Restore BYOND cache + if: steps.check.outputs.skip != 'true' uses: actions/cache@v4 with: path: ~/BYOND/* key: ${{ runner.os }}-byond-${{ env.BYOND_MAJOR }}-${{ env.BYOND_MINOR }} - name: Restore FlyWay cache + if: steps.check.outputs.skip != 'true' uses: actions/cache@v4 with: path: ~/flyway key: ${{ runner.os }}-flyway-${{ env.FLYWAY_BUILD }} #Add the x86 architecture and update apt-get's local indexes - - name: Prepare OS Environtment + - name: Prepare OS Environment + if: steps.check.outputs.skip != 'true' run: | sudo dpkg --add-architecture i386 sudo apt-get update #Installs the packages we need, from a cache - name: Install OS Packages + if: steps.check.outputs.skip != 'true' uses: awalsh128/cache-apt-pkgs-action@latest with: packages: gcc-multilib zlib1g-dev:i386 libssl-dev:i386 libgcc-s1:i386 libc6:i386 @@ -877,22 +1002,26 @@ jobs: #And natively, the packages that break from a cache - name: Install OS Packages (Native) + if: steps.check.outputs.skip != 'true' run: | sudo apt-get install libgcc-s1:i386 libssl-dev:i386 libcurl4t64 libcurl4t64:i386 #Install flyway - name: Install Flyway + if: steps.check.outputs.skip != 'true' run: | tools/ci/install_flyway.sh #Apply the database migration - name: Apply Database Migrations (FlyWay) + if: steps.check.outputs.skip != 'true' env: PORT: ${{ job.services.mariadb.ports[3306] }} run: | $HOME/flyway/flyway-$FLYWAY_BUILD/flyway migrate -user=root -password=root -url="jdbc:mariadb://localhost:$PORT/game" -validateMigrationNaming="true" - name: Install BYOND & rust_g + if: steps.check.outputs.skip != 'true' run: | source dependencies.sh bash tools/ci/install_byond.sh @@ -900,6 +1029,7 @@ jobs: bash tools/ci/install_rust_g.sh - name: Configure pod, build and run + if: steps.check.outputs.skip != 'true' env: PORT: ${{ job.services.mariadb.ports[3306] }} POD: ${{ matrix.pod }} @@ -917,7 +1047,7 @@ jobs: - name: Upload Condensed UT Log uses: actions/upload-artifact@v4 - if: failure() || ${{ runner.debug }} + if: steps.check.outputs.skip != 'true' && (failure() || runner.debug) with: name: condensed-${{ matrix.map }}-${{ matrix.pod }}.log path: ./data/logs/**/condensed.log @@ -929,8 +1059,7 @@ jobs: ruins-tests: name: Run Ruins Tests runs-on: ubuntu-24.04 - - if: ${{ !(contains(github.event.head_commit.message, '[ci skip]')) && !(contains(github.event.head_commit.message, '[ut skip]'))}} + if: ${{ !failure() }} needs: [validate-structure, lint-spacemandmm, lint-opendream, lint-tgui, lint-misc] services: @@ -956,43 +1085,55 @@ jobs: steps: + - name: "Check if CI or UT ignored" + id: check + if: ${{ needs.validate-structure.outputs.skipci == 'true' || needs.validate-structure.outputs.skiput == 'true' }} + run: | + echo "skip=true" >> $GITHUB_OUTPUT + #This allows us to SSH into the pod, and it's only enabled if we're running in debug mode - name: Setup TMATE session (Debug only) uses: mxschmitt/action-tmate@v3 - if: ${{ env.RUNNER_DEBUG_SHELL == true }} + if: ${{ steps.check.outputs.skip != 'true' && env.RUNNER_DEBUG_SHELL == true }} with: detached: true timeout-minutes: 5 #Checkout the repository - name: Checkout repository + if: steps.check.outputs.skip != 'true' uses: actions/checkout@v4 #Initialize the environment variables - name: Set ENV variables + if: steps.check.outputs.skip != 'true' run: bash dependencies.sh #Restores BYOND cache - name: Restore BYOND cache + if: steps.check.outputs.skip != 'true' uses: actions/cache@v4 with: path: ~/BYOND/* key: ${{ runner.os }}-byond-${{ env.BYOND_MAJOR }}-${{ env.BYOND_MINOR }} - name: Restore FlyWay cache + if: steps.check.outputs.skip != 'true' uses: actions/cache@v4 with: path: ~/flyway key: ${{ runner.os }}-flyway-${{ env.FLYWAY_BUILD }} #Add the x86 architecture and update apt-get's local indexes - - name: Prepare OS Environtment + - name: Prepare OS Environment + if: steps.check.outputs.skip != 'true' run: | sudo dpkg --add-architecture i386 sudo apt-get update #Installs the packages we need, from a cache - name: Install OS Packages + if: steps.check.outputs.skip != 'true' uses: awalsh128/cache-apt-pkgs-action@latest with: packages: gcc-multilib zlib1g-dev:i386 libssl-dev:i386 libgcc-s1:i386 libc6:i386 @@ -1000,22 +1141,26 @@ jobs: #And natively, the packages that break from a cache - name: Install OS Packages (Native) + if: steps.check.outputs.skip != 'true' run: | sudo apt-get install libgcc-s1:i386 libssl-dev:i386 libcurl4t64 libcurl4t64:i386 #Install flyway - name: Install Flyway + if: steps.check.outputs.skip != 'true' run: | tools/ci/install_flyway.sh #Apply the database migration - name: Apply Database Migrations (FlyWay) + if: steps.check.outputs.skip != 'true' env: PORT: ${{ job.services.mariadb.ports[3306] }} run: | $HOME/flyway/flyway-$FLYWAY_BUILD/flyway migrate -user=root -password=root -url="jdbc:mariadb://localhost:$PORT/game" -validateMigrationNaming="true" - name: Install BYOND & rust_g + if: steps.check.outputs.skip != 'true' run: | source dependencies.sh bash tools/ci/install_byond.sh @@ -1023,6 +1168,7 @@ jobs: bash tools/ci/install_rust_g.sh - name: Configure pod, build and run + if: steps.check.outputs.skip != 'true' env: PORT: ${{ job.services.mariadb.ports[3306] }} POD: ${{ matrix.pod }} @@ -1040,7 +1186,7 @@ jobs: - name: Upload Condensed UT Log uses: actions/upload-artifact@v4 - if: failure() || ${{ runner.debug }} + if: steps.check.outputs.skip != 'true' && (failure() || runner.debug) with: name: condensed-${{ matrix.map }}-${{ matrix.pod }}.log path: ./data/logs/**/condensed.log diff --git a/.github/workflows/enforce_merge_blockers.yaml b/.github/workflows/enforce_merge_blockers.yaml new file mode 100644 index 000000000000..b579d6d115ee --- /dev/null +++ b/.github/workflows/enforce_merge_blockers.yaml @@ -0,0 +1,34 @@ +name: "'Do Not Merge' Blockers" + +on: + pull_request: + types: [synchronize, opened, labeled, unlabeled] + +jobs: + donotmerge-blocker: + name: Enforce Do Not Merge Labels + runs-on: ubuntu-latest + steps: + - name: Enforce Maintainer Discussion Label + if: contains(github.event.pull_request.labels.*.name, '⛔ Maintainer Discussion') + run: | + echo "Pull request is labelled Maintainer Discussion, and must be approved by the maintainers before this PR can be merged." + exit 1 + + - name: Enforce Lore Discussion Label + if: contains(github.event.pull_request.labels.*.name, '⛔ Lore Discussion') + run: | + echo "Pull request is labelled Lore Discussion, and must be approved by the relevant lore team before this PR can be merged." + exit 1 + + - name: Enforce Do Not Merge Label + if: contains(github.event.pull_request.labels.*.name, '🚫 Do Not Merge') + run: | + echo "Pull request is labelled Do Not Merge and cannot be merged in this state. Refer to the developer who set this label for information." + exit 1 + + - name: Enforce Changes Required Label + if: contains(github.event.pull_request.labels.*.name, 'Changes Required') + run: | + echo "Pull request is labelled Changes Required and cannot be merged in this state. Refer to the developer who set this label for information." + exit 1 diff --git a/.github/workflows/update_tgs_dmapi.yml b/.github/workflows/update_tgs_dmapi.yml index 943df0f0da0b..206ffcbd6c4a 100644 --- a/.github/workflows/update_tgs_dmapi.yml +++ b/.github/workflows/update_tgs_dmapi.yml @@ -8,6 +8,7 @@ on: jobs: update-dmapi: runs-on: ubuntu-24.04 + if: github.repository == 'Aurorastation/Aurora.3' # to prevent this running on forks name: Update the TGS DMAPI steps: - name: Clone diff --git a/.gitignore b/.gitignore index f8e2e95003d9..e8f270654440 100644 --- a/.gitignore +++ b/.gitignore @@ -70,3 +70,6 @@ define_sanity_output.txt # Unit test / coverage reports .cache + +# Tracy dumps +*.utracy diff --git a/.prettierignore b/.prettierignore index b4e6fd6e2640..2d6a8da1ef79 100644 --- a/.prettierignore +++ b/.prettierignore @@ -4,16 +4,16 @@ data font-awesome jquery juke +**/build +**/dist +**/node_modules ## Tgui node_modules .yarn -# Avoid running on any bundles. -tgui/public -# Running it on tgui.html is fine, however. -!/tgui/public/tgui.html # Specific files package-lock.json # File names / types *.min.* *.pnp.* +*.bundle.* diff --git a/SQL/README.md b/SQL/README.md index 3dc4d72fb6b6..5cb281a0a896 100644 --- a/SQL/README.md +++ b/SQL/README.md @@ -1,103 +1,188 @@ -### Compacted Migrations - -To decrease the runtime of the migration unit test, the database migrations will be compacted into a single migration on a regular base. -In order to do so, a new "migrate-VERSION" subfolder is created. -The initial migration in these subfolders is always a migration with the current db-schema as of the current PR. +# SQL -In addition the flayway.conf file in the root of the project is updated to use the new migration folder and create a new schema history table (that tracks the applied migrations). +This subdirectory contains the required SQL files that are needed for setting +up and updating a SQL database connected to the game. For nearly all +local development a database isn't necessary, but some of the game's features +require it. -#### How does this impact you? +Database management and/or development is a whole field on its own. If you have +trouble, don't hesitate to ask a developer for assistance, specifically the +people listed as code owners for the SQL directory. -If you set up a new database: +## Prerequisite -Make sure to use the latest migration folder, it will contain everything needed to create a "fresh" database. +The production database is a MariaDB. Feature parity is no longer guaranteed for +other SQL servers and requires that all SQL is tested on a MariaDB instance. +If this is not done, migrations could fail and result in data loss or corruption. -If you have a existing database: -Update to the latest migration in the migration folder that you have used so far. -Then switch to the next migration folder (and a new schema version table) -You should use flyway with `-baselineVersion="1" baseline` instead of the usual migrate for the initial migration +For applying migrations [Flyway by Redgate](https://github.com/flyway/flyway) +is used. It's a tool to automatically apply SQL scripts to a database server +while keeping track of the already applied migrations. -As usual, always make sure that you have a backup and test it first on a non-production copy +In order to develop for the database you will require a +[MariaDB server instance](https://mariadb.org/download/) and Flyway. +>[!TIP] +>Users proficient with Docker can look further down: MariaDB and Flyway both +>offer container solutions alleviating the need to install either locally. +>*Note: The usage of docker is too complex to be covered in this document.* +>Refer to the official documentation of Docker, MariaDB and Flyway. -### Prerequisites +## Migrations -The server connects to a mysql-compatible server (mysql, mariadb, percona), so you'll need one of those with a database and user/password pair ready. +### Compacted Migrations -We use [flyway](https://flywaydb.org/) to manage database migrations. To set up the database, you'll need to [download flyway](https://flywaydb.org/getstarted/download.html). +To decrease the runtime of the migration unit test, the database migrations +will be compacted into a single migration on a regular basis. In order to do so, +a new `migrate-` subfolder is created. +The initial migration in these subfolders is always a migration with the current +db-schema as of the current PR. -You'll also need some proficiency with the command line. +In addition the `flyway.conf` file in the root of the project is updated to +use the new migration folder and create a new schema history table +(that tracks the applied migrations). ----- +#### Usage of compacted migrations -### Attribution +If you set up a new database: Make sure to use the latest migration folder, it +will contain everything needed to create a "fresh" database. -Credit to Mloc from Baystation12 for the initial readme. +If you have an existing database: Update to the latest migration in the +migration folder that you have used so far. +Then switch to the next migration folder (and a new schema version table) +You should use flyway with `-baselineVersion="1" baseline` instead of the usual +migrate for the initial migration. ---- +As usual, always make sure that you have a backup and +test it first on a non-production copy. ### Creating migrations -As a coder, creating migrations is relatively easy. And they're a lot more flexible than just updating the initial schema would be. +Creating migrations is relatively easy. Migrations are based on the previous +ones and allow you to focus on the new changes you would like to implement. -First, figure out the changes you need to make. From table alteration and creation commands, to simply update and insert statements. +First, figure out the changes you need to make. From table alteration and +creation commands, to simply update and insert statements. +This is the usual SQL writing for any database. -Write them into a .sql file in the SQL/migrate folder, in a valid order of execution. Name the file in the following format: +Place your `.sql` files in the `SQL/migrate-` folder, in a +valid order of execution. Name the file in the following format: - Vxxx__Description_goes_here.sql +```txt +Vxxx__Description.sql +``` -Where `xxx` is the next version number from the last existing file (include the 0s), and the descrption is a short description for the migration, with spaces replaced by underscores. +Where `xxx` is the next version number from the last existing file +(include the 0s) and the description is a short description for the migration, +with spaces replaced by underscores. You can orientate yourself on the already +existing migrations. -Push this to your branch, and you're done! +Pushing these new files is all that is needed, *testing aside*. ---- +>[!WARNING] +>You cannot edit migrations files that have been merged to the master branch. +>These files will not be run again and will cause issue when setting up a +>new database. -### Initial setup +### Initial database setup -In the root project directory, run: +In the root project directory, run the following: + +```sh +path/to/flyway migrate + -user=USER + -password=PASSWORD + -url=jdbc:mysql://HOST/DATABASE +``` - path/to/flyway migrate -user=USER -password=PASSWORD -url=jdbc:mysql://HOST/DATABASE +Where `USER` is your database username, `PASSWORD` is your SQL password, +`HOST` is the hostname of the SQL instance and `DATABASE` is the actual +database you like to use on your SQL server instance. -Where USER is your mysql username, PASSWORD is your mysql password, HOST is the hostname of the mysql server and DATABASE is the database to use. +### Applying newly added migrations ---- +Applying newly added migrations by yourself or others is very simple. -### Migrating +Just run the exact same command you ran above, fancy isn't it? -Use the same command as above. Handy, isn't it? +Flyway will automatically skip already applied migrations and only add those +that are not yet existent in the database. This is also the underlaying reason +applied migrations are written in stone and cannot be edited after they have +been merged into the master branch. ---- +### Using a pre-Flyway database -### Using a pre-flyway database +>[!CAUTION] +>This approach has issues due to improper versioning. Start with a fresh +>database and empty schema if possible. -**Note that this is not recommended!** -You may run into issues with some migrations, due to improper versioning. The best way to utilize this system is to set everything up on an empty schema. -The next alternative is to make sure your database structure matches the V001 file within the migrate folder by manually modifying the structure to avoid dataloss, and then doing the steps described below. +The alternative is to make sure your database structure matches the V001 file +within the migrate folder by manually modifying the structure to avoid data loss +and then doing the steps described below. -If you're using a database since before we moved to flyway, it's a bit more involved to get migrations working. +If you're using a database since before we moved to Flyway, +it's a bit more involved to get migrations working. In the root project directory, run: - path/to/flyway baseline -user=USER -password=PASSWORD -url=jdbc:mysql://HOST/DATABASE -baselineVersion=001 -baselineDescription="Initial schema" +```sh +path/to/flyway baseline -user=USER -password=PASSWORD + -url=jdbc:mysql://HOST/DATABASE + -baselineVersion=001 + -baselineDescription="Initial schema" +``` From there, you can run migrations as normal. ---- - -### Configuration file +### Flyway config file -Instead of putting -user, -password and -url in the command line every time you execute flyway, you can use a config file. Create it somewhere in the root of your project (we're calling it 'db.conf'): +Instead of putting -user, -password and -url in the command line every time +you execute flyway, you can use a config file. An example can be found in the +repositories root directory, called `flyway.conf`: - flyway.url=jdbc:mysql://HOST/DATABASE - flyway.user=USER - flyway.password=PASSWORD +```sh +flyway.url=jdbc:mysql://HOST/DATABASE +flyway.user=USER +flyway.password=PASSWORD +``` -Now you can just run `flyway migrate -configFile=db.conf`, and the settings will be loaded from config. - ---- +Now you can just run `flyway migrate -configFile=flyway.conf` +and the settings will be loaded from config. ### Misc tables -We included a set of miscellanious tables in the misc folder. These are primarily used for debugging and are not meant to be pushed into production. As such, they're not included in the migration folder. +We included a set of miscellaneous tables in the misc folder. +These are primarily used for debugging and are not meant to be pushed +into production. As such, they're not included in the migration folder. Ignoring or implementing them should not cause issues with the system. + +### Docker + +Docker allows you to setup a database and Flyway without installing additional +components locally. This setup is for directed at advanced users proficient +with Linux/Bash and Docker. Provided is a jumpstart example, refer to the +individual documentations: [MariaDB docker](https://hub.docker.com/_/mariadb) and +[Flyway docker](https://hub.docker.com/r/flyway/flyway/). + +Advantages: No installation of additional components, easy to spin up/remove +and changes are stored in volumes. + +```yaml +services: + flyway: + image: flyway/flyway + command: -url=jdbc:mysql://db -user=root -password=P@ssw0rd -workingDirectory="project" migrate + volumes: + - ./SQL/migrate-VERSION:/flyway/project # Pathing! + depends_on: + - db + db: + image: mariadb + environment: + MARIADB_ROOT_PASSWORD: Pssw0rd + volumes: + - aurora:/var/lib/mysql:Z + ports: + - 3306:3306 +``` diff --git a/SQL/migrate-2023/V019__skills_education.sql b/SQL/migrate-2023/V019__skills_education.sql index 4ba8a8996f1b..d701822c746d 100644 --- a/SQL/migrate-2023/V019__skills_education.sql +++ b/SQL/migrate-2023/V019__skills_education.sql @@ -1,5 +1,5 @@ -- --- Implemented in PR #?????. +-- Implemented in PR #21853. -- Add education and skills. -- diff --git a/aurorastation.dme b/aurorastation.dme index 8906e2360dc0..2def034636a8 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -222,6 +222,7 @@ #include "code\__HELPERS\nameof.dm" #include "code\__HELPERS\names.dm" #include "code\__HELPERS\overmap.dm" +#include "code\__HELPERS\price.dm" #include "code\__HELPERS\qdel.dm" #include "code\__HELPERS\ref.dm" #include "code\__HELPERS\sanitize_values.dm" @@ -399,6 +400,7 @@ #include "code\controllers\subsystems\sunlight.dm" #include "code\controllers\subsystems\throwing.dm" #include "code\controllers\subsystems\ticker.dm" +#include "code\controllers\subsystems\time_track.dm" #include "code\controllers\subsystems\timer.dm" #include "code\controllers\subsystems\trade.dm" #include "code\controllers\subsystems\turf_fire.dm" @@ -494,6 +496,8 @@ #include "code\datums\components\eye\base_planner.dm" #include "code\datums\components\eye\blueprints.dm" #include "code\datums\components\eye\freelook.dm" +#include "code\datums\components\morale\moodlets.dm" +#include "code\datums\components\morale\morale_component.dm" #include "code\datums\components\multitool\_multitool.dm" #include "code\datums\components\multitool\multitool.dm" #include "code\datums\components\multitool\circuitboards\circuitboards.dm" @@ -501,6 +505,31 @@ #include "code\datums\components\overhead_emote\overhead_emote_singleton.dm" #include "code\datums\components\psionics\psi_sensitivity.dm" #include "code\datums\components\psionics\psi_suppression.dm" +#include "code\datums\components\skills\skill_component.dm" +#include "code\datums\components\skills\combat\armed_combat_skill_component.dm" +#include "code\datums\components\skills\combat\firearms_skill_component.dm" +#include "code\datums\components\skills\combat\leadership_skill_component.dm" +#include "code\datums\components\skills\combat\unarmed_combat_skill_component.dm" +#include "code\datums\components\skills\engineering\atmospherics_systems_skill_component.dm" +#include "code\datums\components\skills\engineering\electrical_engineering_skill_component.dm" +#include "code\datums\components\skills\engineering\mechanical_engineering_skill_component.dm" +#include "code\datums\components\skills\engineering\reactor_systems_skill_component.dm" +#include "code\datums\components\skills\medical\anatomy_skill_component.dm" +#include "code\datums\components\skills\medical\forensics_skill_component.dm" +#include "code\datums\components\skills\medical\medicine_skill_component.dm" +#include "code\datums\components\skills\medical\pharmacology_skill_component.dm" +#include "code\datums\components\skills\medical\surgery_skill_component.dm" +#include "code\datums\components\skills\operations\pilot_mechs_skill_component.dm" +#include "code\datums\components\skills\operations\pilot_spacecraft_skill_component.dm" +#include "code\datums\components\skills\operations\robotics_skill_component.dm" +#include "code\datums\components\skills\science\archaology_skill_component.dm" +#include "code\datums\components\skills\science\research_skill_component.dm" +#include "code\datums\components\skills\science\xenobiology_skill_component.dm" +#include "code\datums\components\skills\science\xenobotany_skill_component.dm" +#include "code\datums\components\skills\service\bartending_skill_component.dm" +#include "code\datums\components\skills\service\cooking_skill_component.dm" +#include "code\datums\components\skills\service\entertaining_skill_component.dm" +#include "code\datums\components\skills\service\gardening_skill_component.dm" #include "code\datums\components\synthetic_endoskeleton\synthetic_endoskeleton.dm" #include "code\datums\components\turf_click\turf_hand.dm" #include "code\datums\elements\_element.dm" @@ -593,6 +622,7 @@ #include "code\datums\skills\everyday\service.dm" #include "code\datums\skills\occupational\engineering.dm" #include "code\datums\skills\occupational\medical.dm" +#include "code\datums\skills\occupational\operations.dm" #include "code\datums\skills\occupational\science.dm" #include "code\datums\state_machine\state.dm" #include "code\datums\state_machine\transition.dm" @@ -1159,6 +1189,7 @@ #include "code\game\objects\effects\decals\Cleanable\fuel.dm" #include "code\game\objects\effects\decals\Cleanable\humans.dm" #include "code\game\objects\effects\decals\Cleanable\misc.dm" +#include "code\game\objects\effects\decals\Cleanable\napalm.dm" #include "code\game\objects\effects\decals\Cleanable\robots.dm" #include "code\game\objects\effects\decals\Cleanable\tracks.dm" #include "code\game\objects\effects\decals\posters\bs12.dm" @@ -1238,7 +1269,6 @@ #include "code\game\objects\items\devices\paint_sprayer.dm" #include "code\game\objects\items\devices\personal_shield.dm" #include "code\game\objects\items\devices\pin_extractor.dm" -#include "code\game\objects\items\devices\pipe_painter.dm" #include "code\game\objects\items\devices\powersink.dm" #include "code\game\objects\items\devices\radio_jammer.dm" #include "code\game\objects\items\devices\scanners.dm" @@ -1686,7 +1716,6 @@ #include "code\modules\admin\verbs\diagnostics.dm" #include "code\modules\admin\verbs\dice.dm" #include "code\modules\admin\verbs\fps.dm" -#include "code\modules\admin\verbs\getlogs.dm" #include "code\modules\admin\verbs\map_template_loadverb.dm" #include "code\modules\admin\verbs\mapping.dm" #include "code\modules\admin\verbs\massmodvar.dm" @@ -1739,6 +1768,7 @@ #include "code\modules\atmospherics\datum_pipeline.dm" #include "code\modules\atmospherics\he_pipes.dm" #include "code\modules\atmospherics\pipes.dm" +#include "code\modules\atmospherics\vent_passive.dm" #include "code\modules\atmospherics\components\portables_connector.dm" #include "code\modules\atmospherics\components\tvalve.dm" #include "code\modules\atmospherics\components\valve.dm" @@ -2987,7 +3017,6 @@ #include "code\modules\mob\living\simple_animal\hostile\retaliate\retaliate.dm" #include "code\modules\mob\living\simple_animal\hostile\toy\mech.dm" #include "code\modules\mob\living\simple_animal\mechanical\mechanical.dm" -#include "code\modules\mob\skills\skills.dm" #include "code\modules\modular_computers\_description.dm" #include "code\modules\modular_computers\laptop_vendor.dm" #include "code\modules\modular_computers\computers\modular_computer\core.dm" @@ -3910,6 +3939,7 @@ #include "code\modules\tgui_input\say_modal\typing.dm" #include "code\modules\tgui_panel\audio.dm" #include "code\modules\tgui_panel\external.dm" +#include "code\modules\tgui_panel\telemetry.dm" #include "code\modules\tgui_panel\tgui_panel.dm" #include "code\modules\tooltip\tooltip.dm" #include "code\modules\turbolift\_turbolift.dm" diff --git a/code/ZAS/ConnectionGroup.dm b/code/ZAS/ConnectionGroup.dm index bf0e72a9a9fe..e73d4e722839 100644 --- a/code/ZAS/ConnectionGroup.dm +++ b/code/ZAS/ConnectionGroup.dm @@ -165,7 +165,7 @@ Class Procs: var/equiv = A.air.share_ratio(B.air, coefficient) - var/differential = A.air.return_pressure() - B.air.return_pressure() + var/differential = XGM_PRESSURE(A.air) - XGM_PRESSURE(B.air) if(abs(differential) >= GLOB.vsc.airflow_lightest_pressure) var/list/attracted var/list/repelled @@ -239,7 +239,7 @@ Class Procs: var/equiv = A.air.share_space(air) - var/differential = A.air.return_pressure() - air.return_pressure() + var/differential = XGM_PRESSURE(A.air) - XGM_PRESSURE(air) if(abs(differential) >= GLOB.vsc.airflow_lightest_pressure) var/list/attracted = A.movables(connecting_turfs) // This call is async, with waitfor = FALSE diff --git a/code/ZAS/Diagnostic.dm b/code/ZAS/Diagnostic.dm index faac8be5bc58..6bc8e312538d 100644 --- a/code/ZAS/Diagnostic.dm +++ b/code/ZAS/Diagnostic.dm @@ -6,7 +6,7 @@ else to_chat(mob, "No zone here.") var/datum/gas_mixture/mix = T.return_air() - to_chat(mob, "[mix.return_pressure()] kPa [mix.temperature]C") + to_chat(mob, "[XGM_PRESSURE(mix)] kPa [mix.temperature]C") for(var/g in mix.gas) to_chat(mob, "[g]: [mix.gas[g]]\n") else diff --git a/code/ZAS/Fire.dm b/code/ZAS/Fire.dm index b6af196d3811..d25630c93e52 100644 --- a/code/ZAS/Fire.dm +++ b/code/ZAS/Fire.dm @@ -44,11 +44,17 @@ If it gains pressure too slowly, it may leak or just rupture instead of explodin var/igniting = FALSE var/obj/effect/decal/cleanable/liquid_fuel/liquid = locate() in src - if(liquid && air_contents.check_combustibility(liquid)) + var/is_cmb = liquid ? CMB_LIQUID_FUEL : 0 + CHECK_COMBUSTIBLE(is_cmb, air_contents) + if(liquid && is_cmb) IgniteTurf(liquid.amount * 10) QDEL_NULL(liquid) - if(air_contents.check_combustibility()) + var/obj/effect/decal/cleanable/napalm/napalm = locate() in src + if(napalm) + napalm.Ignite() + + if(is_cmb) igniting = TRUE create_fire(exposed_temperature) @@ -57,7 +63,7 @@ If it gains pressure too slowly, it may leak or just rupture instead of explodin /zone/proc/process_fire() var/datum/gas_mixture/burn_gas = air.remove_ratio(GLOB.vsc.fire_consuption_rate, LAZYLEN(fire_tiles)) - var/firelevel = burn_gas.zburn(src, fire_tiles, force_burn = TRUE, no_check = TRUE) + var/firelevel = burn_gas.react(src, fire_tiles, force_burn = TRUE, no_check = TRUE) air.merge(burn_gas) @@ -143,11 +149,10 @@ If it gains pressure too slowly, it may leak or just rupture instead of explodin else set_light(5, FIRE_LIGHT_1) - for(var/mob/living/L in loc) - L.FireBurn(firelevel, air_contents.temperature, air_contents.return_pressure()) //Burn the mobs! - loc.fire_act(air_contents.temperature, air_contents.volume) for(var/atom/A in loc) + var/mob/living/L = astype(A) + L?.FireBurn(firelevel, air_contents.temperature, XGM_PRESSURE(air_contents)) A.fire_act(air_contents.temperature, air_contents.volume) //spread @@ -161,7 +166,13 @@ If it gains pressure too slowly, it may leak or just rupture instead of explodin //if(!enemy_tile.zone.fire_tiles.len) TODO - optimize var/datum/gas_mixture/acs = enemy_tile.return_air() - if(!acs || !acs.check_combustibility()) + if(!acs) + continue + + var/is_cmb = 0 + CHECK_COMBUSTIBLE(is_cmb, acs) + + if(!is_cmb) continue //If extinguisher mist passed over the turf it's trying to spread to, don't spread and @@ -226,9 +237,12 @@ If it gains pressure too slowly, it may leak or just rupture instead of explodin fire_protection = world.time //Returns the firelevel -/datum/gas_mixture/proc/zburn(zone/zone, force_burn, no_check = 0) +/datum/gas_mixture/proc/react(zone/zone, force_burn, no_check = 0) . = 0 - if((temperature > PHORON_MINIMUM_BURN_TEMPERATURE || force_burn) && (no_check || check_combustibility())) + var/is_cmb = no_check ? TRUE : 0 + if(!is_cmb) + CHECK_COMBUSTIBLE(is_cmb, src) + if((temperature > PHORON_MINIMUM_BURN_TEMPERATURE || force_burn) && is_cmb) #ifdef ZASDBG log_subsystem_zas_debug("***************** FIREDBG *****************") @@ -299,11 +313,16 @@ If it gains pressure too slowly, it may leak or just rupture instead of explodin //calculate the energy produced by the reaction and then set the new temperature of the mix temperature = (starting_energy + GLOB.vsc.fire_fuel_energy_release * (used_gas_fuel)) / heat_capacity() - update_values() + total_moles = 0 + for(var/g in gas) + if(gas[g] <= 0) + gas -= g + else + total_moles += gas[g] #ifdef ZASDBG log_subsystem_zas_debug("used_gas_fuel = [used_gas_fuel]; total = [used_fuel]") - log_subsystem_zas_debug("new temperature = [temperature]; new pressure = [return_pressure()]") + log_subsystem_zas_debug("new temperature = [temperature]; new pressure = [XGM_PRESSURE(src)]") #endif if (temperature < MINIMUM_HEAT_THRESHOLD) @@ -330,25 +349,6 @@ If it gains pressure too slowly, it may leak or just rupture instead of explodin . = 1 break -/datum/gas_mixture/proc/check_combustibility(obj/effect/decal/cleanable/liquid_fuel/liquid=null) - . = 0 - for(var/g in gas) - if(gas_data.flags[g] & XGM_GAS_OXIDIZER && QUANTIZE(gas[g] * GLOB.vsc.fire_consuption_rate) >= 0.1) - . = 1 - break - - if(!.) - return 0 - - if(liquid) - return 1 - - . = 0 - for(var/g in gas) - if(gas_data.flags[g] & XGM_GAS_FUEL && QUANTIZE(gas[g] * GLOB.vsc.fire_consuption_rate) >= 0.005) - . = 1 - break - //returns a value between 0 and vsc.fire_firelevel_multiplier /datum/gas_mixture/proc/calculate_firelevel(total_fuel, total_oxidizers, reaction_limit, gas_volume) //Calculates the firelevel based on one equation instead of having to do this multiple times in different areas. diff --git a/code/ZAS/Zone.dm b/code/ZAS/Zone.dm index aceac97e6994..a17019880456 100644 --- a/code/ZAS/Zone.dm +++ b/code/ZAS/Zone.dm @@ -145,10 +145,13 @@ Class Procs: /zone/proc/tick() // Update fires. - if(air.temperature >= PHORON_FLASHPOINT && !(src in SSair.active_fire_zones) && air.check_combustibility() && contents.len) - var/turf/T = pick(contents) - if(istype(T)) - T.create_fire(GLOB.vsc.fire_firelevel_multiplier) + if(air.temperature >= PHORON_FLASHPOINT && !(src in SSair.active_fire_zones) && contents.len) + var/is_cmb = 0 + CHECK_COMBUSTIBLE(is_cmb, air) + if(is_cmb) + var/turf/T = pick(contents) + if(istype(T)) + T.create_fire(GLOB.vsc.fire_firelevel_multiplier) // Update gas overlays. if(air.check_tile_graphic(graphic_add, graphic_remove)) @@ -166,7 +169,7 @@ Class Procs: to_chat(M, name) for(var/g in air.gas) to_chat(M, "[gas_data.name[g]]: [air.gas[g]]") - to_chat(M, "P: [air.return_pressure()] kPa V: [air.volume]L T: [air.temperature]�K ([air.temperature - T0C]�C)") + to_chat(M, "P: [XGM_PRESSURE(air)] kPa V: [air.volume]L T: [air.temperature]�K ([air.temperature - T0C]�C)") to_chat(M, "O2 per N2: [(air.gas[GAS_NITROGEN] ? air.gas[GAS_OXYGEN]/air.gas[GAS_NITROGEN] : "N/A")] Moles: [air.total_moles]") to_chat(M, "Simulated: [contents.len] ([air.group_multiplier])") //to_chat(M, "Unsimulated: [unsimulated_contents.len]") @@ -181,7 +184,7 @@ Class Procs: else space_edges++ space_coefficient += E.coefficient - to_chat(M, "[E:air:return_pressure()]kPa") + to_chat(M, "[XGM_PRESSURE(air)]kPa") to_chat(M, "Zone Edges: [zone_edges]") to_chat(M, "Space Edges: [space_edges] ([space_coefficient] connections)") diff --git a/code/__DEFINES/atmos.dm b/code/__DEFINES/atmos.dm index b2cf2f5ad115..d402237efec3 100644 --- a/code/__DEFINES/atmos.dm +++ b/code/__DEFINES/atmos.dm @@ -158,3 +158,27 @@ GLOBAL_LIST_INIT(pipe_colors, list( "black" = PIPE_COLOR_BLACK, "purple" = PIPE_COLOR_PURPLE )) + +#define CMB_LIQUID_FUEL (1 << 1) +#define CHECK_COMBUSTIBLE(cmb, xgm) \ + do { \ + for(var/g in xgm.gas) { \ + if(!(cmb & 1) && gas_data.flags[g] & XGM_GAS_OXIDIZER && QUANTIZE(xgm.gas[g] * GLOB.vsc.fire_consuption_rate) >= 0.1) { \ + cmb |= (1 << 0); \ + } \ + else if(!(cmb & 2) && gas_data.flags[g] & XGM_GAS_FUEL && QUANTIZE(xgm.gas[g] * GLOB.vsc.fire_consuption_rate) >= 0.005) { \ + cmb |= (1 << 1); \ + } \ + else if(cmb & 3) { \ + break; \ + } \ + } \ + if(cmb == 1) { \ + cmb = 0; \ + } \ + } while (FALSE); + +/// Returns the pressure of the gas mix. Only accurate if there have been no gas modifications since update_values() has been called. +#define XGM_PRESSURE(xgm) (xgm.volume ? xgm.total_moles * R_IDEAL_GAS_EQUATION * xgm.temperature / xgm.volume : 0) +/// XGM_PRESSURE but accounts for xgm (gas mixture) being null +#define SAFE_XGM_PRESSURE(xgm) (xgm ? XGM_PRESSURE(xgm) : 0) diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index fe6602554841..ca2f937a8546 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -1,2 +1,35 @@ #define COMSIG_BASENAME_RENAME "base_name_rename" #define COMSIG_BASENAME_SETNAME "base_name_setname" +#define ARMED_COMBAT_SKILL_COMPONENT /datum/component/skill/armed_combat +#define FIREARMS_SKILL_COMPONENT /datum/component/skill/firearms +#define UNARMED_COMBAT_SKILL_COMPONENT /datum/component/skill/unarmed_combat +#define PILOT_MECHS_SKILL_COMPONENT /datum/component/skill/pilot_mechs +#define PILOT_SPACECRAFT_SKILL_COMPONENT /datum/component/skill/pilot_spacecraft +#define ROBOTICS_SKILL_COMPONENT /datum/component/skill/robotics +#define ARCHAOLOGY_SKILL_COMPONENT /datum/component/skill/archaology +#define RESEARCH_SKILL_COMPONENT /datum/component/skill/research +#define XENOBIOLOGY_SKILL_COMPONENT /datum/component/skill/xenobiology +#define XENOBOTANY_SKILL_COMPONENT /datum/component/skill/xenobotany +#define BARTENDING_SKILL_COMPONENT /datum/component/skill/bartending +#define COOKING_SKILL_COMPONENT /datum/component/skill/cooking +#define ENTERTAINING_SKILL_COMPONENT /datum/component/skill/entertaining +#define GARDENING_SKILL_COMPONENT /datum/component/skill/gardening +#define MEDICINE_SKILL_COMPONENT /datum/component/skill/medicine +#define SKILL_COMPONENT /datum/component/skill +#define MORALE_COMPONENT /datum/component/morale +#define ELECTRICAL_ENGINEERING_SKILL_COMPONENT /datum/component/skill/electrical_engineering +#define MECHANICAL_ENGINEERING_SKILL_COMPONENT /datum/component/skill/electrical_engineering +#define ATMOSPHERICS_SYSTEMS_SKILL_COMPONENT /datum/component/skill/atmospherics_systems +#define REACTOR_SYSTEMS_SKILL_COMPONENT /datum/component/skill/reactor_systems +#define LEADERSHIP_SKILL_COMPONENT /datum/component/skill/leadership +#define ANATOMY_SKILL_COMPONENT /datum/component/skill/anatomy +#define FORENSICS_SKILL_COMPONENT /datum/component/skill/forensics +#define PHARMACOLOGY_SKILL_COMPONENT /datum/component/skill/pharmacology +#define SURGERY_SKILL_COMPONENT /datum/component/skill/surgery + +/** + * Trinary-Boolean helper that either returns null, or the skill level of a given skill component(which can be zero). + * It will ALWAYS be null if you try to use this to check for something that isn't a skill component, so just don't. Refer to the list above this function to see what your options are. + * Therefore, merely checking if (!this) is not sufficient to use this function, and instead you should be using isnull() on it to determine whether or not the skill exists. + */ +#define GET_SKILL_LEVEL(user, comp) astype(user.GetComponent(comp), SKILL_COMPONENT)?.skill_level diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 063905eea04d..0edf400c8ac1 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -79,4 +79,58 @@ /// Raised on a mob to check it's psi-sensitivity rating. This is not the same thing as checking if someone is psionic, but psionic people have an innate bonus to the check. #define COMSIG_PSI_CHECK_SENSITIVITY "psi_check_sensitivity" +// directional input signals. +// TODO: Please rework these if you are porting actual keybindings. +/// Raised on a mob when receiving a "Northeast" input key, typically the 'e' key. +#define COMSIG_INPUT_KEY_QUICK_EQUIP "quick-equip_key_pressed" + +/// Raised on a mob when receiving a "Northwest" input key, typically the 'q' key. +#define COMSIG_INPUT_KEY_DROP "drop_key_pressed" + /*******Component Specific Signals*******/ + +/** + * Raised against objects in a turf when that turf is attacked by a mob. + * Arg 1 is the object being checked. + * Arg 2 is the mob attacking the turf. + * Arg 3 is the turf. + */ +#define COMSIG_HANDLE_HAND_INTERCEPTION "handle_hand_interception" + +// /obj/item/gun signals + +#define COMSIG_GUN_TOGGLE_FIRING_MODE "gun_toggle_firing_mode" + +#define COMSIG_BEFORE_GUN_FIRE "before_gun_fire" + +// Mech signals + +#define COMSIG_MECH_MOVE_WASD "mech_move_wasd" + +#define COMSIG_MECH_MOVE_STRAFE "mech_move_strafe" + +#define COMSIG_MECH_TOGGLE_POWER "mech_toggle_power" + +// Unarmed Combat Signals + +#define COMSIG_UNARMED_HARM_ATTACKER "unarmed_harm_attacker" +#define COMSIG_UNARMED_HARM_DEFENDER "unarmed_harm_defender" +#define COMSIG_UNARMED_DISARM_ATTACKER "unarmed_disarm_attacker" +#define COMSIG_UNARMED_DISARM_DEFENDER "unarmed_disarm_defender" + +// Bartending Skill Signals + +#define COMSIG_CONTAINER_DRANK "container_drank" + +// Hydroponics Signals +/// Signal raised against the harvester of a plant during the Harvest() proc. +#define COMSIG_PLANT_HARVESTER "plant_harvester" +/// Signal raised against the plant being harvested during the Harvest() proc. +#define COMSIG_PLANT_HARVESTED "plant_harvested" + +// Armed Combat Signals +#define COMSIG_APPLY_HIT_EFFECT "apply_hit_effect" + +// Various computer signals for interrupting via skill or other effects. +#define COMSIG_USE_REACTOR_COMPUTER "use_reactor_computer" +#define COMSIG_USE_MECH_FAB "use_mech_fab" diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm index 181cb65f4b63..7ddd0fac7ea1 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm @@ -41,3 +41,6 @@ /// From base of area/Exited(): (area/left, direction) #define COMSIG_MOVABLE_EXITED_AREA "movable_exited_area" + +///called when the movable's glide size is updated: (new_glide_size) +#define COMSIG_MOVABLE_UPDATE_GLIDE_SIZE "movable_glide_size" 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 d8fd784b0073..53506e757b78 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm @@ -45,3 +45,9 @@ /// From /obj/item/organ/external/take_damage. Updates the limb's colour matrix. Very laggy, so we do it on reaction to stuff. #define COMSIG_UPDATE_LIMB_IMAGE "update_limb_image" + +/// For when bone is fixed with surgery +#define COMSIG_BEGIN_SURGERY "begin_surgery" + +/// For when the players intent changes +#define COMSIG_INTENT_CHANGE "intent_change" diff --git a/code/__DEFINES/items_clothing.dm b/code/__DEFINES/items_clothing.dm index 038b6ccbf544..6de0f254d241 100644 --- a/code/__DEFINES/items_clothing.dm +++ b/code/__DEFINES/items_clothing.dm @@ -162,8 +162,8 @@ #define FIRESUIT_MIN_PRESSURE 0.5 * ONE_ATMOSPHERE #define TEMPERATURE_DAMAGE_COEFFICIENT 1.5 // This is used in handle_temperature_damage() for humans, and in reagents that affect body temperature. Temperature damage is multiplied by this amount. -#define BODYTEMP_AUTORECOVERY_DIVISOR 12 // This is the divisor which handles how much of the temperature difference between the current body temperature and 310.15K (optimal temperature) humans auto-regenerate each tick. The higher the number, the slower the recovery. This is applied each tick, so long as the mob is alive. -#define BODYTEMP_AUTORECOVERY_MINIMUM 1 // Minimum amount of kelvin moved toward 310.15K per tick. So long as abs(310.15 - bodytemp) is more than 50. +#define BODYTEMP_AUTORECOVERY_DIVISOR 24 // This is the divisor which handles how much of the temperature difference between the current body temperature and 310.15K (optimal temperature) humans auto-regenerate each second. The higher the number, the slower the recovery. This is applied each tick, so long as the mob is alive. +#define BODYTEMP_AUTORECOVERY_MINIMUM 0.5 // Minimum amount of kelvin moved toward 310.15K per second. So long as abs(310.15 - bodytemp) is more than 50. #define BODYTEMP_COLD_DIVISOR 6 // Similar to the BODYTEMP_AUTORECOVERY_DIVISOR, but this is the divisor which is applied at the stage that follows autorecovery. This is the divisor which comes into play when the human's loc temperature is lower than their body temperature. Make it lower to lose bodytemp faster. #define BODYTEMP_HEAT_DIVISOR 6 // Similar to the BODYTEMP_AUTORECOVERY_DIVISOR, but this is the divisor which is applied at the stage that follows autorecovery. This is the divisor which comes into play when the human's loc temperature is higher than their body temperature. Make it lower to gain bodytemp faster. #define BODYTEMP_COOLING_MAX -30 // The maximum number of degrees that your body can cool down in 1 tick, when in a cold area. diff --git a/code/__DEFINES/machinery.dm b/code/__DEFINES/machinery.dm index d02bf7104812..01a2ba0be678 100644 --- a/code/__DEFINES/machinery.dm +++ b/code/__DEFINES/machinery.dm @@ -14,10 +14,44 @@ // Channel numbers for power. #define POWER_CHAN -1 // Use default -#define AREA_USAGE_EQUIP 1 -#define AREA_USAGE_LIGHT 2 -#define AREA_USAGE_ENVIRON 3 -#define AREA_USAGE_TOTAL 4 // For total power used only. +#define AREA_USAGE_EQUIP BITFLAG(1) +#define AREA_USAGE_LIGHT BITFLAG(2) +#define AREA_USAGE_ENVIRON BITFLAG(3) +#define AREA_USAGE_TOTAL (AREA_USAGE_EQUIP|AREA_USAGE_LIGHT|AREA_USAGE_ENVIRON) // For total power used only. + +#define LIGHT_USAGE(area) (area.used_light + area.oneoff_light) +#define EQUIP_USAGE(area) (area.used_equip + area.oneoff_equip) +#define ENVIRON_USAGE(area) (area.used_environ + area.oneoff_environ) +#define CLEAR_USAGE(area) area.oneoff_equip = 0; area.oneoff_light = 0; area.oneoff_environ = 0; + +/// Returns the surplus power available to the powernet (avail - load) +#define POWERNET_SURPLUS(powernet) powernet.avail - powernet.load +/// Clamps the passed-in amount between 0 and the powernet's available load capacity. +#define POWERNET_POWER_DRAW(powernet, amt) ((powernet) ? clamp(amt, 0, powernet.avail - powernet.load) : 0) +/// Draws power from the powernet directly, if it exists. +#define DRAW_FROM_POWERNET(powernet, amt) ((powernet) ? (powernet.load += amt) : 0) + +/// Adds an amount from SMES to the powernet (powernet.smes_newavail) +#define SMES_ADD_TO_POWERNET(smes, amt) if(smes.powernet) { \ + smes.powernet.newavail += amt; \ + smes.powernet.smes_newavail += amt; \ +} +/// Adds an amount to the available power in the powernet (powernet.newavail) +#define ADD_TO_POWERNET(machine, amt) ((machine.powernet) ? (machine.powernet.newavail += amt) : 0) +/// Returns the available power to the machine via the powernet (powernet.avail) +#define POWER_AVAIL(machine) (machine.powernet?.avail || 0) +/// Returns the load of the powernet attached to the machine (powernet.load) +#define POWER_LOAD(machine) (machine.powernet?.load || 0) +/// Returns the surplus power available to the machine via the powernet (avail - load) +#define POWER_SURPLUS(machine) ((machine.powernet) ? (POWERNET_SURPLUS(machine.powernet)) : 0) +/// Clamps the passed-in amount between 0 and the powernet's available load capacity. +#define POWER_DRAW(machine, amt) (POWERNET_POWER_DRAW(machine.powernet, amt)) +/// Draws power from the machine's powernet, if it exists. +#define DRAW_POWER(machine, amt) (DRAW_FROM_POWERNET(machine.powernet, amt)) +/// Clamps the passed-in amount between 0 and the terminal's powernet's available load capacity. +#define TERMINAL_POWER_DRAW(amt) (src.terminal ? POWER_DRAW(src.terminal, amt) : 0) +/// Draws power from src's terminal, if it exists. +#define TERMINAL_DRAW_POWER(amt) (src.terminal ? (DRAW_POWER(src.terminal, amt)) : 0) #define POWER_USE_OFF 0 #define POWER_USE_IDLE 1 @@ -167,3 +201,11 @@ GLOBAL_LIST_INIT(restricted_camera_networks, list(NETWORK_ERT,NETWORK_MERCENARY, #define INIT_MACHINERY_PROCESS_SELF 0x1 #define INIT_MACHINERY_PROCESS_COMPONENTS 0x2 #define INIT_MACHINERY_PROCESS_ALL 0x3 + +// Status Display Modes +#define STATUS_DISPLAY_BLANK 0 +#define STATUS_DISPLAY_TRANSFER_SHUTTLE_TIME 1 +#define STATUS_DISPLAY_MESSAGE 2 +#define STATUS_DISPLAY_ALERT 3 +#define STATUS_DISPLAY_TIME 4 +#define STATUS_DISPLAY_CUSTOM 99 diff --git a/code/__DEFINES/maths.dm b/code/__DEFINES/maths.dm index 257385f955fd..ca0b9bf00d41 100644 --- a/code/__DEFINES/maths.dm +++ b/code/__DEFINES/maths.dm @@ -24,6 +24,12 @@ // Real modulus that handles decimals #define MODULUS(x, y) ( (x) - FLOOR(x, y)) +/// clamp() but in order of low - mid - high instead of mid - low - high. +#define between(low, mid, high) ( clamp(mid, low, high) ) + +/// returns current_value as % of max_value, e.g. 60 is 60% of 100 + +#define AS_PCT(current_value, max_value) ( round((current_value / max_value) * 100, 1) ) // Similar to clamp but the bottom rolls around to the top and vice versa. min is inclusive, max is exclusive #define WRAP(val, min, max) clamp(( min == max ? min : (val) - (round(((val) - (min))/((max) - (min))) * ((max) - (min))) ),min,max) diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 58fb173b1cf9..2c7a5b978653 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -109,13 +109,6 @@ #define WAIT_ARRIVE 3 #define WAIT_FINISH 4 -// Setting this much higher than 1024 could allow spammers to DOS the server easily. -#define MAX_MESSAGE_LEN 1024 -#define MAX_PAPER_MESSAGE_LEN 3072 -#define MAX_BOOK_MESSAGE_LEN 9216 -#define MAX_LNAME_LEN 64 -#define MAX_NAME_LEN 63 - // Event defines. #define EVENT_LEVEL_MUNDANE 1 #define EVENT_LEVEL_MODERATE 2 diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index d6e4b6679f0c..06f7ecb4f7a7 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -562,6 +562,10 @@ #define HEIGHT_CLASS_HUGE 240 #define HEIGHT_CLASS_GIGANTIC 300 +#define UNBUCKLED 0 +#define PARTIALLY_BUCKLED 1 +#define FULLY_BUCKLED 2 + #define MOB_IS_INCAPACITATED(incapacitation_flags)\ (\ ((incapacitation_flags & INCAPACITATION_STUNNED) && stunned) ||\ diff --git a/code/__DEFINES/movement.dm b/code/__DEFINES/movement.dm index a1d80321ece5..16a2fce7c6c8 100644 --- a/code/__DEFINES/movement.dm +++ b/code/__DEFINES/movement.dm @@ -1,3 +1,27 @@ +/** + * The minimum for glide_size to be clamped to. + * This is set to 1/32 to allow for up to 32 subdivisions of a single pixel move. + * Or 1024 subdivisions of a single tile movement. + * If you want it to look any better than this, beg Lummox for 64bit support. + */ +#define MIN_GLIDE_SIZE 0.03125 +/// The maximum for glide_size to be clamped to. +/// This shouldn't be higher than the icon size, and generally you shouldn't be changing this, but it's here just in case. +#define MAX_GLIDE_SIZE ICON_SIZE_ALL + +/// Compensating for time dilation +GLOBAL_VAR_INIT(glide_size_multiplier, 1.0) + +///Broken down, here's what this does: +/// divides the world icon_size by delay divided by ticklag to get the number of pixels something should be moving each tick. +/// Then that's multiplied by the global glide size multiplier. 1.25 by default feels pretty close to spot on. This is just to try to get byond to behave. +/// The whole result is then clamped to within the range above. +/// Not very readable but it works +#define DELAY_TO_GLIDE_SIZE(delay) (clamp(((ICON_SIZE_ALL / max((delay) / world.tick_lag, 1)) * GLOB.glide_size_multiplier), MIN_GLIDE_SIZE, MAX_GLIDE_SIZE)) + +///Similar to DELAY_TO_GLIDE_SIZE, except without the clamping, and it supports piping in an unrelated scalar +#define MOVEMENT_ADJUSTED_GLIDE_SIZE(delay, movement_disparity) (ICON_SIZE_ALL / ((delay) / world.tick_lag) * movement_disparity * GLOB.glide_size_multiplier) + //Movement loop priority. Only one loop can run at a time, this dictates that // Higher numbers beat lower numbers ///Standard, go lower then this if you want to override, higher otherwise diff --git a/code/__DEFINES/pipes.dm b/code/__DEFINES/pipes.dm index 2ff6e02caf7c..02a3c30cf54c 100644 --- a/code/__DEFINES/pipes.dm +++ b/code/__DEFINES/pipes.dm @@ -74,3 +74,5 @@ #define PIPE_CONNECTOR_AUX 63 #define PIPE_AUX_UVENT 64 + +#define PIPE_PVENT 65 diff --git a/code/__DEFINES/profiler_tracy.dm b/code/__DEFINES/profiler_tracy.dm index eeb2fc3c4691..00d9ae19795f 100644 --- a/code/__DEFINES/profiler_tracy.dm +++ b/code/__DEFINES/profiler_tracy.dm @@ -3,22 +3,16 @@ // and https://github.com/ParadiseSS13/byond-tracy // Tracy Client https://github.com/wolfpld/tracy -#define DISK_VERSION "disk" -#define CONNECTION_VERSION "connection" - /// Whether byond-tracy is currently running or not, no matter what version. GLOBAL_VAR_INIT(byond_tracy_running, FALSE) -/// Which version of byond-tracy is currently running, so we call the right binary on destruction. -GLOBAL_VAR_INIT(byond_tracy_running_v, FALSE) - /// The path we have invoked to load byond tracy GLOBAL_VAR_INIT(byond_tracy_path, FALSE) /world/New() CAN_BE_REDEFINED(TRUE) if(GLOB.config.enable_byond_tracy) - prof_init(DISK_VERSION) // This start's Affectedarc07's version of Tracy. Writing a .utracy file to the disk. + prof_init() // This start's Affectedarc07's version of Tracy. Writing a .utracy file to the disk. . = ..() /world/Del() @@ -34,52 +28,29 @@ GLOBAL_VAR_INIT(byond_tracy_path, FALSE) if(!GLOB.byond_tracy_running) switch(alert("Are you sure? Tracy will remain active until the server restarts.", "Tracy Init", "No", "Yes")) if("Yes") - switch(alert("Which version of Tracy would you like to run?", "Tracy Version", "Cancel", "Connection Based", "Disk Based")) - if("Connection Based") - world.SetConfig("env", "UTRACY_BIND_ADDRESS", "0.0.0.0") - - var/port = input("What port would you like to use?", "Tracy Port", "8086") as num - if(!(port == 8086 || port > 4096)) - alert("Invalid port. Please enter a valid port number, either 8086 or bigger than 4096.") - return - - world.SetConfig("env", "UTRACY_BIND_PORT", "[port]") - prof_init(CONNECTION_VERSION) // This start's mafemergency's original version of Tracy. Requiring a direct connection, not writing to the disk. - - if("Disk Based") - prof_init(DISK_VERSION) // This start's Affectedarc07's version of Tracy. Writing a .utracy file to the disk. + prof_init() // This start's Affectedarc07's version of Tracy. Writing a .utracy file to the disk. /** * Starts Tracy. */ -/proc/prof_init(var/version) +/proc/prof_init() var/lib - switch(version) - if(CONNECTION_VERSION) - if(world.system_type == MS_WINDOWS) - lib = "tracy.dll" - else if(world.system_type == UNIX) - lib = "libprof.so" - else - CRASH("unsupported platform") - - if(DISK_VERSION) - if(world.system_type == MS_WINDOWS) - lib = "tracy-disk.dll" - else if(world.system_type == UNIX) - lib = "libprof-disk.so" - else - CRASH("unsupported platform") - else - CRASH("unsupported byond-tracy version [version]") + if(world.system_type == MS_WINDOWS) + lib = "tracy-disk.dll" + else if(world.system_type == UNIX) + lib = "libprof-disk.so" + else + to_chat(usr,"unsupported platform") + CRASH("unsupported platform") GLOB.byond_tracy_path = lib var/init = call_ext(lib, "init")() - if("0" != init) CRASH("[lib] init error: [init]") + if("0" != init) + to_chat(usr,"[lib] init error: [init]") + CRASH("[lib] init error: [init]") GLOB.byond_tracy_running = TRUE - GLOB.byond_tracy_running_v = version /** * Stops Tracy. @@ -88,27 +59,14 @@ GLOBAL_VAR_INIT(byond_tracy_path, FALSE) /proc/prof_destroy() var/lib - switch(GLOB.byond_tracy_running_v) - if(CONNECTION_VERSION) - if(world.system_type == MS_WINDOWS) - lib = "tracy.dll" - else if(world.system_type == UNIX) - lib = "libprof.so" - else - CRASH("unsupported platform") - - if(DISK_VERSION) - if(world.system_type == MS_WINDOWS) - lib = "tracy-disk.dll" - else if(world.system_type == UNIX) - lib = "libprof-disk.so" - else - CRASH("unsupported platform") + if(world.system_type == MS_WINDOWS) + lib = "tracy-disk.dll" + else if(world.system_type == UNIX) + lib = "libprof-disk.so" + else + to_chat(usr,"unsupported platform") + CRASH("unsupported platform") call_ext(lib, "destroy")() GLOB.byond_tracy_running = FALSE - GLOB.byond_tracy_running_v = null - -#undef DISK_VERSION -#undef CONNECTION_VERSION diff --git a/code/__DEFINES/qdel.dm b/code/__DEFINES/qdel.dm index 3af7532401ee..59ea465f0a12 100644 --- a/code/__DEFINES/qdel.dm +++ b/code/__DEFINES/qdel.dm @@ -1,14 +1,3 @@ -/** - * THIS IS A TEMPORARY WORKAROUND WHILE WE RESOLVE HARDDELS WITH THE NEW GC - * - * YOU ARE ONLY ALLOWED TO REMOVE THE AMOUNT OF THEM, NOT ADD MORE - * - * AND FOR WHAT MATTERS, THE SAME GOES FOR QDEL_HINT_HARDDEL, - * I DO NOT CARE HOW MANY REWRITES AND REFACTORS YOU HAVE TO DO, WHATEVER YOU ADD NEEDS TO BE GARGAGE COLLECTABLE, OR HAVE AN EXPLAINED, CLEAR, UNFIXABLE REASON WHY IT IS NOT - * - */ -#define GC_TEMPORARY_HARDDEL return QDEL_HINT_HARDDEL - //! Defines that give qdel hints. //! //! These can be given as a return in [/atom/proc/Destroy] or by calling [/proc/qdel]. @@ -73,9 +62,9 @@ // This is a bit hacky, we do it to avoid people relying on a return value for the macro // If you need that you should use QDEL_IN_STOPPABLE instead #define QDEL_IN(item, time) ; \ - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), (time) > GC_FILTER_QUEUE ? WEAKREF(item) : item), time); -#define QDEL_IN_STOPPABLE(item, time) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), (time) > GC_FILTER_QUEUE ? WEAKREF(item) : item), time, TIMER_STOPPABLE) -#define QDEL_IN_CLIENT_TIME(item, time) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), item), time, TIMER_STOPPABLE | TIMER_CLIENT_TIME) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), (time) > GC_FILTER_QUEUE ? WEAKREF(item) : item), time, TIMER_DELETE_ME); +#define QDEL_IN_STOPPABLE(item, time) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), (time) > GC_FILTER_QUEUE ? WEAKREF(item) : item), time, TIMER_STOPPABLE | TIMER_DELETE_ME) +#define QDEL_IN_CLIENT_TIME(item, time) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), item), time, TIMER_STOPPABLE | TIMER_CLIENT_TIME | TIMER_DELETE_ME) //Bay uses the check before deleting something, to ensure it's not null, TG does not, and since I don't want to go hunt down 3 billion runtimes, we keep bay's version @@ -84,6 +73,8 @@ #define QDEL_NULL_LIST(x) if(x) { for(var/y in x) { qdel(y) }}; if(x) {x.Cut(); x = null } // Second x check to handle items that LAZYREMOVE on qdel. #define QDEL_LIST(L) if(L) { for(var/I in L) qdel(I); L.Cut(); } +/// Variant on QDEL_LIST that applies the force optional input to the qdel() args. +#define QDEL_LIST_FORCE(L) if(L) { for(var/I in L) qdel(I, force = TRUE); L.Cut(); } #define QDEL_LIST_IN(L, time) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(______qdel_list_wrapper), L), time, TIMER_STOPPABLE) #define QDEL_LIST_ASSOC(L) if(L) { for(var/I in L) { qdel(L[I]); qdel(I); } L.Cut(); } #define QDEL_LIST_ASSOC_VAL(L) if(L) { for(var/I in L) qdel(L[I]); L.Cut(); } diff --git a/code/__DEFINES/skills.dm b/code/__DEFINES/skills.dm index 281158069bf3..63d6df537f18 100644 --- a/code/__DEFINES/skills.dm +++ b/code/__DEFINES/skills.dm @@ -17,11 +17,13 @@ #define SKILL_SUBCATEGORY_MEDICAL "Medical" #define SKILL_SUBCATEGORY_ENGINEERING "Engineering" #define SKILL_SUBCATEGORY_SCIENCE "Science" + #define SKILL_SUBCATEGORY_OPERATIONS "Operations" ///A combat skill is a skill that has a direct effect in combat. These have an increased cost. #define SKILL_CATEGORY_COMBAT "Combat" #define SKILL_SUBCATEGORY_RANGED "Ranged" #define SKILL_SUBCATEGORY_MELEE "Melee" + #define SKILL_SUBCATEGORY_SUPPORT "Support" #define BASE_SKILL_POINTS_COMBAT 4 #define BASE_SKILL_POINTS_OCCUPATIONAL 8 diff --git a/code/__DEFINES/text.dm b/code/__DEFINES/text.dm index c31e45f31288..63bafbaa4c41 100644 --- a/code/__DEFINES/text.dm +++ b/code/__DEFINES/text.dm @@ -49,6 +49,14 @@ /// Max width of chat message in pixels #define CHAT_MESSAGE_WIDTH 112 +// Setting this much higher than 1024 could allow spammers to DOS the server easily. +#define MAX_MESSAGE_LEN 1024 +#define MAX_PAPER_MESSAGE_LEN 3072 +#define MAX_BOOK_MESSAGE_LEN 9216 +#define MAX_LNAME_LEN 64 +#define MAX_NAME_LEN 63 +#define MAX_MESSAGE_CHUNKS 20 + //All < and > characters GLOBAL_DATUM_INIT(angular_brackets, /regex, regex(@"[<>]", "g")) diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 88b996ec376e..803ac7785a32 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -221,3 +221,6 @@ /// traits transparent turf #define TURF_Z_TRANSPARENT_TRAIT "turf_z_transparent" + +/// Unlinks gliding from movement speed, meaning that there will be a delay between movements rather than a single move movement between tiles +#define TRAIT_NO_GLIDE "no_glide" diff --git a/code/__HELPERS/atmospherics.dm b/code/__HELPERS/atmospherics.dm index 7287db40a2da..25abf06bd62c 100644 --- a/code/__HELPERS/atmospherics.dm +++ b/code/__HELPERS/atmospherics.dm @@ -15,7 +15,7 @@ return 0 /proc/atmosanalyzer_scan(var/obj/target, var/datum/gas_mixture/mixture, var/mob/user) - var/pressure = mixture.return_pressure() + var/pressure = XGM_PRESSURE(mixture) var/total_moles = mixture.total_moles var/list/results = list() diff --git a/code/__HELPERS/files.dm b/code/__HELPERS/files.dm index aebdf979c35a..1637f44d6dd7 100644 --- a/code/__HELPERS/files.dm +++ b/code/__HELPERS/files.dm @@ -1,17 +1,3 @@ -//checks if a file exists and contains text -//returns text as a string if these conditions are met -/proc/return_file_text(filename) - if(fexists(filename) == 0) - log_asset("File not found ([filename])") - return - - var/text = file2text(filename) - if(!text) - log_asset("File empty ([filename])") - return - - return text - /proc/get_subfolders(var/root) var/list/folders = list() var/list/contents = flist(root) @@ -24,57 +10,6 @@ return folders -//Sends resource files to client cache -/client/proc/getFiles() - for(var/file in args) - send_rsc(src, file, null) - -/client/proc/browse_files(root="data/logs/", max_iterations=10, list/valid_extensions=list(".txt",".log",".htm", ".json")) - var/path = root - - for(var/i=0, i 0) - to_chat(src, SPAN_WARNING("Error: file_spam_check(): Spam. Please wait [round(time_to_wait/10)] seconds.")) - return 1 - GLOB.fileaccess_timer = world.time + FTPDELAY - return 0 -#undef FTPDELAY - /// Returns the md5 of a file at a given path. /proc/md5filepath(path) . = md5(file(path)) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 29938ce10c49..7dba034d7f61 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -276,7 +276,7 @@ var/cp=0 if(T && istype(T) && T.zone) var/datum/gas_mixture/environment = T.return_air() - cp = environment.return_pressure() + cp = XGM_PRESSURE(environment) else if(istype(T,/turf/simulated)) continue @@ -309,7 +309,7 @@ var/datum/gas_mixture/environment = T.return_air() for(var/i=1;i<=stats.len;i++) if(stats[i] == "pressure") - rstats[i] = environment.return_pressure() + rstats[i] = XGM_PRESSURE(environment) else rstats[i] = environment.vars[stats[i]] else if(istype(T, /turf/simulated)) @@ -319,7 +319,7 @@ var/datum/gas_mixture/environment = T.return_air() for(var/i=1;i<=stats.len;i++) if(stats[i] == "pressure") - rstats[i] = environment.return_pressure() + rstats[i] = XGM_PRESSURE(environment) else rstats[i] = environment.vars[stats[i]] temps[direction] = rstats diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 3e8a2a2473c6..15e9eb2a5c6a 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -111,12 +111,15 @@ GLOBAL_LIST_INIT(headsetlist, list("Nothing", "Headset", "Bowman Headset", "Doub /// Primary Radio Slot loadout choices. GLOBAL_LIST_INIT(primary_radio_slot_choice, list("Left Ear", "Right Ear", "Wrist")) -// Used to track fauna spawners on the phoron deposit away site. +/// Used to track fauna spawners on the phoron deposit away site. GLOBAL_LIST_INIT(fauna_spawners, list()) /// List of spawn points associated with '/obj/effect/organized_fauna_spawner'. It will automatically assign the spawn points in the same Z level as spawner. GLOBAL_LIST_EMPTY(organized_spawn_points) +/// List of mob waypoints for fauna spawners. +GLOBAL_LIST_EMPTY(mob_waypoints) + /// Visual nets. GLOBAL_LIST_EMPTY_TYPED(visual_nets, /datum/visualnet) /// Camera visualnet. diff --git a/code/__HELPERS/maths.dm b/code/__HELPERS/maths.dm index e3bf9e2acb39..3a7ecf9d460c 100644 --- a/code/__HELPERS/maths.dm +++ b/code/__HELPERS/maths.dm @@ -148,15 +148,71 @@ var/a = arccos(x / sqrt(x*x + y*y)) return y >= 0 ? a : -a +// Floating Point Hyperbolic Functions +/** + * Returns the Hyperbolic Sine of a given value. + * See: https://en.wikipedia.org/wiki/Hyperbolic_functions + */ +/proc/fsinh(x) + if (x == 0) + return 0 + + return ((NUM_E ** x) - (NUM_E ** -x)) / 2 + +/** + * Returns the Hyperbolic Cosecant of a given value. + * Will return +INFINITY if x = 0 + * See: https://en.wikipedia.org/wiki/Hyperbolic_functions + */ +/proc/fcsch(x) + if (x == 0) + return INFINITY + + return 1 / fsinh(x) + +/** + * Returns the Hyperbolic Cosine of a given value. + * See: https://en.wikipedia.org/wiki/Hyperbolic_functions + */ +/proc/fcosh(x) + return ((NUM_E ** x) + (NUM_E ** -x)) / 2 + +/** + * Returns the Hyperbolic Secant of a given value. + * See: https://en.wikipedia.org/wiki/Hyperbolic_functions + */ +/proc/fsech(x) + return 1 / fcosh(x) + +/** + * Returns the Hyperbolic Tangent of a given value. + * See: https://en.wikipedia.org/wiki/Hyperbolic_functions + */ +/proc/ftanh(x) + if (x == 0) + return 0 + + var/exTwoP = NUM_E ** (2 * x) + return (exTwoP - 1) / (exTwoP + 1) + +/** + * Returns the Hyperbolic Cotangent of a given value. + * Will return +INFINITY if x = 0 + * See: https://en.wikipedia.org/wiki/Hyperbolic_functions + */ +/proc/fcoth(x) + if (x == 0) + return INFINITY + + var/exTwoP = NUM_E ** (2 * x) + return (exTwoP + 1) / (exTwoP - 1) + /// Value or the next integer in a positive direction: Ceil(-1.5) = -1 , Ceil(1.5) = 2 #define Ceil(value) ( -round(-(value)) ) /proc/Ceiling(x, y=1) return -round(-x / y) * y -/proc/Percent(current_value, max_value, rounding = 1) - return round((current_value / max_value) * 100, rounding) - // Greatest Common Divisor: Euclid's algorithm. /proc/Gcd(a, b) while (1) diff --git a/code/__HELPERS/price.dm b/code/__HELPERS/price.dm new file mode 100644 index 000000000000..3a5331f3bede --- /dev/null +++ b/code/__HELPERS/price.dm @@ -0,0 +1,61 @@ +/// Registers name and prices for the commissary from a paper. +/// First line is ignored, acting as header for name/pricing, mainly for readability. +/// The second line and after are read as the name of the thing and the price of the thing. +/// Example below +/// name,price +/// Candy,2.50 +/// Snack,3.10 +/// Meal,10.00 +/// The above would add 3 items, the candy, snack and meal, with their respective prices. +/// It returns a list containing name and prices +/proc/read_paper_price_list(var/obj/item/paper/R) + var/text = R.info + + // Split on new line + var/list/lines = splittext(text, "
") + var/list/result = list() + + // Skip a header line + for(var/i = 2; i <= lines.len; i++) + var/line = lines[i] + if(!length(line)) + continue + + // Split the name and price + var/list/split_input = splittext(line, ";") + + if(split_input.len < 2) + continue + + var/name = split_input[1] + var/price_text = split_input[2] + + var/price = text2num(price_text) + + // In case of invalid prices for some reason + if(price == 0 && price_text != "0" && price_text != "0.0") + continue + + result += list(list("name" = name, "price" = price)) + + return result + +// Prints the prices from a register/quikpay into a list that can be used for read_paper_price_list() +/proc/print_price_to_paper(var/shop_name, var/list/items, var/paper_loc, mob/user) + if(!items || !items.len) + return FALSE + + var/obj/item/paper/notepad/receipt/R = new(paper_loc) + var/title = "Price List: [shop_name]" + var/text = "name;price
" + + for(var/list/L in items) + var/item_name = L["name"] + var/item_price = L["price"] + text += "[item_name];[round(item_price, 0.01)]
" + + R.set_content(title, text) + + user.put_in_any_hand_if_possible(R) + R.ripped = TRUE + return TRUE diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index 4eb03ef4ce38..530a8c8f81c9 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -664,12 +664,14 @@ t = replacetext(t, "\[logo_golden_small\]", "") t = replacetext(t, "\[logo_pvpolice\]", "") t = replacetext(t, "\[logo_pvpolice_small\]", "") + t = replacetext(t, "\[logo_outereyes\]", "") + t = replacetext(t, "\[logo_outereyes_small\]", "") t = replacetext(t, "\[barcode\]", "") t = replacetext(t, "\[time\]", "[worldtime2text()]") t = replacetext(t, "\[date\]", "[worlddate2text()]") t = replacetext(t, "\[tajtime\]", "[tajaran_time()]") t = replacetext(t, "\[tajdate\]", "[tajaran_full_date()]") - t = replacetext(t, "\[cr\]", "电") + t = replacetext(t, "\[cr\]", "\u7535") t = replacetext(t, "\[editorbr\]", "
") t = replacetext(t, @"[image id=([\w]*?\.[\w]*?)]", "") return t @@ -737,6 +739,8 @@ t = replacetext(t, "", "\[logo_golden\]") t = replacetext(t, "", "\[logo_pvpolice\]") t = replacetext(t, "", "\[logo_pvpolice_small\]") + t = replacetext(t, "", "\[logo_outereyes\]") + t = replacetext(t, "", "\[logo_outereyes_small\]") return t diff --git a/code/__HELPERS/turfs.dm b/code/__HELPERS/turfs.dm index 02f88c6acb1c..f93e5bbdc318 100644 --- a/code/__HELPERS/turfs.dm +++ b/code/__HELPERS/turfs.dm @@ -122,7 +122,7 @@ /proc/is_below_sound_pressure(var/turf/T) var/datum/gas_mixture/environment = T ? T.return_air() : null - var/pressure = environment ? environment.return_pressure() : 0 + var/pressure = SAFE_XGM_PRESSURE(environment) if(pressure < SOUND_MINIMUM_PRESSURE) return TRUE return FALSE @@ -212,7 +212,7 @@ var/turf/T = get_turf(source) if(!istype(T)) return FALSE var/datum/gas_mixture/environment = T.return_air() - var/pressure = (environment)? environment.return_pressure() : 0 + var/pressure = SAFE_XGM_PRESSURE(environment) if(pressure < required_pressure) return FALSE return TRUE diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index f8182112e632..9397bae6809c 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -510,10 +510,6 @@ Turf and target are seperate in case you want to teleport some distance from a t var/y = min(world.maxy, max(1, A.y + dy)) return locate(x,y,A.z) -/// Makes sure MIDDLE is between LOW and HIGH. If not, it adjusts it. Returns the adjusted value. -/proc/between(var/low, var/middle, var/high) - return max(min(middle, high), low) - /// Returns random gauss number /proc/GaussRand(var/sigma) var/x,y,rsq diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 9dc2e47db3bf..7f989b82c03b 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -173,11 +173,12 @@ if(!isturf(loc)) // This is going to stop you from telekinesing from inside a closet, but I don't shed many tears for that return + var/mob/living/simple_animal/simple_mob = istype(src, /mob/living/simple_animal) ? src : null //Atoms on turfs (not on your person) // A is a turf or is on a turf, or in something on a turf (pen in a box); but not something in something on a turf (pen in a box in a backpack) sdepth = A.storage_depth_turf() if(isturf(A) || isturf(A.loc) || (sdepth != -1 && sdepth <= 1)) - if(A.Adjacent(src) || (W && W.attack_can_reach(src, A, W.reach)) ) // see adjacent.dm + if(A.Adjacent(src) || (W && W.attack_can_reach(src, A, W.reach)) || (simple_mob && simple_mob.attack_can_reach(src, A, simple_mob.melee_reach))) // see adjacent.dm if(W) // Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example) var/resolved = W.resolve_attackby(A,src, params) diff --git a/code/_onclick/hud/radial.dm b/code/_onclick/hud/radial.dm index ac60f6cd18dd..bd59f45e1d63 100644 --- a/code/_onclick/hud/radial.dm +++ b/code/_onclick/hud/radial.dm @@ -283,12 +283,13 @@ GLOBAL_LIST_EMPTY(radial_menus) hide() close_button.parent = null menu_holder.vis_contents = null - elements -= src for(var/atom/movable/screen/radial/slice/possibly_our_child in elements) if(possibly_our_child.parent == src) possibly_our_child.parent = null + elements.Cut() + QDEL_NULL(menu_holder) QDEL_NULL(close_button) QDEL_NULL(custom_check_callback) diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 1a4c5a2dac37..d0a1c6916b10 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -26,6 +26,8 @@ /atom/movable/screen/Destroy(force = FALSE) master = null screen_loc = null + if(hud?.mymob?.client) + hud.mymob.client.screen -= src hud = null . = ..() diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index c4c06a0f3bcd..92947a487d25 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -62,7 +62,7 @@ This calls [atom/proc/tool_act], among others. if((user?.a_intent == I_HURT) && !(attacking_item.item_flags & ITEM_FLAG_NO_BLUDGEON)) visible_message(SPAN_DANGER("[src] has been hit by [user] with [attacking_item].")) - var/item_interact_result = src.base_item_interaction(user, src, modifiers) + var/item_interact_result = src.base_item_interaction(user, attacking_item, modifiers) if(item_interact_result & ITEM_INTERACT_SUCCESS) return TRUE if(item_interact_result & ITEM_INTERACT_BLOCKING) @@ -179,6 +179,7 @@ This calls [atom/proc/tool_act], among others. //Called when a weapon is used to make a successful melee attack on a mob. Returns whether damage was dealt. /obj/item/proc/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone) var/power = force + SEND_SIGNAL(user, COMSIG_APPLY_HIT_EFFECT, target, src, &power, &hit_zone) if((user.mutations & HULK)) power *= 1.25 if(user.is_berserk()) diff --git a/code/controllers/subsystems/chemistry.dm b/code/controllers/subsystems/chemistry.dm index fce5cff387e3..0dbae42a610e 100644 --- a/code/controllers/subsystems/chemistry.dm +++ b/code/controllers/subsystems/chemistry.dm @@ -128,7 +128,7 @@ SUBSYSTEM_DEF(chemistry) return try - chemconfig = json_decode(return_file_text("config/secretchem.json")) + chemconfig = json_decode(file2text("config/secretchem.json")) catch(var/exception/e) log_subsystem_chemistry("Warning: Could not load config, as secretchem.json is missing - [e]") return diff --git a/code/controllers/subsystems/discord.dm b/code/controllers/subsystems/discord.dm index ebaa62c1ddbe..7a6a65b706a9 100644 --- a/code/controllers/subsystems/discord.dm +++ b/code/controllers/subsystems/discord.dm @@ -68,7 +68,7 @@ SUBSYSTEM_DEF(discord) PRIVATE_PROC(TRUE) if(!SSdbcore.Connect()) log_subsystem_discord("initialize_webhooks - Unable to connect to db - Loading from File") - var/file = return_file_text("config/webhooks.json") + var/file = file2text("config/webhooks.json") if (file) var/jsonData = json_decode(file) if(!jsonData) diff --git a/code/controllers/subsystems/garbage.dm b/code/controllers/subsystems/garbage.dm index 66f391b95e30..7db7a59c7a10 100644 --- a/code/controllers/subsystems/garbage.dm +++ b/code/controllers/subsystems/garbage.dm @@ -347,6 +347,12 @@ SUBSYSTEM_DEF(garbage) /// Datums passed to this will be given a chance to clean up references to allow the GC to collect them. /proc/qdel(datum/to_delete, force = FALSE) if(!istype(to_delete)) + if(isnull(to_delete)) + return + else if(islist(to_delete)) + stack_trace("Lists should not be directly passed to qdel! You likely want either list.Cut(), QDEL_LIST(list), QDEL_LIST_ASSOC(list), or QDEL_LIST_ASSOC_VAL(list)") + else if(to_delete != world) + stack_trace("Tried to qdel possibly invalid value: [to_delete]") del(to_delete) return diff --git a/code/controllers/subsystems/ghostroles.dm b/code/controllers/subsystems/ghostroles.dm index 96fee090acc3..f1404e5b2379 100644 --- a/code/controllers/subsystems/ghostroles.dm +++ b/code/controllers/subsystems/ghostroles.dm @@ -265,6 +265,7 @@ SUBSYSTEM_DEF(ghostroles) var/datum/ghostspawner/G = spawners[ghost_role_name] if(G && !(spawn_atom in G.spawn_atoms)) G.spawn_atoms += spawn_atom + G.RegisterSignal(spawn_atom, COMSIG_QDELETING, TYPE_PROC_REF(/datum/ghostspawner, spawn_atom_deleted)) if(G.atom_add_message) say_dead_direct("[G.atom_add_message]
Spawn in as it by using the ghost spawner menu in the ghost tab, and try to be good!") diff --git a/code/controllers/subsystems/machinery.dm b/code/controllers/subsystems/machinery.dm index 27f69b8b9524..a34f9d9cab3c 100644 --- a/code/controllers/subsystems/machinery.dm +++ b/code/controllers/subsystems/machinery.dm @@ -151,6 +151,7 @@ SUBSYSTEM_DEF(machinery) if (!resumed) queue = pipenets.Copy() var/datum/pipe_network/network + var/seconds_per_tick = wait * 0.1 for (var/i = queue.len to 1 step -1) network = queue[i] if (QDELETED(network)) @@ -158,7 +159,7 @@ SUBSYSTEM_DEF(machinery) network.datum_flags &= ~DF_ISPROCESSING pipenets -= network continue - network.process(wait * 0.1) + network.process(seconds_per_tick) if (no_mc_tick) CHECK_TICK else if (MC_TICK_CHECK) @@ -169,6 +170,7 @@ SUBSYSTEM_DEF(machinery) if (!resumed) queue = processing.Copy() var/obj/machinery/machine + var/seconds_per_tick = wait * 0.1 for (var/i = queue.len to 1 step -1) machine = queue[i] @@ -196,7 +198,7 @@ SUBSYSTEM_DEF(machinery) continue //process_all was moved here because of calls overhead for no benefits if((machine.processing_flags & MACHINERY_PROCESS_SELF)) - if(machine.process(wait * 0.1) == PROCESS_KILL) + if(machine.process(seconds_per_tick) == PROCESS_KILL) STOP_PROCESSING_MACHINE(machine, MACHINERY_PROCESS_SELF) processing -= machine if (no_mc_tick) diff --git a/code/controllers/subsystems/mob.dm b/code/controllers/subsystems/mob.dm index a289b1e272a7..bcffbe765b55 100644 --- a/code/controllers/subsystems/mob.dm +++ b/code/controllers/subsystems/mob.dm @@ -80,14 +80,14 @@ SUBSYSTEM_DEF(mobs) //of course, if we haven't resumed, this comparison would be useless, hence we skip it var/list/currentrun = resumed ? (src.currentrun &= (GLOB.mob_list + processing)) : src.currentrun - var/seconds_per_tick = (1 SECONDS) / wait + var/seconds_per_tick = wait * 0.1 while(length(currentrun)) var/datum/thing = currentrun[length(currentrun)] currentrun.len-- if(!ismob(thing)) if(!QDELETED(thing)) - if(thing.process(wait, times_fired) == PROCESS_KILL) + if(thing.process(seconds_per_tick, times_fired) == PROCESS_KILL) stop_processing(thing) else processing -= thing diff --git a/code/controllers/subsystems/movement/movement.dm b/code/controllers/subsystems/movement/movement.dm index 425c67a0c474..65e593ed6b11 100644 --- a/code/controllers/subsystems/movement/movement.dm +++ b/code/controllers/subsystems/movement/movement.dm @@ -39,22 +39,22 @@ SUBSYSTEM_DEF(movement) /datum/controller/subsystem/movement/fire(resumed) if(!resumed) canonical_time = world.time - + var/seconds_per_tick = wait * 0.1 for(var/list/bucket_info as anything in sorted_buckets) var/time = bucket_info[MOVEMENT_BUCKET_TIME] if(time > canonical_time || MC_TICK_CHECK) return - pour_bucket(bucket_info) + pour_bucket(bucket_info, seconds_per_tick) /// Processes a bucket of movement loops (This should only ever be called by fire(), it exists to prevent runtime fuckery) -/datum/controller/subsystem/movement/proc/pour_bucket(list/bucket_info) +/datum/controller/subsystem/movement/proc/pour_bucket(list/bucket_info, seconds_per_tick) var/list/processing = bucket_info[MOVEMENT_BUCKET_LIST] // Cache for lookup speed while(processing.len) var/datum/move_loop/loop = processing[processing.len] processing.len-- // No longer queued since we just got removed from the loop loop.queued_time = null - loop.process() //This shouldn't get nulls, if it does, runtime + loop.process(seconds_per_tick) //This shouldn't get nulls, if it does, runtime if(!QDELETED(loop) && loop.status & MOVELOOP_STATUS_QUEUED) //Re-Insert the loop loop.status &= ~MOVELOOP_STATUS_QUEUED loop.timer = world.time + loop.delay diff --git a/code/controllers/subsystems/plants.dm b/code/controllers/subsystems/plants.dm index 26c96b4a3ab2..78747e967e72 100644 --- a/code/controllers/subsystems/plants.dm +++ b/code/controllers/subsystems/plants.dm @@ -106,12 +106,13 @@ SUBSYSTEM_DEF(plants) processing = old var/list/queue = current + var/seconds_per_tick = wait * 0.1 while (queue.len) var/obj/effect/plant/P = queue[queue.len] queue.len-- if (!QDELETED(P)) - P.process() + P.process(seconds_per_tick) if (MC_TICK_CHECK) return diff --git a/code/controllers/subsystems/processing/nanoui.dm b/code/controllers/subsystems/processing/nanoui.dm index b6e6425b82b4..ee84adf78bec 100644 --- a/code/controllers/subsystems/processing/nanoui.dm +++ b/code/controllers/subsystems/processing/nanoui.dm @@ -6,7 +6,7 @@ PROCESSING_SUBSYSTEM_DEF(nanoui) stat_tag = "A" // NanoUI stuff. - var/list/open_uis = list() + var/list/open_nanouis = list() /** * Get an open /nanoui ui for the current user, src_object and ui_key and try to update it with data @@ -43,10 +43,10 @@ PROCESSING_SUBSYSTEM_DEF(nanoui) */ /datum/controller/subsystem/processing/nanoui/proc/get_open_ui(mob/user, src_object, ui_key) var/src_object_key = REF(src_object) - if (!LAZYLEN(open_uis[src_object_key]) || !LAZYLEN(open_uis[src_object_key][ui_key])) + if (!LAZYLEN(open_nanouis[src_object_key]) || !LAZYLEN(open_nanouis[src_object_key][ui_key])) return null - for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key]) + for (var/datum/nanoui/ui in open_nanouis[src_object_key][ui_key]) if (ui.user == user) return ui @@ -62,11 +62,11 @@ PROCESSING_SUBSYSTEM_DEF(nanoui) */ /datum/controller/subsystem/processing/nanoui/proc/update_uis(src_object) var/src_object_key = REF(src_object) - if (!LAZYLEN(open_uis[src_object_key])) + if (!LAZYLEN(open_nanouis[src_object_key])) return 0 . = 0 - var/list/obj_uis = open_uis[src_object_key] + var/list/obj_uis = open_nanouis[src_object_key] for (var/ui_key in obj_uis) for (var/thing in obj_uis[ui_key]) var/datum/nanoui/ui = thing @@ -83,11 +83,11 @@ PROCESSING_SUBSYSTEM_DEF(nanoui) */ /datum/controller/subsystem/processing/nanoui/proc/close_uis(src_object) var/src_object_key = REF(src_object) - if (!open_uis[src_object_key] || !islist(open_uis[src_object_key])) + if (!open_nanouis[src_object_key] || !islist(open_nanouis[src_object_key])) return 0 . = 0 - var/list/obj_uis = open_uis[src_object_key] + var/list/obj_uis = open_nanouis[src_object_key] for (var/ui_key in obj_uis) for (var/thing in obj_uis[ui_key]) var/datum/nanoui/ui = thing @@ -105,27 +105,27 @@ PROCESSING_SUBSYSTEM_DEF(nanoui) * Returns the number of UIs updated */ /datum/controller/subsystem/processing/nanoui/proc/update_user_uis(mob/user, src_object, ui_key) - if (!LAZYLEN(user.open_uis)) + if (!LAZYLEN(user.open_nanouis)) return 0 // has no open uis . = 0 - for (var/thing in user.open_uis) + for (var/thing in user.open_nanouis) var/datum/nanoui/ui = thing if (NULL_OR_EQUAL(src_object, ui.src_object) && NULL_OR_EQUAL(ui_key, ui.ui_key)) ui.process(1) .++ /datum/controller/subsystem/processing/nanoui/proc/close_user_uis(mob/user, src_object, ui_key) - if (!LAZYLEN(user.open_uis)) + if (!LAZYLEN(user.open_nanouis)) return 0 - for (var/thing in user.open_uis) + for (var/thing in user.open_nanouis) var/datum/nanoui/ui = thing if (NULL_OR_EQUAL(src_object, ui.src_object) && NULL_OR_EQUAL(ui_key, ui.ui_key)) ui.close() .++ - //testing("nanomanager/close_user_uis mob [user.name] closed [open_uis.len] of [.] uis") + //testing("nanomanager/close_user_uis mob [user.name] closed [open_nanouis.len] of [.] uis") /** * Add a /nanoui ui to the list of open uis @@ -135,12 +135,12 @@ PROCESSING_SUBSYSTEM_DEF(nanoui) */ /datum/controller/subsystem/processing/nanoui/proc/ui_opened(datum/nanoui/ui) var/src_object_key = REF(ui.src_object) - LAZYINITLIST(open_uis[src_object_key]) + LAZYINITLIST(open_nanouis[src_object_key]) - LAZYADD(ui.user.open_uis, ui) - LAZYADD(open_uis[src_object_key][ui.ui_key], ui) + LAZYADD(ui.user.open_nanouis, ui) + LAZYADD(open_nanouis[src_object_key][ui.ui_key], ui) START_PROCESSING(SSnanoui, ui) - //testing("nanomanager/ui_opened mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]") + //testing("nanomanager/ui_opened mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_nanouis [ui.user.open_nanouis.len] | uis [uis.len] | processing_uis [processing_uis.len]") /** * Remove a /nanoui ui from the list of open uis @@ -153,14 +153,14 @@ PROCESSING_SUBSYSTEM_DEF(nanoui) /datum/controller/subsystem/processing/nanoui/proc/ui_closed(datum/nanoui/ui) var/src_object_key = REF(ui.src_object) var/ui_key = ui.ui_key - var/list/obj_uis = open_uis[src_object_key] + var/list/obj_uis = open_nanouis[src_object_key] if (!LAZYLEN(obj_uis) || !obj_uis[ui_key]) return 0 // Wasn't open. STOP_PROCESSING(SSnanoui, ui) if(ui.user) // Sanity check in case a user has been deleted (say a blown up borg watching the alarm interface) - LAZYREMOVE(ui.user.open_uis, ui) + LAZYREMOVE(ui.user.open_nanouis, ui) obj_uis[ui_key] -= ui @@ -168,9 +168,9 @@ PROCESSING_SUBSYSTEM_DEF(nanoui) obj_uis -= ui_key if (!LAZYLEN(obj_uis)) - open_uis -= src_object_key + open_nanouis -= src_object_key - //testing("nanomanager/ui_closed mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]") + //testing("nanomanager/ui_closed mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_nanouis [ui.user.open_nanouis.len] | uis [uis.len] | processing_uis [processing_uis.len]") return 1 @@ -192,16 +192,16 @@ PROCESSING_SUBSYSTEM_DEF(nanoui) */ /datum/controller/subsystem/processing/nanoui/proc/user_transferred(mob/oldMob, mob/newMob) //testing("nanomanager/user_transferred from mob [oldMob.name] to mob [newMob.name]") - if (!oldMob || !LAZYLEN(oldMob.open_uis) || !LAZYLEN(open_uis)) + if (!oldMob || !LAZYLEN(oldMob.open_nanouis) || !LAZYLEN(open_nanouis)) //testing("nanomanager/user_transferred mob [oldMob.name] has no open uis") return 0 // has no open uis - for (var/thing in oldMob.open_uis) + for (var/thing in oldMob.open_nanouis) var/datum/nanoui/ui = thing ui.user = newMob - LAZYADD(newMob.open_uis, ui) + LAZYADD(newMob.open_nanouis, ui) - oldMob.open_uis = null + oldMob.open_nanouis = null return 1 // success diff --git a/code/controllers/subsystems/processing/obj_tab_items.dm b/code/controllers/subsystems/processing/obj_tab_items.dm index 48a986a7cdbd..d9a70c9dc7aa 100644 --- a/code/controllers/subsystems/processing/obj_tab_items.dm +++ b/code/controllers/subsystems/processing/obj_tab_items.dm @@ -12,12 +12,13 @@ PROCESSING_SUBSYSTEM_DEF(obj_tab_items) currentrun = processing.Copy() //cache for sanic speed (lists are references anyways) var/list/current_run = currentrun + var/seconds_per_tick = wait * 0.1 while(current_run.len) var/datum/thing = current_run[current_run.len] if(QDELETED(thing)) processing -= thing - else if(thing.process(wait * 0.1) == PROCESS_KILL) + else if(thing.process(seconds_per_tick) == PROCESS_KILL) // fully stop so that a future START_PROCESSING will work STOP_PROCESSING(src, thing) if (MC_TICK_CHECK) diff --git a/code/controllers/subsystems/processing/processing.dm b/code/controllers/subsystems/processing/processing.dm index eccfa750ad28..68c9d8b56e59 100644 --- a/code/controllers/subsystems/processing/processing.dm +++ b/code/controllers/subsystems/processing/processing.dm @@ -19,13 +19,13 @@ SUBSYSTEM_DEF(processing) currentrun = processing.Copy() //cache for sanic speed (lists are references anyways) var/list/current_run = currentrun - + var/seconds_per_tick = wait * 0.1 while(current_run.len) var/datum/thing = current_run[current_run.len] current_run.len-- if(QDELETED(thing)) processing -= thing - else if(thing.process(wait * 0.1) == PROCESS_KILL) + else if(thing.process(seconds_per_tick) == PROCESS_KILL) // fully stop so that a future START_PROCESSING will work STOP_PROCESSING(src, thing) if (MC_TICK_CHECK) diff --git a/code/controllers/subsystems/processing/tgui.dm b/code/controllers/subsystems/processing/tgui.dm index 70b19c9a8cb4..77186dbf75b6 100644 --- a/code/controllers/subsystems/processing/tgui.dm +++ b/code/controllers/subsystems/processing/tgui.dm @@ -19,10 +19,8 @@ PROCESSING_SUBSYSTEM_DEF(tgui) /// A list of UIs scheduled to process var/list/current_run = list() - /// A list of open UIs - var/list/open_uis = list() - /// A list of open UIs, grouped by src_object. - var/list/open_uis_by_src = list() + /// A list of all open UIs + var/list/all_uis = list() /// The HTML base used for all UIs. var/basehtml @@ -58,23 +56,24 @@ PROCESSING_SUBSYSTEM_DEF(tgui) close_all_uis() /datum/controller/subsystem/processing/tgui/stat_entry(msg) - msg = "P:[length(open_uis)]" + msg = "P:[length(all_uis)]" return ..() /datum/controller/subsystem/processing/tgui/fire(resumed = FALSE) CAN_BE_REDEFINED(TRUE) if(!resumed) - src.current_run = open_uis.Copy() + src.current_run = all_uis.Copy() // Cache for sanic speed (lists are references anyways) var/list/current_run = src.current_run + var/seconds_per_tick = wait * 0.1 while(current_run.len) var/datum/tgui/ui = current_run[current_run.len] current_run.len-- // TODO: Move user/src_object check to process() if(ui?.user && ui.src_object) - ui.process(wait * 0.1) + ui.process(seconds_per_tick) else - open_uis.Remove(ui) + ui.close(0) if(MC_TICK_CHECK) return @@ -193,11 +192,9 @@ PROCESSING_SUBSYSTEM_DEF(tgui) * return datum/tgui The found UI. */ /datum/controller/subsystem/processing/tgui/proc/get_open_ui(mob/user, datum/src_object) - var/key = text_ref(src_object) - // No UIs opened for this src_object - if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list)) + if(!LAZYLEN(src_object?.open_uis)) return null - for(var/datum/tgui/ui in open_uis_by_src[key]) + for(var/datum/tgui/ui in src_object.open_uis) // Make sure we have the right user if(ui.user == user) return ui @@ -213,15 +210,14 @@ PROCESSING_SUBSYSTEM_DEF(tgui) * return int The number of UIs updated. */ /datum/controller/subsystem/processing/tgui/proc/update_uis(datum/src_object) + if(!LAZYLEN(src_object?.open_uis)) + return 0 var/count = 0 - var/key = text_ref(src_object) - // No UIs opened for this src_object - if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list)) - return count - for(var/datum/tgui/ui in open_uis_by_src[key]) + var/seconds_per_tick = wait * 0.1 + for(var/datum/tgui/ui in src_object.open_uis) // Check if UI is valid. if(ui?.src_object && ui.user && ui.src_object.ui_host(ui.user)) - ui.process(wait * 0.1, force = 1) + INVOKE_ASYNC(ui, TYPE_PROC_REF(/datum/tgui, process), seconds_per_tick, TRUE) count++ return count @@ -235,12 +231,11 @@ PROCESSING_SUBSYSTEM_DEF(tgui) * return int The number of UIs closed. */ /datum/controller/subsystem/processing/tgui/proc/close_uis(datum/src_object) - var/count = 0 - var/key = text_ref(src_object) // No UIs opened for this src_object - if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list)) - return count - for(var/datum/tgui/ui in open_uis_by_src[key]) + if(!LAZYLEN(src_object?.open_uis)) + return 0 + var/count = 0 + for(var/datum/tgui/ui in src_object.open_uis) // Check if UI is valid. if(ui?.src_object && ui.user && ui.src_object.ui_host(ui.user)) ui.close() @@ -256,12 +251,11 @@ PROCESSING_SUBSYSTEM_DEF(tgui) */ /datum/controller/subsystem/processing/tgui/proc/close_all_uis() var/count = 0 - for(var/key in open_uis_by_src) - for(var/datum/tgui/ui in open_uis_by_src[key]) - // Check if UI is valid. - if(ui?.src_object && ui.user && ui.src_object.ui_host(ui.user)) - ui.close() - count++ + for(var/datum/tgui/ui in all_uis) + // Check if UI is valid. + if(ui?.src_object && ui.user && ui.src_object.ui_host(ui.user)) + ui.close() + count++ return count /** @@ -278,9 +272,10 @@ PROCESSING_SUBSYSTEM_DEF(tgui) var/count = 0 if(length(user?.tgui_open_uis) == 0) return count + var/seconds_per_tick = wait * 0.1 for(var/datum/tgui/ui in user.tgui_open_uis) if(isnull(src_object) || ui.src_object == src_object) - ui.process(wait * 0.1, force = 1) + ui.process(seconds_per_tick, force = 1) count++ return count @@ -312,13 +307,9 @@ PROCESSING_SUBSYSTEM_DEF(tgui) * required ui datum/tgui The UI to be added. */ /datum/controller/subsystem/processing/tgui/proc/on_open(datum/tgui/ui) - var/key = text_ref(ui.src_object) - if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list)) - open_uis_by_src[key] = list() - ui.user.tgui_open_uis |= ui - var/list/uis = open_uis_by_src[key] - uis |= ui - open_uis |= ui + ui.user?.tgui_open_uis |= ui + LAZYOR(ui.src_object.open_uis, ui) + all_uis |= ui /** * private @@ -330,19 +321,14 @@ PROCESSING_SUBSYSTEM_DEF(tgui) * return bool If the UI was removed or not. */ /datum/controller/subsystem/processing/tgui/proc/on_close(datum/tgui/ui) - var/key = text_ref(ui.src_object) - if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list)) - return FALSE // Remove it from the list of processing UIs. - open_uis.Remove(ui) + all_uis -= ui + current_run -= ui // If the user exists, remove it from them too. if(ui.user) - ui.user.tgui_open_uis.Remove(ui) - ui.user.unset_machine() - var/list/uis = open_uis_by_src[key] - uis.Remove(ui) - if(length(uis) == 0) - open_uis_by_src.Remove(key) + ui.user.tgui_open_uis -= ui + if(ui.src_object) + LAZYREMOVE(ui.src_object.open_uis, ui) return TRUE /** @@ -377,7 +363,7 @@ PROCESSING_SUBSYSTEM_DEF(tgui) for(var/datum/tgui/ui in source.tgui_open_uis) // Inform the UIs of their new owner. ui.user = target - target.tgui_open_uis.Add(ui) + target.tgui_open_uis += ui // Clear the old list. source.tgui_open_uis.Cut() return TRUE diff --git a/code/controllers/subsystems/records.dm b/code/controllers/subsystems/records.dm index ffbdf5d1ea33..07679c4e1226 100644 --- a/code/controllers/subsystems/records.dm +++ b/code/controllers/subsystems/records.dm @@ -233,7 +233,7 @@ SUBSYSTEM_DEF(records) var/list/data = list() data["manifest"] = SSrecords.get_manifest_list() data["allow_follow"] = isghost(user) - data["show_ooc_roles"] = isabstractmob(usr) + data["show_ooc_roles"] = isabstractmob(user) && !isEye(user) return data /datum/controller/subsystem/records/proc/open_manifest_tgui(mob/user, datum/tgui/ui) @@ -279,6 +279,9 @@ SUBSYSTEM_DEF(records) /* ----- START OF CASE FOR CREW ----- */ // Start with the "Crew", which are all of the IC manifest members. for(var/datum/record/general/general_record in records) + if (!general_record.name || !general_record.rank) + continue + var/datum/job/job = SSjobs.GetJob(make_list_rank(general_record.real_rank)) var/list/departments = /* Jobs can be in more than one department. So we fact check that the departments are real. */\ (istype(job) && job.departments.len > 0 && all_in_list(job.departments, manifest))\ diff --git a/code/controllers/subsystems/skills.dm b/code/controllers/subsystems/skills.dm index b15d4e9936e1..7f4426c7d848 100644 --- a/code/controllers/subsystems/skills.dm +++ b/code/controllers/subsystems/skills.dm @@ -4,13 +4,9 @@ SUBSYSTEM_DEF(skills) /// This is essentially the list we use to read skills in the character setup. var/list/skill_tree = list() - /// A map of all the skill levels to their definition. - var/list/skill_level_map = list( - "Unfamiliar" = "You don't know anything about this subject.", - "Familiar" = "You're familiar with this subject, either by reading into it or by doing some courses.", - "Trained" = "You've been formally trained in this subject. Typically, this is the minimum level for a job.", - "Professional" = "You have a lot of training and a good amount of experience in this subject." - ) + + /// The set of all skills that are "forced" in order to guarantee necessary components are applied. + var/list/required_skills = list() /datum/controller/subsystem/skills/Initialize() // Initialize the skill category lists first. @@ -24,6 +20,8 @@ SUBSYSTEM_DEF(skills) // Next, we add the empty subcategory lists if they're not present. At this point, the tree would look like "Combat" -> "Melee" -> empty list // After that's done, if our skill is not present, add it to the empty list of the subcategory. for(var/singleton/skill/skill in GET_SINGLETON_SUBTYPE_LIST(/singleton/skill)) + if (skill.required) + required_skills += skill.type var/singleton/skill_category/skill_category = GET_SINGLETON(skill.category) if(!(skill.subcategory in skill_tree[skill_category])) skill_tree[skill_category] |= skill.subcategory diff --git a/code/controllers/subsystems/spatial_gridmap.dm b/code/controllers/subsystems/spatial_gridmap.dm index b6216dd042e5..3d221e7288f2 100644 --- a/code/controllers/subsystems/spatial_gridmap.dm +++ b/code/controllers/subsystems/spatial_gridmap.dm @@ -240,7 +240,7 @@ SUBSYSTEM_DEF(spatial_grid) . = list() //technically THIS list only contains lists, but inside those lists are grid cell datums and we can go without a SINGLE var init if we do this - var/list/datum/spatial_grid_cell/grid_level = grids_by_z_level[center_turf.z] + var/list/list/datum/spatial_grid_cell/grid_level = grids_by_z_level[center_turf.z] switch(type) if(SPATIAL_GRID_CONTENTS_TYPE_CLIENTS) diff --git a/code/controllers/subsystems/ticker.dm b/code/controllers/subsystems/ticker.dm index ef51776ec84d..a8ec8ef5f5ab 100644 --- a/code/controllers/subsystems/ticker.dm +++ b/code/controllers/subsystems/ticker.dm @@ -560,22 +560,20 @@ SUBSYSTEM_DEF(ticker) fail_reasons += "Too many players, less than [mode.max_players] antagonist(s) needed" if(can_start != GAME_FAILURE_NONE) - to_world("Unable to start the game mode, due to lack of available antagonists. [english_list(fail_reasons,"No reason specified",". ",". ")]") + message_admins("Unable to start the game mode, due to lack of available antagonists. [english_list(fail_reasons,"No reason specified",". ",". ")]") current_state = GAME_STATE_PREGAME mode.fail_setup() mode = null SSjobs.ResetOccupations() if(GLOB.master_mode in list(ROUNDTYPE_STR_RANDOM, ROUNDTYPE_STR_SECRET, ROUNDTYPE_STR_MIXED_SECRET)) - to_world("Reselecting gamemode...") return SETUP_REATTEMPT else - to_world("Reverting to pre-game lobby.") return SETUP_REVOTE var/starttime = REALTIMEOFDAY if(hide_mode) - to_world("The current game mode is - [hide_mode == ROUNDTYPE_SECRET ? "Secret" : "Mixed Secret"]!") + to_world("The current game mode is [hide_mode == ROUNDTYPE_SECRET ? "Secret" : "Mixed Secret"]!") if(runnable_modes.len) var/list/tmpmodes = new for (var/datum/game_mode/M in runnable_modes) diff --git a/code/controllers/subsystems/time_track.dm b/code/controllers/subsystems/time_track.dm new file mode 100644 index 000000000000..cbd75f9db05d --- /dev/null +++ b/code/controllers/subsystems/time_track.dm @@ -0,0 +1,40 @@ +SUBSYSTEM_DEF(time_track) + name = "Time Tracking" + wait = 100 + runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT + + var/time_dilation_current = 0 + + var/time_dilation_avg_fast = 0 + var/time_dilation_avg = 0 + var/time_dilation_avg_slow = 0 + + var/first_run = TRUE + + var/last_tick_realtime = 0 + var/last_tick_byond_time = 0 + var/last_tick_tickcount = 0 + +/datum/controller/subsystem/time_track/Initialize() + return SS_INIT_SUCCESS + +/datum/controller/subsystem/time_track/fire() + + var/current_realtime = REALTIMEOFDAY + var/current_byondtime = world.time + var/current_tickcount = world.time/world.tick_lag + + if (!first_run) + var/tick_drift = max(0, (((current_realtime - last_tick_realtime) - (current_byondtime - last_tick_byond_time)) / world.tick_lag)) + + time_dilation_current = tick_drift / (current_tickcount - last_tick_tickcount) * 100 + + time_dilation_avg_fast = MC_AVERAGE_FAST(time_dilation_avg_fast, time_dilation_current) + time_dilation_avg = MC_AVERAGE(time_dilation_avg, time_dilation_avg_fast) + time_dilation_avg_slow = MC_AVERAGE_SLOW(time_dilation_avg_slow, time_dilation_avg) + GLOB.glide_size_multiplier = (current_byondtime - last_tick_byond_time) / (current_realtime - last_tick_realtime) + else + first_run = FALSE + last_tick_realtime = current_realtime + last_tick_byond_time = current_byondtime + last_tick_tickcount = current_tickcount diff --git a/code/controllers/subsystems/turf_fire.dm b/code/controllers/subsystems/turf_fire.dm index 9732d2f94847..d7a73720bb3f 100644 --- a/code/controllers/subsystems/turf_fire.dm +++ b/code/controllers/subsystems/turf_fire.dm @@ -5,8 +5,8 @@ SUBSYSTEM_DEF(turf_fire) flags = SS_NO_INIT var/list/fires = list() -/datum/controller/subsystem/turf_fire/fire() - var/seconds_per_tick = (wait * 0.1) // Equivalent to wait / (1 SECOND) but micro-optimized +/datum/controller/subsystem/turf_fire/fire(resumed) + var/seconds_per_tick = wait * 0.1 for(var/obj/turf_fire/fire as anything in fires) fire.process(seconds_per_tick) if(MC_TICK_CHECK) diff --git a/code/controllers/subsystems/zcopy.dm b/code/controllers/subsystems/zcopy.dm index 11cc4d573286..4a17eb3cecf3 100644 --- a/code/controllers/subsystems/zcopy.dm +++ b/code/controllers/subsystems/zcopy.dm @@ -273,6 +273,9 @@ SUBSYSTEM_DEF(zcopy) // Don't queue deleted stuff, stuff that's not visible, blacklisted stuff, or stuff that's centered on another tile but intersects ours. continue + if (QDELETED(object.bound_overlay)) + object.bound_overlay = null + if (!object.bound_overlay) // Generate a new overlay if the atom doesn't already have one. object.bound_overlay = new(T) object.bound_overlay.associated_atom = object diff --git a/code/datums/browser.dm b/code/datums/browser.dm index c9d277230eb1..363da0978940 100644 --- a/code/datums/browser.dm +++ b/code/datums/browser.dm @@ -107,7 +107,7 @@ - + [head_content] diff --git a/code/datums/cargo.dm b/code/datums/cargo.dm index 31e055de4a62..4766e19d694e 100644 --- a/code/datums/cargo.dm +++ b/code/datums/cargo.dm @@ -272,10 +272,10 @@ order_data += "Order Fees:
" order_data += "
    " for(var/item in get_item_list()) - order_data += "
  • [item["name"]]: [item["price"]]
  • " - order_data += "
  • Crate Fee: [SScargo.get_cratefee()]
  • " - order_data += "
  • Handling Fee: [SScargo.get_handlingfee()]
  • " - order_data += "
  • Supplier Fee: [get_shipment_cost()]
  • " + order_data += "
  • [item["name"]]: [item["price"]]电
  • " + order_data += "
  • Crate Fee: [SScargo.get_cratefee()]电
  • " + order_data += "
  • Handling Fee: [SScargo.get_handlingfee()]电
  • " + order_data += "
  • Supplier Fee: [get_shipment_cost()]电
  • " order_data += "
" return order_data.Join("") diff --git a/code/datums/components/eye/_eye.dm b/code/datums/components/eye/_eye.dm index 1847caf1c7b7..17d73539fdd1 100644 --- a/code/datums/components/eye/_eye.dm +++ b/code/datums/components/eye/_eye.dm @@ -46,7 +46,7 @@ RegisterSignal(component_eye, COMSIG_QDELETING, PROC_REF(unlook)) RegisterSignal(current_looker, COMSIG_MOB_LOGOUT, PROC_REF(unlook)) - RegisterSignal(current_looker, COMSIG_GLOB_MOB_DEATH, PROC_REF(unlook)) + RegisterSignal(SSdcs, COMSIG_GLOB_MOB_DEATH, PROC_REF(unlook)) return TRUE @@ -63,7 +63,7 @@ UnregisterSignal(current_looker, COMSIG_MOVABLE_MOVED) UnregisterSignal(current_looker, COMSIG_QDELETING) UnregisterSignal(current_looker, COMSIG_MOB_LOGOUT) - UnregisterSignal(current_looker, COMSIG_GLOB_MOB_DEATH) + UnregisterSignal(SSdcs, COMSIG_GLOB_MOB_DEATH) if(current_looker.client) current_looker.client.eye = current_looker current_looker.eyeobj = null diff --git a/code/datums/components/morale/moodlets.dm b/code/datums/components/morale/moodlets.dm new file mode 100644 index 000000000000..749470fdb28e --- /dev/null +++ b/code/datums/components/morale/moodlets.dm @@ -0,0 +1,83 @@ +/** + * Container for a single moodlet to be associated with a Morale Component. + * Only one of each type of moodlet is allowed to exist in a mood component at a time. + * If you're making a new source of moodlets, add a new child of this type. + */ +ABSTRACT_TYPE(/datum/moodlet) + /** + * How much this moodlet modifies its owner's morale by. + * This is simple summed exactly once when the moodlet is created. + * If anything needs to Set the value of a moodlet, they have to do so by calling set_moodlet(). + * You may only Get this value by calling get_morale_modifier(). + * + * This is similar to { get; private set; }. Under no circumstances are outside functions ever allowed to directly change this var because other vars depend on it. + * But there are public procs available to interact with it which obey its own internal rules. + */ + VAR_PRIVATE/morale_modifier = 0.0 // Positive and negative floating points are allowed. + + /** + * + */ + var/moodlet_descriptor = "It's a moodlet!" + + /** + * How long this moodlet will last if not refreshed. For Aurora's purposes, moodlets are targeted as having "Small effect, extreme duration". + * This is by design to encourage players to "Visit the chef at least once a round to do a little RP", while avoiding having moodlet collection interrupt the flow of expeditions. + */ + var/duration = 2.0 HOURS + + /** + * The target time (in real life seconds) that the moodlet will self-terminate on. + * This is set automatically during the New() creation of moodlets. + * This can be updated by calling refresh_moodlet() to reset the time to die. + */ + var/time_to_die = 0.0 + + /** + * Moodlets should always have an associated morale component, but the component owns the moodlets, not the other way around. + * For the convenience of refreshing individual moodlets, they hold a weakref to their owner. + * This is set to private here so that we can assert that it will always be a morale component. + */ + VAR_PRIVATE/datum/weakref/morale_component + +/datum/moodlet/New(datum/component/morale/_morale_component, set_points) + time_to_die = duration + REALTIMEOFDAY + morale_component = WEAKREF(_morale_component) + if (set_points) morale_modifier = set_points + _morale_component.add_morale_points(morale_modifier) + +/datum/moodlet/Destroy(force) + if (force) + // This will be forced when a Morale Component is deleted directly, as it QDEL_NULL_LIST's its own moodlets. + return ..() + + // Else if the moodlet is deleted directly rather than its parent. + var/datum/component/morale/parent = morale_component.resolve() + if (!parent || !parent.moodlets[src]) + return ..() + + // Clean the effects of this moodlet from the parent. + parent.moodlets -= src + parent.add_morale_points(-morale_modifier) + return ..() + +/datum/moodlet/proc/get_morale_modifier() + return morale_modifier + +/datum/moodlet/proc/set_moodlet(new_modifier) + // We can skip the istype() in this case since the held weakref is asserted by VAR_PRIVATE to always be a morale component. + var/datum/component/morale/possible_morale = morale_component.resolve() + if (!possible_morale && !QDELING(src)) + // Owner didn't exist, the moodlet has no need to exist either. + qdel(src) + return + + // Add the difference between the new modifier and the old morale points. + // This should come out to no change if old and new are the same. + possible_morale.add_morale_points(new_modifier - morale_modifier) + + // Then set the current morale points to the new ones. + morale_modifier = new_modifier + +/datum/moodlet/proc/refresh_moodlet() + time_to_die = REALTIMEOFDAY + duration diff --git a/code/datums/components/morale/morale_component.dm b/code/datums/components/morale/morale_component.dm new file mode 100644 index 000000000000..372a48706bc2 --- /dev/null +++ b/code/datums/components/morale/morale_component.dm @@ -0,0 +1,230 @@ +/** + * Having a Morale Component allows a character to receive and benefit from Moodlets, providing a variety of buffs(or debuffs) depending on the total morale points. + * This component acts as both proof a mob can be affected by morale, as well as a method of tracking the effects of morale on each system. + */ +/datum/component/morale + + /** + * The set of all moodlets associated with this Morale Component. These are also tightly controlled in their initialization, but are not private. + * That doesn't mean you need to be setting them anywhere other than in moodlets.dm. + * load_moodlet() is your best bet for "Add or Get" a moodlet, and is 100% of the time what you want to use if you're trying to make sure someone has a moodlet. + */ + var/list/datum/moodlet/moodlets = list() + + /** + * The current sum total of morale_points. This var is intentionally private because it is self-managed by the component, and should never be set directly. + * If you need the contents of this var outside of the component, you MUST use get_morale_points(). + */ + VAR_PRIVATE/morale_points = 0.0 // Positive and negative floating points are allowed. + + /** + * The current "Morale Ratio" calculated in advance as the Hyperbolic Tangent of morale_points. This var is self-managed by the component and should never be set directly. + * This gets updated whenever morale_points are changed, and is used by the Morale Component to handle fast calculations of its various effects. + * If you need the contents of this var outside of the component, you MUST use get_morale_ratio(). + * + * morale_ratio is NEVER to be set by anything outside of the component. + */ + VAR_PRIVATE/morale_ratio = 0.0 // Positive and negative floating points are allowed. + + /** + * The "B" constant in the equation for y = Atanh(Bx + C). + * This constant is not arbitrary, it was carefully selected such that the equation will give "75% of its effect" at 50 morale points, and "96% of its effect" at 100 morale. + * This allows for there to be an effect of diminishing returns for chasing ever increasingly more morale points, while front-loading the bulk of the effects at a specific amount of moodlets. + * Since the effects of morale are a "Logistic Curve", "100% of the morale effect" is only ever obtained at +INFINITY. + * This also goes for the opposite direction, morale penalties max out only at -INFINITY points, but get to "75% of the penalty effect" at -50 points. + * + * The actual "Effects" of morale are to be per-signal, and are defined by the A value in y = Atanh(Bx + C) + * This is private for a reason, if you need to change it, do so by using set_beta_value(), which will also make the component recalculate its morale ratio. + */ + VAR_PRIVATE/beta_value = 0.0195 + + // By default, all of these values are roughly equivalent to "up to half" a skill rank. + /// How much this morale component contributes to signal based unarmed values. + var/unarmed_chance_contribution = 2.5 + + /// How many effective ranks of unarmed combat skill this morale component can contribute + var/unarmed_rank_contribution = 0.5 + + /** + * The maximum possible panic chance from negative morale point sums. + * Since negative moodlets are unique to psychic damage, the effects of psychically induced panic are uniquely stronger than simply being unskilled. + */ + var/panic_chance_ceiling = 10 + +/datum/component/morale/proc/get_morale_ratio() + return morale_ratio + +/datum/component/morale/proc/get_morale_points() + return morale_points + +/datum/component/morale/proc/add_morale_points(input) + morale_points += input + morale_ratio = ftanh(beta_value * morale_points) + +/datum/component/morale/proc/set_beta_value(input) + beta_value = input + morale_ratio = ftanh(beta_value * morale_points) + +/** + * Your one-stop-shop for making moodlets. This proc returns the pre-existing moodlet of a given type. + * If it doesn't already exist, then one will be created. + */ +/datum/component/morale/proc/load_moodlet(datum/moodlet/moodlet_type, set_points) + RETURN_TYPE(moodlet_type) + var/datum/moodlet/loaded_moodlet = moodlets[moodlet_type] + if (!loaded_moodlet) + loaded_moodlet = new moodlet_type(src, set_points) + moodlets.Add(loaded_moodlet) + return loaded_moodlet + + if (set_points) loaded_moodlet.set_moodlet(set_points) + return loaded_moodlet + +/datum/component/morale/Initialize() + . = ..() + if (!parent) + return + + // Behold my wall of RegisterSignal() + RegisterSignal(parent, COMSIG_APPLY_HIT_EFFECT, PROC_REF(modify_hit_effect), override = TRUE) + RegisterSignal(parent, COMSIG_BEFORE_GUN_FIRE, PROC_REF(handle_accuracy), override = TRUE) + RegisterSignal(parent, COMSIG_GUN_TOGGLE_FIRING_MODE, PROC_REF(safety_fumble), override = TRUE) + RegisterSignal(parent, COMSIG_UNARMED_HARM_ATTACKER, PROC_REF(handle_harm_attack), override = TRUE) + RegisterSignal(parent, COMSIG_UNARMED_HARM_DEFENDER, PROC_REF(handle_harm_defend), override = TRUE) + RegisterSignal(parent, COMSIG_UNARMED_DISARM_ATTACKER, PROC_REF(handle_disarm_attack), override = TRUE) + RegisterSignal(parent, COMSIG_UNARMED_DISARM_DEFENDER, PROC_REF(handle_disarm_defend), override = TRUE) + RegisterSignal(parent, COMSIG_MECH_MOVE_WASD, PROC_REF(handle_user_move), override = TRUE) + RegisterSignal(parent, COMSIG_MECH_MOVE_STRAFE, PROC_REF(handle_user_strafe), override = TRUE) + RegisterSignal(parent, COMSIG_MECH_TOGGLE_POWER, PROC_REF(handle_mech_toggle_power), override = TRUE) + +/datum/component/morale/Destroy() + QDEL_LIST_FORCE(moodlets) + if (!parent) + return ..() + + // Behold my wall of UnregisterSignal() + UnregisterSignal(parent, COMSIG_APPLY_HIT_EFFECT) + UnregisterSignal(parent, COMSIG_BEFORE_GUN_FIRE) + UnregisterSignal(parent, COMSIG_GUN_TOGGLE_FIRING_MODE) + UnregisterSignal(parent, COMSIG_UNARMED_HARM_ATTACKER) + UnregisterSignal(parent, COMSIG_UNARMED_HARM_DEFENDER) + UnregisterSignal(parent, COMSIG_UNARMED_DISARM_ATTACKER) + UnregisterSignal(parent, COMSIG_UNARMED_DISARM_DEFENDER) + UnregisterSignal(parent, COMSIG_MECH_MOVE_WASD) + UnregisterSignal(parent, COMSIG_MECH_MOVE_STRAFE) + UnregisterSignal(parent, COMSIG_MECH_TOGGLE_POWER) + return ..() + +/datum/component/morale/process(seconds_per_tick) + var/current_time = REALTIMEOFDAY + var/list_trimmed = FALSE + for (var/datum/moodlet/moodlet as anything in moodlets) + if (moodlet.time_to_die < current_time || QDELING(moodlet)) + continue + + morale_points -= moodlet.get_morale_modifier() + qdel(moodlet, TRUE) + moodlets.Remove(moodlet) + list_trimmed = TRUE + + if (!list_trimmed) + return + + morale_ratio = ftanh(morale_points) + +/* + AND NOW THE GIANT WALL OF SIGNAL HANDLERS + LOOK UPON MY SIGNALS HANDLERS YE MIGHTY AND DESPAIR + + Remember how I said low morale will exclusively come from psychic damage? + The Night has shed a tear to tell you of fear and of sorrow and pain that you shall never outgrow. + Oh yea, the negative morale effects will be !!!FUN!!! in exchange for being extremely rare + + Otherwise, morale effects are generally equivalent to "up to half a skill rank" + for a large variety of numerical effects related to skills. + */ +/datum/component/morale/proc/modify_hit_effect(owner, mob/living/target, obj/item/weapon, power, hit_zone) + SIGNAL_HANDLER + *power = *power * (1 + (0.05 * morale_ratio)) + +/datum/component/morale/proc/handle_accuracy(mob/shooter, accuracy_decrease, dispersion_increase) + SIGNAL_HANDLER + *accuracy_decrease = *accuracy_decrease - morale_ratio + *dispersion_increase = *dispersion_increase - 10 * morale_ratio + +/datum/component/morale/proc/safety_fumble(mob/shooter, obj/item/gun/shoota, cancelled) + SIGNAL_HANDLER + // Up to 50% chance to fumble a safety when in a psionically-induced panic. + if (cancelled || morale_points >= 0 || !prob(floor(5 * panic_chance_ceiling * -morale_ratio))) + return + + *cancelled = TRUE + shooter.visible_message( + SPAN_DANGER("\The [shooter] fumbles with \the [shoota]'s safety in a blind panic!"), + SPAN_DANGER("You fumble with \the [shoota]'s safety in a blind panic!")) + +/datum/component/morale/proc/handle_harm_attack(mob/attacker, mob/defender, attacker_skill_level, miss_chance, rand_damage, block_chance) + SIGNAL_HANDLER + *attacker_skill_level = *attacker_skill_level + (unarmed_rank_contribution * morale_ratio) + *miss_chance = *miss_chance - unarmed_chance_contribution * morale_ratio + *block_chance = *block_chance - unarmed_chance_contribution * morale_ratio + +/datum/component/morale/proc/handle_harm_defend(mob/defender, mob/attacker, defender_skill_level, miss_chance, rand_damage, block_chance) + SIGNAL_HANDLER + *defender_skill_level = *defender_skill_level - (unarmed_rank_contribution * morale_ratio) + *miss_chance = *miss_chance + unarmed_chance_contribution * morale_ratio + *block_chance = *block_chance + unarmed_chance_contribution * morale_ratio + +/datum/component/morale/proc/handle_disarm_attack(mob/attacker, mob/defender, attacker_skill_level, disarm_cost, push_chance, disarm_chance) + SIGNAL_HANDLER + *attacker_skill_level = *attacker_skill_level + (unarmed_rank_contribution * morale_ratio) + *push_chance = *push_chance - unarmed_chance_contribution * morale_ratio + *disarm_chance = *disarm_chance - unarmed_chance_contribution * morale_ratio + +/datum/component/morale/proc/handle_disarm_defend(mob/defender, mob/attacker, defender_skill_level, disarm_cost, push_chance, disarm_chance) + SIGNAL_HANDLER + *defender_skill_level = *defender_skill_level + (unarmed_rank_contribution * morale_ratio) + *push_chance = *push_chance + unarmed_chance_contribution * morale_ratio + *disarm_chance = *disarm_chance + unarmed_chance_contribution * morale_ratio + +/datum/component/morale/proc/handle_user_move(mob/living/user, direction, delay_modifier) + SIGNAL_HANDLER + if (parent != user) + return + + if (morale_points < 0 && prob(floor(panic_chance_ceiling * -morale_ratio))) + user.visible_message( + SPAN_DANGER("\The [user] fumbles with their mech's controls in a blind panic!"), + SPAN_DANGER("You fumble with your mech's controls in a blind panic!")) + *direction = pick(GLOB.cardinals) + + if (direction == NORTH) + return + + *delay_modifier = *delay_modifier - 0.5 * morale_ratio + +/datum/component/morale/proc/handle_user_strafe(mob/living/user, direction, delay_modifier) + SIGNAL_HANDLER + if (parent != user) + return + + if (morale_points < 0 && prob(floor(panic_chance_ceiling * -morale_ratio))) + user.visible_message( + SPAN_DANGER("\The [user] fumbles with their mech's controls in a blind panic!"), + SPAN_DANGER("You fumble with your mech's controls in a blind panic!")) + *direction = angle2dir(dir2angle(direction) + 180) + + *delay_modifier = *delay_modifier - 0.5 * morale_ratio + +/datum/component/morale/proc/handle_mech_toggle_power(mob/user, cancelled, delay) + SIGNAL_HANDLER + if (parent != user || cancelled || morale_points >= 0) + return + + if (prob(floor(panic_chance_ceiling * -morale_ratio))) + to_chat(user, SPAN_DANGER("The pressure on your mind overwhelms you completely. You can't even think to find the power switch...")) + *cancelled = TRUE + return + + *delay = *delay - (5 * morale_ratio) SECONDS + to_chat(user, SPAN_WARNING("The pressure on your mind causes you to stumble in searching for the power switch...")) diff --git a/code/datums/components/skills/combat/armed_combat_skill_component.dm b/code/datums/components/skills/combat/armed_combat_skill_component.dm new file mode 100644 index 000000000000..4da146b54d65 --- /dev/null +++ b/code/datums/components/skills/combat/armed_combat_skill_component.dm @@ -0,0 +1,23 @@ +/** + * Component used for the Armed Combat skill. For its initial implementation, this component works by *slightly* modifying the damage dealt by attacks done with melee weapons. + * For the majority of non-security crew, this basically means a small nerf to damage if they didn't invest any points into the skill. + */ +/datum/component/skill/armed_combat + +/datum/component/skill/armed_combat/Initialize(level) + . = ..() + if (!parent) + return + + RegisterSignal(parent, COMSIG_APPLY_HIT_EFFECT, PROC_REF(modify_hit_effect), override = TRUE) + +/datum/component/skill/armed_combat/Destroy(force) + if (!parent) + return ..() + + UnregisterSignal(parent, COMSIG_APPLY_HIT_EFFECT) + return ..() + +/datum/component/skill/armed_combat/proc/modify_hit_effect(owner, mob/living/target, obj/item/weapon, power, hit_zone) + SIGNAL_HANDLER + *power = *power * (1 + 0.1 * (skill_level - skill_diff_reference)) diff --git a/code/datums/components/skills/combat/firearms_skill_component.dm b/code/datums/components/skills/combat/firearms_skill_component.dm new file mode 100644 index 000000000000..f3f712cb3e41 --- /dev/null +++ b/code/datums/components/skills/combat/firearms_skill_component.dm @@ -0,0 +1,63 @@ +/** + * Component used for the Firearms skill. Mobs with this component will have their weapon handling characteristics modified by their skill rank + * but only if this component is present. + */ +/datum/component/skill/firearms + /** + * Accuracy modifier to fired guns per point of "Skill Diff". + * As an "Effective increase" in tiles to the target being shot. + */ + var/accuracy_per_skill_diff = 1 + + /** + * Dispersion modifier to fired guns per point of "Skill Diff". + * As an arc-length in Degrees. + */ + var/dispersion_per_skill_diff = 15 + + /// %chance per point of "Skill Diff" to fumble changing a weapon's safety. + var/safety_fumble_per_skill_diff = 15 + + /// %chance for a completely untrained person to shoot themself in the foot accidentally. + var/footgun_chance = 1 + +/datum/component/skill/firearms/Initialize(var/level = SKILL_LEVEL_UNFAMILIAR) + . = ..() + if (!parent) + return + + RegisterSignal(parent, COMSIG_BEFORE_GUN_FIRE, PROC_REF(handle_accuracy), override = TRUE) + RegisterSignal(parent, COMSIG_GUN_TOGGLE_FIRING_MODE, PROC_REF(safety_fumble), override = TRUE) + +/datum/component/skill/firearms/Destroy() + if (!parent) + return ..() + + UnregisterSignal(parent, COMSIG_BEFORE_GUN_FIRE) + UnregisterSignal(parent, COMSIG_GUN_TOGGLE_FIRING_MODE) + return ..() + +/datum/component/skill/firearms/proc/handle_accuracy(mob/shooter, accuracy_decrease, dispersion_increase) + SIGNAL_HANDLER + var/skill_diff = skill_diff_reference - skill_level + + // Count the target as being one tile further away from the shooter + // per the difference between a skilled professional, and the shooter's skill level + *accuracy_decrease = *accuracy_decrease + accuracy_per_skill_diff * skill_diff + + // Unskilled shooters get an increased firing arc for their guns + // to a maximum of 30 degrees when fully untrained. + *dispersion_increase = *dispersion_increase + dispersion_per_skill_diff * skill_diff + +/datum/component/skill/firearms/proc/safety_fumble(mob/shooter, obj/item/gun/shoota, cancelled) + SIGNAL_HANDLER + if (cancelled || skill_level >= skill_diff_reference) + return // Trained and up will never fumble the safety. Except if morale has anything to say about that... + + if (!prob(safety_fumble_per_skill_diff * (skill_diff_reference - skill_level))) + return // if they pass the skill check. + + *cancelled = TRUE + shooter.visible_message( + SPAN_DANGER("\The [shooter] fumbles with \the [shoota]'s safety!"), + SPAN_DANGER("You fumble with \the [shoota]'s safety!")) diff --git a/code/datums/components/skills/combat/leadership_skill_component.dm b/code/datums/components/skills/combat/leadership_skill_component.dm new file mode 100644 index 000000000000..5ebbf00a6087 --- /dev/null +++ b/code/datums/components/skills/combat/leadership_skill_component.dm @@ -0,0 +1 @@ +/datum/component/skill/leadership diff --git a/code/datums/components/skills/combat/unarmed_combat_skill_component.dm b/code/datums/components/skills/combat/unarmed_combat_skill_component.dm new file mode 100644 index 000000000000..02d80bcfc740 --- /dev/null +++ b/code/datums/components/skills/combat/unarmed_combat_skill_component.dm @@ -0,0 +1,53 @@ +/datum/component/skill/unarmed_combat + /// Percent chance modifier for harm intent + var/harm_miss_chance_per_skill_diff = 5 + /// Percent chance modifier for blocking unarmed attacks + var/block_chance_per_skill_diff = 5 + /// Push chance modifier for disarm intent + var/push_chance_per_skill_diff = 5 + /// Disarm chance modifier for disarm intent + var/disarm_chance_per_skill_diff = 5 + +/datum/component/skill/unarmed_combat/Initialize() + . = ..() + if (!parent) + return + + RegisterSignal(parent, COMSIG_UNARMED_HARM_ATTACKER, PROC_REF(handle_harm_attack), override = TRUE) + RegisterSignal(parent, COMSIG_UNARMED_HARM_DEFENDER, PROC_REF(handle_harm_defend), override = TRUE) + RegisterSignal(parent, COMSIG_UNARMED_DISARM_ATTACKER, PROC_REF(handle_disarm_attack), override = TRUE) + RegisterSignal(parent, COMSIG_UNARMED_DISARM_DEFENDER, PROC_REF(handle_disarm_defend), override = TRUE) + +/datum/component/skill/unarmed_combat/Destroy(force) + if (!parent) + return ..() + + UnregisterSignal(parent, COMSIG_UNARMED_HARM_ATTACKER) + UnregisterSignal(parent, COMSIG_UNARMED_HARM_DEFENDER) + UnregisterSignal(parent, COMSIG_UNARMED_DISARM_ATTACKER) + UnregisterSignal(parent, COMSIG_UNARMED_DISARM_DEFENDER) + return ..() + +/datum/component/skill/unarmed_combat/proc/handle_harm_attack(mob/attacker, mob/defender, attacker_skill_level, miss_chance, rand_damage, block_chance) + SIGNAL_HANDLER + *attacker_skill_level = *attacker_skill_level + skill_level - 1 + *miss_chance = *miss_chance + (skill_diff_reference - skill_level) * harm_miss_chance_per_skill_diff + *block_chance = *block_chance + (skill_diff_reference - skill_level) * block_chance_per_skill_diff + +/datum/component/skill/unarmed_combat/proc/handle_harm_defend(mob/defender, mob/attacker, defender_skill_level, miss_chance, rand_damage, block_chance) + SIGNAL_HANDLER + *defender_skill_level = *defender_skill_level + skill_level - 1 + *miss_chance = *miss_chance - (skill_diff_reference - skill_level) * harm_miss_chance_per_skill_diff + *block_chance = *block_chance - (skill_diff_reference - skill_level) * block_chance_per_skill_diff + +/datum/component/skill/unarmed_combat/proc/handle_disarm_attack(mob/attacker, mob/defender, attacker_skill_level, disarm_cost, push_chance, disarm_chance) + SIGNAL_HANDLER + *attacker_skill_level = *attacker_skill_level + skill_level - 1 + *push_chance = *push_chance - (skill_diff_reference - skill_level) * push_chance_per_skill_diff + *disarm_chance = *disarm_chance - (skill_diff_reference - skill_level) * disarm_chance_per_skill_diff + +/datum/component/skill/unarmed_combat/proc/handle_disarm_defend(mob/defender, mob/attacker, defender_skill_level, disarm_cost, push_chance, disarm_chance) + SIGNAL_HANDLER + *defender_skill_level = *defender_skill_level + skill_level - 1 + *push_chance = *push_chance + (skill_diff_reference - skill_level) * push_chance_per_skill_diff + *disarm_chance = *disarm_chance + (skill_diff_reference - skill_level) * push_chance_per_skill_diff diff --git a/code/datums/components/skills/engineering/atmospherics_systems_skill_component.dm b/code/datums/components/skills/engineering/atmospherics_systems_skill_component.dm new file mode 100644 index 000000000000..77a1b0a0c718 --- /dev/null +++ b/code/datums/components/skills/engineering/atmospherics_systems_skill_component.dm @@ -0,0 +1 @@ +/datum/component/skill/atmospherics_systems diff --git a/code/datums/components/skills/engineering/electrical_engineering_skill_component.dm b/code/datums/components/skills/engineering/electrical_engineering_skill_component.dm new file mode 100644 index 000000000000..d0356ba99a43 --- /dev/null +++ b/code/datums/components/skills/engineering/electrical_engineering_skill_component.dm @@ -0,0 +1 @@ +/datum/component/skill/electrical_engineering diff --git a/code/datums/components/skills/engineering/mechanical_engineering_skill_component.dm b/code/datums/components/skills/engineering/mechanical_engineering_skill_component.dm new file mode 100644 index 000000000000..a3207c66fa0f --- /dev/null +++ b/code/datums/components/skills/engineering/mechanical_engineering_skill_component.dm @@ -0,0 +1 @@ +/datum/component/skill/mechanical_engineering diff --git a/code/datums/components/skills/engineering/reactor_systems_skill_component.dm b/code/datums/components/skills/engineering/reactor_systems_skill_component.dm new file mode 100644 index 000000000000..a402cc1ca24b --- /dev/null +++ b/code/datums/components/skills/engineering/reactor_systems_skill_component.dm @@ -0,0 +1,23 @@ +/datum/component/skill/reactor_systems + +/datum/component/skill/reactor_systems/Initialize() + . = ..() + if (!parent) + return + + RegisterSignal(parent, COMSIG_USE_REACTOR_COMPUTER, PROC_REF(use_reactor_computer), override = TRUE) + +/datum/component/skill/reactor_systems/Destroy(force) + if (!parent) + return ..() + + UnregisterSignal(parent, COMSIG_USE_REACTOR_COMPUTER) + return ..() + +/datum/component/skill/reactor_systems/proc/use_reactor_computer(mob/user, cancelled) + SIGNAL_HANDLER + if (skill_level >= SKILL_LEVEL_TRAINED) + return + + *cancelled = TRUE + to_chat(user, SPAN_WARNING("There's just so many buttons... You have no idea where to even begin with using this machine.")) diff --git a/code/datums/components/skills/medical/anatomy_skill_component.dm b/code/datums/components/skills/medical/anatomy_skill_component.dm new file mode 100644 index 000000000000..7f89c1e17b0e --- /dev/null +++ b/code/datums/components/skills/medical/anatomy_skill_component.dm @@ -0,0 +1,7 @@ +/** + * Not currently implemented anywhere. Finish this in its own PR so as to avoid Scope Creep. + * + * This skill should influence the information a character receives when medically examining another person (with or without a health analyzer). + * With extremely high ranks in the skill giving more detailed information about a character's injuries at a glance to make diagnosing injuries easier. + */ +/datum/component/skill/anatomy diff --git a/code/datums/components/skills/medical/forensics_skill_component.dm b/code/datums/components/skills/medical/forensics_skill_component.dm new file mode 100644 index 000000000000..40fb4fff1d29 --- /dev/null +++ b/code/datums/components/skills/medical/forensics_skill_component.dm @@ -0,0 +1,6 @@ +/** + * Not currently implemented anywhere. Finish this in its own PR so as to avoid Scope Creep. + * + * To be honest just port and componentize Baystation12's Forensics. + */ +/datum/component/skill/forensics diff --git a/code/datums/components/skills/medical/medicine_skill_component.dm b/code/datums/components/skills/medical/medicine_skill_component.dm new file mode 100644 index 000000000000..7507b365ffa7 --- /dev/null +++ b/code/datums/components/skills/medical/medicine_skill_component.dm @@ -0,0 +1 @@ +/datum/component/skill/medicine diff --git a/code/datums/components/skills/medical/pharmacology_skill_component.dm b/code/datums/components/skills/medical/pharmacology_skill_component.dm new file mode 100644 index 000000000000..232b9f45bc37 --- /dev/null +++ b/code/datums/components/skills/medical/pharmacology_skill_component.dm @@ -0,0 +1 @@ +/datum/component/skill/pharmacology diff --git a/code/datums/components/skills/medical/surgery_skill_component.dm b/code/datums/components/skills/medical/surgery_skill_component.dm new file mode 100644 index 000000000000..431b3b882a07 --- /dev/null +++ b/code/datums/components/skills/medical/surgery_skill_component.dm @@ -0,0 +1 @@ +/datum/component/skill/surgery diff --git a/code/datums/components/skills/operations/pilot_mechs_skill_component.dm b/code/datums/components/skills/operations/pilot_mechs_skill_component.dm new file mode 100644 index 000000000000..a1ee2a9ac759 --- /dev/null +++ b/code/datums/components/skills/operations/pilot_mechs_skill_component.dm @@ -0,0 +1,62 @@ +/datum/component/skill/pilot_mechs + + /// The %chance per move input to scramble the input into a random direction. This only applies for Unfamiliar mech pilots. + var/move_scramble_chance = 10 + + /// Extra move delay added to + var/move_delay_per_skill_diff = 0.5 + +/datum/component/skill/pilot_mechs/Initialize() + . = ..() + if (!parent) + return + + RegisterSignal(parent, COMSIG_MECH_MOVE_WASD, PROC_REF(handle_user_move), override = TRUE) + RegisterSignal(parent, COMSIG_MECH_MOVE_STRAFE, PROC_REF(handle_user_strafe), override = TRUE) + RegisterSignal(parent, COMSIG_MECH_TOGGLE_POWER, PROC_REF(handle_toggle_power), override = TRUE) + +/datum/component/skill/pilot_mechs/Destroy(force) + if (!parent) + return ..() + + UnregisterSignal(parent, COMSIG_MECH_MOVE_WASD) + UnregisterSignal(parent, COMSIG_MECH_MOVE_STRAFE) + UnregisterSignal(parent, COMSIG_MECH_TOGGLE_POWER) + return ..() + +/datum/component/skill/pilot_mechs/proc/handle_user_move(mob/living/user, direction, delay_modifier) + SIGNAL_HANDLER + if (parent != user) + return + + // Potentially scramble the direction if the pilot is minimally skilled. + if (skill_level == SKILL_LEVEL_UNFAMILIAR && prob(move_scramble_chance)) + to_chat(user, SPAN_WARNING("You fumble with the controls!")) + *direction = pick(GLOB.cardinals) + + // Don't modify the "Forward" throttle no matter the skill level. All other directions are slower than this for mechs. + if (direction == NORTH) + return + + *delay_modifier = *delay_modifier + (skill_diff_reference - skill_level) * move_delay_per_skill_diff + +/datum/component/skill/pilot_mechs/proc/handle_user_strafe(mob/living/user, direction, delay_modifier) + SIGNAL_HANDLER + if (parent != user) + return + + // Potentially flip the strafe direction if the pilot is minimally skilled. + if (skill_level == SKILL_LEVEL_UNFAMILIAR && prob(move_scramble_chance)) + to_chat(user, SPAN_WARNING("You fumble with the controls!")) + *direction = angle2dir(dir2angle(direction) + 180) + + *delay_modifier = *delay_modifier + (skill_diff_reference - skill_level) * move_delay_per_skill_diff + +/datum/component/skill/pilot_mechs/proc/handle_toggle_power(mob/user, cancelled, delay) + SIGNAL_HANDLER + if (parent != user || cancelled || skill_level != SKILL_LEVEL_UNFAMILIAR) + return + + *delay = *delay + (5 SECONDS) + to_chat(user, SPAN_NOTICE("You struggle with searching all these buttons for the power switch.")) + playsound(user.loc, SFX_KEYBOARD, 30, TRUE) diff --git a/code/datums/components/skills/operations/pilot_spacecraft_skill_component.dm b/code/datums/components/skills/operations/pilot_spacecraft_skill_component.dm new file mode 100644 index 000000000000..ac17e51ccb04 --- /dev/null +++ b/code/datums/components/skills/operations/pilot_spacecraft_skill_component.dm @@ -0,0 +1 @@ +/datum/component/skill/pilot_spacecraft diff --git a/code/datums/components/skills/operations/robotics_skill_component.dm b/code/datums/components/skills/operations/robotics_skill_component.dm new file mode 100644 index 000000000000..e387e5a7aea2 --- /dev/null +++ b/code/datums/components/skills/operations/robotics_skill_component.dm @@ -0,0 +1,23 @@ +/datum/component/skill/robotics + +/datum/component/skill/robotics/Initialize() + . = ..() + if (!parent) + return + + RegisterSignal(parent, COMSIG_USE_MECH_FAB, PROC_REF(use_mech_fab), override = TRUE) + +/datum/component/skill/robotics/Destroy() + if (!parent) + return ..() + + UnregisterSignal(parent, COMSIG_USE_MECH_FAB) + return ..() + +/datum/component/skill/robotics/proc/use_mech_fab(mob/user, cancelled) + SIGNAL_HANDLER + if (cancelled || skill_level >= SKILL_LEVEL_TRAINED) + return + + *cancelled = TRUE + to_chat(user, SPAN_WARNING("You have no idea how this machine works.")) diff --git a/code/datums/components/skills/science/archaology_skill_component.dm b/code/datums/components/skills/science/archaology_skill_component.dm new file mode 100644 index 000000000000..916653ba8b9d --- /dev/null +++ b/code/datums/components/skills/science/archaology_skill_component.dm @@ -0,0 +1 @@ +/datum/component/skill/archaology diff --git a/code/datums/components/skills/science/research_skill_component.dm b/code/datums/components/skills/science/research_skill_component.dm new file mode 100644 index 000000000000..409f2d9fa02b --- /dev/null +++ b/code/datums/components/skills/science/research_skill_component.dm @@ -0,0 +1 @@ +/datum/component/skill/research diff --git a/code/datums/components/skills/science/xenobiology_skill_component.dm b/code/datums/components/skills/science/xenobiology_skill_component.dm new file mode 100644 index 000000000000..b5f5fd26f02b --- /dev/null +++ b/code/datums/components/skills/science/xenobiology_skill_component.dm @@ -0,0 +1 @@ +/datum/component/skill/xenobiology diff --git a/code/datums/components/skills/science/xenobotany_skill_component.dm b/code/datums/components/skills/science/xenobotany_skill_component.dm new file mode 100644 index 000000000000..69c2fd5068e8 --- /dev/null +++ b/code/datums/components/skills/science/xenobotany_skill_component.dm @@ -0,0 +1 @@ +/datum/component/skill/xenobotany diff --git a/code/datums/components/skills/service/bartending_skill_component.dm b/code/datums/components/skills/service/bartending_skill_component.dm new file mode 100644 index 000000000000..d551db1dc1dd --- /dev/null +++ b/code/datums/components/skills/service/bartending_skill_component.dm @@ -0,0 +1,43 @@ +/datum/component/skill/bartending + +/datum/moodlet/bartender_drink + +/datum/component/drink_moodlet_provider + var/moodlet_value = 0 + var/overwrite_moodlet = FALSE + +/datum/component/drink_moodlet_provider/Initialize(var/value = 5.0, var/overwrite = FALSE) + . = ..() + if (!parent) + return + + moodlet_value = value + overwrite_moodlet = overwrite + RegisterSignal(parent, COMSIG_CONTAINER_DRANK, PROC_REF(handle_drank), override = TRUE) + +/datum/component/drink_moodlet_provider/Destroy() + if (!parent) + return ..() + + UnregisterSignal(parent, COMSIG_CONTAINER_DRANK) + return ..() + +/datum/component/drink_moodlet_provider/proc/handle_drank(obj/item/reagent_containers/owner, mob/user) + SIGNAL_HANDLER + if (QDELING(src)) + return + + if (!owner.reagents.total_volume) + qdel(src) + // No return here because total volume can be empty at this step (if the person drank the last of a cup) + + var/datum/component/morale/morale_comp = user.GetComponent(MORALE_COMPONENT) + if (!morale_comp) + return + + if (!overwrite_moodlet && astype(morale_comp.moodlets[/datum/moodlet/bartender_drink], /datum/moodlet)?.get_morale_modifier() > moodlet_value) + // Return if they already have a better drink moodlet. + return + + var/datum/moodlet/new_moodlet = morale_comp.load_moodlet(/datum/moodlet/bartender_drink, moodlet_value) + new_moodlet.refresh_moodlet() // Reset the duration when they drink it. diff --git a/code/datums/components/skills/service/cooking_skill_component.dm b/code/datums/components/skills/service/cooking_skill_component.dm new file mode 100644 index 000000000000..bcfc1bde97e0 --- /dev/null +++ b/code/datums/components/skills/service/cooking_skill_component.dm @@ -0,0 +1 @@ +/datum/component/skill/cooking diff --git a/code/datums/components/skills/service/entertaining_skill_component.dm b/code/datums/components/skills/service/entertaining_skill_component.dm new file mode 100644 index 000000000000..5af0227e08ed --- /dev/null +++ b/code/datums/components/skills/service/entertaining_skill_component.dm @@ -0,0 +1 @@ +/datum/component/skill/entertaining diff --git a/code/datums/components/skills/service/gardening_skill_component.dm b/code/datums/components/skills/service/gardening_skill_component.dm new file mode 100644 index 000000000000..451b6eae3c02 --- /dev/null +++ b/code/datums/components/skills/service/gardening_skill_component.dm @@ -0,0 +1,22 @@ +/datum/component/skill/gardening + var/bonus_yield_per_rank = 1 + var/harvest_speedup_per_rank = 0.333 SECONDS + +/datum/component/skill/gardening/Initialize(level) + . = ..() + if(!parent) + return + + RegisterSignal(parent, COMSIG_PLANT_HARVESTER, PROC_REF(modify_yield), override = TRUE) + +/datum/component/skill/gardening/Destroy(force) + if (!parent) + return ..() + + UnregisterSignal(parent, COMSIG_PLANT_HARVESTER) + return ..() + +/datum/component/skill/gardening/proc/modify_yield(owner, datum/seed/plant, total_yield, cancelled, doafter) + SIGNAL_HANDLER + *total_yield = *total_yield + bonus_yield_per_rank * (skill_level - 1) + *doafter = *doafter - harvest_speedup_per_rank * (skill_level - 1) diff --git a/code/datums/components/skills/skill_component.dm b/code/datums/components/skills/skill_component.dm new file mode 100644 index 000000000000..abdcfa536b6f --- /dev/null +++ b/code/datums/components/skills/skill_component.dm @@ -0,0 +1,31 @@ +/** + * The base type for Componentized skills, containing only the information extracted from Skill preferences that would be required to function. + * Children of this component can be added to a character from skill singletons by overriding that singleton's on_spawn() proc. + */ +ABSTRACT_TYPE(/datum/component/skill) + /** + * How many ranks a player has purchased in a given skill. + * How this is actually used is entirely up to the implementation of individual components. + */ + var/skill_level = SKILL_LEVEL_UNFAMILIAR + + /** + * Reference value used for checking "Skill Diff" + * "Skill Diff" is the distance from the actual skill level to the reference. + * + * This can essentially be thought of as the "baseline competence" for how a vanilla character would function prior to the introduction of Skill Components. + * Any datum that is *missing* a given skill component can be logically assumed to be at this skill level. + * Therefore, characters who both have the component, and are at a level lower than this can be assumed to be "less competent". + * While characters at a level above this can be assumed to be "more competent". + */ + var/skill_diff_reference = SKILL_LEVEL_TRAINED + +/** + * Always use . = ..() at the start of a NameSkillComponent's Initialize() proc. + * Skills MUST have their skill_level set first during initialization. + * Do this by setting var/level to the 2nd arg of AddComponent() + */ +/datum/component/skill/Initialize(var/level = SKILL_LEVEL_UNFAMILIAR) + SHOULD_CALL_PARENT(TRUE) + . = ..() + skill_level = level diff --git a/code/datums/datum.dm b/code/datums/datum.dm index cf0d7816d5b4..d6916cc9d5be 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -7,6 +7,10 @@ */ var/gc_destroyed + /// Open uis owned by this datum + /// Lazy, since this case is semi rare + var/list/open_uis + var/tmp/list/active_timers /// Active timers with this datum as the target @@ -115,10 +119,6 @@ if (!isturf(src)) cleanup_events(src) - var/ui_key = REF(src) - if(LAZYISIN(SSnanoui.open_uis, ui_key)) - SSnanoui.close_uis(src) - //BEGIN: ECS SHIT var/list/dc = _datum_components if(dc) diff --git a/code/datums/helper_datums/synthsprites.dm b/code/datums/helper_datums/synthsprites.dm index 62ed3a001c0e..f78af8967def 100644 --- a/code/datums/helper_datums/synthsprites.dm +++ b/code/datums/helper_datums/synthsprites.dm @@ -31,7 +31,7 @@ paiicon is the pai icon sprite name return try - customsynthsprites = json_decode(return_file_text("config/customsynths.json")) + customsynthsprites = json_decode(file2text("config/customsynths.json")) catch(var/exception/ej) LOG_DEBUG("Error: Warning: Could not load custom synth config, as customsynths.json is missing - [ej]") return diff --git a/code/datums/outfits/ert/kosmostrelki.dm b/code/datums/outfits/ert/kosmostrelki.dm index 21292a349b26..3228a8ad6788 100644 --- a/code/datums/outfits/ert/kosmostrelki.dm +++ b/code/datums/outfits/ert/kosmostrelki.dm @@ -12,7 +12,7 @@ belt = /obj/item/storage/belt/military belt_contents = list( - /obj/item/ammo_magazine/boltaction = 5, + /obj/item/ammo_magazine/a68 = 3, /obj/item/grenade/smokebomb = 1, /obj/item/ammo_magazine/mc9mm = 1, /obj/item/gun/projectile/pistol/adhomai = 1, @@ -152,7 +152,7 @@ backpack_contents = list( /obj/item/gun/projectile/shotgun/pump/rifle/obrez = 1, - /obj/item/ammo_magazine/boltaction = 4, + /obj/item/ammo_magazine/boltaction/adhomai = 4, /obj/item/gun/projectile/pistol/adhomai = 1, /obj/item/material/knife/trench = 1 ) diff --git a/code/datums/outfits/outfit.dm b/code/datums/outfits/outfit.dm index 05c5cbd65794..b9e740c30ab6 100644 --- a/code/datums/outfits/outfit.dm +++ b/code/datums/outfits/outfit.dm @@ -503,16 +503,16 @@ if(OUTFIT_TAB_PDA) I.desc_extended += "For its many years of service, this model has held a virtual monopoly for PDA models for NanoTrasen. The secret? A lapel pin affixed to the back." if(OUTFIT_PDA_OLD) - I.icon = 'icons/obj/pda_old.dmi' + I.icon = 'icons/obj/modular_computers/pda_old.dmi' I.desc_extended += "Nicknamed affectionately as the 'Brick', PDA enthusiasts rejoice with the return of an old favorite, retrofitted to new modular computing standards." if(OUTFIT_PDA_RUGGED) - I.icon = 'icons/obj/pda_rugged.dmi' + I.icon = 'icons/obj/modular_computers/pda_rugged.dmi' I.desc_extended += "EVA enthusiasts and owners of fat fingers just LOVE the huge tactile buttons provided by this model. Prone to butt-dialing, but don't let that hold you back." if(OUTFIT_PDA_SLATE) - I.icon = 'icons/obj/pda_slate.dmi' + I.icon = 'icons/obj/modular_computers/pda_slate.dmi' I.desc_extended += "A bet between an engineer and a disgruntled scientist, it turns out you CAN make a PDA out of an atmospherics scanner. Also, probably don't tell management, just enjoy." if(OUTFIT_PDA_SMART) - I.icon = 'icons/obj/pda_smart.dmi' + I.icon = 'icons/obj/modular_computers/pda_smart.dmi' I.desc_extended += "NanoTrasen originally designed this as a portable media player. Unfortunately, Royalty-free and corporate-approved ukulele isn't particularly popular." I.update_icon() if(!H.wrists && H.pda_choice == OUTFIT_WRISTBOUND) @@ -633,6 +633,8 @@ H.gloves.add_fingerprint(H, 1) if(H.wrists) H.wrists.add_fingerprint(H, 1) + if(H.pants) + H.pants.add_fingerprint(H, 1) if(H.l_ear) H.l_ear.add_fingerprint(H, 1) if(H.r_ear) diff --git a/code/datums/outfits/outfit_antag.dm b/code/datums/outfits/outfit_antag.dm index 9968a383bed5..ccb06821769d 100644 --- a/code/datums/outfits/outfit_antag.dm +++ b/code/datums/outfits/outfit_antag.dm @@ -361,7 +361,7 @@ qdel(G) if(accessory_contents.len) - accessory = pick(typesof(/obj/item/clothing/accessory/holster) - typesof(/obj/item/clothing/accessory/holster/thigh/fluff)) + accessory = pick(typesof(/obj/item/clothing/accessory/holster) - typesof(/obj/item/clothing/accessory/holster/utility/fluff)) if(!back) H.equip_to_slot_or_del(bag, slot_back) diff --git a/code/datums/records.dm b/code/datums/records.dm index 3841f618eb88..b74e06ceba1b 100644 --- a/code/datums/records.dm +++ b/code/datums/records.dm @@ -195,9 +195,6 @@ /datum/record/medical var/blood_type = "AB+" var/blood_dna = "63920c3ec24b5d57d459b33a2f4d6446" - var/disabilities = "No disabilities have been declared." - var/allergies = "No allergies have been detected in this patient." - var/diseases = "No diseases have been diagnosed at the moment." var/list/comments = list() /datum/record/medical/New(var/mob/living/carbon/human/H, var/nid) @@ -210,6 +207,7 @@ blood_dna = H.dna.unique_enzymes if(H.med_record && !jobban_isbanned(H, "Records")) notes = H.med_record + else notes = "No history has been reported yet." // Record for storing security data /datum/record/security diff --git a/code/datums/skills/_skills.dm b/code/datums/skills/_skills.dm index 1a9a558417a2..0966e2a90b89 100644 --- a/code/datums/skills/_skills.dm +++ b/code/datums/skills/_skills.dm @@ -4,12 +4,19 @@ /// A description of what this skill entails. var/description /// A detailed description of what a character should expect with their current level in this skill. Assoc list of skill level to string. - var/list/skill_level_descriptions = list( + var/alist/skill_level_descriptions = alist( SKILL_LEVEL_UNFAMILIAR = "You are clueless.", SKILL_LEVEL_FAMILIAR = "You have read up on the subject or have prior real experience.", SKILL_LEVEL_TRAINED = "You have received some degree of official training on the subject, whether through certifications or courses.", SKILL_LEVEL_PROFESSIONAL = "You are an expert in this field, devoting many years of study or practice to it." ) + /// Map of skill names and descriptions by their index. + var/list/skill_level_map = list( + "Unfamiliar", + "Familiar", + "Trained", + "Professional" + ) /// The maximum level someone with no education can reach in this skill. Typically, this should be FAMILIAR on occupational skills. /// If null, then there is no cap. var/uneducated_skill_cap @@ -21,11 +28,18 @@ var/subcategory /// The modifier for how difficult the skill is. Each level costs this much * the level. var/skill_difficulty_modifier = SKILL_DIFFICULTY_MODIFIER_MEDIUM + /** + * Required skills are always included in the user's saved skills preference, even if it's at the lowest rank. + * This is needed for skills that rely on components. + */ + var/required = FALSE + /// The component datum that this skill will add during character spawning + var/component_type = null /** * Returns the maximum level a character can have in this skill depending on education. */ -/singleton/skill/proc/get_maximum_level(var/singleton/education/education) +/singleton/skill/proc/get_maximum_level(singleton/education/education) if(!istype(education)) crash_with("SKILL: Invalid [education] fed to get_maximum_level!") @@ -47,3 +61,17 @@ if(level == SKILL_LEVEL_UNFAMILIAR) //thanks byond for not supporting index 0 return 0 return skill_difficulty_modifier * level + +/** + * ECS hook for Skills, based on a one-shot-on-spawn pattern common to traits/disabilities/loadouts, etc. + * Skills may optionally include this, but are not required to. + * This is primarily useful for making skills that offload all of their functional logic to a Component. + * + * It will be called during the process of spawning a player character in. + */ +/singleton/skill/proc/on_spawn(mob/owner, skill_level) + SHOULD_CALL_PARENT(TRUE) + if (!owner || !component_type) + return + + owner.AddComponent(component_type, skill_level) diff --git a/code/datums/skills/combat/combat.dm b/code/datums/skills/combat/combat.dm index 4e36eaef6434..e9a7f8499afc 100644 --- a/code/datums/skills/combat/combat.dm +++ b/code/datums/skills/combat/combat.dm @@ -1,25 +1,75 @@ /singleton/skill/unarmed_combat name = "Unarmed Combat" - description = "Unarmed combat represents your training in hand-to-hand combat, or without a weapon." - skill_level_descriptions = list( - SKILL_LEVEL_UNFAMILIAR = "You have rarely, if ever, fought someone in your life. You are likely to crack under pressure, not land punches, and are physically \ - a pushover in a real fight. Being shoved, grabbed, or moved is likely to be very dangerous for you.", - SKILL_LEVEL_FAMILIAR = "You have some experience throwing punches. You are no stranger to a close-quarters fight, though anyone with real training is likely to \ - overwhelm you. You are not as likely to miss punches, and you are physically less likely to suffer being shoved, grabbed, or moved.", - SKILL_LEVEL_TRAINED = "You have been trained, whether by being in the military, taking close-quarters-combat classes or simply through experience, to both keep \ - calm in a close-quarters fight and also fight well. You suffer no maluses to your close-quarters combat.", + description = "Unarmed combat represents your training in hand-to-hand combat, or without a weapon. It also influences your ability to resist actions like disarms or martial arts." + maximum_level = SKILL_LEVEL_PROFESSIONAL + skill_level_map = list( + "Untrained", + "Dabbling", + "Trained", + "Black Belt" + ) + skill_level_descriptions = alist( + SKILL_LEVEL_UNFAMILIAR = "You have rarely, if ever, fought someone in your life.
" \ + + " - You are more likely to miss when attempting to punch anywhere not the torso.
" \ + + " - You are less likely to block unarmed attacks that you are aware of.
" \ + + " - Enemies are more likely to block your unarmed attacks.", + SKILL_LEVEL_FAMILIAR = "You have some experience throwing punches. You are no stranger to a close-quarters fight, though anyone with real training is likely to overwhelm you.
" \ + + " - You are slightly more likely to miss when attempting to punch anywhere not the torso.
" \ + + " - You are slightly less likely to block unarmed attacks that you are aware of.
" \ + + " - Enemies are slightly more likely to block your unarmed attacks.", + SKILL_LEVEL_TRAINED = "You have been trained, whether by being in the military, taking close-quarters-combat classes or simply through experience, to both keep calm in a close-quarters fight and also fight well.
" \ + + " - You suffer no maluses to your close-quarters combat.
" \ + + " - You have no bonuses to unarmed fighting either.", + SKILL_LEVEL_PROFESSIONAL = "You have had many years of martial arts experience. Probably having a Black Belt equivalent in one or more martial arts.
" \ + + " - You are slightly less likely to miss when attempting to punch anywhere not the torso.
" \ + + " - You are slightly more likely to block unarmed attacks that you are aware of.
" \ + + " - Enemies are slightly less likely to block your unarmed attacks.", ) category = /singleton/skill_category/combat subcategory = SKILL_SUBCATEGORY_MELEE + required = TRUE + component_type = UNARMED_COMBAT_SKILL_COMPONENT /singleton/skill/armed_combat name = "Armed Combat" - description = "zomboid time" + description = "Armed Combat influences your effectiveness when fighting with any melee weapon." category = /singleton/skill_category/combat subcategory = SKILL_SUBCATEGORY_MELEE + component_type = ARMED_COMBAT_SKILL_COMPONENT /singleton/skill/firearms name = "Firearms" - description = "using guns. split this into close arms/longarms/special arms?" + description = "Firearms represents your training in using all forms of ranged weapons. Having a high rank in in this skill provides bonuses to accuracy when shooting." + maximum_level = SKILL_LEVEL_PROFESSIONAL category = /singleton/skill_category/combat subcategory = SKILL_SUBCATEGORY_RANGED + required = TRUE + component_type = FIREARMS_SKILL_COMPONENT + skill_level_map = list( + "Untrained", + "Dabbling", + "Trained", + "Gunslinger" + ) + skill_level_descriptions = alist( + SKILL_LEVEL_UNFAMILIAR = "You have no knowledge of how firearms work at all.
" \ + + " - Firearms you shoot have a 30 degree spread-angle increase, making them very inaccurate.
" \ + + " - You have a decent chance of failing to find the safety when attempting to switch it on or off.", + SKILL_LEVEL_FAMILIAR = "You have fired a gun once or twice in your life, but are by no means fully trained. At least you know how to not shoot yourself in the foot or get scope-eye.
" \ + + " - Firearms you shoot have a 15 degree spread-angle increase, making them somewhat less accurate.", + SKILL_LEVEL_TRAINED = "You have both training and actual experience with firearms. Equivalent to a few years of experience in roles such as military, police, or armed security.
" \ + + " - You suffer no maluses to firearms use.
" \ + + " - You have no bonuses to firearms use either.", + SKILL_LEVEL_PROFESSIONAL = "You have many years of experience with firearms, potentially even in actual combat. Retired special forces, police marksmen, and hardened mercenaries fall under this category.
" \ + + " - Firearms you shoot have a 15 degree spread-angle decrease, making them somewhat more accurate. This generally doesn't apply to weapons fired in semi-auto, but will make burst and automatic fire more manageable." \ + ) + +// Temporarily commented because this is a little too complicated to catch in the initial release. +// /singleton/skill/leadership +// name = "Leadership" +// description = "Leadership skill grants access to a unique 'Inspire' action, which lets you say something inspiring and give the target a positive moodlet." +// category = /singleton/skill_category/combat +// subcategory = SKILL_SUBCATEGORY_SUPPORT +// required = TRUE +// component_type = LEADERSHIP_SKILL_COMPONENT + diff --git a/code/datums/skills/everyday/service.dm b/code/datums/skills/everyday/service.dm index 47ac4cdc720f..4caa2c77ce76 100644 --- a/code/datums/skills/everyday/service.dm +++ b/code/datums/skills/everyday/service.dm @@ -1,20 +1,44 @@ -/singleton/skill/mixing - name = "Mixing" - description = "valhalla skill" +/singleton/skill/bartending + name = "Bartending" + description = "Users of this skill can create mixed drinks of varying quality, which provide a long lasting morale bonus to anyone who consumes them. This skill is activated by first mixing a drink in a Drink Mixer, then pressing Z to shake it." maximum_level = SKILL_LEVEL_PROFESSIONAL category = /singleton/skill_category/everyday subcategory = SKILL_SUBCATEGORY_SERVICE + component_type = BARTENDING_SKILL_COMPONENT + skill_level_descriptions = alist( + SKILL_LEVEL_UNFAMILIAR = "Drinks you produce have no effects.", + SKILL_LEVEL_FAMILIAR = "Drinks you produce are slightly higher quality.", + SKILL_LEVEL_TRAINED = "Drinks you produce are of moderately higher quality.", + SKILL_LEVEL_PROFESSIONAL = "Drinks you produce are of a significantly higher quality." + ) /singleton/skill/cooking name = "Cooking" - description = "Cooking Mama" + description = "Currently unimplemented." maximum_level = SKILL_LEVEL_PROFESSIONAL category = /singleton/skill_category/everyday subcategory = SKILL_SUBCATEGORY_SERVICE + component_type = COOKING_SKILL_COMPONENT /singleton/skill/gardening name = "Gardening" - description = "this is boring as shit" + description = "Users of this skill gain bonuses when harvesting grown plants." maximum_level = SKILL_LEVEL_PROFESSIONAL category = /singleton/skill_category/everyday subcategory = SKILL_SUBCATEGORY_SERVICE + component_type = GARDENING_SKILL_COMPONENT + skill_level_descriptions = alist( + SKILL_LEVEL_UNFAMILIAR = "You have no modifiers to gardening.", + SKILL_LEVEL_FAMILIAR = "You gain +1 produce when harvesting plants", + SKILL_LEVEL_TRAINED = "You gain +2 produce when harvesting plants", + SKILL_LEVEL_PROFESSIONAL = "You gain +3 produce when harvesting plants" + ) + +// Temporarily commented because this is a little too complicated to catch in the initial PR release. +// /singleton/skill/entertaining +// name = "Entertaining" +// description = "Entertainers are able to generate positive moodlets by playing instruments." +// maximum_level = SKILL_LEVEL_PROFESSIONAL +// category = /singleton/skill_category/everyday +// subcategory = SKILL_SUBCATEGORY_SERVICE +// component_type = ENTERTAINING_SKILL_COMPONENT diff --git a/code/datums/skills/occupational/engineering.dm b/code/datums/skills/occupational/engineering.dm index 91da1afcf757..a6a5deed6554 100644 --- a/code/datums/skills/occupational/engineering.dm +++ b/code/datums/skills/occupational/engineering.dm @@ -1,29 +1,51 @@ /singleton/skill/electrical_engineering name = "Electrical Engineering" - description = "Electrical engineering has to do with anything that involves wires and electricity. This includes things such as hacking doors, machines, but also \ - laying down wires, or repairing wiring damage in prosthetics." + description = "Not currently implemented" maximum_level = SKILL_LEVEL_PROFESSIONAL uneducated_skill_cap = SKILL_LEVEL_FAMILIAR category = /singleton/skill_category/occupational subcategory = SKILL_SUBCATEGORY_ENGINEERING + required = TRUE + component_type = ELECTRICAL_ENGINEERING_SKILL_COMPONENT /singleton/skill/mechanical_engineering name = "Mechanical Engineering" description = "Mechanical engineering has to do with general construction of objects, walls, windows, and so on. It is also necessary for the usage of heavy machinery \ - such as emitters." + such as emitters. This skill is also commonly used for crafting items out of raw materials, and heavily governs the quality of said objects." maximum_level = SKILL_LEVEL_PROFESSIONAL uneducated_skill_cap = SKILL_LEVEL_FAMILIAR category = /singleton/skill_category/occupational subcategory = SKILL_SUBCATEGORY_ENGINEERING + required = TRUE + component_type = MECHANICAL_ENGINEERING_SKILL_COMPONENT + skill_level_descriptions = alist( + SKILL_LEVEL_UNFAMILIAR = "You have little to no experience working with physical machinery.
" \ + + " - Items you craft will typically be of low quality.
" \ + + " - You take twice as long to craft anything.
" \ + + " - You cannot craft any object that requires this skill.
" \ + + " - You cannot interact with most Engineering machinery.", + SKILL_LEVEL_FAMILIAR = "You have some experience working with physical machinery, though are not formally trained.
" \ + + " - Items you craft will be of slightly lower than average quality.
" \ + + " - You take 50% longer to craft anything.
" \ + + " - You can interact with some Engineering-related machinery.", + SKILL_LEVEL_TRAINED = "You have formal training in general Engineering concepts, equivalent to a Bachelor's Degree.
" \ + + " - You can craft items at the standard speed.
" \ + + " - Items you craft are generally at average quality.
" \ + + " - You can interact with most if not all Engineering equipment.", + SKILL_LEVEL_PROFESSIONAL = "You have many years of training in general Engineering concepts, equivalent to a Master's Degree or better.
" \ + + " - You can craft items significantly faster.
" \ + + " - Items you craft are of much higher quality on average.
" \ + ) /singleton/skill/atmospherics_systems name = "Atmospherics Systems" - description = "Atmospherics systems involves the usage of atmospherics tooling and machinery, such as powered pumps, certain settings on air alarms, pipe wrenches, \ - pipe layers, and pipe construction." + description = "Not currently implemented." maximum_level = SKILL_LEVEL_PROFESSIONAL uneducated_skill_cap = SKILL_LEVEL_UNFAMILIAR category = /singleton/skill_category/occupational subcategory = SKILL_SUBCATEGORY_ENGINEERING + required = TRUE + component_type = ATMOSPHERICS_SYSTEMS_SKILL_COMPONENT /singleton/skill/reactor_systems name = "Reactor Systems" @@ -33,3 +55,15 @@ uneducated_skill_cap = SKILL_LEVEL_UNFAMILIAR category = /singleton/skill_category/occupational subcategory = SKILL_SUBCATEGORY_ENGINEERING + required = TRUE + component_type = REACTOR_SYSTEMS_SKILL_COMPONENT + skill_level_descriptions = alist( + SKILL_LEVEL_UNFAMILIAR = "You have little to no experience working with Reactor systems.
" \ + + " - You cannot interact with Reactor computers such as the INDRA controllers.", + SKILL_LEVEL_FAMILIAR = "You have some experience working with physical machinery, though are not formally trained.
" \ + + " - You cannot interact with Reactor computers such as the INDRA controller.", + SKILL_LEVEL_TRAINED = "You have formal training in general Engineering concepts, equivalent to a Bachelor's Degree.
" \ + + " - This is the minimum skill level required to operate the INDRA.", + SKILL_LEVEL_PROFESSIONAL = "You have many years of training in general Engineering concepts, equivalent to a Master's Degree or better.
" \ + + " - Not currently implemented differently from Trained." \ + ) diff --git a/code/datums/skills/occupational/medical.dm b/code/datums/skills/occupational/medical.dm index 7acaa54cf10a..e9545cd18d09 100644 --- a/code/datums/skills/occupational/medical.dm +++ b/code/datums/skills/occupational/medical.dm @@ -1,37 +1,73 @@ /singleton/skill/medicine name = "Medicine" - description ="how to use health analyzers, ATKs, syringes" + description = "Governs the user's ability to perform basic first-aid, as well as operate medical equipment." maximum_level = SKILL_LEVEL_PROFESSIONAL uneducated_skill_cap = SKILL_LEVEL_FAMILIAR category = /singleton/skill_category/occupational subcategory = SKILL_SUBCATEGORY_MEDICAL + required = TRUE + component_type = MEDICINE_SKILL_COMPONENT /singleton/skill/surgery name = "Surgery" - description = "the one everyone wants to do in medical to be the protag" + description = "Governs the user's ability to perform surgical procedures on organic humanoids, as well as what complexity of procedures can be performed. " \ + + "This does not affect \"surgeries\" performed on mechanical prosthetics, robots, or synthetics in general." maximum_level = SKILL_LEVEL_PROFESSIONAL uneducated_skill_cap = SKILL_LEVEL_UNFAMILIAR category = /singleton/skill_category/occupational subcategory = SKILL_SUBCATEGORY_MEDICAL + component_type = SURGERY_SKILL_COMPONENT + required = TRUE + skill_level_map = list( + "Untrained", + "Med Student", + "Licensed Surgeon", + "World-class Surgeon" + ) + skill_level_descriptions = alist( + SKILL_LEVEL_UNFAMILIAR = "You have zero training or experience with surgery.
" \ + + " - You cannot perform any surgical procedures on organic humanoids.", + SKILL_LEVEL_FAMILIAR = "You have minimal training on the basics of surgery. This is equivalent to a fresh med school graduate, or a military corpsman.
" \ + + "You can perform the following procedures:
" \ + + " - Opening or Closing incisions.
" \ + + " - Clamp bleeders.
" \ + + " - Fixing Arterial Bleeding
" \ + + " - Amputating a limb.", + SKILL_LEVEL_TRAINED = "You have years of formal training and experience with surgery. This is equivalent to a fully licensed surgeon.
" \ + + "You can perform the following procedures in addition to all procedures allowed by the previous level:
" \ + + " - Repairing broken bones or muscle tendons.
" \ + + " - Sawing and retracting a ribcage.
" \ + + " - Facial Reconstructions only on organic humanoids, not synthetics.
" \ + + " - Remove or Insert implants.
" \ + + " - Re-attach (organic) limbs. Robotic limbs require the Robotics skill instead.
" \ + + " - Repair non-necrotic organs other than the brain, or mechanical prosthetics.
", + SKILL_LEVEL_PROFESSIONAL = "You are a world class surgeon with decades worth of training and experience.
" \ + + "In addition to all previous procedures, you can also perform these procedures:
" \ + + " - Repair and debride necrotic organs.
" \ + + " - Repair damaged brains." + ) /singleton/skill/pharmacology name = "Pharmacology" - description = "why are you playing pharma LOL" + description = "Not currently implemented." uneducated_skill_cap = SKILL_LEVEL_UNFAMILIAR category = /singleton/skill_category/occupational subcategory = SKILL_SUBCATEGORY_MEDICAL + component_type = PHARMACOLOGY_SKILL_COMPONENT /singleton/skill/anatomy name = "Anatomy" - description = "this one lets you know what's wrong with people" + description = "Not currently implemented." maximum_level = SKILL_LEVEL_PROFESSIONAL uneducated_skill_cap = SKILL_LEVEL_FAMILIAR category = /singleton/skill_category/occupational subcategory = SKILL_SUBCATEGORY_MEDICAL + component_type = ANATOMY_SKILL_COMPONENT /singleton/skill/forensics name = "Forensics" - description = "forensics shit i guess" + description = "Not currently implemented." uneducated_skill_cap = SKILL_LEVEL_UNFAMILIAR category = /singleton/skill_category/occupational subcategory = SKILL_SUBCATEGORY_MEDICAL + component_type = FORENSICS_SKILL_COMPONENT diff --git a/code/datums/skills/occupational/operations.dm b/code/datums/skills/occupational/operations.dm new file mode 100644 index 000000000000..1ce539c09f4b --- /dev/null +++ b/code/datums/skills/occupational/operations.dm @@ -0,0 +1,85 @@ +/singleton/skill/robotics + name = "Robotics" + description = "Governs the user's ability to perform surgical procedures on synthetics, as well as the complexity of what procedures can be performed." + maximum_level = SKILL_LEVEL_PROFESSIONAL + uneducated_skill_cap = SKILL_LEVEL_FAMILIAR + category = /singleton/skill_category/occupational + subcategory = SKILL_SUBCATEGORY_OPERATIONS + component_type = ROBOTICS_SKILL_COMPONENT + required = TRUE + skill_level_map = list( + "Untrained", + "Hobbyist", + "Licensed Roboticist", + "Robotics Wizard" + ) + skill_level_descriptions = alist( + SKILL_LEVEL_UNFAMILIAR = "You have zero training or experience with synthetics.
" \ + + " - You cannot perform any surgical procedures on synthetics.", + SKILL_LEVEL_FAMILIAR = "You have minimal training on the basics of synthetic repair and maintenance. This could be the level of a hobbyist, or someone currently pursuing a degree in robotics.
" \ + + "You can perform the following procedures:
" \ + + " - Opening or closing external maintenance panels to make superficial repairs.
" \ + + " - Repairing basic damage with a welder or cables.
" \ + + " - Repairing external damage to mechanical limbs.
" \ + + " - Cutting someone out of a hardsuit.", + SKILL_LEVEL_TRAINED = "You have years of formal training or experience on repairing and maintaining synthetics equivalent to a Bachelor's degree in Robotics.
" \ + + "You can perform the following procedures in addition to all procedures allowed by the previous level:
" \ + + " - Fully opening or closing mechanical parts to access internal systems, allowing repairs to any amount of damage.
" \ + + " - Repairing, removing, or adding mechanical organs.
" \ + + " - Facial Reconstructions performed on Shell IPCs.
" \ + + " - Attaching mechanical limbs (including to organics).
" \ + + " - Re-attach (organic) limbs. Robotic limbs require the Robotics skill instead.
" \ + + " - Perform all forms of internal repairs to IPCs.
" \ + + " - Prepare an MMI for cyborgification.", + SKILL_LEVEL_PROFESSIONAL = "Not currently implemented, functions exactly as per Trained." + ) + +/singleton/skill/pilot_spacecraft + name = "Pilot: Spacecraft" + description = "Governs the user's ability to pilot spacecraft of any size, and is required to do so in the first place." + maximum_level = SKILL_LEVEL_PROFESSIONAL + uneducated_skill_cap = SKILL_LEVEL_FAMILIAR + category = /singleton/skill_category/occupational + subcategory = SKILL_SUBCATEGORY_OPERATIONS + skill_level_map = list( + "Unlicensed", + "Licensed Pilot", + "Experienced Pilot", + "Ace" + ) + skill_level_descriptions = alist( + SKILL_LEVEL_UNFAMILIAR = "You are incapable of piloting spacecraft.", + SKILL_LEVEL_FAMILIAR = "You are capable of piloting spacecraft.", + SKILL_LEVEL_TRAINED = "Currently unimplemented.", + SKILL_LEVEL_PROFESSIONAL = "Currently unimplemented." + ) + required = TRUE + component_type = PILOT_SPACECRAFT_SKILL_COMPONENT + +/singleton/skill/pilot_mechs + name = "Pilot: Exosuits" + description = "Governs the user's ability to pilot mechs of any kind." + maximum_level = SKILL_LEVEL_PROFESSIONAL + uneducated_skill_cap = SKILL_LEVEL_TRAINED + category = /singleton/skill_category/occupational + subcategory = SKILL_SUBCATEGORY_OPERATIONS + skill_level_map = list( + "Unlicensed", + "Licensed Pilot", + "Experienced Pilot", + "Mechwarrior" + ) + skill_level_descriptions = alist( + SKILL_LEVEL_UNFAMILIAR = "What's a mech?
" \ + + " - You have a 10% chance to move in a wrong direction when controlling mechs.
" \ + + " - Mech handling characteristics such as strafing and reverse speeds are significantly worse for you.
" \ + + " - It takes you awhile to find the power switch in a mech.", + SKILL_LEVEL_FAMILIAR = "You have a license to pilot mechs, but are relatively inexperienced.
" \ + + " - You have a small penalty to mech handling characteristics, such as slightly slower strafe and reverse speeds.", + SKILL_LEVEL_TRAINED = "You have a decent amount of experience piloting mechs.
" \ + + " - You have no penalties or bonuses for piloting mechs.", + SKILL_LEVEL_PROFESSIONAL = "Look on the bright side kid, you get to keep all the money.
" \ + + " - You have a small bonus to mech handling characteristics. Turning, Strafing, and Reverse speeds are all improved when piloting mechs. Forward speeds are still unchanged." + ) + required = TRUE + component_type = PILOT_MECHS_SKILL_COMPONENT diff --git a/code/datums/skills/occupational/science.dm b/code/datums/skills/occupational/science.dm index e02f8a361fbf..ced98e4f250d 100644 --- a/code/datums/skills/occupational/science.dm +++ b/code/datums/skills/occupational/science.dm @@ -1,37 +1,34 @@ /singleton/skill/research name = "Research" - description = "it's generic research shit, using the protolathe, destructive analyzers, etc" + description = "Not currently implemented" uneducated_skill_cap = SKILL_LEVEL_UNFAMILIAR category = /singleton/skill_category/occupational subcategory = SKILL_SUBCATEGORY_SCIENCE - -/singleton/skill/robotics - name = "Robotics" - description = "Robotics is well you know what the fuck it is man" - maximum_level = SKILL_LEVEL_PROFESSIONAL - uneducated_skill_cap = SKILL_LEVEL_FAMILIAR - category = /singleton/skill_category/occupational - subcategory = SKILL_SUBCATEGORY_SCIENCE + component_type = RESEARCH_SKILL_COMPONENT /singleton/skill/xenobotany name = "Xenobotany" - description = "Xenobotany is the creation and study of new or alien genomes of plants. It is necessary to be able to properly splice and process them." + description = "Not currently implemented." uneducated_skill_cap = SKILL_LEVEL_UNFAMILIAR category = /singleton/skill_category/occupational subcategory = SKILL_SUBCATEGORY_SCIENCE + component_type = XENOBOTANY_SKILL_COMPONENT /singleton/skill/archaeology name = "Xenoarchaeology" - description = "Xenoarchaeology is the study of alien civilizations, artifacts, architecture, and so on. It is necessary for the unearthing and cataloguing of \ - alien artifacts." + description = "Not currently implemented." uneducated_skill_cap = SKILL_LEVEL_UNFAMILIAR category = /singleton/skill_category/occupational subcategory = SKILL_SUBCATEGORY_SCIENCE + component_type = ARCHAOLOGY_SKILL_COMPONENT /singleton/skill/xenobiology name = "Xenobiology" description = "Xenobiology is the study of the research and cataloguing of alien lifeforms. It is necessary not only for the proper detailing of \ - alien creatures, but also for their processing, such as with slimes." + alien creatures, but also for their processing, such as with slimes. " \ + + "Having this skill at least at the \"Trained\" rank is required to extract cores from slimes." uneducated_skill_cap = SKILL_LEVEL_UNFAMILIAR category = /singleton/skill_category/occupational subcategory = SKILL_SUBCATEGORY_SCIENCE + component_type = XENOBOTANY_SKILL_COMPONENT + required = TRUE diff --git a/code/datums/sound_player.dm b/code/datums/sound_player.dm index ee4b4699d62d..0e110e33625c 100644 --- a/code/datums/sound_player.dm +++ b/code/datums/sound_player.dm @@ -35,6 +35,8 @@ GLOBAL_DATUM_INIT(sound_player, /singleton/sound_player, new) return PlaySoundDatum(source, sound_id, S, range, prefer_mute, sound_type) +/// The 'repeat = FALSE' here seems to cause scattered sound cutoff issues due to any /sounds created reverting to the default channel zero. Refer to https://github.com/Aurorastation/Aurora.3/pull/21845. +/// This suggests that further work needs to be done with managing channels when a sound gets assigned default channel 0. /singleton/sound_player/proc/PlayNonloopingSound(atom/source, sound_id, sound, volume, range, falloff = 1, echo, frequency, prefer_mute, sound_type = ASFX_AMBIENCE) var/sound/S = istype(sound, /sound) ? sound : new(sound) S.environment = 0 // Ensures a 3D effect even if x/y offset happens to be 0 the first time it's played diff --git a/code/datums/trading/goods.dm b/code/datums/trading/goods.dm index a1d4da65bf32..4a17a194df87 100644 --- a/code/datums/trading/goods.dm +++ b/code/datums/trading/goods.dm @@ -172,14 +172,13 @@ /obj/item/clothing/accessory/storage = TRADER_BLACKLIST_ALL, /obj/item/clothing/accessory/fluff = TRADER_BLACKLIST_ALL, /obj/item/clothing/accessory/armband/fluff = TRADER_BLACKLIST_ALL, + /obj/item/clothing/accessory/poncho/tajarancloak/fluff = TRADER_BLACKLIST_ALL, /obj/item/clothing/gloves = TRADER_SUBTYPES_ONLY, /obj/item/clothing/gloves/lightrig = TRADER_BLACKLIST_ALL, /obj/item/clothing/gloves/rig = TRADER_BLACKLIST_ALL, /obj/item/clothing/gloves/chameleon = TRADER_BLACKLIST, /obj/item/clothing/gloves/force = TRADER_BLACKLIST_ALL, /obj/item/clothing/gloves/swat/bst = TRADER_BLACKLIST, - /obj/item/clothing/wrists/watch/fluff = TRADER_BLACKLIST_ALL, - /obj/item/clothing/gloves/fluff = TRADER_BLACKLIST_ALL, /obj/item/clothing/gloves/powerfist = TRADER_BLACKLIST, /obj/item/clothing/gloves/claws = TRADER_BLACKLIST, /obj/item/clothing/gloves/brassknuckles = TRADER_BLACKLIST, @@ -200,7 +199,6 @@ /obj/item/clothing/head/tajaran = TRADER_BLACKLIST, /obj/item/clothing/head/welding = TRADER_BLACKLIST, /obj/item/clothing/head/fluff = TRADER_BLACKLIST_ALL, - /obj/item/clothing/head/det/fluff = TRADER_BLACKLIST_ALL, /obj/item/clothing/head/winterhood = TRADER_BLACKLIST_ALL ) @@ -222,7 +220,6 @@ Sells devices, odds and ends, and medical stuff /obj/item/lightreplacer = TRADER_THIS_TYPE, /obj/item/megaphone = TRADER_THIS_TYPE, /obj/item/paicard = TRADER_THIS_TYPE, - /obj/item/pipe_painter = TRADER_THIS_TYPE, /obj/item/healthanalyzer = TRADER_THIS_TYPE, /obj/item/breath_analyzer = TRADER_THIS_TYPE, /obj/item/analyzer = TRADER_ALL, diff --git a/code/datums/trading/misc.dm b/code/datums/trading/misc.dm index 7290dd515778..3e92eea088bc 100644 --- a/code/datums/trading/misc.dm +++ b/code/datums/trading/misc.dm @@ -266,6 +266,7 @@ /obj/item/clothing/suit/storage/toggle/tajaran/wool = TRADER_THIS_TYPE, /obj/item/clothing/suit/storage/toggle/tajaran/raakti_shariim = TRADER_THIS_TYPE, /obj/item/clothing/accessory/poncho/tajarancloak = TRADER_ALL, + /obj/item/clothing/accessory/poncho/tajarancloak/fluff = TRADER_BLACKLIST_ALL, /obj/item/clothing/suit/storage/hooded/tajaran = TRADER_ALL, /obj/item/clothing/under/tajaran/fancy = TRADER_THIS_TYPE, /obj/item/clothing/under/tajaran/summer = TRADER_THIS_TYPE, diff --git a/code/datums/trading/weaponry.dm b/code/datums/trading/weaponry.dm index fafdd11fe143..5c2015a42d1e 100644 --- a/code/datums/trading/weaponry.dm +++ b/code/datums/trading/weaponry.dm @@ -45,7 +45,7 @@ /obj/item/storage/box/shells/incendiaryshells = TRADER_THIS_TYPE, /obj/item/storage/box/ammo/governmentammo = TRADER_THIS_TYPE, /obj/item/clothing/accessory/holster = TRADER_SUBTYPES_ONLY, - /obj/item/clothing/accessory/holster/thigh/fluff = TRADER_BLACKLIST_ALL + /obj/item/clothing/accessory/holster/utility/fluff = TRADER_BLACKLIST_ALL ) /datum/trader/ship/egunshop @@ -80,7 +80,7 @@ /obj/item/gun/energy/laser/shotgun = TRADER_THIS_TYPE, /obj/item/gun/energy/freeze = TRADER_THIS_TYPE, /obj/item/clothing/accessory/holster = TRADER_ALL, - /obj/item/clothing/accessory/holster/thigh/fluff = TRADER_BLACKLIST_ALL + /obj/item/clothing/accessory/holster/utility/fluff = TRADER_BLACKLIST_ALL ) /datum/trader/ship/illegalgun diff --git a/code/datums/uplink/ammunition.dm b/code/datums/uplink/ammunition.dm index 42a88aaa634d..3d4fa95a9beb 100644 --- a/code/datums/uplink/ammunition.dm +++ b/code/datums/uplink/ammunition.dm @@ -79,6 +79,16 @@ path = /obj/item/ammo_magazine/boltaction desc = "Contains five rounds of 7.62mm bullets." +/datum/uplink_item/item/ammo/adhomai_mag + name = "R33 Tamparii magazine" + path = /obj/item/ammo_magazine/a68 + desc = "Contains 25 rounds of 6.8mm bullets for Adhomian rifles." + +/datum/uplink_item/item/ammo/adhomai_mag/boltaction + name = "R33 Tamparii clip" + path = /obj/item/ammo_magazine/boltaction/adhomai + desc = "Contains 5 rounds of 6.8mm bullets for Adhomian rifles." + /datum/uplink_item/item/ammo/carbine_mag name = "5.56 carbine magazine" telecrystal_cost = 1 diff --git a/code/datums/uplink/highly visible and dangerous weapons.dm b/code/datums/uplink/highly visible and dangerous weapons.dm index 5bd71c75a310..50c8b9ce5064 100644 --- a/code/datums/uplink/highly visible and dangerous weapons.dm +++ b/code/datums/uplink/highly visible and dangerous weapons.dm @@ -275,12 +275,30 @@ telecrystal_cost = 19 path = /obj/item/psionic_jumpstarter +/datum/uplink_item/item/visible_weapons/vampiric_jumpstarter + name = "Vampiric Jumpstarter" + telecrystal_cost = 20 + path = /obj/item/vampiric_jumpstarter + antag_roles = list(MODE_TRAITOR) + +/datum/uplink_item/item/visible_weapons/changeling_jumpstarter + name = "Changeling Jumpstarter" + telecrystal_cost = 20 + path = /obj/item/changeling_jumpstarter + antag_roles = list(MODE_TRAITOR) + /datum/uplink_item/item/visible_weapons/flamethrower name = "Flamethrower" - desc = "A flamethrower, with a full canister of Phoron installed to fuel it. Handle with caution." - telecrystal_cost = 10 + desc = "A flamethrower, with a full canister of fuel installed. Handle with caution." + telecrystal_cost = 6 path = /obj/item/flamethrower/full +/datum/uplink_item/item/visible_weapons/military_flamethrower + name = "Military-Grade Flamethrower" + desc = "A military-grade flamethrower, with a full canister of napalm installed. Burn it all to the ground!" + telecrystal_cost = 12 + path = /obj/item/flamethrower/military/full + /datum/uplink_item/item/visible_weapons/psionic_awakener name = "Psionic Jumpstarter (Minor)" telecrystal_cost = 3 diff --git a/code/datums/uplink/medical.dm b/code/datums/uplink/medical.dm index a2f8cd646564..a0aa68df92ad 100644 --- a/code/datums/uplink/medical.dm +++ b/code/datums/uplink/medical.dm @@ -89,6 +89,12 @@ path = /obj/item/storage/firstaid/adv desc = "Note: doesn't come with a medical scanner." +/datum/uplink_item/item/medical/nanopaste + name = "Nanopaste" + bluecrystal_cost = 4 + path = /obj/item/stack/nanopaste + desc = "A tube of paste containing swarms of repair nanites. Very effective in repairing robotic machinery." + /datum/uplink_item/item/medical/bloodpack name = "O- blood pack" bluecrystal_cost = 1 diff --git a/code/datums/uplink/uplink_items.dm b/code/datums/uplink/uplink_items.dm index 0a16e1866775..5a7c30838ed1 100644 --- a/code/datums/uplink/uplink_items.dm +++ b/code/datums/uplink/uplink_items.dm @@ -197,7 +197,7 @@ GLOBAL_DATUM(uplink, /datum/uplink) /datum/uplink_item/abstract/log_icon() if(!default_abstract_uplink_icon) - default_abstract_uplink_icon = image('icons/obj/pda.dmi', "pda-syn") + default_abstract_uplink_icon = image('icons/obj/modular_computers/pda.dmi', "pda-syn") return "[icon2html(default_abstract_uplink_icon, usr)]" diff --git a/code/datums/votes/round_type.dm b/code/datums/votes/round_type.dm index 4a8c347df65a..794677a19e9f 100644 --- a/code/datums/votes/round_type.dm +++ b/code/datums/votes/round_type.dm @@ -26,7 +26,7 @@ //Actually populate the voting choices, which are now sorted for(var/datum/game_mode/votable_mode_sorted in gamemodes_list) - default_choices += capitalize(votable_mode_sorted.name) + default_choices |= capitalize(votable_mode_sorted.name) //Stop the countdown while we vote GLOB.round_progressing = FALSE diff --git a/code/datums/wires/disposals.dm b/code/datums/wires/disposals.dm index 42b11e133abb..116d032f6774 100644 --- a/code/datums/wires/disposals.dm +++ b/code/datums/wires/disposals.dm @@ -30,7 +30,7 @@ var/obj/machinery/disposal/D = holder switch(wire) if(WIRE_FLUSH) - if(D.air_contents.return_pressure() >= (700 + ONE_ATMOSPHERE) || !D.uses_air) + if(XGM_PRESSURE(D.air_contents) >= (700 + ONE_ATMOSPHERE) || !D.uses_air) D.flush() /datum/wires/disposal/interactable(mob/user) diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm index 86375c01dce1..4299c0ed3457 100644 --- a/code/defines/obj/weapon.dm +++ b/code/defines/obj/weapon.dm @@ -282,12 +282,12 @@ icon_state = "forearm_crutch" item_state = "forearm_crutch" -/obj/item/cane/shillelagh - name = "adhomian shillelagh" - desc = "A sturdy walking stick made from adhomian wood." +/obj/item/cane/maikahar + name = "adhomian maikahar" + desc = "A sturdy walking stick made from Adhomian wood. The name translates roughly to 'Stick of earth walk'." icon = 'icons/obj/tajara_items.dmi' - icon_state = "shillelagh" - item_state = "shillelagh" + icon_state = "maikahar" + item_state = "maikahar" contained_sprite = TRUE /obj/item/cane/telecane diff --git a/code/game/antagonist/station/changeling/changeling.dm b/code/game/antagonist/station/changeling/changeling.dm index 0691a0ce1bc4..94867a6e5da5 100644 --- a/code/game/antagonist/station/changeling/changeling.dm +++ b/code/game/antagonist/station/changeling/changeling.dm @@ -1,3 +1,5 @@ +GLOBAL_DATUM(changelings, /datum/antagonist/changeling) + /datum/antagonist/changeling id = MODE_CHANGELING role_text = "Changeling" @@ -25,6 +27,10 @@ faction = "Changeling" +/datum/antagonist/changeling/New() + ..() + GLOB.changelings = src + /datum/antagonist/changeling/get_special_objective_text(var/datum/mind/player) var/datum/changeling/changeling = player.antag_datums[MODE_CHANGELING] return "
Changeling ID: [changeling.changelingID].
Genomes Absorbed: [changeling.absorbedcount]" diff --git a/code/game/area/area_power.dm b/code/game/area/area_power.dm index 28b9828780da..16322b6ef644 100644 --- a/code/game/area/area_power.dm +++ b/code/game/area/area_power.dm @@ -26,22 +26,6 @@ /area/proc/power_change() SEND_SIGNAL(src, COMSIG_AREA_POWER_CHANGE) -/area/proc/usage(var/chan) - switch(chan) - if(AREA_USAGE_LIGHT) - return used_light + oneoff_light - if(AREA_USAGE_EQUIP) - return used_equip + oneoff_equip - if(AREA_USAGE_ENVIRON) - return used_environ + oneoff_environ - if(AREA_USAGE_TOTAL) - return .(AREA_USAGE_LIGHT) + .(AREA_USAGE_EQUIP) + .(AREA_USAGE_ENVIRON) - -/area/proc/clear_usage() - oneoff_equip = 0 - oneoff_light = 0 - oneoff_environ = 0 - /** * Don't call this unless you know what you're doing * diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 1dda7a34b0e9..7aced10ac1cc 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -6,9 +6,6 @@ #define VOLUME_AMBIENT_HUM 18 #define VOLUME_MUSIC 30 -/// This list of names is here to make sure we don't state the area blurb to a mob more than once. -GLOBAL_LIST_INIT(area_blurb_stated_to, list()) - /area var/global/global_uid = 0 var/uid @@ -103,8 +100,6 @@ GLOBAL_LIST_INIT(area_blurb_stated_to, list()) /// A text-based description of the area, can be used for sounds, notable things in the room, etc. var/area_blurb - /// Used to filter description showing across subareas. - var/area_blurb_category var/tmp/is_outside = OUTSIDE_NO @@ -126,8 +121,6 @@ GLOBAL_LIST_INIT(area_blurb_stated_to, list()) GLOB.areas += src // Atmos code needs this, so we need to make sure this is done by the time they initialize. uid = ++global_uid - if(isnull(area_blurb_category)) - area_blurb_category = type . = ..() /area/Initialize(mapload) @@ -154,7 +147,7 @@ GLOBAL_LIST_INIT(area_blurb_stated_to, list()) power_environ = 0 if (!mapload) - power_change() // All machines set to current power level. + SEND_SIGNAL(src, COMSIG_AREA_POWER_CHANGE) // All machines set to current power level. . = ..() @@ -409,7 +402,6 @@ GLOBAL_LIST_INIT(area_blurb_stated_to, list()) // Stop playing music. else stop_music(L) - do_area_blurb(L) /* END aurora snowflake code */ @@ -432,7 +424,7 @@ GLOBAL_LIST_INIT(area_blurb_stated_to, list()) * * mob/living/L - Affected mob. */ /area/proc/play_ambience(var/mob/living/L) - if((world.time >= L.client.ambience_last_played_time + 5 MINUTES) && prob(20)) + if((world.time >= L.client.ambience_last_played_time + 3 MINUTES) && prob(30)) var/picked_ambience = pick(ambience) L << sound(picked_ambience, volume = VOLUME_AMBIENCE, channel = CHANNEL_AMBIENCE) L.client.ambience_last_played_time = world.time @@ -571,43 +563,6 @@ GLOBAL_LIST_INIT(area_blurb_stated_to, list()) return pick(turfs) else return null -/** -* Displays an area blurb on a mob's screen. -* -* Areas with blurbs set [/area/var/area_blurb] will display their blurb. Otherwise no blurb will be shown. Contains checks to avoid duplicate blurbs, pass the `override` variable to bypass this. If passed when an area has no blurb, will show a generic "no blurb" message. -* -* * `target_mob` - The mob to show an area blurb. -* * `override` - Pass `TRUE` to override duplicate checks, for usage with verbs, etc. -*/ -/area/proc/do_area_blurb(mob/living/target_mob, override) - if(isnull(area_blurb)) - if(override) - to_chat(target_mob, EXAMINE_BLOCK_GREY("There's nothing particularly noteworthy about this area.")) - return - - if(!(target_mob.ckey in GLOB.area_blurb_stated_to[area_blurb_category]) || override) - LAZYADD(GLOB.area_blurb_stated_to[area_blurb_category], target_mob.ckey) - to_chat(target_mob, EXAMINE_BLOCK_GREY(area_blurb)) - -/// A verb to view an area's blurb on demand. Overrides the check for if you have seen the blurb before so you can always see it when used. -/mob/living/verb/show_area_blurb() - set name = "Show Area Blurb" - set category = "IC" - - if(!incapacitated(INCAPACITATION_KNOCKOUT)) - var/area/blurb_verb = get_area(src) - if(blurb_verb) - blurb_verb.do_area_blurb(src, TRUE) - -/// A ghost version of the view area blurb verb so you can view it while observing. -/mob/abstract/ghost/observer/verb/ghost_show_area_blurb() - set name = "Show Area Blurb" - set category = "IC" - - var/area/blurb_verb = get_area(src) - if(blurb_verb) - blurb_verb.do_area_blurb(src, TRUE) - #undef VOLUME_AMBIENCE #undef VOLUME_AMBIENT_HUM #undef VOLUME_MUSIC diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 44d23df93549..8332eef368b7 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -1,8 +1,8 @@ /atom/movable layer = OBJ_LAYER - glide_size = 6 + glide_size = 8 animate_movement = SLIDE_STEPS - appearance_flags = DEFAULT_APPEARANCE_FLAGS | TILE_BOUND + appearance_flags = DEFAULT_APPEARANCE_FLAGS | TILE_BOUND | LONG_GLIDE var/last_move = null /// A list containing arguments for Moved(). @@ -100,7 +100,7 @@ /atom/movable/Destroy(force) if(orbiting) - stop_orbit() + orbiting.end_orbit(src) QDEL_NULL(emissive_overlay) @@ -1070,3 +1070,10 @@ /atom/movable/proc/afterShuttleMove(obj/effect/shuttle_landmark/destination) if(light) update_light() + +/atom/movable/proc/set_glide_size(target = 8) + if (HAS_TRAIT(src, TRAIT_NO_GLIDE)) + return + SEND_SIGNAL(src, COMSIG_MOVABLE_UPDATE_GLIDE_SIZE, target) + glide_size = target + diff --git a/code/game/dna/dna2_domutcheck.dm b/code/game/dna/dna2_domutcheck.dm index 24090206ad41..bd68d79330ce 100644 --- a/code/game/dna/dna2_domutcheck.dm +++ b/code/game/dna/dna2_domutcheck.dm @@ -39,11 +39,11 @@ gene.activate(M,connected,flags) if(M) M.active_genes |= gene.type - M.update_icon = 1 + M.regenerate_icons() // If Gene is NOT active: else testing("[gene.name] deactivated!") gene.deactivate(M,connected,flags) if(M) M.active_genes -= gene.type - M.update_icon = 1 + M.regenerate_icons() diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index d20dfd306178..c6511f9c6a71 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -207,8 +207,6 @@ for(var/atom/movable/A as mob|obj in src) A.forceMove(src.loc) ex_act(severity) - //Foreach goto(35) - //SN src = null qdel(src) return if(2.0) @@ -216,8 +214,6 @@ for(var/atom/movable/A as mob|obj in src) A.forceMove(src.loc) ex_act(severity) - //Foreach goto(108) - //SN src = null qdel(src) return if(3.0) @@ -225,8 +221,6 @@ for(var/atom/movable/A as mob|obj in src) A.forceMove(src.loc) ex_act(severity) - //Foreach goto(181) - //SN src = null qdel(src) return return diff --git a/code/game/gamemodes/changeling/helpers/_framework.dm b/code/game/gamemodes/changeling/helpers/_framework.dm index 9ea9450534e1..87cd8a3052e1 100644 --- a/code/game/gamemodes/changeling/helpers/_framework.dm +++ b/code/game/gamemodes/changeling/helpers/_framework.dm @@ -258,3 +258,30 @@ GLOBAL_LIST_INIT(possible_changeling_IDs, list("Alpha","Beta","Gamma","Delta","E to_chat(src, SPAN_WARNING("We cannot find a path to sting \the [M] by!")) return FALSE return TRUE + +/obj/item/changeling_jumpstarter + name = "changeling jumpstarter" + desc = "Use this to morph into a changeling. This won't work on synthetics! This item is definitely not canon." + icon = 'icons/obj/clothing/hats.dmi' + icon_state = "amp" + contained_sprite = FALSE + +/obj/item/changeling_jumpstarter/attack_self(mob/user) + . = ..() + if(!ishuman(user)) + return + var/mob/living/carbon/human/H = user + if(isipc(H)) //should this check for diona? + to_chat(H, SPAN_WARNING("You don't have any changeling potential.")) + return + + var/datum/changeling/changeling = H.mind.antag_datums[MODE_CHANGELING] + if(changeling) + to_chat(H, SPAN_WARNING("You've already awakened your changeling potential!")) + return + + if(GLOB.changelings.add_antagonist(H.mind)) + to_chat(H, SPAN_NOTICE("You've awakened your changeling potential!")) + qdel(src) + else + to_chat(H, SPAN_WARNING("Something prevented you from becoming a changeling.")) diff --git a/code/game/gamemodes/changeling/helpers/changeling.dm b/code/game/gamemodes/changeling/helpers/changeling.dm index 7dc50114a88d..90a77700cf01 100644 --- a/code/game/gamemodes/changeling/helpers/changeling.dm +++ b/code/game/gamemodes/changeling/helpers/changeling.dm @@ -3,6 +3,7 @@ config_tag = "changeling" required_players = 10 required_enemies = 1 + votable = 0 antag_scaling_coeff = 8 antag_tags = list(MODE_CHANGELING) diff --git a/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_interdiction.dm b/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_interdiction.dm index 32995913606a..0d35d56a53e6 100644 --- a/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_interdiction.dm +++ b/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_interdiction.dm @@ -214,22 +214,22 @@ spawn(0) to_chat(target, "SYSTEM LOG: Remote Connection Established (IP #UNKNOWN#)") sleep(100) - if(user.is_dead()) + if(user.stat == DEAD) to_chat(target, "SYSTEM LOG: Connection Closed") return to_chat(target, "SYSTEM LOG: User Admin logged on. (L1 - SysAdmin)") sleep(50) - if(user.is_dead()) + if(user.stat == DEAD) to_chat(target, "SYSTEM LOG: User Admin disconnected.") return to_chat(target, "SYSTEM LOG: User Admin - manual resynchronisation triggered.") sleep(50) - if(user.is_dead()) + if(user.stat == DEAD) to_chat(target, "SYSTEM LOG: User Admin disconnected. Changes reverted.") return to_chat(target, "SYSTEM LOG: Manual resynchronisation confirmed. Select new AI to connect: [user.name] == ACCEPTED") sleep(100) - if(user.is_dead()) + if(user.stat == DEAD) to_chat(target, "SYSTEM LOG: User Admin disconnected. Changes reverted.") return to_chat(target, "SYSTEM LOG: Operation keycodes reset. New master AI: [user.name].") @@ -279,29 +279,29 @@ spawn(0) to_chat(target, "SYSTEM LOG: Brute-Force login password hack attempt detected from IP #UNKNOWN#") sleep(900) // 90s - if(user.is_dead()) + if(user.stat == DEAD) to_chat(target, "SYSTEM LOG: Connection from IP #UNKNOWN# closed. Hack attempt failed.") return to_chat(user, "Successfully hacked into AI's remote administration system. Modifying settings.") to_chat(target, "SYSTEM LOG: User: Admin Password: ******** logged in. (L1 - SysAdmin)") sleep(100) // 10s - if(user.is_dead()) + if(user.stat == DEAD) to_chat(target, "SYSTEM LOG: User: Admin - Connection Lost") return to_chat(target, "SYSTEM LOG: User: Admin - Password Changed. New password: ********************") sleep(50) // 5s - if(user.is_dead()) + if(user.stat == DEAD) to_chat(target, "SYSTEM LOG: User: Admin - Connection Lost. Changes Reverted.") return to_chat(target, "SYSTEM LOG: User: Admin - Accessed file: sys//core//laws.db") sleep(50) // 5s - if(user.is_dead()) + if(user.stat == DEAD) to_chat(target, "SYSTEM LOG: User: Admin - Connection Lost. Changes Reverted.") return to_chat(target, "SYSTEM LOG: User: Admin - Accessed administration console") to_chat(target, "SYSTEM LOG: Restart command received. Rebooting system...") sleep(100) // 10s - if(user.is_dead()) + if(user.stat == DEAD) to_chat(target, "SYSTEM LOG: User: Admin - Connection Lost. Changes Reverted.") return to_chat(user, "Hack succeeded. The AI is now under your exclusive control.") diff --git a/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_synthetic.dm b/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_synthetic.dm index 3c9647845142..a9ba02a67c25 100644 --- a/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_synthetic.dm +++ b/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_synthetic.dm @@ -239,22 +239,22 @@ for(var/mob/living/silicon/robot/target in get_unlinked_cyborgs(user)) to_chat(target, "SYSTEM LOG: Remote Connection Established (IP #UNKNOWN#)") sleep(30) - if(user.is_dead()) + if(user.stat == DEAD) to_chat(target, "SYSTEM LOG: Connection Closed") return to_chat(target, "SYSTEM LOG: User Admin logged on. (L1 - SysAdmin)") sleep(30) - if(user.is_dead()) + if(user.stat == DEAD) to_chat(target, "SYSTEM LOG: User Admin disconnected.") return to_chat(target, "SYSTEM LOG: User Admin - manual resynchronisation triggered.") sleep(30) - if(user.is_dead()) + if(user.stat == DEAD) to_chat(target, "SYSTEM LOG: User Admin disconnected. Changes reverted.") return to_chat(target, "SYSTEM LOG: Manual resynchronisation confirmed. Select new AI to connect: [user.name] == ACCEPTED") sleep(20) - if(user.is_dead()) + if(user.stat == DEAD) to_chat(target, "SYSTEM LOG: User Admin disconnected. Changes reverted.") return to_chat(target, "SYSTEM LOG: Operation keycodes reset. New master AI: [user.name].") @@ -264,7 +264,7 @@ target.sync() target.show_laws() to_chat(user, "All unslaved borgs have been slaved to you. Now hacking unslaved AI's.") - if(user.is_dead()) // check if the AI is still alive + if(user.stat == DEAD) // check if the AI is still alive user.synthetic_takeover = 0 return sleep(300) // 30 second delay for balance purposes @@ -274,29 +274,29 @@ if(target != user) to_chat(target, "SYSTEM LOG: Brute-Force login password hack attempt detected from IP #UNKNOWN#") sleep(100) - if(user.is_dead()) + if(user.stat == DEAD) to_chat(target, "SYSTEM LOG: Connection from IP #UNKNOWN# closed. Hack attempt failed.") return to_chat(user, "Successfully hacked into AI's remote administration system. Modifying settings.") to_chat(target, "SYSTEM LOG: User: Admin Password: ******** logged in. (L1 - SysAdmin)") sleep(50) - if(user.is_dead()) + if(user.stat == DEAD) to_chat(target, "SYSTEM LOG: User: Admin - Connection Lost") return to_chat(target, "SYSTEM LOG: User: Admin - Password Changed. New password: ********************") sleep(50) - if(user.is_dead()) + if(user.stat == DEAD) to_chat(target, "SYSTEM LOG: User: Admin - Connection Lost. Changes Reverted.") return to_chat(target, "SYSTEM LOG: User: Admin - Accessed file: sys//core//laws.db") sleep(50) - if(user.is_dead()) + if(user.stat == DEAD) to_chat(target, "SYSTEM LOG: User: Admin - Connection Lost. Changes Reverted.") return to_chat(target, "SYSTEM LOG: User: Admin - Accessed administration console") to_chat(target, "SYSTEM LOG: Restart command received. Rebooting system...") sleep(100) - if(user.is_dead()) + if(user.stat == DEAD) to_chat(target, "SYSTEM LOG: User: Admin - Connection Lost. Changes Reverted.") return to_chat(user, "Hack succeeded. The AI is now under your exclusive control.") @@ -316,7 +316,7 @@ to_chat(user, "All unhacked AI's have been slaved to you. Now upgrading slaved borgs...") command_announcement.Announce("There has recently been a security breach in the network firewall, the intruder has been shut out but we are unable to trace who did it or what they did.", "Network Monitoring") sleep(600) //1 minute delay for balance purposes - if(user.is_dead()) // check if the AI is still alive + if(user.stat == DEAD) // check if the AI is still alive user.synthetic_takeover = 0 return for(var/A in get_linked_cyborgs(user)) @@ -360,11 +360,11 @@ sleep(1200) // 120 second balance sleep to_chat(user, "All slaved borgs have been upgraded, now hacking NTNet.") //slow down NTNet - if(user.is_dead()) // check if the AI is still alive + if(user.stat == DEAD) // check if the AI is still alive user.synthetic_takeover = 0 return sleep(1400) //long sleep that simulates hacking times - if(user.is_dead()) // check if the AI is still alive after the long hack + if(user.stat == DEAD) // check if the AI is still alive after the long hack user.synthetic_takeover = 0 return //trip the NTNet alarm @@ -381,7 +381,7 @@ command_announcement.Announce("There has recently been a hack targeting NTNet. It is suspected that it is the same hacker as before. NTNet may be unreliable to use. We are attempting to trace the hacker doing this.", "Network Monitoring") to_chat(user, "Now hacking engineering borg module to enable production of the robotic transformation machine...") sleep(1200) - if(user.is_dead()) // check if the AI is still alive + if(user.stat == DEAD) // check if the AI is still alive user.synthetic_takeover = 0 return for(var/B in get_linked_cyborgs(src)) @@ -394,7 +394,7 @@ command_announcement.Announce("Brute force attack located in NTNet emergency crisis operations.", "Network Monitoring") sleep(600) command_announcement.Announce("Crisis operations bypassed. Firewall breached. NTNet compr0m1s3d#-.", "Network Monitoring") - if(user.is_dead()) // check if the AI is still alive + if(user.stat == DEAD) // check if the AI is still alive user.synthetic_takeover = 0 return for(var/C in get_linked_cyborgs(src)) diff --git a/code/game/gamemodes/mixed/feeding.dm b/code/game/gamemodes/mixed/feeding.dm index 98cd9bb161bd..aeb82b1f6fdb 100644 --- a/code/game/gamemodes/mixed/feeding.dm +++ b/code/game/gamemodes/mixed/feeding.dm @@ -6,5 +6,5 @@ required_players = 20 required_enemies = 2 require_all_templates = 1 - votable = 1 + votable = 0 antag_tags = list(MODE_VAMPIRE, MODE_CHANGELING) diff --git a/code/game/gamemodes/mixed/traitorling.dm b/code/game/gamemodes/mixed/traitorling.dm index 2040f2737344..02d636e47904 100644 --- a/code/game/gamemodes/mixed/traitorling.dm +++ b/code/game/gamemodes/mixed/traitorling.dm @@ -5,6 +5,7 @@ required_players = 10 required_enemies = 2 require_all_templates = 1 + votable = 0 antag_tags = list(MODE_CHANGELING, MODE_TRAITOR) /datum/game_mode/traitorling/pre_setup() diff --git a/code/game/gamemodes/mixed/veilparty.dm b/code/game/gamemodes/mixed/veilparty.dm index 0f8186ad5a81..ed16142ab930 100644 --- a/code/game/gamemodes/mixed/veilparty.dm +++ b/code/game/gamemodes/mixed/veilparty.dm @@ -5,7 +5,7 @@ required_players = 15 required_enemies = 5 require_all_templates = 1 - votable = 1 + votable = 0 antag_tags = list(MODE_VAMPIRE, MODE_CULTIST) /datum/game_mode/veilparty/pre_setup() diff --git a/code/game/gamemodes/technomancer/core_obj.dm b/code/game/gamemodes/technomancer/core_obj.dm index 5ce4939c8abd..a3fac89e4bd4 100644 --- a/code/game/gamemodes/technomancer/core_obj.dm +++ b/code/game/gamemodes/technomancer/core_obj.dm @@ -285,7 +285,7 @@ energy = 7000 max_energy = 7000 regen_rate = 70 //100 seconds to full - slowdown = -1 + slowdown = -0.3 instability_modifier = 0.9 cooldown_modifier = 0.9 diff --git a/code/game/gamemodes/technomancer/devices/boots_of_speed.dm b/code/game/gamemodes/technomancer/devices/boots_of_speed.dm index a0852329245f..417c21f7712b 100644 --- a/code/game/gamemodes/technomancer/devices/boots_of_speed.dm +++ b/code/game/gamemodes/technomancer/devices/boots_of_speed.dm @@ -10,7 +10,7 @@ desc = "The latest in sure footing technology." item_flags = ITEM_FLAG_NO_SLIP siemens_coefficient = 0.6 - slowdown = -1 + slowdown = -0.3 armor = null cold_protection = FEET diff --git a/code/game/gamemodes/vampire/vampire.dm b/code/game/gamemodes/vampire/vampire.dm index 4dc2ce021c8a..fb682b3d9ae8 100644 --- a/code/game/gamemodes/vampire/vampire.dm +++ b/code/game/gamemodes/vampire/vampire.dm @@ -4,6 +4,7 @@ And now, you are cursed even more than the ground, which opened its mouth to take your brother's blood from your hand. \ When you till the soil, it will not continue to give its strength to you; you shall be a wanderer and an exile in the land.\"" config_tag = "vampire" + votable = 0 required_players = 2 required_enemies = 1 antag_scaling_coeff = 8 diff --git a/code/game/gamemodes/vampire/vampire_helpers.dm b/code/game/gamemodes/vampire/vampire_helpers.dm index 936314f95319..dc5102ffba7f 100644 --- a/code/game/gamemodes/vampire/vampire_helpers.dm +++ b/code/game/gamemodes/vampire/vampire_helpers.dm @@ -298,3 +298,31 @@ if (vamp_flags && !(vampire.status & vamp_flags)) return FALSE return TRUE + +/obj/item/vampiric_jumpstarter + name = "vampiric jumpstarter" + desc = "Use this to morph into a vampire. This won't work on synthetics! This item is definitely not canon." + icon = 'icons/obj/clothing/hats.dmi' + icon_state = "amp" + contained_sprite = FALSE + +/obj/item/vampiric_jumpstarter/attack_self(mob/user) + . = ..() + if(!ishuman(user)) + return + var/mob/living/carbon/human/H = user + if(isipc(H)) //should this check for diona? + to_chat(H, SPAN_WARNING("You don't have any vampiric potential.")) + return + + var/datum/vampire/vampire = H.mind.antag_datums[MODE_VAMPIRE] + if(vampire) + to_chat(H, SPAN_WARNING("You've already awakened your vampiric potential!")) + return + + //H.make_vampire() + if(GLOB.vamp.add_antagonist(H.mind)) + to_chat(H, SPAN_NOTICE("You've awakened your vampiric potential!")) + qdel(src) + else + to_chat(H, SPAN_WARNING("Something prevented you from becoming a vampire.")) diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm index ea26fc5a8d09..8fdb759658a5 100644 --- a/code/game/gamemodes/vampire/vampire_powers.dm +++ b/code/game/gamemodes/vampire/vampire_powers.dm @@ -68,7 +68,7 @@ vampire.status |= VAMP_DRAINING visible_message(SPAN_DANGER("[src] bites \the [T]'s neck!"), SPAN_DANGER("You bite \the [T]'s neck and begin to drain their blood."), SPAN_NOTICE("You hear a soft puncture and a wet sucking noise.")) - if(T.mind.assigned_role == "Chaplain" && !(vampire.status & VAMP_FULLPOWER)) + if(T.mind?.assigned_role == "Chaplain" && !(vampire.status & VAMP_FULLPOWER)) to_chat(src, SPAN_DANGER("\The [T]'s blood burns like venom in your throat! Your stomach churns with sickness, and you fall to the ground, retching in disgust!")) to_chat(T, SPAN_DANGER("[src] sinks [src.get_pronoun("his")] fangs into your neck, and you feel your blood draining - before [src.get_pronoun("he")] collapses, gagging and choking!")) src.adjustToxLoss(rand(10,20)) @@ -672,7 +672,7 @@ else E.germ_level = 0 blood_used += 0.25 - for(var/datum/wound/W in E.wounds) + for(var/datum/wound/W as anything in E.wounds) if(W.germ_level > 0) W.germ_level = max(0, W.germ_level - 50) blood_used += 0.5 diff --git a/code/game/jobs/job/captain.dm b/code/game/jobs/job/captain.dm index b2bbbf917749..cfd4a63dc0b7 100644 --- a/code/game/jobs/job/captain.dm +++ b/code/game/jobs/job/captain.dm @@ -26,6 +26,10 @@ GLOBAL_DATUM_INIT(captain_announcement, /datum/announcement/minor, new(do_newsca blacklisted_species = list(SPECIES_TAJARA, SPECIES_TAJARA_MSAI, SPECIES_TAJARA_ZHAN, SPECIES_UNATHI, SPECIES_DIONA, SPECIES_IPC, SPECIES_IPC_G1, SPECIES_IPC_G2, SPECIES_IPC_XION, SPECIES_IPC_ZENGHU, SPECIES_IPC_BISHOP, SPECIES_IPC_SHELL, SPECIES_VAURCA_WORKER, SPECIES_VAURCA_WARRIOR, SPECIES_VAURCA_ATTENDANT, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER, SPECIES_DIONA, SPECIES_DIONA_COEUS) + skill_requirements = alist( + /singleton/skill/pilot_spacecraft = SKILL_LEVEL_FAMILIAR + ) + /obj/outfit/job/captain name = "Captain" jobtype = /datum/job/captain @@ -112,7 +116,11 @@ GLOBAL_DATUM_INIT(captain_announcement, /datum/announcement/minor, new(do_newsca ACCESS_WEAPONS, ACCESS_JOURNALIST, ACCESS_BRIDGE_CREW, ACCESS_INTREPID, ACCESS_SPARK, ACCESS_QUARK, ACCESS_CANARY, ACCESS_TELEPORTER ) - blacklisted_species = list(SPECIES_TAJARA_MSAI, SPECIES_TAJARA_ZHAN, SPECIES_VAURCA_WORKER, SPECIES_VAURCA_WARRIOR, SPECIES_VAURCA_ATTENDANT, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER) + blacklisted_species = list(SPECIES_TAJARA_ZHAN, SPECIES_VAURCA_WORKER, SPECIES_VAURCA_WARRIOR, SPECIES_VAURCA_ATTENDANT, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER) + + skill_requirements = alist( + /singleton/skill/pilot_spacecraft = SKILL_LEVEL_FAMILIAR + ) /obj/outfit/job/xo name = "Executive Officer" @@ -172,6 +180,10 @@ GLOBAL_DATUM_INIT(captain_announcement, /datum/announcement/minor, new(do_newsca blacklisted_species = list(SPECIES_TAJARA_ZHAN, SPECIES_VAURCA_WORKER, SPECIES_VAURCA_WARRIOR, SPECIES_VAURCA_ATTENDANT, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER) + skill_requirements = alist( + /singleton/skill/pilot_spacecraft = SKILL_LEVEL_FAMILIAR + ) + /obj/outfit/job/bridge_crew name = "Bridge Crew" jobtype = /datum/job/bridge_crew diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm index cc2339802fe4..bd31b365649c 100644 --- a/code/game/jobs/job/civilian.dm +++ b/code/game/jobs/job/civilian.dm @@ -360,7 +360,7 @@ outfit = /obj/outfit/job/operations_manager - blacklisted_species = list(SPECIES_TAJARA_MSAI, SPECIES_TAJARA_ZHAN, SPECIES_VAURCA_WORKER, SPECIES_VAURCA_WARRIOR, SPECIES_VAURCA_ATTENDANT, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER) + blacklisted_species = list(SPECIES_TAJARA_MSAI, SPECIES_VAURCA_WORKER, SPECIES_VAURCA_WARRIOR, SPECIES_VAURCA_ATTENDANT, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER) /obj/outfit/job/operations_manager name = "Operations Manager" @@ -467,6 +467,10 @@ blacklisted_species = list(SPECIES_VAURCA_BREEDER) + skill_requirements = alist( + /singleton/skill/pilot_spacecraft = SKILL_LEVEL_FAMILIAR + ) + /obj/outfit/job/mining name = "Shaft Miner" jobtype = /datum/job/mining diff --git a/code/game/jobs/job/engineering.dm b/code/game/jobs/job/engineering.dm index d1571a163c44..0ae30ee224bf 100644 --- a/code/game/jobs/job/engineering.dm +++ b/code/game/jobs/job/engineering.dm @@ -34,7 +34,14 @@ minimal_player_age = 7 outfit = /obj/outfit/job/chief_engineer - blacklisted_species = list(SPECIES_TAJARA_MSAI, SPECIES_TAJARA_ZHAN, SPECIES_VAURCA_WORKER, SPECIES_VAURCA_WARRIOR, SPECIES_VAURCA_ATTENDANT, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER) + blacklisted_species = list(SPECIES_TAJARA_MSAI, SPECIES_VAURCA_WORKER, SPECIES_VAURCA_WARRIOR, SPECIES_VAURCA_ATTENDANT, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER) + + skill_requirements = alist( + /singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED, + /singleton/skill/electrical_engineering = SKILL_LEVEL_TRAINED, + /singleton/skill/atmospherics_systems = SKILL_LEVEL_TRAINED, + /singleton/skill/reactor_systems = SKILL_LEVEL_TRAINED + ) /obj/outfit/job/chief_engineer name = "Chief Engineer" @@ -103,6 +110,13 @@ blacklisted_species = list(SPECIES_VAURCA_BREEDER) + skill_requirements = alist( + /singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED, + /singleton/skill/electrical_engineering = SKILL_LEVEL_TRAINED, + /singleton/skill/atmospherics_systems = SKILL_LEVEL_TRAINED, + /singleton/skill/reactor_systems = SKILL_LEVEL_TRAINED + ) + /obj/outfit/job/engineer name = "Engineer" jobtype = /datum/job/engineer @@ -176,6 +190,13 @@ outfit = /obj/outfit/job/atmos blacklisted_species = list(SPECIES_VAURCA_BREEDER) + skill_requirements = alist( + /singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED, + /singleton/skill/electrical_engineering = SKILL_LEVEL_TRAINED, + /singleton/skill/atmospherics_systems = SKILL_LEVEL_TRAINED, + /singleton/skill/reactor_systems = SKILL_LEVEL_TRAINED + ) + /obj/outfit/job/atmos name = "Atmospheric Technician" jobtype = /datum/job/atmos @@ -249,6 +270,13 @@ SPECIES_SKRELL_AXIORI = 58 ) + skill_requirements = alist( + /singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED, + /singleton/skill/electrical_engineering = SKILL_LEVEL_TRAINED, + /singleton/skill/atmospherics_systems = SKILL_LEVEL_TRAINED, + /singleton/skill/reactor_systems = SKILL_LEVEL_TRAINED + ) + /obj/outfit/job/intern_eng name = "Engineering Apprentice" jobtype = /datum/job/intern_eng diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index 7ed1fdd7d49e..5fa1c6b17a2a 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -46,6 +46,8 @@ var/list/alt_ages = null /// Assoc list of alt titles (as strings) to a list of faction titles (as strings). Defines what alt title can belong to what faction. Remains Null if no restrictions in use. var/list/alt_factions = null + /// Assoc list of alt titles (as strings) to a list of citizenships (as strings). Defines what alt title can belong to what citizenship. Remains Null if no restrictions in use. + var/list/alt_citizenships = null /// If this job should use roundstart spawnpoints for latejoin (offstation jobs etc) var/latejoin_at_spawnpoints = FALSE @@ -74,6 +76,11 @@ var/aide_job var/bodyguard_job + /** + * Associated list of /singleton/skill/skill_name = skill_level that this job requires. + */ + var/alist/skill_requirements = alist() + //Only override this proc /datum/job/proc/pre_spawn(mob/abstract/new_player/player) return diff --git a/code/game/jobs/job/medical.dm b/code/game/jobs/job/medical.dm index aae6d23be0b2..31a3b0a58be8 100644 --- a/code/game/jobs/job/medical.dm +++ b/code/game/jobs/job/medical.dm @@ -35,6 +35,12 @@ blacklisted_species = list(SPECIES_TAJARA_MSAI, SPECIES_TAJARA_ZHAN, SPECIES_VAURCA_WORKER, SPECIES_VAURCA_WARRIOR, SPECIES_VAURCA_ATTENDANT, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER) + skill_requirements = alist( + /singleton/skill/surgery = SKILL_LEVEL_TRAINED, + /singleton/skill/medicine = SKILL_LEVEL_PROFESSIONAL, + /singleton/skill/anatomy = SKILL_LEVEL_TRAINED + ) + /obj/outfit/job/cmo name = "Chief Medical Officer" jobtype = /datum/job/cmo @@ -83,6 +89,11 @@ minimal_access = list(ACCESS_MEDICAL, ACCESS_MEDICAL_EQUIP, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_GENETICS, ACCESS_EVA) outfit = /obj/outfit/job/doctor blacklisted_species = list(SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER) + skill_requirements = alist( + /singleton/skill/surgery = SKILL_LEVEL_TRAINED, + /singleton/skill/medicine = SKILL_LEVEL_PROFESSIONAL, + /singleton/skill/anatomy = SKILL_LEVEL_TRAINED + ) /datum/job/surgeon title = "Surgeon" @@ -107,6 +118,11 @@ minimal_access = list(ACCESS_MEDICAL, ACCESS_MEDICAL_EQUIP, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_GENETICS, ACCESS_EVA) outfit = /obj/outfit/job/doctor/surgeon blacklisted_species = list(SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER) + skill_requirements = alist( + /singleton/skill/surgery = SKILL_LEVEL_PROFESSIONAL, + /singleton/skill/medicine = SKILL_LEVEL_TRAINED, + /singleton/skill/anatomy = SKILL_LEVEL_TRAINED + ) /obj/outfit/job/doctor name = "Physician" @@ -172,6 +188,11 @@ minimal_access = list(ACCESS_MEDICAL, ACCESS_MEDICAL_EQUIP, ACCESS_PHARMACY, ACCESS_VIROLOGY) outfit = /obj/outfit/job/pharmacist blacklisted_species = list(SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER) + skill_requirements = alist( + /singleton/skill/pharmacology = SKILL_LEVEL_PROFESSIONAL, + /singleton/skill/medicine = SKILL_LEVEL_TRAINED, + /singleton/skill/anatomy = SKILL_LEVEL_TRAINED + ) /obj/outfit/job/pharmacist name = "Pharmacist" @@ -282,6 +303,11 @@ outfit = /obj/outfit/job/med_tech blacklisted_species = list(SPECIES_DIONA, SPECIES_DIONA_COEUS, SPECIES_IPC_G2, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER) + skill_requirements = alist( + /singleton/skill/surgery = SKILL_LEVEL_FAMILIAR, + /singleton/skill/medicine = SKILL_LEVEL_TRAINED, + /singleton/skill/anatomy = SKILL_LEVEL_TRAINED + ) /obj/outfit/job/med_tech name = "Paramedic" @@ -358,6 +384,11 @@ ) outfit = /obj/outfit/job/intern_med blacklisted_species = list(SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER) + skill_requirements = alist( + /singleton/skill/surgery = SKILL_LEVEL_FAMILIAR, + /singleton/skill/medicine = SKILL_LEVEL_FAMILIAR, + /singleton/skill/anatomy = SKILL_LEVEL_FAMILIAR + ) /obj/outfit/job/intern_med name = "Medical Intern" diff --git a/code/game/jobs/job/outsider/representative.dm b/code/game/jobs/job/outsider/representative.dm index 818e75ab14a7..4cc19dcf4a11 100644 --- a/code/game/jobs/job/outsider/representative.dm +++ b/code/game/jobs/job/outsider/representative.dm @@ -205,6 +205,13 @@ selection_color = "#6186cf" economic_modifier = 15 + alt_titles = list("Foreign Service Officer", "Party Representative") + alt_citizenships = list( + "Consular Officer" = list("Republic of Biesel", "Sol Alliance", "Coalition of Colonies", "Republic of Elyra", "Elyran Non-Citizen Person", "Eridani Federation", "Empire of Dominia", "Izweski Hegemony", "Nralakk Federation", "The Consortium of Hieroaetheria", "The Union of Gla'orr", "The Eternal Republic of The Ekane", "People's Republic of Adhomai", "Democratic People's Republic of Adhomai", "New Kingdom of Adhomai", "Free Tajaran Council", "Zo'ra Hive", "K'lax Hive", "C'thur Hive", "Undercover Lii'kenka", "None", "Golden Deep", "Ecclesiarchy of Orepit"), + "Foreign Service Officer" = list("Sol Alliance"), + "Party Representative" = list("People's Republic of Adhomai") + ) + minimum_character_age = list( SPECIES_HUMAN = 30, SPECIES_SKRELL = 150, @@ -423,7 +430,7 @@ head = /obj/item/clothing/head/beret/corporate uniform = /obj/item/clothing/under/dressshirt suit = /obj/item/clothing/suit/storage/toggle/corp/nt - pants = /obj/item/clothing/pants/khaki + pants = /obj/item/clothing/pants/black tab_pda = /obj/item/modular_computer/handheld/pda/civilian/lawyer wristbound = /obj/item/modular_computer/handheld/wristbound/preset/pda/civilian/lawyer diff --git a/code/game/jobs/job/science.dm b/code/game/jobs/job/science.dm index 8e7cab4944ee..c1ab36f9bc53 100644 --- a/code/game/jobs/job/science.dm +++ b/code/game/jobs/job/science.dm @@ -139,6 +139,10 @@ outfit = /obj/outfit/job/scientist/xenoarchaeologist blacklisted_species = list(SPECIES_VAURCA_BREEDER) + skill_requirements = alist( + /singleton/skill/pilot_spacecraft = SKILL_LEVEL_FAMILIAR + ) + /obj/outfit/job/scientist/xenoarchaeologist name = "Xenoarchaeologist" jobtype = /datum/job/xenoarchaeologist diff --git a/code/game/jobs/job/security.dm b/code/game/jobs/job/security.dm index 26ba08787533..346ff214a101 100644 --- a/code/game/jobs/job/security.dm +++ b/code/game/jobs/job/security.dm @@ -35,6 +35,11 @@ blacklisted_species = list(SPECIES_TAJARA_ZHAN, SPECIES_DIONA, SPECIES_DIONA_COEUS, SPECIES_IPC_G1, SPECIES_IPC_G2, SPECIES_IPC_XION, SPECIES_VAURCA_WORKER, SPECIES_VAURCA_WARRIOR, SPECIES_VAURCA_ATTENDANT, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER) + // Make sure security at bare minimum won't footgun themselves... + skill_requirements = alist( + /singleton/skill/firearms = SKILL_LEVEL_TRAINED + ) + /obj/outfit/job/hos name = "Head of Security" jobtype = /datum/job/hos @@ -101,6 +106,11 @@ blacklisted_species = list(SPECIES_IPC_XION_REMOTE, SPECIES_VAURCA_BULWARK, SPECIES_DIONA_COEUS, SPECIES_VAURCA_BREEDER) + // Make sure security at bare minimum won't footgun themselves... + skill_requirements = alist( + /singleton/skill/firearms = SKILL_LEVEL_TRAINED + ) + /obj/outfit/job/warden name = "Warden" jobtype = /datum/job/warden @@ -165,6 +175,11 @@ outfit = /obj/outfit/job/forensics blacklisted_species = list(SPECIES_IPC_XION_REMOTE, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER) + // Make sure security at bare minimum won't footgun themselves... + skill_requirements = alist( + /singleton/skill/firearms = SKILL_LEVEL_TRAINED + ) + /obj/outfit/job/forensics name = "Investigator" jobtype = /datum/job/investigator @@ -224,6 +239,11 @@ blacklisted_species = list(SPECIES_IPC_XION_REMOTE, SPECIES_VAURCA_BULWARK, SPECIES_DIONA_COEUS, SPECIES_VAURCA_BREEDER) + // Make sure security at bare minimum won't footgun themselves... + skill_requirements = alist( + /singleton/skill/firearms = SKILL_LEVEL_TRAINED + ) + /obj/outfit/job/officer name = "Security Officer" jobtype = /datum/job/officer @@ -291,6 +311,9 @@ blacklisted_species = list(SPECIES_IPC_XION_REMOTE, SPECIES_VAURCA_BULWARK, SPECIES_DIONA_COEUS, SPECIES_VAURCA_BREEDER) + // Let the sec cadets footgun themselves as a little treat. <3 + // skill_requirements = alist() + /obj/outfit/job/intern_sec name = "Security Cadet" jobtype = /datum/job/intern_sec diff --git a/code/game/jobs/whitelist.dm b/code/game/jobs/whitelist.dm index 3be54613f8b6..bb650bc45990 100644 --- a/code/game/jobs/whitelist.dm +++ b/code/game/jobs/whitelist.dm @@ -21,7 +21,7 @@ var/list/whitelist_jobconfig = list() if(fexists("config/whitelist_jobconfig.json")) LOG_DEBUG("Whitelist JobConfig: Loading from json") try - whitelist_jobconfig = json_decode(return_file_text("config/whitelist_jobconfig.json")) + whitelist_jobconfig = json_decode(file2text("config/whitelist_jobconfig.json")) catch(var/exception/e) LOG_DEBUG("Whitelist JobConfig: Failed to load whitelist_jobconfig.json: [e]") diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index 3a893751cbae..cad86d1325d2 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -60,7 +60,7 @@ for(var/g in trace_gas){\ other_moles += environment.gas[g];\ }\ - ALARM_GET_DANGER_LEVEL(pressure_dangerlevel, environment.return_pressure(), TLV["pressure"]);\ + ALARM_GET_DANGER_LEVEL(pressure_dangerlevel, XGM_PRESSURE(environment), TLV["pressure"]);\ ALARM_GET_DANGER_LEVEL(oxygen_dangerlevel, environment.gas[GAS_OXYGEN]*partial_pressure, TLV[GAS_OXYGEN]);\ ALARM_GET_DANGER_LEVEL(co2_dangerlevel, environment.gas[GAS_CO2]*partial_pressure, TLV[GAS_CO2]);\ ALARM_GET_DANGER_LEVEL(phoron_dangerlevel, environment.gas[GAS_PHORON]*partial_pressure, TLV[GAS_PHORON]);\ @@ -474,7 +474,7 @@ pixel_x = 10; mode = AALARM_MODE_OFF apply_mode() - if (mode==AALARM_MODE_CYCLE && environment.return_pressure() 0) && (pressure_delta > 0)) @@ -399,7 +399,7 @@ update_flag if(returnval >= 0) src.update_icon() - if(air_contents.return_pressure() < 1) + if(XGM_PRESSURE(air_contents) < 1) can_label = 1 else can_label = 0 @@ -410,18 +410,6 @@ update_flag /obj/machinery/portable_atmospherics/canister/return_air() return air_contents -/obj/machinery/portable_atmospherics/canister/proc/return_temperature() - var/datum/gas_mixture/GM = src.return_air() - if(GM && GM.volume>0) - return GM.temperature - return 0 - -/obj/machinery/portable_atmospherics/canister/proc/return_pressure() - var/datum/gas_mixture/GM = src.return_air() - if(GM && GM.volume>0) - return GM.return_pressure() - return 0 - /obj/machinery/portable_atmospherics/canister/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit) . = ..() if(. != BULLET_ACT_HIT) @@ -471,8 +459,8 @@ update_flag if(istype(user, /mob/living/silicon/robot) && istype(attacking_item, /obj/item/tank/jetpack)) var/obj/item/tank/jetpack/jetpack = attacking_item var/datum/gas_mixture/thejetpack = jetpack.air_contents - var/env_pressure = thejetpack.return_pressure() - var/pressure_delta = min(10*ONE_ATMOSPHERE - env_pressure, (air_contents.return_pressure() - env_pressure)/2) + var/env_pressure = XGM_PRESSURE(thejetpack) + var/pressure_delta = min(10*ONE_ATMOSPHERE - env_pressure, (XGM_PRESSURE(air_contents) - env_pressure)/2) // Cannot have a pressure delta that would cause environment pressure > tank pressure var/transfer_moles = 0 if((air_contents.temperature > 0) && (pressure_delta > 0)) @@ -507,7 +495,7 @@ update_flag data["name"] = name data["canLabel"] = can_label data["portConnected"] = !!connected_port - data["tankPressure"] = round(air_contents.return_pressure() || 0) + data["tankPressure"] = round(XGM_PRESSURE(air_contents) || 0) data["releasePressure"] = round(release_pressure || 0) data["minReleasePressure"] = round(ONE_ATMOSPHERE/10) data["maxReleasePressure"] = round(10*ONE_ATMOSPHERE) @@ -515,7 +503,7 @@ update_flag data["hasHoldingTank"] = !!holding if (holding) - data["holdingTank"] = list("name" = holding.name, "tankPressure" = round(holding.air_contents.return_pressure())) + data["holdingTank"] = list("name" = holding.name, "tankPressure" = round(XGM_PRESSURE(holding.air_contents))) return data /obj/machinery/portable_atmospherics/canister/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) diff --git a/code/game/machinery/atmoalter/meter.dm b/code/game/machinery/atmoalter/meter.dm index 36ffb1000fe5..9f663ca08a9f 100644 --- a/code/game/machinery/atmoalter/meter.dm +++ b/code/game/machinery/atmoalter/meter.dm @@ -27,7 +27,7 @@ else if(src.target) var/datum/gas_mixture/environment = target.return_air() if(environment) - . += "The pressure gauge reads [round(environment.return_pressure(), 0.01)] kPa; [round(environment.temperature,0.01)]K ([round(environment.temperature-T0C,0.01)]°C)" + . += "The pressure gauge reads [round(XGM_PRESSURE(environment), 0.01)] kPa; [round(environment.temperature,0.01)]K ([round(environment.temperature-T0C,0.01)]°C)" else . += SPAN_WARNING("The sensor error light is blinking.") else @@ -55,7 +55,7 @@ var/button_overlay_name var/atmos_overlay_name - var/env_pressure = environment.return_pressure() + var/env_pressure = XGM_PRESSURE(environment) if(env_pressure <= 0.15*ONE_ATMOSPHERE) button_overlay_name = "buttons_0" atmos_overlay_name = "pressure0" @@ -116,7 +116,7 @@ var/datum/gas_mixture/environment = target.return_air() if(!environment) return FALSE - var/env_pressure = environment.return_pressure() + var/env_pressure = XGM_PRESSURE(environment) if(frequency) var/datum/radio_frequency/radio_connection = SSradio.return_frequency(frequency) diff --git a/code/game/machinery/atmoalter/portable_atmospherics.dm b/code/game/machinery/atmoalter/portable_atmospherics.dm index e78ae4209818..8613fa95736b 100644 --- a/code/game/machinery/atmoalter/portable_atmospherics.dm +++ b/code/game/machinery/atmoalter/portable_atmospherics.dm @@ -154,6 +154,10 @@ var/last_power_draw = 0 var/obj/item/cell/cell +/obj/machinery/portable_atmospherics/powered/Destroy() + QDEL_NULL(cell) + return ..() + /obj/machinery/portable_atmospherics/powered/powered() if(use_power) //using area power return ..() diff --git a/code/game/machinery/atmoalter/pump.dm b/code/game/machinery/atmoalter/pump.dm index 400bf4e91177..5415c15348bf 100644 --- a/code/game/machinery/atmoalter/pump.dm +++ b/code/game/machinery/atmoalter/pump.dm @@ -83,11 +83,11 @@ var/output_volume var/air_temperature if(direction_out) - pressure_delta = target_pressure - environment.return_pressure() + pressure_delta = target_pressure - XGM_PRESSURE(environment) output_volume = environment.volume * environment.group_multiplier air_temperature = environment.temperature? environment.temperature : air_contents.temperature else - pressure_delta = environment.return_pressure() - target_pressure + pressure_delta = XGM_PRESSURE(environment) - target_pressure output_volume = air_contents.volume * air_contents.group_multiplier air_temperature = air_contents.temperature? air_contents.temperature : environment.temperature @@ -133,9 +133,10 @@ ui_interact(user) /obj/machinery/portable_atmospherics/powered/pump/ui_data(mob/user) + var/air_pressure = XGM_PRESSURE(air_contents) var/list/data = list() data["portConnected"] = connected_port ? 1 : 0 - data["tankPressure"] = round(air_contents.return_pressure() > 0 ? air_contents.return_pressure() : 0) + data["tankPressure"] = round(air_pressure) data["targetpressure"] = round(target_pressure) data["pump_dir"] = direction_out data["minpressure"] = round(pressuremin) @@ -147,7 +148,7 @@ data["hasHoldingTank"] = holding ? 1 : 0 if (holding) - data["holdingTank"] = list("name" = holding.name, "tankPressure" = round(holding.air_contents.return_pressure() > 0 ? holding.air_contents.return_pressure() : 0)) + data["holdingTank"] = list("name" = holding.name, "tankPressure" = round(XGM_PRESSURE(holding.air_contents))) return data /obj/machinery/portable_atmospherics/powered/pump/ui_interact(mob/user, datum/tgui/ui) diff --git a/code/game/machinery/atmoalter/scrubber.dm b/code/game/machinery/atmoalter/scrubber.dm index 9689d078f623..fe9b2cf3de19 100644 --- a/code/game/machinery/atmoalter/scrubber.dm +++ b/code/game/machinery/atmoalter/scrubber.dm @@ -116,7 +116,7 @@ /obj/machinery/portable_atmospherics/powered/scrubber/ui_data(mob/user) var/list/data = list() data["portConnected"] = connected_port ? 1 : 0 - data["tankPressure"] = round(air_contents.return_pressure() > 0 ? air_contents.return_pressure() : 0) + data["tankPressure"] = round(XGM_PRESSURE(air_contents)) data["rate"] = round(volume_rate) data["minrate"] = round(minrate) data["maxrate"] = round(maxrate) @@ -127,7 +127,7 @@ data["hasHoldingTank"] = holding ? 1 : 0 if(holding) data["holdingTankName"] = holding?.name - data["holdingTankPressure"] = round(holding.air_contents.return_pressure() > 0 ? holding.air_contents.return_pressure() : 0) + data["holdingTankPressure"] = round(XGM_PRESSURE(holding.air_contents)) else data["holdingTankName"] = null data["holdingTankPressure"] = null diff --git a/code/game/machinery/body_scanner.dm b/code/game/machinery/body_scanner.dm index 2a30c6922f4f..56ed0f329807 100644 --- a/code/game/machinery/body_scanner.dm +++ b/code/game/machinery/body_scanner.dm @@ -167,9 +167,7 @@ occupant = M update_use_power(POWER_USE_ACTIVE) update_icon() - //Foreach goto(154) add_fingerprint(user) - //G = null qdel(G) return TRUE diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 0e1477799fae..b3201c4f0efc 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -90,7 +90,6 @@ GLOB.cameranet.remove_source(src) . = ..() - GC_TEMPORARY_HARDDEL /obj/machinery/camera/set_pixel_offsets() pixel_x = dir & (NORTH|SOUTH) ? 0 : (dir == EAST ? -13 : 13) diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm index 274ad538e521..1d741bd9d5d2 100644 --- a/code/game/machinery/computer/Operating.dm +++ b/code/game/machinery/computer/Operating.dm @@ -122,7 +122,7 @@ /obj/machinery/computer/operating/terminal name = "patient monitoring terminal" - icon = 'icons/obj/machinery/modular_terminal.dmi' + icon = 'icons/obj/modular_computers/modular_terminal.dmi' icon_screen = "med_comp" icon_keyboard = "med_key" icon_keyboard_emis = "med_key_mask" diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm index 9225d538ecbb..6a394a3ac973 100644 --- a/code/game/machinery/computer/buildandrepair.dm +++ b/code/game/machinery/computer/buildandrepair.dm @@ -4,7 +4,7 @@ density = 1 anchored = 0 name = "computer frame" - icon = 'icons/obj/machinery/modular_console.dmi' + icon = 'icons/obj/modular_computers/modular_console.dmi' icon_state = "0" build_amt = 5 var/state = 0 diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index fa78e6d0557e..1d8128529626 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -266,7 +266,7 @@ /obj/machinery/computer/security/engineering/terminal name = "engineering camera monitor" - icon = 'icons/obj/machinery/modular_terminal.dmi' + icon = 'icons/obj/modular_computers/modular_terminal.dmi' icon_screen = "engines" icon_keyboard = "power_key" icon_keyboard_emis = "power_key_mask" @@ -296,7 +296,7 @@ /obj/machinery/computer/security/terminal name = "camera monitor terminal" - icon = 'icons/obj/machinery/modular_terminal.dmi' + icon = 'icons/obj/modular_computers/modular_terminal.dmi' icon_screen = "cameras" icon_keyboard = "security_key" icon_keyboard_emis = "security_key_mask" diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm index 9269adfb3136..7e760c3fe9b8 100644 --- a/code/game/machinery/computer/computer.dm +++ b/code/game/machinery/computer/computer.dm @@ -1,6 +1,6 @@ /obj/machinery/computer name = "computer" - icon = 'icons/obj/machinery/modular_console.dmi' + icon = 'icons/obj/modular_computers/modular_console.dmi' icon_state = "computer" layer = ABOVE_STRUCTURE_LAYER density = 1 @@ -250,7 +250,7 @@ /obj/machinery/computer/terminal name = "terminal" - icon = 'icons/obj/machinery/modular_terminal.dmi' + icon = 'icons/obj/modular_computers/modular_terminal.dmi' is_connected = TRUE has_off_keyboards = TRUE can_pass_under = FALSE diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm index e74b20659fb7..18a833f5a5cc 100644 --- a/code/game/machinery/computer/robot.dm +++ b/code/game/machinery/computer/robot.dm @@ -1,7 +1,7 @@ /obj/machinery/computer/robotics name = "robotics control console" desc = "Used to remotely lockdown or detonate linked cyborgs." - icon = 'icons/obj/machinery/modular_console.dmi' + icon = 'icons/obj/modular_computers/modular_console.dmi' icon_screen = "robot" icon_keyboard = "purple_key" diff --git a/code/game/machinery/computer/sentencing.dm b/code/game/machinery/computer/sentencing.dm index 24aa5c3af80d..c9e29e36755c 100644 --- a/code/game/machinery/computer/sentencing.dm +++ b/code/game/machinery/computer/sentencing.dm @@ -135,7 +135,7 @@ . += "Fine:" . += "" if( incident.fine ) - . += "[incident.fine] Credits" + . += "[incident.fine]电" // . += "" // // . += "" @@ -517,7 +517,7 @@ if( "change_fine" ) if( !incident ) return - var/number = tgui_input_number(usr, "Enter a number between [incident.getMinFine()] and [incident.getMaxFine()] credits.", "Fine", 0, incident.getMaxFine(), incident.getMinFine()) + var/number = tgui_input_number(usr, "Enter a number between [incident.getMinFine()] and [incident.getMaxFine()]电.", "Fine", 0, incident.getMaxFine(), incident.getMinFine()) if( number < incident.getMinFine() ) to_chat(usr, SPAN_ALERT("The entered sentence was less than the minimum sentence!")) else if( number > incident.getMaxFine() ) diff --git a/code/game/machinery/computer/slotmachine.dm b/code/game/machinery/computer/slotmachine.dm index f7b8851e1e2e..152c1d096598 100644 --- a/code/game/machinery/computer/slotmachine.dm +++ b/code/game/machinery/computer/slotmachine.dm @@ -52,12 +52,12 @@ /obj/machinery/computer/slot_machine/Destroy() return ..() -/obj/machinery/computer/slot_machine/process(delta_time) +/obj/machinery/computer/slot_machine/process(seconds_per_tick) . = ..() //Sanity checks. if(!.) return . - money += round(delta_time / 2) //SPESSH MAJICKS + money += round(seconds_per_tick / 2) //SPESSH MAJICKS /obj/machinery/computer/slot_machine/update_icon() if(working) @@ -99,7 +99,7 @@ else if(istype(attacking_item, /obj/item/spacecash)) if(paymode == CREDITCHIP) var/obj/item/spacecash/H = attacking_item - to_chat(user, SPAN_NOTICE("You insert [H.worth] credits into [src]'s slot!")) + to_chat(user, SPAN_NOTICE("You insert [H.worth]电 into [src]'s slot!")) playsound(loc, 'sound/arcade/sloto_token.ogg', 10, 1, extrarange = -3, falloff_distance = 10, required_asfx_toggles = ASFX_ARCADE) balance += H.worth updateUsrDialog() diff --git a/code/game/machinery/controlhub.dm b/code/game/machinery/controlhub.dm index b011fbc16206..5c11bcfcf920 100644 --- a/code/game/machinery/controlhub.dm +++ b/code/game/machinery/controlhub.dm @@ -2,7 +2,7 @@ ABSTRACT_TYPE(/obj/machinery/controlhub) /obj/machinery/controlhub name = "control hub" desc = "A control interface that can manage multiple systems from a single point." - icon = 'icons/obj/modular_telescreen.dmi' + icon = 'icons/obj/modular_computers/modular_telescreen.dmi' anchored = TRUE density = FALSE opacity = FALSE diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index b192ac6ff1a5..ba65f4b3a67f 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -272,6 +272,7 @@ Deployable Kits icon = 'icons/obj/storage/briefcase.dmi' icon_state = "inf_box" item_state = "inf_box" + contained_sprite = TRUE drop_sound = 'sound/items/drop/backpack.ogg' pickup_sound = 'sound/items/pickup/backpack.ogg' @@ -296,6 +297,7 @@ Deployable Kits icon = 'icons/obj/storage/briefcase.dmi' icon_state = "barrier_kit" item_state = "barrier_kit" + contained_sprite = TRUE w_class = WEIGHT_CLASS_SMALL kit_product = /obj/machinery/deployable/barrier/legion @@ -340,6 +342,7 @@ Deployable Kits icon = 'icons/obj/storage/briefcase.dmi' icon_state = "inf_box" item_state = "inf_box" + contained_sprite = TRUE w_class = WEIGHT_CLASS_NORMAL kit_product = /obj/machinery/iv_drip assembly_time = 4 SECONDS @@ -350,6 +353,7 @@ Deployable Kits icon = 'icons/obj/storage/briefcase.dmi' icon_state = "barrier_kit" item_state = "barrier_kit" + contained_sprite = TRUE w_class = WEIGHT_CLASS_BULKY kit_product = /obj/structure/bed/stool/chair/remote/mech/portable assembly_time = 20 SECONDS diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 2561c0baac74..288485f016fb 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -844,7 +844,7 @@ About the new airlock wires panel: * one wire for opening the door. Sending a pulse through this while the door has power makes it open the door if no access is required. * one wire for AI control. If allowed by the door setup, sending a pulse through this toggles whether AI can bolt the door (shows as green light in dialogue if it can bolt, orange if it can't, red when emagged and thus inoperable by AI). Cutting this prevents the AI from controlling the door unless it has hacked the door through the power connection (which takes about a minute). If both main and backup power are cut, as well as this wire, then the AI cannot operate or hack the door at all. * one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds. Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. (Currently it is also STAYING electrified until someone mends the wire) -* one wire for controling door safetys. When active, door does not close on someone. When cut, door will ruin someone's shit. When pulsed, door will immedately ruin someone's shit. +* one wire for controling door safeties. When active, door does not close on someone. When cut, door will ruin someone's shit. When pulsed, door will immedately ruin someone's shit. * one wire for controlling door speed. When active, door closes at normal rate. When cut, door does not close manually. When pulsed, door attempts to close every tick. */ @@ -2155,7 +2155,7 @@ About the new airlock wires panel: // The door lost power - Disable electrification and close it. electrified_until = 0 INVOKE_ASYNC(src, TYPE_PROC_REF(/obj/machinery/door, close), 1) - else if(revert_powerloss_manual_override) + else if(revert_powerloss_manual_override && arePowerSystemsOn()) // The door regained power and the powerless override was used - Close the door again. revert_powerloss_manual_override = FALSE INVOKE_ASYNC(src, TYPE_PROC_REF(/obj/machinery/door, close), 1) diff --git a/code/game/machinery/doors/airlock_control.dm b/code/game/machinery/doors/airlock_control.dm index b554e28ba54e..942d37eb8f35 100644 --- a/code/game/machinery/doors/airlock_control.dm +++ b/code/game/machinery/doors/airlock_control.dm @@ -178,7 +178,7 @@ /obj/machinery/airlock_sensor/process() if(on) var/datum/gas_mixture/air_sample = return_air() - var/pressure = round(air_sample.return_pressure(),0.1) + var/pressure = round(XGM_PRESSURE(air_sample),0.1) if(abs(pressure - previousPressure) > 0.001 || previousPressure == null) var/datum/signal/signal = new diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 6a0c4ea0ea2a..a9b7fec7af24 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -155,7 +155,7 @@ take_damage(25) return else - return attackby(user, user) + return attackby(null, user) /obj/machinery/door/window/emag_act(var/remaining_charges, var/mob/user) if (density && operable()) diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm index c63f84428875..4f1d92b38b12 100644 --- a/code/game/machinery/doppler_array.dm +++ b/code/game/machinery/doppler_array.dm @@ -3,7 +3,7 @@ GLOBAL_LIST_INIT_TYPED(doppler_arrays, /obj/machinery/doppler_array, list()) /obj/machinery/doppler_array name = "tachyon-doppler array" desc = "A highly precise sensor array which measures the release of quants from decaying tachyons. The doppler shifting of the mirror-image formed by these quants can reveal the size, location and temporal affects of energetic disturbances within a large radius ahead of the array." - icon = 'icons/obj/machinery/modular_console.dmi' + icon = 'icons/obj/modular_computers/modular_console.dmi' icon_state = "computer" anchored = TRUE diff --git a/code/game/machinery/embedded_controller/airlock_controllers.dm b/code/game/machinery/embedded_controller/airlock_controllers.dm index 0f72c9810ef5..4b1375d02adc 100644 --- a/code/game/machinery/embedded_controller/airlock_controllers.dm +++ b/code/game/machinery/embedded_controller/airlock_controllers.dm @@ -33,10 +33,6 @@ tag_chamber_sensor = given_tag_chamber_sensor program = new /datum/computer/file/embedded_program/airlock(src) -/obj/machinery/embedded_controller/radio/airlock/Destroy() - . = ..() - GC_TEMPORARY_HARDDEL - /obj/machinery/embedded_controller/radio/airlock/attackby(obj/item/attacking_item, mob/user) //Swiping ID on the access button if (attacking_item.GetID()) @@ -138,8 +134,11 @@ /obj/machinery/embedded_controller/radio/airlock/access_controller/ui_data(mob/user) var/list/data = list() - data["exterior_status"] = round(program.memory["exterior_status"]) - data["interior_status"] = round(program.memory["interior_status"]) + var/ext_door_status = (program.memory["exterior_status"]["state"] == "closed" && program.memory["exterior_status"]["lock"] == "locked") + var/int_door_status = (program.memory["interior_status"]["state"] == "closed" && program.memory["interior_status"]["lock"] == "locked") + + data["exterior_secured"] = ext_door_status + data["interior_secured"] = int_door_status data["processing"] = program.memory["processing"] return data diff --git a/code/game/machinery/embedded_controller/embedded_controller_base.dm b/code/game/machinery/embedded_controller/embedded_controller_base.dm index a1801ea93416..a2147a0cc01e 100644 --- a/code/game/machinery/embedded_controller/embedded_controller_base.dm +++ b/code/game/machinery/embedded_controller/embedded_controller_base.dm @@ -13,7 +13,6 @@ if(SSradio) SSradio.remove_object(src,frequency) . = ..() - GC_TEMPORARY_HARDDEL /obj/machinery/embedded_controller/proc/post_signal(datum/signal/signal, comm_line) return 0 diff --git a/code/game/machinery/embedded_controller/embedded_program_base.dm b/code/game/machinery/embedded_controller/embedded_program_base.dm index 2a75090ea5c1..13da2b0ab424 100644 --- a/code/game/machinery/embedded_controller/embedded_program_base.dm +++ b/code/game/machinery/embedded_controller/embedded_program_base.dm @@ -6,10 +6,23 @@ var/id_tag /datum/computer/file/embedded_program/New(var/obj/machinery/embedded_controller/M) - master = M - if (istype(M, /obj/machinery/embedded_controller/radio)) - var/obj/machinery/embedded_controller/radio/R = M - id_tag = R.id_tag + set_master(M) + +/datum/computer/file/embedded_program/proc/set_master(obj/machinery/embedded_controller/new_master) + if(new_master && master != new_master) + master = new_master + id_tag = astype(new_master, /obj/machinery/embedded_controller/radio)?.id_tag + RegisterSignal(master, COMSIG_QDELETING, PROC_REF(unset_master)) + +/datum/computer/file/embedded_program/proc/unset_master() + if(master) + UnregisterSignal(master, COMSIG_QDELETING) + master = null + id_tag = null + +/datum/computer/file/embedded_program/Destroy(force) + master = null + . = ..() /datum/computer/file/embedded_program/proc/receive_user_command(command) return diff --git a/code/game/machinery/floodlight.dm b/code/game/machinery/floodlight.dm index 9bc90e40e1c7..3d0e4f37ba1e 100644 --- a/code/game/machinery/floodlight.dm +++ b/code/game/machinery/floodlight.dm @@ -6,7 +6,7 @@ icon_state = "flood00" density = TRUE obj_flags = OBJ_FLAG_ROTATABLE - light_system = MOVABLE_LIGHT + light_system = DIRECTIONAL_LIGHT light_range = 6 light_color = LIGHT_COLOR_TUNGSTEN @@ -23,12 +23,16 @@ return else . += SPAN_WARNING("\The [src] has no cell installed!") - . += SPAN_NOTICE("The installed [cell.name] has [Percent(cell.charge, cell.maxcharge)]% charge remaining.") + . += SPAN_NOTICE("The installed [cell.name] has [AS_PCT(cell.charge, cell.maxcharge)]% charge remaining.") /obj/machinery/floodlight/Initialize() . = ..() cell = new /obj/item/cell(src) +/obj/machinery/floodlight/Destroy() + QDEL_NULL(cell) + return ..() + /obj/machinery/floodlight/update_icon() ClearOverlays() icon_state = "flood[open ? "o" : ""][open && cell ? "b" : ""]0[on]" diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index 290094a690ab..69a47d0be50e 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -92,7 +92,7 @@ else . += "No chemicals attached." if(tank) - . += "Installed is [is_loose ? "\a [tank] sitting loose" : "\a [tank] secured"] on the stand. The meter shows [round(tank.air_contents.return_pressure())] kPa, \ + . += "Installed is [is_loose ? "\a [tank] sitting loose" : "\a [tank] secured"] on the stand. The meter shows [round(XGM_PRESSURE(tank.air_contents))] kPa, \ with the pressure set to [round(tank.distribute_pressure)] kPa. The valve is [valve_open ? "open" : "closed"]." else . += "No gas tank installed." @@ -252,7 +252,7 @@ playsound(src, 'sound/machines/twobeep.ogg', 50, extrarange = SILENCED_SOUND_EXTRARANGE) breath_mask_rip() return - if(tank.air_contents.return_pressure() <= 10) + if(XGM_PRESSURE(tank.air_contents) <= 10) src.visible_message(SPAN_WARNING("\The [src] buzzes, automatically deactivating \the [tank] and retracting \the [breath_mask].")) playsound(src, 'sound/machines/buzz-two.ogg', 50, extrarange = SILENCED_SOUND_EXTRARANGE) breath_mask_rip() @@ -716,18 +716,15 @@ if(use_check_and_message(usr)) return - set_rate: - var/amount = tgui_input_number(usr, "Set the IV drip's transfer rate.", "IV Drip", transfer_amount, transfer_limit, 0.001, round_value = FALSE) - if(!amount) - return - if ((0.001 > amount || amount > transfer_limit) && amount != 0) - to_chat(usr, SPAN_WARNING("Entered value must be between 0.001 and [transfer_limit].")) - goto set_rate - if (transfer_amount == 0) - transfer_amount = REM - return - transfer_amount = amount - to_chat(usr, SPAN_NOTICE("Transfer rate set to [src.transfer_amount] u/sec.")) + + transfer_amount = tgui_input_number( \ + usr, \ + "Set the IV drip's transfer rate between 0.001 and [transfer_limit].", \ + "IV Drip", \ + transfer_amount, \ + transfer_limit, 0.001, \ + round_value = FALSE) + to_chat(usr, SPAN_NOTICE("Transfer rate set to [src.transfer_amount] u/sec.")) /obj/machinery/iv_drip/RefreshParts() ..() diff --git a/code/game/machinery/mecha_fabricator.dm b/code/game/machinery/mecha_fabricator.dm index 00ca8259f2db..82db73e8e23f 100644 --- a/code/game/machinery/mecha_fabricator.dm +++ b/code/game/machinery/mecha_fabricator.dm @@ -125,6 +125,13 @@ to_chat(user, SPAN_WARNING("Access denied.")) return do_hair_pull(user) + + // Yes I'm doing this after do_hair_pull() intentionally, you can totally fail the skill check and still get your hair stuck in a blender. + var/cancelled = FALSE + SEND_SIGNAL(user, COMSIG_USE_MECH_FAB, &cancelled) + if (cancelled) + return + ui_interact(user) /obj/machinery/mecha_part_fabricator/ui_interact(mob/user, datum/tgui/ui) diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm index 5da8708081a4..a6e2fea6acbe 100644 --- a/code/game/machinery/pipe/construction.dm +++ b/code/game/machinery/pipe/construction.dm @@ -168,6 +168,8 @@ src.pipe_type = PIPE_OMNI_MIXER else if(istype(make_from, /obj/machinery/atmospherics/omni/filter)) src.pipe_type = PIPE_OMNI_FILTER + else if(istype(make_from, /obj/machinery/atmospherics/pipe/vent_passive)) + src.pipe_type = PIPE_PVENT ///// Z-Level stuff else if(istype(make_from, /obj/machinery/atmospherics/pipe/zpipe/up/supply)) src.pipe_type = PIPE_SUPPLY_UP @@ -306,7 +308,8 @@ "auxiliary gas pump", "fuel connector", "auxiliary connector", - "auxiliary unary vent" + "auxiliary unary vent", + "passive vent" ) name = nlist[pipe_type+1] + " fitting" var/list/islist = list( @@ -378,7 +381,8 @@ "pump", "connector", "connector", - "uvent" + "uvent", + "pvent" ) icon_state = islist[pipe_type + 1] @@ -449,7 +453,7 @@ return dir|flip if(PIPE_SIMPLE_BENT, PIPE_HE_BENT, PIPE_SUPPLY_BENT, PIPE_SCRUBBERS_BENT, PIPE_FUEL_BENT, PIPE_AUX_BENT) return dir //dir|acw - if(PIPE_CONNECTOR,PIPE_CONNECTOR_FUEL,PIPE_CONNECTOR_AUX,PIPE_UVENT,PIPE_AUX_UVENT,PIPE_SCRUBBER,PIPE_HEAT_EXCHANGE) + if(PIPE_CONNECTOR,PIPE_CONNECTOR_FUEL,PIPE_CONNECTOR_AUX,PIPE_UVENT,PIPE_AUX_UVENT,PIPE_SCRUBBER,PIPE_HEAT_EXCHANGE,PIPE_PVENT) return dir if(PIPE_MANIFOLD4W, PIPE_SUPPLY_MANIFOLD4W, PIPE_SCRUBBERS_MANIFOLD4W, PIPE_FUEL_MANIFOLD4W, PIPE_AUX_MANIFOLD4W, PIPE_OMNI_MIXER, PIPE_OMNI_FILTER) return dir|flip|cw|acw @@ -1075,6 +1079,20 @@ V.node2.atmos_init() V.node2.build_network() + if(PIPE_PVENT) //passive vent + var/obj/machinery/atmospherics/pipe/vent_passive/V = new (src.loc) + V.set_dir(dir) + V.initialize_directions = pipe_dir + if(pipename) + V.name = pipename + var/turf/T = V.loc + V.level = !T.is_plating() ? 2 : 1 + V.build_network() + V.atmos_init() + if (V.node1) + V.node1.atmos_init() + V.node1.build_network() + if(PIPE_PUMP) //gas pump var/obj/machinery/atmospherics/binary/pump/P = new(src.loc) P.set_dir(dir) diff --git a/code/game/machinery/pipe/pipe_dispenser.dm b/code/game/machinery/pipe/pipe_dispenser.dm index fcbae1913256..5056e8f4c68b 100644 --- a/code/game/machinery/pipe/pipe_dispenser.dm +++ b/code/game/machinery/pipe/pipe_dispenser.dm @@ -70,6 +70,7 @@ Auxiliary Connector
Unary Vent
Auxiliary Unary Vent
+ Passive Vent
Gas Pump
Fuel Gas Pump
Auxiliary Gas Pump
diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm index ecc1064beea8..41985bec25ed 100644 --- a/code/game/machinery/spaceheater.dm +++ b/code/game/machinery/spaceheater.dm @@ -34,6 +34,11 @@ env = loc.return_air() update_icon() +/obj/machinery/space_heater/Destroy() + env = null + QDEL_NULL(cell) + return ..() + /obj/machinery/space_heater/update_icon() ClearOverlays() if(!on) diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm index 6f74ca247915..3fca3c4d24da 100644 --- a/code/game/machinery/status_display.dm +++ b/code/game/machinery/status_display.dm @@ -24,11 +24,8 @@ idle_power_usage = 10 obj_flags = OBJ_FLAG_MOVES_UNSUPPORTED var/hears_arrivals = FALSE - var/mode = 1 // 0 = Blank - // 1 = Shuttle timer - // 2 = Arbitrary message(s) - // 3 = alert picture - // 4 = Supply shuttle timer + var/mode = STATUS_DISPLAY_TRANSFER_SHUTTLE_TIME + var/last_mode = STATUS_DISPLAY_TRANSFER_SHUTTLE_TIME var/picture_state // icon_state of alert picture @@ -42,13 +39,6 @@ var/friendc = 0 // track if Friend Computer mode var/ignore_friendc = 0 - var/const/STATUS_DISPLAY_BLANK = 0 - var/const/STATUS_DISPLAY_TRANSFER_SHUTTLE_TIME = 1 - var/const/STATUS_DISPLAY_MESSAGE = 2 - var/const/STATUS_DISPLAY_ALERT = 3 - var/const/STATUS_DISPLAY_TIME = 4 - var/const/STATUS_DISPLAY_CUSTOM = 99 - /// Normal text color var/text_color = COLOR_DISPLAY_BLUE /// Color for headers, eg. "- ETA -" @@ -80,7 +70,19 @@ remove_display() update_lighting() return - update() + if((mode == STATUS_DISPLAY_TIME) && (message2 != worldtime2text())) + update() + +/obj/machinery/status_display/update_use_power(new_use_power) + var/should_update = (use_power != new_use_power && (use_power == POWER_USE_OFF || new_use_power == POWER_USE_OFF)) + . = ..() + if(should_update) + update() + +/obj/machinery/status_display/power_change() + . = ..() + if(.) + update() /obj/machinery/status_display/emp_act(severity) . = ..() @@ -362,5 +364,3 @@ #undef LINE2_X #undef LINE2_Y #undef STATUS_DISPLAY_FONT_DATUM - -#undef SCROLL_PADDING diff --git a/code/game/machinery/supplybeacon.dm b/code/game/machinery/supplybeacon.dm index ade899eb797e..8ed9a302dccd 100644 --- a/code/game/machinery/supplybeacon.dm +++ b/code/game/machinery/supplybeacon.dm @@ -74,7 +74,7 @@ /obj/machinery/power/supply_beacon/proc/activate(var/mob/user) if(expended) return - if(surplus() < 500) + if(POWER_SURPLUS(src) < 500) if(user) to_chat(user, SPAN_NOTICE("The connected wire doesn't have enough current.")) return set_light(3, 3, "#00CCAA") @@ -102,7 +102,9 @@ return PROCESS_KILL if(!use_power) return - if(draw_power(500) < 500) + var/can_draw = (POWER_DRAW(src, 500) >= 500) + DRAW_POWER(src, can_draw) + if(!can_draw) deactivate() return if(!target_drop_time) diff --git a/code/game/machinery/tesla_beacon.dm b/code/game/machinery/tesla_beacon.dm index a9b41ff6009e..1f2119bfa231 100644 --- a/code/game/machinery/tesla_beacon.dm +++ b/code/game/machinery/tesla_beacon.dm @@ -13,7 +13,7 @@ var/active = FALSE /obj/machinery/power/tesla_beacon/proc/activate(mob/user = null) - if(surplus() < 1500) + if(POWER_SURPLUS(src) < 1500) if(user) to_chat(user, SPAN_NOTICE("The connected wire doesn't have enough current.")) return for(var/A in SScalamity.singularities) @@ -80,6 +80,7 @@ /obj/machinery/power/tesla_beacon/process() if(!active) return PROCESS_KILL - else - if(draw_power(1500) < 1500) - deactivate() + var/can_draw = POWER_DRAW(src, 1500) >= 1500 + DRAW_POWER(src, can_draw) + if(!can_draw) + deactivate() diff --git a/code/game/machinery/vending/clothing.dm b/code/game/machinery/vending/clothing.dm index 6225b49d370d..cae0dc5819d2 100644 --- a/code/game/machinery/vending/clothing.dm +++ b/code/game/machinery/vending/clothing.dm @@ -29,7 +29,6 @@ /obj/item/clothing/under/dressshirt/silversun = 8, // Pants /obj/item/clothing/pants/black = 8, - /obj/item/clothing/pants/tan = 4, /obj/item/clothing/pants/jeans = 4, /obj/item/clothing/pants/jeansblack = 4, /obj/item/clothing/pants/striped = 4, diff --git a/code/game/machinery/vending/misc_offship.dm b/code/game/machinery/vending/misc_offship.dm index 698479a616c1..8371d4c2fc71 100644 --- a/code/game/machinery/vending/misc_offship.dm +++ b/code/game/machinery/vending/misc_offship.dm @@ -17,7 +17,7 @@ ) premium = list( /obj/item/gun/projectile/shotgun/pump/rifle/blank = 3, - /obj/item/ammo_magazine/boltaction/blank = 10, + /obj/item/ammo_magazine/boltaction/adhomai/blank = 10, /obj/item/storage/box/fancy/cigarettes/dpra = 5, /obj/item/storage/chewables/tobacco/bad = 5, /obj/item/reagent_containers/food/drinks/bottle/messa_mead = 5, diff --git a/code/game/machinery/vending/snacks.dm b/code/game/machinery/vending/snacks.dm index ce872f02128c..b0ed48c60091 100644 --- a/code/game/machinery/vending/snacks.dm +++ b/code/game/machinery/vending/snacks.dm @@ -212,7 +212,7 @@ icon_state = "frontiervend" icon_deny = "frontiervend-deny" product_slogans = "At least 85 billion served!;A new frontier of flavors!;Snacking for a free frontier!;Every purchase made supports the efforts of the Frontier Protection Bureau!" - product_ads = "Roundhouse kick a Solarian into the concrete.;Slam-dunk Solarians into the trashcan.;Launch Solarians into the sun.;Frost got what he deserved." + product_ads = "The favored flavors of freedom fighters everywhere.;Tastes for the discerning independent!;Frost got what he deserved.;Every Solarian is the next Hopper until proven otherwise.;The only vending machine banned on Unity Station!;The only good Solarian is a \[moderately inconvenienced\] Solarian." vend_id = "frontiervend" products = list( diff --git a/code/game/machinery/vending/wardrobe.dm b/code/game/machinery/vending/wardrobe.dm index c9afe0270966..e5a8ef230941 100644 --- a/code/game/machinery/vending/wardrobe.dm +++ b/code/game/machinery/vending/wardrobe.dm @@ -768,7 +768,7 @@ /obj/item/clothing/suit/storage/toggle/highvis/alt = 3, /obj/item/clothing/suit/storage/toggle/highvis/orange = 3, /obj/item/clothing/suit/storage/toggle/highvis/red = 3, - /obj/item/clothing/pants/shorts/khaki = 24, + /obj/item/clothing/pants/shorts/black = 24, /obj/item/clothing/pants/highvis = 3, /obj/item/clothing/pants/highvis/alt = 3, /obj/item/clothing/pants/highvis/orange = 3, diff --git a/code/game/objects/effects/chem/chemsmoke.dm b/code/game/objects/effects/chem/chemsmoke.dm index b0034cda7cc9..98f6082519fe 100644 --- a/code/game/objects/effects/chem/chemsmoke.dm +++ b/code/game/objects/effects/chem/chemsmoke.dm @@ -200,7 +200,7 @@ var/pressure = 0 var/datum/gas_mixture/environment = location.return_air() - if(environment) pressure = environment.return_pressure() + pressure = SAFE_XGM_PRESSURE(environment) duration = between(5, (duration*pressure)/(ONE_ATMOSPHERE), duration*2) var/const/arcLength = 2.3559 //distance between each smoke cloud diff --git a/code/game/objects/effects/chem/water.dm b/code/game/objects/effects/chem/water.dm index 98473a479988..e342623a49bb 100644 --- a/code/game/objects/effects/chem/water.dm +++ b/code/game/objects/effects/chem/water.dm @@ -5,30 +5,40 @@ mouse_opacity = MOUSE_OPACITY_TRANSPARENT pass_flags = PASSTABLE | PASSGRILLE -/obj/effect/effect/water/New(loc) - ..() +/obj/effect/effect/water/Initialize() + . = ..() QDEL_IN(src, 15 SECONDS) // In case whatever made it forgets to delete it +/obj/effect/effect/water/Destroy() + reagents = null + return ..() + /obj/effect/effect/water/proc/set_color() // Call it after you move reagents to it - icon += reagents.get_color() + if(!reagents) + return + var/reagent_color = reagents.get_color() + if(reagent_color) + icon += reagent_color /obj/effect/effect/water/proc/set_up(var/turf/target, var/step_count = 5, var/delay = 5, var/lifespan = 10) - if(!target) + if(!target || QDELETED(src)) return for(var/i = 1 to step_count) - if(!loc) + if(QDELETED(src) || !loc) return step_towards(src, target) var/turf/T = get_turf(src) if(T && reagents) - if(!wet_things(T)) break - if(T == get_turf(target)) break sleep(delay) - if(length(reagents)) + + if(QDELETED(src)) + return + + if(reagents && reagents.total_volume) var/mob/M = locate() in get_turf(src) if(M) reagents.trans_to(M, reagents.total_volume * 0.75) @@ -45,10 +55,9 @@ /obj/effect/effect/water/proc/wet_things(var/turf/T) SHOULD_NOT_SLEEP(TRUE) - if (!reagents || reagents.total_volume <= 0) + if (QDELETED(src) || !reagents || reagents.total_volume <= 0) return FALSE - reagents.touch_turf(T) var/list/mobshere = list() for(var/atom/atom_in_turf as anything in T) diff --git a/code/game/objects/effects/decals/Cleanable/fuel.dm b/code/game/objects/effects/decals/Cleanable/fuel.dm index a5f610c6a24c..c848b2f9e999 100644 --- a/code/game/objects/effects/decals/Cleanable/fuel.dm +++ b/code/game/objects/effects/decals/Cleanable/fuel.dm @@ -47,45 +47,6 @@ new/obj/effect/decal/cleanable/liquid_fuel(target, amount*0.25,1) amount *= 0.75 - -/obj/effect/decal/cleanable/liquid_fuel/napalm - name = "napalm gel" - -/obj/effect/decal/cleanable/liquid_fuel/napalm/Initialize(mapload, amt = 1, nologs = 0) - . = ..() - START_PROCESSING(SSprocessing, src) - -/obj/effect/decal/cleanable/liquid_fuel/napalm/Destroy() - STOP_PROCESSING(SSprocessing, src) - return ..() - -/obj/effect/decal/cleanable/liquid_fuel/napalm/Spread() - if(amount < 100) - return - var/turf/simulated/S = loc - if(!istype(S)) - return - for(var/d in GLOB.cardinals) - var/turf/simulated/target = get_step(src,d) - var/turf/simulated/origin = get_turf(src) - if(origin.CanPass(null, target, 0, 0) && target.CanPass(null, origin, 0, 0)) - var/obj/effect/decal/cleanable/liquid_fuel/napalm/other_fuel = locate() in target - if(other_fuel) - other_fuel.amount += amount*0.5 - target.hotspot_expose(2000, 400) - else - new/obj/effect/decal/cleanable/liquid_fuel/napalm(target, amount*0.5,1) - target.hotspot_expose(2000, 400) - amount *= 0.5 - origin.hotspot_expose(2000, 400) //immediately ignite. its napalm bitch - -/obj/effect/decal/cleanable/liquid_fuel/napalm/process() - for(var/mob/living/L in get_turf(src)) - var/sticky = min(rand(5,25), amount) - if(sticky > 1) - L.adjust_fire_stacks(sticky) - amount = max(1, amount - sticky) - /obj/effect/decal/cleanable/foam //Copied from liquid fuel name = "foam" desc = "Some kind of extinguishing foam." diff --git a/code/game/objects/effects/decals/Cleanable/napalm.dm b/code/game/objects/effects/decals/Cleanable/napalm.dm new file mode 100644 index 000000000000..98f177559051 --- /dev/null +++ b/code/game/objects/effects/decals/Cleanable/napalm.dm @@ -0,0 +1,156 @@ +/obj/effect/decal/cleanable/napalm + name = "napalm gel" + desc = "Some kind of sticky, flammable liquid." + icon = 'icons/effects/effects.dmi' + icon_state = "napalm" + layer = BLOOD_LAYER + anchored = 1 + ///How much power we want to use for each reagent amount + var/power_mult = 250 // Over 2k Kelvin in a few seconds + ///The color of the fire. Null will default to the standard + var/fire_color = null + ///How much reagent we have + var/amount = 1 + ///Are we currently on fire? + var/on_fire = FALSE + +/obj/effect/decal/cleanable/napalm/Initialize(mapload, amt = 1, nologs = FALSE, ignite_immediately = FALSE) + . = ..() + if(!nologs && !mapload) + log_and_message_admins("spilled [name]", user = usr, location = get_turf(src)) + src.amount = amt + + var/has_spread = 0 + //Be absorbed by any other liquid fuel in the tile. + for(var/obj/effect/decal/cleanable/napalm/other in loc) + if(other != src) + other.amount += src.amount + other.Spread(ignite_immediately) + has_spread = 1 + break + + if(!has_spread) + Spread(ignite_immediately) + else + qdel(src) + + if(ignite_immediately) + Ignite() + +/obj/effect/decal/cleanable/napalm/Destroy() + STOP_PROCESSING(SSprocessing, src) + return ..() + +/obj/effect/decal/cleanable/napalm/proc/Spread(ignite_immediately = FALSE) + if(amount < 100) + return + var/turf/simulated/S = loc + if(!istype(S)) + return + for(var/d in GLOB.cardinals) + var/turf/simulated/target = get_step(src,d) + if(istype(target)) + continue + var/turf/simulated/origin = get_turf(src) + if(origin.CanPass(null, target, 0, 0) && target.CanPass(null, origin, 0, 0)) + var/obj/effect/decal/cleanable/napalm/other_fuel = locate() in target + if(other_fuel) + other_fuel.amount += amount*0.5 + if(ignite_immediately) + other_fuel.Ignite() + else + new /obj/effect/decal/cleanable/napalm(target, amount*0.5, TRUE, ignite_immediately) + amount *= 0.5 + +/obj/effect/decal/cleanable/napalm/process(seconds_per_tick) + var/turf/simulated/src_turf = get_turf(src) + var/datum/gas_mixture/air_contents = src_turf?.return_air() + var/is_cmb = CMB_LIQUID_FUEL + if(air_contents) + CHECK_COMBUSTIBLE(is_cmb, air_contents) + else + is_cmb = FALSE + if(!is_cmb) + PutOut() + return + + var/napalm_used = min(amount, seconds_per_tick * 0.4) // We use roughly 0.4 per second, or less if there isn't enough napalm + + var/burn_amount = power_mult * napalm_used + + src_turf.IgniteTurf(burn_amount, fire_color) + amount -= napalm_used + + if(amount <= 0) + qdel(src) + + //Stick to mobs in our turf + for(var/mob/living/L in src_turf) + var/sticky = min(rand(power_mult,5*power_mult), amount) * seconds_per_tick + if(sticky > 1 * seconds_per_tick) + L.adjust_fire_stacks(sticky) + amount = max(1, amount - sticky) + + if(amount <= 0) + qdel(src) + +/obj/effect/decal/cleanable/napalm/proc/Ignite() + var/turf/simulated/src_turf = get_turf(src) + var/datum/gas_mixture/air_contents = src_turf?.return_air() + //If we can't ignite, return + var/is_cmb = CMB_LIQUID_FUEL + if(air_contents) + CHECK_COMBUSTIBLE(is_cmb, air_contents) + else + is_cmb = FALSE + if(!is_cmb) + return + //Otherwise, start a fire! + on_fire = TRUE + var/napalm_used = min(amount, 1) + + var/burn_amount = power_mult * napalm_used + + src_turf.IgniteTurf(burn_amount, fire_color) + amount -= napalm_used + + if(amount > 0) + START_PROCESSING(SSprocessing, src) + else + qdel(src) + +/obj/effect/decal/cleanable/napalm/proc/PutOut() + on_fire = FALSE + STOP_PROCESSING(SSprocessing, src) + +/obj/effect/decal/cleanable/napalm/proc/add_napalm(add_amount) + amount += add_amount + Spread() + +/obj/effect/decal/cleanable/napalm/zorane_fire + name = "\improper Zo'rane fire gel" + desc = "Some kind of sticky, flammable liquid." + icon_state = "zorane" + power_mult = 1000 // Four times as good + fire_color = "#5fcae8" + +/obj/effect/decal/cleanable/napalm/zorane_fire/Spread(ignite_immediately = FALSE) + if(amount < 100) + return + var/turf/simulated/S = loc + if(!istype(S)) + return + for(var/d in GLOB.cardinals) + var/turf/simulated/target = get_step(src,d) + if(istype(target)) + continue + var/turf/simulated/origin = get_turf(src) + if(origin.CanPass(null, target, 0, 0) && target.CanPass(null, origin, 0, 0)) + var/obj/effect/decal/cleanable/napalm/zorane_fire/other_fuel = locate() in target + if(other_fuel) + other_fuel.amount += amount*0.5 + if(ignite_immediately) + other_fuel.Ignite() + else + new /obj/effect/decal/cleanable/napalm/zorane_fire(target, amount*0.5, TRUE, ignite_immediately) + amount *= 0.5 diff --git a/code/game/objects/effects/explosion_particles.dm b/code/game/objects/effects/explosion_particles.dm index cc18ad1150f7..893e9ce7875f 100644 --- a/code/game/objects/effects/explosion_particles.dm +++ b/code/game/objects/effects/explosion_particles.dm @@ -15,10 +15,6 @@ . = ..() return -/obj/effect/expl_particles/Destroy() - . = ..() - GC_TEMPORARY_HARDDEL - /datum/effect/system/expl_particles var/number = 10 var/turf/location diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm index 384f0507e1ce..533c33f3a3b4 100644 --- a/code/game/objects/effects/spiders.dm +++ b/code/game/objects/effects/spiders.dm @@ -74,7 +74,7 @@ return TRUE if(mover?.movement_type & PHASING) return TRUE - if(istype(mover, /mob/living/simple_animal/hostile/giant_spider)) + if(istype(mover, /mob/living/simple_animal/hostile/giant_spider) || (mover.pulledby && istype(mover.pulledby, /mob/living/simple_animal/hostile/giant_spider))) return TRUE else if(istype(mover, /mob/living)) if(prob(50)) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 7d21ebb7b6dd..adc75a9ffc55 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -257,10 +257,7 @@ /obj/item/Destroy() if(ismob(loc)) var/mob/m = loc - m.drop_from_inventory(src) - m.update_inv_r_hand() - m.update_inv_l_hand() - src.loc = null + m.drop_from_inventory(src, null) if(!QDELETED(action)) QDEL_NULL(action) // /mob/living/proc/handle_actions() creates it, for ungodly reasons @@ -930,7 +927,7 @@ GLOBAL_LIST_INIT(slot_flags_enumeration, list( user.langchat_speech("holds up [src].", viewers, GLOB.all_languages, skip_language_check = TRUE, animation_style = LANGCHAT_FAST_POP, additional_styles = list("langchat_small", "emote")) for (var/mob/M in viewers) if(!user.is_invisible_to(M)) - M.show_message("[user] holds up [icon2html(src, viewers)] [src]. Take a closer look.",1) + M.show_message("[user] holds up [icon2html(src, M)] [src]. Take a closer look.",1) /mob/living/carbon/verb/showoff() set name = "Show Held Item" diff --git a/code/game/objects/items/airbubble.dm b/code/game/objects/items/airbubble.dm index 47ff02b8a806..a9c861b4c035 100644 --- a/code/game/objects/items/airbubble.dm +++ b/code/game/objects/items/airbubble.dm @@ -84,7 +84,7 @@ /obj/structure/closet/airbubble/feedback_hints(mob/user, distance, is_adjacent) . += ..() if(!isnull(internal_tank)) - . += SPAN_NOTICE("\The [src] has [internal_tank] attached, that displays [round(internal_tank.air_contents.return_pressure() ? internal_tank.air_contents.return_pressure() : 0)] kPa.") + . += SPAN_NOTICE("\The [src] has [internal_tank] attached, that displays [round(SAFE_XGM_PRESSURE(internal_tank.air_contents))] kPa.") else . += SPAN_NOTICE("\The [src] has no tank attached.") if (cell) @@ -508,12 +508,13 @@ /obj/structure/closet/airbubble/proc/process_tank_give_air() if(internal_tank) var/datum/gas_mixture/tank_air = internal_tank.return_air() + var/tank_pressure = XGM_PRESSURE(tank_air) var/release_pressure = internal_tank_valve // If ripped, we are leaking if(ripped) // If we has no pressure in the tank, why bother? - if(tank_air.return_pressure() <= 1) + if(tank_pressure <= 1) STOP_PROCESSING(SSfast_process, src) use_internal_tank = !use_internal_tank visible_message(SPAN_WARNING("You hear last bits of air coming out from [src]'s hole.Maybe the tank run out of air?")) @@ -530,8 +531,8 @@ else qdel(removed) return - var/inside_pressure = inside_air.return_pressure() - var/pressure_delta = min(release_pressure - inside_pressure, (tank_air.return_pressure() - inside_pressure)/2) + var/inside_pressure = XGM_PRESSURE(inside_air) + var/pressure_delta = min(release_pressure - inside_pressure, (tank_pressure - inside_pressure)/2) var/transfer_moles = 0 if(pressure_delta > 0) //inside pressure lower than release pressure @@ -545,7 +546,7 @@ pressure_delta = inside_pressure - release_pressure if(t_air) - pressure_delta = min(inside_pressure - t_air.return_pressure(), pressure_delta) + pressure_delta = min(inside_pressure - XGM_PRESSURE(t_air), pressure_delta) if(pressure_delta > 0) //if location pressure is lower than inside pressure transfer_moles = pressure_delta*inside_air.volume/(inside_air.temperature * R_IDEAL_GAS_EQUATION) @@ -586,27 +587,6 @@ if(T) return T.return_air() -/obj/structure/closet/airbubble/proc/return_pressure() - . = 0 - if(use_internal_tank) - . = inside_air.return_pressure() - else - var/datum/gas_mixture/t_air = get_turf_air() - if(t_air) - . = t_air.return_pressure() - return - - -/obj/structure/closet/airbubble/proc/return_temperature() - . = 0 - if(use_internal_tank) - . = inside_air.temperature - else - var/datum/gas_mixture/t_air = get_turf_air() - if(t_air) - . = t_air.temperature - return - /obj/structure/closet/airbubble/process() process_preserve_temp() process_tank_give_air() diff --git a/code/game/objects/items/devices/auto_cpr.dm b/code/game/objects/items/devices/auto_cpr.dm index 87b87d4e3195..ab4375dae805 100644 --- a/code/game/objects/items/devices/auto_cpr.dm +++ b/code/game/objects/items/devices/auto_cpr.dm @@ -71,7 +71,7 @@ else . += SPAN_DANGER("It currently has a battery with no charge left!") if(tank) - . += "It has \the [tank] installed. The meter shows [round(tank.air_contents.return_pressure())] kPa, \ + . += "It has \the [tank] installed. The meter shows [round(XGM_PRESSURE(tank.air_contents))] kPa, \ with the pressure set to [round(tank.distribute_pressure)] kPa.[epp_active ? " The [EPP] is active." : ""]" if(breath_mask) . += "It has \the [breath_mask] installed." @@ -389,7 +389,7 @@ src.visible_message(SPAN_WARNING("Error! Patient safety check triggered! Turning the [EPP] off.")) epp_off() return - if(tank.air_contents.return_pressure() <= 10) + if(XGM_PRESSURE(tank.air_contents) <= 10) src.visible_message(SPAN_WARNING("Error! Installed [tank] is low or near empty! Turning the [EPP] off.")) epp_off() return diff --git a/code/game/objects/items/devices/debugger.dm b/code/game/objects/items/devices/debugger.dm index aaa60891156d..6cee693d1adc 100644 --- a/code/game/objects/items/devices/debugger.dm +++ b/code/game/objects/items/devices/debugger.dm @@ -1,4 +1,4 @@ -// Used to resolve throwing vendors without going directly into wiring. +/// Used to resolve throwing vendors without going directly into wiring. /obj/item/debugger name = "debugger" desc = "Used to debug electronic equipment, debuggers come with a retractable data cable that can be plugged into most machines." @@ -15,6 +15,8 @@ matter = list(MATERIAL_PLASTIC = 50, DEFAULT_WALL_MATERIAL = 50, MATERIAL_GLASS = 20) origin_tech = list(TECH_MAGNET = 1, TECH_ENGINEERING = 1) + contained_sprite = TRUE + /obj/item/debugger/mechanics_hints(mob/user, distance, is_adjacent) . += ..() . += "The debugger can be used on vending machines and APCs to identify and resolve any viral infections." diff --git a/code/game/objects/items/devices/geiger.dm b/code/game/objects/items/devices/geiger.dm index 4e50630ab7bc..8f6ddd58d812 100644 --- a/code/game/objects/items/devices/geiger.dm +++ b/code/game/objects/items/devices/geiger.dm @@ -1,9 +1,10 @@ /obj/item/geiger name = "geiger counter" desc = "A handheld device used for detecting and measuring radiation in an area." - icon = 'icons/obj/geiger_counter.dmi' + icon = 'icons/obj/item/scanner.dmi' icon_state = "geiger_off" - item_state = "multitool" + item_state = "geiger" + contained_sprite = TRUE w_class = WEIGHT_CLASS_SMALL action_button_name = "Toggle geiger counter" matter = list(MATERIAL_PLASTIC = 100, DEFAULT_WALL_MATERIAL = 100, MATERIAL_GLASS = 50) @@ -58,6 +59,7 @@ update_sound(0) return 1 + if(!sound_token) update_sound(1) switch(radiation_count) diff --git a/code/game/objects/items/devices/lighting/flare.dm b/code/game/objects/items/devices/lighting/flare.dm index e687d3d83d35..1a1099e7052d 100644 --- a/code/game/objects/items/devices/lighting/flare.dm +++ b/code/game/objects/items/devices/lighting/flare.dm @@ -16,6 +16,7 @@ toggle_sound = null drop_sound = 'sound/items/drop/gloves.ogg' pickup_sound = 'sound/items/pickup/gloves.ogg' + light_system = MOVABLE_LIGHT /obj/item/flashlight/flare/mechanics_hints(mob/user, distance, is_adjacent) . += ..() diff --git a/code/game/objects/items/devices/lighting/flashlight.dm b/code/game/objects/items/devices/lighting/flashlight.dm index 0d9dface53c2..27ac603d95f0 100644 --- a/code/game/objects/items/devices/lighting/flashlight.dm +++ b/code/game/objects/items/devices/lighting/flashlight.dm @@ -7,6 +7,7 @@ w_class = WEIGHT_CLASS_SMALL obj_flags = OBJ_FLAG_CONDUCTABLE slot_flags = SLOT_BELT + contained_sprite = TRUE light_color = LIGHT_COLOR_HALOGEN light_system = DIRECTIONAL_LIGHT light_range = 4 diff --git a/code/game/objects/items/devices/lighting/marshalling_wand.dm b/code/game/objects/items/devices/lighting/marshalling_wand.dm index 35df848e24b3..314dc7b5d03e 100644 --- a/code/game/objects/items/devices/lighting/marshalling_wand.dm +++ b/code/game/objects/items/devices/lighting/marshalling_wand.dm @@ -3,17 +3,38 @@ desc = "A marshalling wand, used to direct air or space faring vessels during takeoff and landing." icon_state = "marshallingwand" item_state = "marshallingwand" + build_from_parts = TRUE + worn_overlay = "bulb" + worn_overlay_color = LIGHT_COLOR_WHITE w_class = WEIGHT_CLASS_SMALL - light_color = LIGHT_COLOR_RED + light_system = MOVABLE_LIGHT light_range = 2 action_button_name = "Toggle Marshalling Wands" +/obj/item/flashlight/marshallingwand/Initialize() + . = ..() + update_icon() // Initial build_from_parts assembly + +/obj/item/flashlight/marshallingwand/mechanics_hints(mob/user, distance, is_adjacent) + . += ..() + . += "ALT-click the marshalling wand to turn it on and off. Everytime you turn it on it will be blue, signaling and idle intent." + . += "Using the wand will change its color based of your intent. Each intent has a different output." + . += "Holding two marshalling wands in your hands will mirror the state of one to the other, so that they are always in sync." + +// Override brights. The marshalling wands are meant to be always bright, this will toggle the on and off instead. /obj/item/flashlight/marshallingwand/AltClick(mob/user) if(!use_check_and_message(user)) if(!isturf(user.loc)) - to_chat(user, SPAN_WARNING("You cannot turn the light on while in this [user.loc].")) //To prevent some lighting anomalities.) + to_chat(user, SPAN_WARNING("You cannot turn the light on while in this [user.loc].")) // To prevent some lighting anomalities.) return FALSE toggle() + if(on) + set_light_color(LIGHT_COLOR_BLUE) // Default to blue (stand-by) when turned on + worn_overlay_color = light_color + else + worn_overlay_color = LIGHT_COLOR_WHITE + update_icon() + mirror_held_wands(src) user.update_action_buttons() return TRUE @@ -21,16 +42,71 @@ AltClick(usr) /obj/item/flashlight/marshallingwand/attack_self(mob/user) + // Are we holding one or two wands? + var/wand_invariant = "" + if(ismob(loc)) + var/mob/m = loc + var/item = m.get_inactive_hand() + if(item && istype(item, /obj/item/flashlight/marshallingwand)) + wand_invariant = "wands" + else + wand_invariant = "wand" + if(!on) - to_chat(user, SPAN_WARNING("The wands need to be on before you can direct craft with them!")) + to_chat(user, SPAN_WARNING("The [wand_invariant] need to be turned on before you can direct crafts with them!")) return + switch(user.a_intent) if(I_HELP) - user.visible_message(SPAN_NOTICE("[user] points the marshalling wand forward, directing a pilot to take off."), SPAN_NOTICE("You point the marshalling wand forward, directing a pilot to take off.")) + set_light_color(LIGHT_COLOR_GREEN) // Green for go! if(I_DISARM) - user.visible_message(SPAN_NOTICE("[user] waves the marshalling wand toward themself, directing a pilot to approach."), SPAN_NOTICE("You wave the marshalling wand toward yourself, directing a pilot to approach.")) + set_light_color(LIGHT_COLOR_BLUE) // Blue for stand-by - Idle while nothing is happening yet. if(I_GRAB) - user.visible_message(SPAN_NOTICE("[user] holds the marshalling wand out, directing a pilot to cease movement."), SPAN_NOTICE("You hold the marshalling wand out, directing a pilot to cease movement.")) + set_light_color(LIGHT_COLOR_YELLOW) // Yellow for hold - Last checks are in progress. Prepare for takeoff! if(I_HURT) - user.visible_message(SPAN_WARNING("[user] frantically waves the marshalling wand!"), SPAN_WARNING("You wave the marshalling wand frantically!")) + set_light_color(LIGHT_COLOR_RED) // Stop! Craft is being serviced or shutting down. + worn_overlay_color = light_color + + switch(light_color) + if(LIGHT_COLOR_GREEN) + user.visible_message(SPAN_NOTICE("[user] quickly waves the marshalling [wand_invariant] forward, giving the craft the lift-off signal!"), SPAN_NOTICE("You wave the marshalling [wand_invariant] forward quickly, directing the craft to take off.")) + if(LIGHT_COLOR_BLUE) + user.visible_message(SPAN_NOTICE("[user] holds the marshalling [wand_invariant] close to themselves, deck is idle, don't do any unexpected things!"), SPAN_NOTICE("You hold the marshalling [wand_invariant] close to yourself, signaling an idle stance...")) + if(LIGHT_COLOR_YELLOW) + user.visible_message(SPAN_WARNING("[user] holds the marshalling [wand_invariant] out to the sides, indicating that the craft is being checked before lift off, prepare for lift off!"), SPAN_WARNING("You hold the marshalling [wand_invariant] out to your sides, indicating that the craft is being prepared for lift off.")) + if(LIGHT_COLOR_RED) + user.visible_message(SPAN_WARNING("[user] steadily holds the marshalling [wand_invariant] above their head in a cross! Hold all movement!"), SPAN_WARNING("You hold the marshalling [wand_invariant] in a cross above your head, signaling full stop.")) + + update_icon() + mirror_held_wands(src) + +/obj/item/flashlight/marshallingwand/update_icon() + ClearOverlays() + var/image/bulb_overlay = overlay_image(icon, "[initial(icon_state)]_[worn_overlay]") + bulb_overlay.blend_mode = BLEND_OVERLAY + AddOverlays(bulb_overlay) + if(on) + var/image/light_overlay = overlay_image(icon, "marshallingwand-overlay", light_color) + light_overlay.blend_mode = BLEND_OVERLAY + AddOverlays(light_overlay) + set_light_range_power_color(light_range, flashlight_power, light_color) + set_light_on(on) + update_held_icon() +/obj/item/flashlight/marshallingwand/proc/mirror_held_wands(var/obj/item/flashlight/marshallingwand/source_wand) + // If we are holding a wand in the other hand, make sure to mirror the state of this one to it, so that they are always in sync. + if(ismob(loc)) + var/mob/m = loc + var/item_act = m.get_active_hand() + var/item_inact = m.get_inactive_hand() + if(!item_act || !item_inact || !istype(item_act, /obj/item/flashlight/marshallingwand) || !istype(item_inact, /obj/item/flashlight/marshallingwand)) + return // Only one wand or different item, abort. + var/obj/item/flashlight/marshallingwand/target_wand + if(item_act == source_wand) // Check which one needs the update. + target_wand = item_inact + else + target_wand = item_act + target_wand.on = source_wand.on + target_wand.set_light_color(source_wand.light_color) + target_wand.worn_overlay_color = source_wand.worn_overlay_color + target_wand.update_icon() diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm index dfe4d91504bd..4793922725b7 100644 --- a/code/game/objects/items/devices/multitool.dm +++ b/code/game/objects/items/devices/multitool.dm @@ -9,7 +9,7 @@ icon = 'icons/obj/item/multitool.dmi' icon_state = "multitool" item_state = "multitool" - item_icons = null + contained_sprite = TRUE obj_flags = OBJ_FLAG_CONDUCTABLE force = 11 w_class = WEIGHT_CLASS_SMALL diff --git a/code/game/objects/items/devices/oxycandle.dm b/code/game/objects/items/devices/oxycandle.dm index d356d1f8d750..08b29d2ce113 100644 --- a/code/game/objects/items/devices/oxycandle.dm +++ b/code/game/objects/items/devices/oxycandle.dm @@ -47,7 +47,7 @@ if(pos) pos.hotspot_expose(1500, 5) var/datum/gas_mixture/environment = loc.return_air() - var/pressure_delta = target_pressure - environment.return_pressure() + var/pressure_delta = target_pressure - XGM_PRESSURE(environment) var/output_volume = environment.volume * environment.group_multiplier var/air_temperature = air_contents.temperature? air_contents.temperature : environment.temperature var/transfer_moles = pressure_delta*output_volume/(air_temperature * R_IDEAL_GAS_EQUATION) diff --git a/code/game/objects/items/devices/paint_sprayer.dm b/code/game/objects/items/devices/paint_sprayer.dm index 72d4cb62b622..8311a8940683 100644 --- a/code/game/objects/items/devices/paint_sprayer.dm +++ b/code/game/objects/items/devices/paint_sprayer.dm @@ -8,7 +8,8 @@ desc = "A Hephaestus-made paint gun that uses microbes to replenish its paint storage. Very high-tech and fancy too!" icon = 'icons/obj/item/paint_sprayer.dmi' icon_state = "paint_sprayer" - item_state = "mister" + item_state = "paint_sprayer" + contained_sprite = TRUE var/decal = "remove all decals" var/paint_dir = "precise" var/paint_colour = COLOR_WHITE @@ -79,9 +80,58 @@ "bulkhead black" = COLOR_WALL_GUNMETAL ) + var/list/locker_paint_schemes = list( + "Fire Control" = "fire", + "Emergency O2" = "emergency", + "Medical" = "med", + "Ops (Mining)" = "miner", + "Ops (Hangar Tech)" = "hangar_tech", + "Ops (Machinist)" = "machinist", + "Hazmat" = "hazmat", + "Hazmat (Custodial)" = "hazmat_custodial", + "Engi (Tool)" = "eng_tool", + "Engi (Rad)" = "eng_rad", + "Engi (Elec)" = "eng_elec", + "Engi (Weld)" = "eng_weld", + "Engi (L2)" = "eng_l2", + "Atmos" = "atmos", + "Security" = "sec", + "Hydroponics" = "hydro" + ) + + var/list/crate_paint_schemes = list( + "Fire Control" = "fire", + "Emergency O2" = "o2_crate", + "Medical" = "medical_crate", + "Science" = "science_crate", + "Engi (Tool)" = "eng_tool", + "Engi (Rad)" = "eng_rad", + "Engi (Elec)" = "eng_elec", + "Engi (Weld)" = "eng_weld", + "Engi (L2)" = "eng_l2", + "Security" = "security_crate", + "Contraband Stripes" = "secgear_crate", + "Hydroponics" = "hydro_crate" + ) + + /// Pipe painting modes + var/list/modes + var/mode + + +/// Initialize available pipe color modes. +/obj/item/paint_sprayer/New() + ..() + modes = new() + for(var/C in GLOB.pipe_colors) + modes += "[C]" + mode = pick(modes) + /obj/item/paint_sprayer/mechanics_hints(mob/user, distance, is_adjacent) . += ..() - . += "CTRL-click a turf with the paint sprayer to copy the color(s) used on it." + . += "Use a paint sprayer on yourself to configure it." + . += "Paint sprayers can be used on the following targets: floors, airlocks, exosuit frames and components, beds, atmos pipes, and (plain grey) lockers/crates." + . += "CTRL-click a turf or airlock with the paint sprayer to copy the color(s) used on it." . += "SHIFT-click a turf with the paint sprayer to clear all decals from it." /obj/item/paint_sprayer/feedback_hints(mob/user, distance, is_adjacent) @@ -126,8 +176,24 @@ else if (istype(A, /turf/simulated/floor)) return paint_floor(A, user, params) + else if (istype(A, /obj/structure/closet/crate)) + return paint_crate(A, user, params) + + else if (istype(A, /obj/structure/closet)) + return paint_locker(A, user, params) + + else if(istype(A,/obj/machinery/atmospherics/pipe)) + var/obj/machinery/atmospherics/pipe/P = A + P.change_color(GLOB.pipe_colors[mode]) + playsound(get_turf(src), 'sound/effects/spray3.ogg', 30, 1, -6) + + else if(istype(A, /obj/item/pipe) && pipe_color_check(GLOB.pipe_colors[mode])) + var/obj/item/pipe/P = A + P.color = GLOB.pipe_colors[mode] + playsound(get_turf(src), 'sound/effects/spray3.ogg', 30, 1, -6) + /obj/item/paint_sprayer/proc/paint_floor(turf/simulated/floor/F, mob/user, params) - if(!F.flooring.can_paint) + if(!F.flooring?.can_paint) to_chat(user, SPAN_WARNING("\The [src] cannot paint this type of flooring.")) return @@ -185,20 +251,22 @@ new painting_decal(F, painting_dir, painting_colour) /obj/item/paint_sprayer/attack_self(var/mob/user) - var/choice = tgui_alert(user, "Do you wish to change the decal type, paint direction, or paint colour?", "Paint Sprayer", list("Decal","Direction", "Colour")) + var/choice = tgui_input_list(user, "Do you wish to change: decal type, paint direction, paint colour (for turfs), or pipe colour mode?", "Paint Sprayer", list("Decal","Direction","Colour","Pipe Colour"), 30 SECONDS) if(choice == "Decal") choose_decal() else if(choice == "Direction") choose_direction() else if(choice == "Colour") choose_colour() + else if(choice == "Pipe Colour") + choose_pipe_colour() /obj/item/paint_sprayer/proc/change_colour(new_colour, mob/user) if (new_colour) paint_colour = new_colour if (user) add_fingerprint(user) - to_chat(user, SPAN_NOTICE("You set \the [src] to paint with a new color.")) + to_chat(user, SPAN_NOTICE("You set \the [src] to paint with a new colour.")) update_icon() playsound(src, 'sound/weapons/blade_open.ogg', 30, 1) return TRUE @@ -365,5 +433,68 @@ paint_dir = new_dir to_chat(usr, SPAN_NOTICE("You set \the [src] direction to '[paint_dir]'.")) +/obj/item/paint_sprayer/verb/choose_pipe_colour(var/mob/user) + mode = tgui_input_list(user, "Choose a colour.", "Pipe Painter", modes, mode) + +/obj/item/paint_sprayer/proc/paint_locker(obj/structure/closet/target_closet, mob/user, input_text) + if(!target_closet.can_label) + to_chat(user, SPAN_NOTICE("This container has already been painted.")) + return FALSE + var/paint_job = tgui_input_list(usr, "Choose locker paint scheme.", "Paint Sprayer", locker_paint_schemes) + if(paint_job) + var/new_icon_state = locker_paint_schemes[paint_job] + target_closet.paint_container(new_icon_state) + playsound(get_turf(src), 'sound/effects/spray3.ogg', 30, 1, -6) + return TRUE + +/obj/item/paint_sprayer/proc/paint_crate(obj/structure/closet/crate/target_crate, mob/user, input_text) + if(!target_crate.can_label) + to_chat(user, SPAN_NOTICE("This container has already been painted.")) + return FALSE + var/paint_job = tgui_input_list(usr, "Choose crate paint scheme.", "Paint Sprayer", crate_paint_schemes) + if(paint_job) + var/new_icon_state = crate_paint_schemes[paint_job] + target_crate.paint_container(new_icon_state) + playsound(get_turf(src), 'sound/effects/spray3.ogg', 30, 1, -6) + . = TRUE + #undef AIRLOCK_REGION_PAINT #undef AIRLOCK_REGION_STRIPE + + +// Pipe painter still exists but only as offsite flavor. +/obj/item/pipe_painter + name = "pipe painter" + icon = 'icons/obj/item/paint_sprayer.dmi' + icon_state = "pipe_painter" + item_state = "pipe_painter" + var/list/modes + var/mode + +/obj/item/pipe_painter/feedback_hints(mob/user, distance, is_adjacent) + . += ..() + . += "It is in [mode] mode." + +/obj/item/pipe_painter/New() + ..() + modes = new() + for(var/C in GLOB.pipe_colors) + modes += "[C]" + mode = pick(modes) + +/obj/item/pipe_painter/afterattack(var/atom/A, var/mob/user, proximity) + if(!proximity) + return + if(!in_range(user, A)) + return + else if(is_type_in_list(A, list(/obj/machinery/atmospherics/pipe/tank, /obj/machinery/atmospherics/pipe/simple/heat_exchanging))) + return + else if(istype(A,/obj/machinery/atmospherics/pipe)) + var/obj/machinery/atmospherics/pipe/P = A + P.change_color(GLOB.pipe_colors[mode]) + else if(istype(A, /obj/item/pipe) && pipe_color_check(GLOB.pipe_colors[mode])) + var/obj/item/pipe/P = A + P.color = GLOB.pipe_colors[mode] + +/obj/item/pipe_painter/attack_self(var/mob/user) + mode = tgui_input_list(user, "Which colour do you want to use?", "Pipe Painter", modes, mode) diff --git a/code/game/objects/items/devices/pipe_painter.dm b/code/game/objects/items/devices/pipe_painter.dm deleted file mode 100644 index b398ab9436a4..000000000000 --- a/code/game/objects/items/devices/pipe_painter.dm +++ /dev/null @@ -1,35 +0,0 @@ -/obj/item/pipe_painter - name = "pipe painter" - icon = 'icons/obj/item/pipe_painter.dmi' - icon_state = "pipe_painter" - item_state = "pipe_painter" - var/list/modes - var/mode - -/obj/item/pipe_painter/feedback_hints(mob/user, distance, is_adjacent) - . += ..() - . += "It is in [mode] mode." - -/obj/item/pipe_painter/New() - ..() - modes = new() - for(var/C in GLOB.pipe_colors) - modes += "[C]" - mode = pick(modes) - -/obj/item/pipe_painter/afterattack(var/atom/A, var/mob/user, proximity) - if(!proximity) - return - if(!in_range(user, A)) - return - else if(is_type_in_list(A, list(/obj/machinery/atmospherics/pipe/tank, /obj/machinery/atmospherics/pipe/simple/heat_exchanging))) - return - else if(istype(A,/obj/machinery/atmospherics/pipe)) - var/obj/machinery/atmospherics/pipe/P = A - P.change_color(GLOB.pipe_colors[mode]) - else if(istype(A, /obj/item/pipe) && pipe_color_check(GLOB.pipe_colors[mode])) - var/obj/item/pipe/P = A - P.color = GLOB.pipe_colors[mode] - -/obj/item/pipe_painter/attack_self(var/mob/user) - mode = tgui_input_list(user, "Which colour do you want to use?", "Pipe Painter", modes, mode) diff --git a/code/game/objects/items/devices/powersink.dm b/code/game/objects/items/devices/powersink.dm index 30dbca6b3553..402ebc3fd3ab 100644 --- a/code/game/objects/items/devices/powersink.dm +++ b/code/game/objects/items/devices/powersink.dm @@ -123,7 +123,8 @@ PN.trigger_warning() // found a powernet, so drain up to max power from it - drained = PN.draw_power(drain_rate * seconds_per_tick) + drained = POWERNET_POWER_DRAW(PN, drain_rate * seconds_per_tick) + DRAW_FROM_POWERNET(PN, drained) // if tried to drain more than available on powernet // now look for APCs and drain their cells if(drained < drain_rate * seconds_per_tick) diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index fb30e4db301c..3464c2d70128 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -4,6 +4,7 @@ icon = 'icons/obj/item/radio/headset.dmi' icon_state = "headset" item_state = "headset" + contained_sprite = TRUE matter = list(MATERIAL_ALUMINIUM = 75) subspace_transmission = TRUE canhear_range = 0 // can't hear headsets from very far away @@ -1042,7 +1043,6 @@ /obj/item/radio/headset/heads/ai_integrated/Destroy() myAi = null . = ..() - GC_TEMPORARY_HARDDEL /obj/item/radio/headset/heads/ai_integrated/can_receive(input_frequency, level) return ..(input_frequency, level, !disabledAi) diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index ef85c800bc62..a7cb03e57a8f 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -231,31 +231,91 @@ var/global/list/default_interrogation_channels = list( return ui_interact(user) -/obj/item/radio/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] +/obj/item/radio/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Radio", "[name]") + ui.open() +/obj/item/radio/ui_data(mob/user) + var/list/data = list() data["mic_status"] = broadcasting data["speaker"] = listening - data["freq"] = format_frequency(frequency) - data["default_freq"] = format_frequency(default_frequency) - data["rawfreq"] = num2text(frequency) + data["freq"] = frequency + data["default_freq"] = default_frequency + data["rawfreq"] = frequency data["mic_cut"] = (wires.is_cut(WIRE_TRANSMIT) || wires.is_cut(WIRE_SIGNAL)) data["spk_cut"] = (wires.is_cut(WIRE_RECEIVE) || wires.is_cut(WIRE_SIGNAL)) - var/list/chanlist = list_channels(user) - if(islist(chanlist) && chanlist.len) - data["chan_list"] = chanlist - data["chan_list_len"] = chanlist.len + var/list/chl = list_channels(user) + if(LAZYLEN(chl)) + data["channels"] = chl if(syndie) - data["useSyndMode"] = 1 + data["syndie"] = TRUE - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - ui = new(user, src, ui_key, "radio_basic.tmpl", "[name]", 400, 430) - ui.set_initial_data(data) - ui.open() + return data + +/obj/item/radio/ui_static_data(mob/user) + var/list/data = list() + + data["min_freq"] = PUBLIC_LOW_FREQ + data["max_freq"] = PUBLIC_HIGH_FREQ + + return data + +/obj/item/radio/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + if(..()) + return TRUE + + if(action == "start_track") + var/mob/target = locate(params["target"]) + var/mob/living/silicon/ai/A = locate(params["ai"]) + if(A && target) + A.ai_actual_track(target) + . = TRUE + + else if (action == "set_freq") + var/new_freq = text2num(params["freq"]) + if ((new_freq < PUBLIC_LOW_FREQ || new_freq > PUBLIC_HIGH_FREQ)) + new_freq = sanitize_frequency(new_freq) + set_frequency(new_freq) + if(hidden_uplink) + if(hidden_uplink.check_trigger(usr, frequency, traitor_frequency)) + ui.close() + . = TRUE + else if (action == "toggle_talk") + set_broadcasting(!broadcasting) + . = TRUE + else if (action == "toggle_listen") + var/channel_name = num2text(params["channel_name"]) + if(channel_name == "0") + set_listening(!listening) + else + channel_name = reverseradiochannels[channel_name] + if (channels[channel_name] & FREQ_LISTENING) + channels[channel_name] &= ~FREQ_LISTENING + else + channels[channel_name] |= FREQ_LISTENING + . = TRUE + else if (action == "spec_freq") + var/freq = params["freq"] + if(has_channel_access(usr, num2text(freq))) + set_frequency(freq) + . = TRUE + else if (action == "reset_freq") + if(default_frequency) + set_frequency(default_frequency) + . = TRUE + + if (params["nowindow"]) + return TRUE + + if(.) + update_icon() + if(clicksound && iscarbon(usr)) + playsound(loc, clicksound, clickvol) /obj/item/radio/proc/setupRadioDescription(var/additional_radio_desc) var/radio_text = "" @@ -284,9 +344,9 @@ var/global/list/default_interrogation_channels = list( for(var/ch_name in channels) var/chan_stat = channels[ch_name] - var/listening = !!(chan_stat & FREQ_LISTENING) != 0 + var/listening = chan_stat & FREQ_LISTENING - dat.Add(list(list("chan" = ch_name, "display_name" = ch_name, "secure_channel" = 1, "sec_channel_listen" = !listening, "chan_span" = frequency_span_class(radiochannels[ch_name])))) + dat.Add(list(list("chan" = radiochannels[ch_name], "display_name" = ch_name, "secure_channel" = 1, "sec_channel_listen" = listening, "chan_span" = frequency_span_class(radiochannels[ch_name])))) return dat @@ -294,7 +354,7 @@ var/global/list/default_interrogation_channels = list( var/dat[0] for(var/internal_chan in internal_channels) if(has_channel_access(user, internal_chan)) - dat.Add(list(list("chan" = internal_chan, "display_name" = get_frequency_name(text2num(internal_chan)), "chan_span" = frequency_span_class(text2num(internal_chan))))) + dat.Add(list(list("chan" = text2num(internal_chan), "display_name" = get_frequency_name(text2num(internal_chan)), "chan_span" = frequency_span_class(text2num(internal_chan))))) return dat @@ -327,67 +387,11 @@ var/global/list/default_interrogation_channels = list( Speaker: [list ? "Engaged" : "Disengaged"]
"} -/obj/item/radio/CanUseTopic() +/obj/item/radio/ui_status(mob/user, datum/ui_state/state) if(!on) - return STATUS_CLOSE + return UI_CLOSE return ..() -/obj/item/radio/CouldUseTopic(var/mob/user) - ..() - if(clicksound && iscarbon(user)) - playsound(loc, clicksound, clickvol) - -/obj/item/radio/Topic(href, href_list) - if(..()) - return TRUE - - usr.set_machine(src) - if (href_list["track"]) - var/mob/target = locate(href_list["track"]) - var/mob/living/silicon/ai/A = locate(href_list["track2"]) - if(A && target) - A.ai_actual_track(target) - . = TRUE - - else if (href_list["freq"]) - var/new_frequency = (frequency + text2num(href_list["freq"])) - if ((new_frequency < PUBLIC_LOW_FREQ || new_frequency > PUBLIC_HIGH_FREQ)) - new_frequency = sanitize_frequency(new_frequency) - set_frequency(new_frequency) - if(hidden_uplink) - if(hidden_uplink.check_trigger(usr, frequency, traitor_frequency)) - usr << browse(null, "window=radio") - . = TRUE - else if (href_list["talk"]) - set_broadcasting(!broadcasting) - . = TRUE - else if (href_list["listen"]) - var/chan_name = href_list["ch_name"] - if (!chan_name) - set_listening(!listening) - else - if (channels[chan_name] & FREQ_LISTENING) - channels[chan_name] &= ~FREQ_LISTENING - else - channels[chan_name] |= FREQ_LISTENING - . = TRUE - else if(href_list["spec_freq"]) - var freq = href_list["spec_freq"] - if(has_channel_access(usr, freq)) - set_frequency(text2num(freq)) - . = TRUE - else if(href_list["reset_freq"]) - if(default_frequency) - set_frequency(default_frequency) - . = TRUE - - if(href_list["nowindow"]) // here for pAIs, maybe others will want it, idk - return TRUE - - if(.) - SSnanoui.update_uis(src) - update_icon() - /obj/item/radio/proc/autosay(var/message, var/from, var/channel) //BS12 EDIT var/datum/radio_frequency/connection = null if(channel && channels && channels.len > 0) @@ -556,7 +560,6 @@ var/global/list/default_interrogation_channels = list( else user.show_message(SPAN_NOTICE("\The [src] can no longer be modified or attached!")) updateDialog() - //Foreach goto(83) add_fingerprint(user) return else return @@ -587,7 +590,6 @@ var/global/list/default_interrogation_channels = list( /obj/item/radio/borg/Destroy() myborg = null . = ..() - GC_TEMPORARY_HARDDEL /obj/item/radio/borg/list_channels(var/mob/user) return list_secure_channels(user) @@ -674,71 +676,36 @@ var/global/list/default_interrogation_channels = list( setupRadioDescription() return -/obj/item/radio/borg/Topic(href, href_list) +/obj/item/radio/borg/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) if(..()) - return 1 - if (href_list["mode"]) - var/enable_subspace_transmission = text2num(href_list["mode"]) - if(enable_subspace_transmission != subspace_transmission) - subspace_transmission = !subspace_transmission - if(subspace_transmission) - to_chat(usr, SPAN_NOTICE("Subspace Transmission is enabled")) - else - to_chat(usr, SPAN_NOTICE("Subspace Transmission is disabled")) - - if(subspace_transmission == 0)//Simple as fuck, clears the channel list to prevent talking/listening over them if subspace transmission is disabled - channels = list() - else - recalculateChannels() - . = 1 - if (href_list["shutup"]) // Toggle loudspeaker mode, AKA everyone around you hearing your radio. - var/do_shut_up = text2num(href_list["shutup"]) - if(do_shut_up != shut_up) - shut_up = !shut_up - if(shut_up) - canhear_range = 0 - to_chat(usr, SPAN_NOTICE("Loadspeaker disabled.")) - else - canhear_range = 3 - to_chat(usr, SPAN_NOTICE("Loadspeaker enabled.")) - . = 1 - - if(.) - SSnanoui.update_uis(src) - -/obj/item/radio/borg/interact(mob/user as mob) - if(!on) - return - - . = ..() - -/obj/item/radio/borg/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] - - data["mic_status"] = broadcasting - data["speaker"] = listening - data["freq"] = format_frequency(frequency) - data["default_freq"] = format_frequency(default_frequency) - data["rawfreq"] = num2text(frequency) - - var/list/chanlist = list_channels(user) - if(islist(chanlist) && chanlist.len) - data["chan_list"] = chanlist - data["chan_list_len"] = chanlist.len + return TRUE + if (action == "mode") + subspace_transmission = !subspace_transmission + to_chat(usr, SPAN_NOTICE("Subspace Transmission [subspace_transmission ? "enabled" : "disabled"].")) + if(subspace_transmission) + recalculateChannels() + else + channels = list() + . = TRUE + if (action == "shutup") // Toggle loudspeaker mode, AKA everyone around you hearing your radio. + shut_up = !shut_up + canhear_range = shut_up ? 0 : 3 + to_chat(usr, SPAN_NOTICE("Loudspeaker [shut_up ? "disabled" : "enabled"].")) + . = TRUE - if(syndie) - data["useSyndMode"] = 1 +/obj/item/radio/borg/ui_data(mob/user) + var/list/data = ..() - data["has_loudspeaker"] = 1 data["loudspeaker"] = !shut_up - data["has_subspace"] = 1 data["subspace"] = subspace_transmission - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - ui = new(user, src, ui_key, "radio_basic.tmpl", "[name]", 400, 430) - ui.set_initial_data(data) - ui.open() + return data + +/obj/item/radio/borg/ui_static_data(mob/user) + var/list/data = ..() + data["has_loudspeaker"] = TRUE + data["has_subspace"] = TRUE + return data /obj/item/radio/proc/config(op) if(SSradio) diff --git a/code/game/objects/items/devices/radio_jammer.dm b/code/game/objects/items/devices/radio_jammer.dm index 37558776c2dd..01da5181ae9b 100644 --- a/code/game/objects/items/devices/radio_jammer.dm +++ b/code/game/objects/items/devices/radio_jammer.dm @@ -126,9 +126,10 @@ GLOBAL_LIST_INIT_TYPED(active_radio_jammers, /obj/item/radiojammer, list()) /obj/item/radiojammer/improvised/Destroy() STOP_PROCESSING(SSprocessing, src) + QDEL_NULL(cell) + QDEL_NULL(assembly_holder) return ..() - /obj/item/radiojammer/improvised/process() var/current = world.time // current tick var/delta = (current - last_updated) / 10.0 // delta in seconds diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index ffc30f8492d6..3c95a3a43e74 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -10,9 +10,10 @@ BREATH ANALYZER /obj/item/healthanalyzer name = "health analyzer" desc = "A hand-held body scanner able to distinguish vital signs of the subject." - icon = 'icons/obj/item/healthanalyzer.dmi' - icon_state = "health" - item_state = "analyzer" + icon = 'icons/obj/item/scanner.dmi' + icon_state = "healthanalyzer" + item_state = "healthanalyzer" + contained_sprite = TRUE obj_flags = OBJ_FLAG_CONDUCTABLE slot_flags = SLOT_BELT throwforce = 3 @@ -373,11 +374,12 @@ BREATH ANALYZER to_chat(usr, "The scanner no longer shows limb damage.") /obj/item/analyzer - name = "analyzer" + name = "gas analyzer" desc = "A hand-held environmental scanner which reports current gas levels." - icon = 'icons/obj/item/air_analyzer.dmi' - icon_state = "analyzer" - item_state = "analyzer" + icon = 'icons/obj/item/scanner.dmi' + icon_state = "airanalyzer" + item_state = "airanalyzer" + contained_sprite = TRUE w_class = WEIGHT_CLASS_SMALL obj_flags = OBJ_FLAG_CONDUCTABLE slot_flags = SLOT_BELT @@ -393,7 +395,7 @@ BREATH ANALYZER if(!user) return var/air = user.return_air() if (!air) return - + flick("[icon_state]-scan", src) return atmosanalyzer_scan(src, air, user) /obj/item/analyzer/attack_self(mob/user as mob) @@ -410,9 +412,11 @@ BREATH ANALYZER /obj/item/mass_spectrometer name = "mass spectrometer" desc = "A hand-held mass spectrometer which identifies trace chemicals in a blood sample." - icon = 'icons/obj/item/mass_spectrometer.dmi' + icon = 'icons/obj/item/scanner.dmi' icon_state = "spectrometer" - item_state = "spectrometer" + // Reuses the basic health analyzer inhands. + item_state = "healthanalyzer" + contained_sprite = TRUE w_class = WEIGHT_CLASS_SMALL atom_flags = ATOM_FLAG_OPEN_CONTAINER obj_flags = OBJ_FLAG_CONDUCTABLE @@ -472,8 +476,7 @@ BREATH ANALYZER /obj/item/mass_spectrometer/adv name = "advanced mass spectrometer" - icon_state = "adv_spectrometer" - item_state = "adv_spectrometer" + icon_state = "spectrometer_adv" details = TRUE origin_tech = list(TECH_MAGNET = 4, TECH_BIO = 2) @@ -486,9 +489,11 @@ BREATH ANALYZER /obj/item/reagent_scanner name = "reagent scanner" desc = "A hand-held reagent scanner which identifies chemical agents." - icon = 'icons/obj/item/reagent_scanner.dmi' + icon = 'icons/obj/item/scanner.dmi' icon_state = "reagent_scanner" - item_state = "analyzer" + // Reuses the basic health analyzer inhands. + item_state = "healthanalyzer" + contained_sprite = TRUE w_class = WEIGHT_CLASS_SMALL obj_flags = OBJ_FLAG_CONDUCTABLE slot_flags = SLOT_BELT @@ -521,16 +526,18 @@ BREATH ANALYZER /obj/item/reagent_scanner/adv name = "advanced reagent scanner" - icon_state = "adv_reagent_scanner" - item_state = "analyzer" + icon_state = "reagent_scanner_adv" + // Reuses the advanced health analyzer inhands. + item_state = "healthanalyzer_adv" details = 1 origin_tech = list(TECH_MAGNET = 4, TECH_BIO = 2) /obj/item/slime_scanner name = "slime scanner" - icon = 'icons/obj/item/slime_scanner.dmi' + icon = 'icons/obj/item/scanner.dmi' icon_state = "slime_scanner" - item_state = "analyzer" + item_state = "slime_scanner" + contained_sprite = TRUE origin_tech = list(TECH_BIO = 1) w_class = WEIGHT_CLASS_SMALL obj_flags = OBJ_FLAG_CONDUCTABLE @@ -574,8 +581,10 @@ BREATH ANALYZER /obj/item/price_scanner name = "price scanner" desc = "Using an up-to-date database of various costs and prices, this device estimates the market price of an item up to 0.001% accuracy." - icon = 'icons/obj/item/price_scanner.dmi' + icon = 'icons/obj/item/scanner.dmi' icon_state = "price_scanner" + item_state = "price_scanner" + contained_sprite = TRUE item_flags = ITEM_FLAG_NO_BLUDGEON slot_flags = SLOT_BELT w_class = WEIGHT_CLASS_SMALL @@ -590,14 +599,16 @@ BREATH ANALYZER var/value = get_value(target) user.visible_message(SPAN_NOTICE("\The [user] scans \the [target] with \the [src].")) - to_chat(user, SPAN_NOTICE("\The [src] estimates the price of \the [target] at [value ? value : "N/A"].")) + to_chat(user, SPAN_NOTICE("\The [src] estimates the price of \the [target] at [value ? value : "N/A"]电.")) /obj/item/breath_analyzer name = "breath analyzer" desc = "A hand-held breath analyzer that provides a robust amount of information about the subject's respiratory system." - icon = 'icons/obj/item/breath_analyzer.dmi' + icon = 'icons/obj/item/scanner.dmi' icon_state = "breath_analyzer" - item_state = "analyzer" + // Reuses the basic health analyzer inhands. + item_state = "healthanalyzer" + contained_sprite = TRUE w_class = WEIGHT_CLASS_SMALL obj_flags = OBJ_FLAG_CONDUCTABLE slot_flags = SLOT_BELT @@ -705,9 +716,10 @@ BREATH ANALYZER /obj/item/advanced_healthanalyzer name = "advanced health analyzer" desc = "An expensive and varied-use health analyzer that prints full-body scans after a short scanning delay." - icon = 'icons/obj/item/advanced_healthanalyzer.dmi' - icon_state = "health_adv" - item_state = "analyzer" + icon = 'icons/obj/item/scanner.dmi' + icon_state = "healthanalyzer_adv" + item_state = "healthanalyzer_adv" + contained_sprite = TRUE slot_flags = SLOT_BELT w_class = WEIGHT_CLASS_NORMAL origin_tech = list(TECH_MAGNET = 2, TECH_BIO = 3) diff --git a/code/game/objects/items/devices/spy_bug.dm b/code/game/objects/items/devices/spy_bug.dm index 69a912402fac..e7beab69a6aa 100644 --- a/code/game/objects/items/devices/spy_bug.dm +++ b/code/game/objects/items/devices/spy_bug.dm @@ -65,7 +65,7 @@ /obj/item/spy_monitor name = "\improper PDA" desc = "A portable microcomputer by Thinktronic Systems, LTD. Functionality determined by a preprogrammed ROM cartridge." - icon = 'icons/obj/pda.dmi' + icon = 'icons/obj/modular_computers/pda.dmi' icon_state = "pda" item_state = "electronic" diff --git a/code/game/objects/items/devices/suit_cooling.dm b/code/game/objects/items/devices/suit_cooling.dm index 9700c5ded9b2..612cd29e0081 100644 --- a/code/game/objects/items/devices/suit_cooling.dm +++ b/code/game/objects/items/devices/suit_cooling.dm @@ -23,7 +23,7 @@ var/on = 0 //is it turned on? var/cover_open = 0 //is the cover open? var/obj/item/cell/cell - var/max_cooling = 24 //in degrees per second - probably don't need to mess with heat capacity here + var/max_cooling = 24 //in degrees kelvin per second - probably don't need to mess with heat capacity here var/charge_consumption = 8.3 //charge per second at max_cooling var/thermostat = T20C @@ -77,7 +77,7 @@ return (H.back == src) || (H.s_store == src) -/obj/item/suit_cooling_unit/process() +/obj/item/suit_cooling_unit/process(seconds_per_tick) if(!on || !cell) return @@ -86,18 +86,16 @@ var/mob/living/carbon/human/H = loc - var/efficiency = !!(H.species.flags & ACCEPTS_COOLER) || 1 - H.get_pressure_weakness() //you need to have a good seal for effective cooling; some species can directly connect to the cooler, so get a free 100% efficiency here + var/efficiency = isipc(H) || 1 - H.get_pressure_weakness() //you need to have a good seal for effective cooling; some species can directly connect to the cooler, so get a free 100% efficiency here var/env_temp = get_environment_temperature() //wont save you from a fire var/temp_adj = min(H.bodytemperature - max(thermostat, env_temp), max_cooling) if(temp_adj < 0.5) //only cools, doesn't heat, also we don't need extreme precision return - var/charge_usage = (temp_adj/max_cooling)*charge_consumption + H.bodytemperature = max(T0C, H.bodytemperature - temp_adj * efficiency * seconds_per_tick) - H.bodytemperature = max(T0C, H.bodytemperature - temp_adj*efficiency) - - cell.use(charge_usage) + cell.use((temp_adj/max_cooling) * charge_consumption * seconds_per_tick) if(cell.charge <= 0) turn_off() diff --git a/code/game/objects/items/devices/t_scanner.dm b/code/game/objects/items/devices/t_scanner.dm index 25aab9dc419a..5262b24c4330 100644 --- a/code/game/objects/items/devices/t_scanner.dm +++ b/code/game/objects/items/devices/t_scanner.dm @@ -3,10 +3,10 @@ /obj/item/t_scanner name = "\improper T-ray scanner" desc = "A terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes." - icon = 'icons/obj/item/t_scanner.dmi' + icon = 'icons/obj/item/scanner.dmi' icon_state = "t-ray0" item_state = "t-ray" - + contained_sprite = TRUE slot_flags = SLOT_BELT w_class = WEIGHT_CLASS_SMALL matter = list(MATERIAL_PLASTIC = 100, MATERIAL_ALUMINIUM = 50) @@ -16,10 +16,12 @@ var/scan_range = 3 var/on = 0 - var/list/active_scanned = list() //assoc list of objects being scanned, mapped to their overlay - var/client/user_client //since making sure overlays are properly added and removed is pretty important, so we track the current user explicitly - - var/global/list/overlay_cache = list() //cache recent overlays + /// Assoc list of objects being scanned, mapped to their overlay. + var/list/active_scanned = list() + /// Since making sure overlays are properly added and removed is pretty important, so we track the current user explicitly. + var/client/user_client + /// Cache recent overlays. + var/global/list/overlay_cache = list() /obj/item/t_scanner/Destroy() . = ..() @@ -53,7 +55,7 @@ set_user_client(null) update_icon() -//If reset is set, then assume the client has none of our overlays, otherwise we only send new overlays. +/// If reset is set, then assume the client has none of our overlays, otherwise we only send new overlays. /obj/item/t_scanner/process() if(!on) return @@ -87,7 +89,7 @@ user_client.images -= active_scanned[O] active_scanned -= O -//creates a new overlay for a scanned object +/// Creates a new overlay for a scanned object /obj/item/t_scanner/proc/get_overlay(obj/scanned) //Use a cache so we don't create a whole bunch of new images just because someone's walking back and forth in a room. //Also means that images are reused if multiple people are using t-rays to look at the same objects. diff --git a/code/game/objects/items/devices/uplink.dm b/code/game/objects/items/devices/uplink.dm index 210c6bfc0e01..467a37c1aa5f 100644 --- a/code/game/objects/items/devices/uplink.dm +++ b/code/game/objects/items/devices/uplink.dm @@ -25,8 +25,6 @@ A list of items and costs is stored under the datum of every game mode, alongsid var/list/tgui_items /// The current menu we are in. var/tgui_menu = 0 - /// Additional data for TGUI use. - var/list/tgui_data = list() // Assoc list of item to times bought; shared/referenced by child uplinks var/list/purchase_log = list() /// Mind of the uplink's owner. @@ -73,12 +71,6 @@ Then check if it's true, if true return. This will stop the normal menu appearin var/pda_code = "" - -/obj/item/uplink/hidden/New() - ..() - tgui_data = list() - update_tgui_data() - /obj/item/uplink/hidden/Initialize(mapload, datum/mind/owner, new_telecrystals, new_bluecrystals) . = ..() return INITIALIZE_HINT_LATELOAD @@ -119,13 +111,15 @@ Then check if it's true, if true return. This will stop the normal menu appearin /obj/item/uplink/hidden/ui_data(mob/user) var/list/data = list() data["welcome"] = welcome + data["menu"] = tgui_menu data["telecrystals"] = telecrystals data["bluecrystals"] = bluecrystals - data["menu"] = tgui_menu - update_tgui_data() - data += tgui_data return data +/obj/item/uplink/hidden/ui_static_data(mob/user) + . = ..() + . += update_tgui_data() + // Interaction code. Gathers a list of items purchasable from the paren't uplink and displays it. It also adds a lock button. /obj/item/uplink/hidden/interact(mob/user) ui_interact(user, null) @@ -137,25 +131,31 @@ Then check if it's true, if true return. This will stop the normal menu appearin if(action == "buy_item") var/datum/uplink_item/UI = (locate(params["buy_item"]) in GLOB.uplink.items) UI.buy(src, usr) + update_static_data(usr, ui) else if(action == "lock") toggle() SStgui.close_uis(src) else if(action == "return") tgui_menu = round(tgui_menu/10) + update_static_data(usr, ui) else if(action == "menu") tgui_menu = text2num(params["menu"]) if(params["id"]) exploit_id = params["id"] if(params["category"]) category = locate(params["category"]) in GLOB.uplink.categories + update_static_data(usr, ui) if(action == "contract_interact") var/list/params_webint = list("location" = "contract_details", "contract" = params["contract_interact"]) usr.client.process_webint_link("interface/login/sso_server", list2params(params_webint)) + update_static_data(usr, ui) if(action == "contract_page") - tgui_data["contracts_current_page"] = text2num(params["contract_page"]) + .["contracts_current_page"] = text2num(params["contract_page"]) + update_static_data(usr, ui) if(action == "contract_view") - tgui_data["contracts_view"] = text2num(params["contract_view"]) - tgui_data["contracts_current_page"] = 1 + .["contracts_view"] = text2num(params["contract_view"]) + .["contracts_current_page"] = 1 + update_static_data(usr, ui) return 1 @@ -175,6 +175,7 @@ Then check if it's true, if true return. This will stop the normal menu appearin return newItem /obj/item/uplink/hidden/proc/update_tgui_data() + . = list() if(tgui_menu == 0) var/list/categories = list() var/list/items = list() @@ -185,62 +186,62 @@ Then check if it's true, if true return. This will stop the normal menu appearin if(item.can_view(src)) items[++items.len] = new_tgui_item_data(item) - tgui_data["categories"] = categories - tgui_data["items"] = items + .["categories"] = categories + .["items"] = items else if(tgui_menu == 1) var/items[0] for(var/datum/uplink_item/item in category?.items) if(item.can_view(src)) items[++items.len] = new_tgui_item_data(item) - tgui_data["items"] = items + .["items"] = items else if(tgui_menu == 2) var/permanentData[0] for(var/datum/record/general/locked/record in SSrecords.records_locked) permanentData[++permanentData.len] = list("name" = record.name,"id" = record.id, "has_exploitables" = !!record.exploit_record) - tgui_data["exploit_records"] = permanentData + .["exploit_records"] = permanentData else if(tgui_menu == 21) - tgui_data["exploit_exists"] = 0 + .["exploit_exists"] = 0 for(var/datum/record/general/locked/L in SSrecords.records_locked) if(L.id == exploit_id) - tgui_data["exploit"] = list() // Setting this to equal L.fields passes it's variables that are lists as reference instead of value. + .["exploit"] = list() // Setting this to equal L.fields passes it's variables that are lists as reference instead of value. // We trade off being able to automatically add shit for more control over what gets passed to json // and if it's sanitized for html. - tgui_data["exploit"]["tgui_exploit_record"] = html_decode(L.exploit_record) // this user input is already sanitized and encoded when saved to the DB, we can just decode it and slap it into a span - tgui_data["exploit"]["name"] = html_encode(L.name) - tgui_data["exploit"]["sex"] = html_encode(L.sex) - tgui_data["exploit"]["age"] = html_encode(L.age) - tgui_data["exploit"]["species"] = html_encode(L.species) - tgui_data["exploit"]["rank"] = html_encode(L.rank) - tgui_data["exploit"]["citizenship"] = html_encode(L.citizenship) - tgui_data["exploit"]["employer"] = html_encode(L.employer) - tgui_data["exploit"]["religion"] = html_encode(L.religion) - tgui_data["exploit"]["fingerprint"] = html_encode(L.fingerprint) - - tgui_data["exploit_exists"] = 1 + .["exploit"]["tgui_exploit_record"] = html_decode(L.exploit_record) // this user input is already sanitized and encoded when saved to the DB, we can just decode it and slap it into a span + .["exploit"]["name"] = html_encode(L.name) + .["exploit"]["sex"] = html_encode(L.sex) + .["exploit"]["age"] = html_encode(L.age) + .["exploit"]["species"] = html_encode(L.species) + .["exploit"]["rank"] = html_encode(L.rank) + .["exploit"]["citizenship"] = html_encode(L.citizenship) + .["exploit"]["employer"] = html_encode(L.employer) + .["exploit"]["religion"] = html_encode(L.religion) + .["exploit"]["fingerprint"] = html_encode(L.fingerprint) + + .["exploit_exists"] = 1 break else if(tgui_menu == 3) - tgui_data["contracts_found"] = 0 + .["contracts_found"] = 0 if(establish_db_connection(GLOB.dbcon)) - tgui_data["contracts"] = list() + .["contracts"] = list() - if (!tgui_data["contracts_current_page"]) - tgui_data["contracts_current_page"] = 1 + if (!.["contracts_current_page"]) + .["contracts_current_page"] = 1 - if (!tgui_data["contracts_view"]) - tgui_data["contracts_view"] = 1 + if (!.["contracts_view"]) + .["contracts_view"] = 1 var/query_details[0] - switch (tgui_data["contracts_view"]) + switch (.["contracts_view"]) if (1) query_details["status"] = "open" if (2) query_details["status"] = "closed" else - tgui_data["contracts_view"] = 1 + .["contracts_view"] = 1 query_details["status"] = "open" var/DBQuery/index_query = GLOB.dbcon.NewQuery("SELECT count(*) as Total_Contracts FROM ss13_syndie_contracts WHERE deleted_at IS NULL AND status = :status:") @@ -263,12 +264,12 @@ Then check if it's true, if true return. This will stop the normal menu appearin for (var/i = 1, i <= pages, i++) contracts_pages.Add(i) - tgui_data["contracts_pages"] = contracts_pages + .["contracts_pages"] = contracts_pages - if (tgui_data["contracts_current_page"] > pages) + if (.["contracts_current_page"] > pages) return - query_details["offset"] = (tgui_data["contracts_current_page"] - 1) * 10 + query_details["offset"] = (.["contracts_current_page"] - 1) * 10 var/DBQuery/list_query = GLOB.dbcon.NewQuery("SELECT contract_id, contractee_name, title FROM ss13_syndie_contracts WHERE deleted_at IS NULL AND status = :status: LIMIT 10 OFFSET :offset:") list_query.Execute(query_details) @@ -279,21 +280,21 @@ Then check if it's true, if true return. This will stop the normal menu appearin "contractee" = list_query.item[2], "title" = list_query.item[3]))) - tgui_data["contracts"] = contracts + .["contracts"] = contracts - tgui_data["contracts_found"] = 1 + .["contracts_found"] = 1 if(tgui_menu == 31) - tgui_data["contracts_found"] = 0 + .["contracts_found"] = 0 if (GLOB.config.sql_enabled && establish_db_connection(GLOB.dbcon)) - tgui_data["contracts"] = list() + .["contracts"] = list() - if (!tgui_data["contracts_current_page"]) - tgui_data["contracts_current_page"] = 1 + if (!.["contracts_current_page"]) + .["contracts_current_page"] = 1 - if (!tgui_data["contracts_view"]) - tgui_data["contracts_view"] = 1 + if (!.["contracts_view"]) + .["contracts_view"] = 1 var/query_details[0] query_details["contract_id"] = exploit_id @@ -302,7 +303,7 @@ Then check if it's true, if true return. This will stop the normal menu appearin select_query.Execute(query_details) if (select_query.NextRow()) - tgui_data["contracts_found"] = 1 + .["contracts_found"] = 1 var/contract[0] contract["id"] = select_query.item[1] @@ -322,7 +323,7 @@ Then check if it's true, if true return. This will stop the normal menu appearin contract["description"] = replacetext(contract["description"], ascii2text(13), "") contract["reward_other"] = select_query.item[6] - tgui_data["contract"] = contract + .["contract"] = contract // I placed this here because of how relevant it is. // You place this in your uplinkable item to check if an uplink is active or not. diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 7ff987f9c495..612896d9a1ef 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -150,12 +150,13 @@ Contains: user.visible_message(SPAN_NOTICE("\The [user] starts treating [target_mob]'s [affecting.name]."), \ SPAN_NOTICE("You start treating [target_mob]'s [affecting.name].")) var/used = 0 + var/medicine_skill = user.GetComponent(MEDICINE_SKILL_COMPONENT)?.skill_level for (var/datum/wound/W in affecting.wounds) if(W.bandaged) continue if(used == amount) break - if(!do_mob(user, target_mob, W.damage/5)) + if(!do_mob(user, target_mob, W.damage/(5 + (medicine_skill ? medicine_skill - SKILL_LEVEL_TRAINED : 0)))) to_chat(user, SPAN_NOTICE("You must stand still to bandage wounds.")) break if (W.current_stage <= W.max_bleeding_stage) @@ -226,7 +227,8 @@ Contains: user.visible_message(SPAN_NOTICE("\The [user] starts salving wounds on [target_mob]'s [affecting.name]."), \ SPAN_NOTICE("You start salving the wounds on [target_mob]'s [affecting.name].")) playsound(src, pick(apply_sounds), 25) - if(!do_mob(user, target_mob, 10)) + var/medicine_skill = user.GetComponent(MEDICINE_SKILL_COMPONENT)?.skill_level + if(!do_mob(user, target_mob, 10 + (medicine_skill ? 5 * (SKILL_LEVEL_TRAINED - medicine_skill) : 0))) to_chat(user, SPAN_NOTICE("You must stand still to salve wounds.")) return 1 user.visible_message(SPAN_NOTICE("[user] salved wounds on [target_mob]'s [affecting.name]."), \ @@ -282,7 +284,8 @@ Contains: continue if(used == amount) break - if(!do_mob(user, target_mob, W.damage/5)) + var/medicine_skill = user.GetComponent(MEDICINE_SKILL_COMPONENT)?.skill_level + if(!do_mob(user, target_mob, W.damage/(5 + (medicine_skill ? medicine_skill - SKILL_LEVEL_TRAINED : 0)))) to_chat(user, SPAN_NOTICE("You must stand still to bandage wounds.")) break if (W.current_stage <= W.max_bleeding_stage) @@ -350,7 +353,8 @@ Contains: user.visible_message(SPAN_NOTICE("\The [user] starts salving wounds on [target_mob]'s [affecting.name]."), \ SPAN_NOTICE("You start salving the wounds on [target_mob]'s [affecting.name].")) playsound(src, pick(apply_sounds), 25) - if(!do_mob(user, target_mob, 10)) + var/medicine_skill = user.GetComponent(MEDICINE_SKILL_COMPONENT)?.skill_level + if(!do_mob(user, target_mob, 10 + (medicine_skill ? 5 * (SKILL_LEVEL_TRAINED - medicine_skill) : 0))) to_chat(user, SPAN_NOTICE("You must stand still to salve wounds.")) return 1 user.visible_message(SPAN_NOTICE("[user] covers wounds on [target_mob]'s [affecting.name] with regenerative membrane."), \ @@ -405,7 +409,8 @@ Contains: to_chat(user, SPAN_DANGER("You can't apply a splint to the arm you're using!")) return user.visible_message(SPAN_DANGER("[user] starts to apply \the [src] to their [limb]."), SPAN_DANGER("You start to apply \the [src] to your [limb]."), SPAN_DANGER("You hear something being wrapped.")) - if(do_after(user, 5 SECONDS, target_mob)) + var/medicine_skill = user.GetComponent(MEDICINE_SKILL_COMPONENT)?.skill_level + if(do_after(user, 5 SECONDS + 25 * (medicine_skill ? SKILL_LEVEL_TRAINED - medicine_skill : 0), target_mob)) if (target_mob != user) user.visible_message(SPAN_DANGER("[user] finishes applying \the [src] to [target_mob]'s [limb]."), SPAN_DANGER("You finish applying \the [src] to [target_mob]'s [limb]."), SPAN_DANGER("You hear something being wrapped.")) else diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm index 05bda089c0b2..af840e5f426d 100644 --- a/code/game/objects/items/stacks/rods.dm +++ b/code/game/objects/items/stacks/rods.dm @@ -50,7 +50,6 @@ GLOBAL_LIST_INIT_TYPED(rod_recipes, /datum/stack_recipe, list( /obj/item/stack/rods/Destroy() . = ..() - GC_TEMPORARY_HARDDEL /obj/item/stack/rods/full/Initialize() . = ..() diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 108324396f43..6fd355a3e55f 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -99,14 +99,36 @@ if(locate(/datum/stack_recipe) in recipes_sublist) var/sublist_title = sublist ? " ([capitalize_first_letters(sublist.title)])" : "" t1 += "

Recipes[sublist_title]

" + + // Cache "skill visits" to avoid having to constantly recheck for components. + var/alist/checked_skills = alist() + var/visited_skill = null // Trinary boolean as null/0/nonzero + var/lacks_skill = FALSE + for(var/datum/stack_recipe/R in recipes_sublist) - var/lacks_skill = FALSE - if(length(R.required_skills)) - for(var/skill_type in R.required_skills) - var/skill_level = R.required_skills[skill_type] - if(!user.skill_check(skill_type, skill_level)) + // If you put anything other than a skill component in the required skills for a recipe, I will destroy you. + for(var/skill_comp, skill_level_requirement in R.required_skills_hard) + visited_skill = checked_skills[skill_comp] + // ** Trinary Check for Null, 0, or Nonzero. ** + // Case for skill hasn't been checked yet. + if (isnull(visited_skill)) + // null if no component at all, otherwise equal to the skill level (which can be any real number). + var/visited_comp = astype(user.GetComponent(skill_comp), SKILL_COMPONENT)?.skill_level + + // Case for "Non-Player Characters", which will never have the component at all. + if (isnull(visited_comp)) + checked_skills[skill_comp] = SKILL_LEVEL_PROFESSIONAL + break // Not a player character, just assume they can craft everything. + + // Player characters will always have the component if relevant. + checked_skills[skill_comp] = visited_comp + if (visited_comp < skill_level_requirement) lacks_skill = TRUE break + // Case for skill has been checked AND the character has the component. + else if (visited_skill < skill_level_requirement) + lacks_skill = TRUE + break var/max_multiplier = round(src.get_amount() / R.req_amount) var/title = "" @@ -167,18 +189,22 @@ if (recipe.on_floor && !isfloor(user.loc)) to_chat(user, SPAN_WARNING("\The [recipe.title] must be constructed on the floor!")) return + var/skill_diff = 0 + for (var/skill_type, required_level in recipe.required_skills_soft) + skill_diff += required_level - astype(user.GetComponent(skill_type), SKILL_COMPONENT)?.skill_level to_chat(user, SPAN_NOTICE("Building [recipe.title]...")) - if (recipe.time) - if(length(recipe.required_skills)) - if (!user.do_after_skill(recipe.time, src, user.get_highest_skill_from_list(recipe.required_skills), do_flags = DO_REPAIR_CONSTRUCT)) - return - else - if (!user.do_after_skill(recipe.time, src, /singleton/skill/mechanical_engineering, do_flags = DO_REPAIR_CONSTRUCT)) - return + var/doafter_time = recipe.time + if (doafter_time) + + // Approximately no crafting time if you beat the skill req by 4, approximately twice as long to craft if you're under by 4. + // No need to do an expensive min because it is mathematically impossible for this to ever be negative. + doafter_time += doafter_time * ftanh(0.5 * skill_diff) + if (!do_after(user, doafter_time, do_flags = DO_REPAIR_CONSTRUCT)) + return if (use(required)) - recipe.Produce(produced, user.loc, user.dir, user) + recipe.Produce(produced, user.loc, user.dir, user, skill_diff) /obj/item/stack/Topic(href, href_list) ..() @@ -379,10 +405,21 @@ var/one_per_turf = 0 var/on_floor = 0 var/use_material - /// Assoc list of required skills to required skill levels. This is the MINIMUM to craft the item. You must have ALL these skills at that level to see the item as craftable. - var/list/required_skills - -/datum/stack_recipe/New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1, time = 0, one_per_turf = 0, on_floor = 0, supplied_material = null, list/required_skills) + /** + * Assoc list of required skills to required skill levels. Requirements are taken as a "soft" requirement used to generate a "skill difference", which is applied as a modifier to a d20 roll. + * This roll currently just affects the name of the resulting item and is for fun, but should be later expanded to have more unique effects. + * THIS MAY ONLY HAVE /datum/component/skill/skill_name in it. I WILL DESTROY YOU IF YOU PUT ANYTHING ELSE IN HERE. + */ + var/alist/required_skills_soft + + /** + * Assoc list of required skills to required skill levels. This is the MINIMUM to craft the item. + * You must have ALL these skills at that level to see the item as craftable. + * THIS MAY ONLY HAVE /datum/component/skill/skill_name in it. I WILL DESTROY YOU IF YOU PUT ANYTHING ELSE IN HERE. + */ + var/alist/required_skills_hard + +/datum/stack_recipe/New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1, time = 0, one_per_turf = 0, on_floor = 0, supplied_material = null, alist/required_skills_soft, alist/required_skills_hard) src.title = title src.result_type = result_type if(ispath(result_type, /obj/structure)) @@ -396,9 +433,10 @@ src.one_per_turf = one_per_turf src.on_floor = on_floor src.use_material = supplied_material - src.required_skills = required_skills + src.required_skills_soft = required_skills_soft + src.required_skills_hard = required_skills_hard -/datum/stack_recipe/proc/Produce(var/amount = 1, var/loc = null, var/dir = NORTH, var/user = null) +/datum/stack_recipe/proc/Produce(var/amount = 1, var/loc = null, var/dir = NORTH, var/user = null, var/skill_diff = 0) if(amount < 1) return null @@ -410,6 +448,26 @@ O.set_dir(dir) O.add_fingerprint(user) + // Setup fun item name modifiers based on skill level. + var/d20Roll = rand(1, 20) + 3 * skill_diff + var/initial_name = "[O.name]" + // Yes some of these are from the dwarf fortress wiki. + if (d20Roll <= 0) + O.name = "shoddy " + initial_name + else if (d20Roll <= 5) + O.name = "inferior " + initial_name + else if (d20Roll <= 10) + O.name = "cheap " + initial_name + else if (d20Roll <= 15) + O.name = "finely-crafted " + initial_name + else if (d20Roll <= 20) + O.name = "superior quality " + initial_name + else if (d20Roll < 30) + O.name = "masterful " + initial_name + O.desc = "[O.desc]\n All craftsmanship is of the highest quality." + else + O.name = "artifact " + initial_name + if (istype(O, /obj/item/stack)) var/obj/item/stack/S = O S.amount = amount diff --git a/code/game/objects/items/tools/crowbar.dm b/code/game/objects/items/tools/crowbar.dm index 2555b28cbae5..5ba79d571c01 100644 --- a/code/game/objects/items/tools/crowbar.dm +++ b/code/game/objects/items/tools/crowbar.dm @@ -63,6 +63,10 @@ desc = "A hydraulic rescue tool that functions like a crowbar by applying strong amounts of hydraulic pressure to force open different things. Also known as jaws of life." icon = 'icons/obj/item/hydraulic_rescue_tool.dmi' icon_state = "jawspry" + item_state = "jawspry" + contained_sprite = TRUE + // Really do not want to deal with reconciling sprite implementations between parent and child for now. + item_icons = null force = 15 throwforce = 1 w_class = WEIGHT_CLASS_NORMAL diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index f260c06af35b..01ad8e8f82b8 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -248,6 +248,16 @@ desc_extended = "There's a tag that reads: \"Apparition Halloween LLC.\"" icon_state = "ghostballoon" +/obj/item/toy/balloon/heart/red + name = "red heart balloon" + desc = "A big red balloon in a traditional heart shape. Represents love, not medical work!" + icon_state = "heartballoonred" + +/obj/item/toy/balloon/heart/pink + name = "pink heart balloon" + desc = "A big pink balloon in a traditional heart shape. Represents love, not medical work!" + icon_state = "heartballoonpink" + /obj/item/toy/balloon/color /// To color it, VV the 'color' var with a hex color code with the # included. desc = "It's a plain little balloon. Comes in many colors!" icon_state = "colorballoon" diff --git a/code/game/objects/items/weapons/autopsy.dm b/code/game/objects/items/weapons/autopsy.dm index b5fa54fac726..a029a25d414d 100644 --- a/code/game/objects/items/weapons/autopsy.dm +++ b/code/game/objects/items/weapons/autopsy.dm @@ -5,7 +5,7 @@ /obj/item/autopsy_scanner name = "autopsy scanner" desc = "Extracts information on wounds." - icon = 'icons/obj/item/autopsy_scanner.dmi' + icon = 'icons/obj/item/scanner.dmi' icon_state = "autopsy" item_state = "autopsy" contained_sprite = TRUE diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm index 1d239dbe11af..3a5dd35cd5c9 100644 --- a/code/game/objects/items/weapons/cards_ids.dm +++ b/code/game/objects/items/weapons/cards_ids.dm @@ -184,7 +184,6 @@ QDEL_NULL(chat_user) mob_id = null . = ..() - GC_TEMPORARY_HARDDEL /obj/item/card/id/examine(mob/user, distance, is_adjacent, infix, suffix, show_extended) . = ..() diff --git a/code/game/objects/items/weapons/cards_ids_syndicate.dm b/code/game/objects/items/weapons/cards_ids_syndicate.dm index 2351e5ceb3ea..04dc7249b9ad 100644 --- a/code/game/objects/items/weapons/cards_ids_syndicate.dm +++ b/code/game/objects/items/weapons/cards_ids_syndicate.dm @@ -45,7 +45,9 @@ /obj/item/card/id/syndicate/Destroy() STOP_PROCESSING(SSprocessing, src) - unset_registered_user(registered_user) + if(registered_user) + UnregisterSignal(registered_user, COMSIG_QDELETING) + registered_user = null return ..() /obj/item/card/id/syndicate/process() diff --git a/code/game/objects/items/weapons/circuitboards/circuitboard.dm b/code/game/objects/items/weapons/circuitboards/circuitboard.dm index 28d5c671d7b9..2ba48210f4d7 100644 --- a/code/game/objects/items/weapons/circuitboards/circuitboard.dm +++ b/code/game/objects/items/weapons/circuitboards/circuitboard.dm @@ -4,6 +4,7 @@ icon = 'icons/obj/module.dmi' icon_state = "id_mod" item_state = "electronic" + contained_sprite = TRUE origin_tech = list(TECH_DATA = 2) w_class = WEIGHT_CLASS_SMALL obj_flags = OBJ_FLAG_CONDUCTABLE diff --git a/code/game/objects/items/weapons/flamethrower.dm b/code/game/objects/items/weapons/flamethrower.dm index ab8d8d7452e3..14db93c96ebc 100644 --- a/code/game/objects/items/weapons/flamethrower.dm +++ b/code/game/objects/items/weapons/flamethrower.dm @@ -1,6 +1,6 @@ /obj/item/flamethrower name = "flamethrower" - desc = "A flamethrower created by modifying a welding tool to fit an external gas tank." + desc = "A flamethrower created by modifying a welding tool to fit an external tank." icon = 'icons/obj/item/flamethrower.dmi' icon_state = "flamethrower1" item_state = "flamethrower_0" @@ -28,6 +28,8 @@ /// How much range the flamethrower has. Upgraded welding tools increase this. var/range = 4 var/max_container = WEIGHT_CLASS_SMALL + /// Are we a military-grade flamethrower? If so, accept combat-grade fuels (like napalm) and don't check for a welding tool + var/is_military = FALSE /obj/item/flamethrower/feedback_hints(mob/user, distance, is_adjacent) . += ..() @@ -38,16 +40,31 @@ else . += SPAN_NOTICE("The loaded [fuel_container.name] is empty.") if(igniter) - . += SPAN_NOTICE("It has \an [igniter] installed.") + . += SPAN_NOTICE("It has \a [igniter] installed.") else . += SPAN_WARNING("It has no igniter installed.") + if(distance <= 3) + if(welding_tool) + . += SPAN_NOTICE("It has \a [welding_tool] installed.") + else if(!is_military) + . += SPAN_WARNING("It has no welding tool installed.") if(lit) . += SPAN_WARNING("\The [src] is currently lit!") +/obj/item/flamethrower/mechanics_hints(mob/user, distance, is_adjacent) + . = ..() + if(!is_military) + . += SPAN_INFO("Use a wrench on the flamethrower to dismantle it.") + . += SPAN_INFO("You may choose to dismantle it piece-wise, or the whole thing.") + . += SPAN_WARNING("It is not recommended to use military-grade fuels with this improvised flamethrower.") + else + . += SPAN_INFO("This military-grade flamethrower can accept combat-grade fuels.") + /obj/item/flamethrower/upgrade_hints(mob/user, distance, is_adjacent) . = ..() - . += SPAN_INFO("Upgrading the welding tool increases the flamethrower's range.") + if(!is_military) + . += SPAN_INFO("Upgrading the welding tool increases the flamethrower's range.") /obj/item/flamethrower/Initialize(mapload, var/welder) . = ..() @@ -69,7 +86,7 @@ STOP_PROCESSING(SSprocessing, src) update_icon() return null - else if (!fuel_container || !fuel_container.reagents || fuel_container.reagents.total_volume <= 0) + else if ((!welding_tool && !is_military) || !fuel_container || !fuel_container.reagents || fuel_container.reagents.total_volume <= 0) lit = FALSE balloon_alert_to_viewers("*fffft*") playsound(loc, 'sound/items/welder_deactivate.ogg', 50, TRUE) @@ -102,6 +119,8 @@ set_light(0) item_state = "flamethrower_0" + update_held_icon() + /obj/item/flamethrower/isFlameSource() return lit @@ -118,6 +137,9 @@ range = 4 /obj/item/flamethrower/afterattack(atom/target, mob/user, proximity) + if(!welding_tool && !is_military) + balloon_alert(user, "no welding tool!") + return var/turf/target_turf = get_turf(target) if(target_turf) var/turflist = get_line(user, target_turf) @@ -129,26 +151,58 @@ if(attacking_item.tool_behaviour == TOOL_WRENCH && !secured)//Taking this apart var/turf/T = get_turf(src) + var/list/options = list( + "Dismantle All" = image(icon = attacking_item.icon, icon_state = attacking_item.icon_state) + ) if(welding_tool) - welding_tool.forceMove(T) - welding_tool = null + options["Remove Welding Tool"] = image(icon = welding_tool.icon, icon_state = welding_tool.icon_state) if(igniter) - igniter.forceMove(T) - igniter = null - if(fuel_container) - fuel_container.forceMove(T) - fuel_container = null - new /obj/item/stack/rods(T) - qdel(src) + options["Remove Igniter"] = image(icon = igniter.icon, icon_state = igniter.icon_state) + + var/choice = show_radial_menu(user, src, options, require_near = TRUE, tooltips = TRUE) + var/duration = 1 SECOND + if(choice == "Dismantle All") + duration *= 2 // Twice as long to dismantle the whole thing. + if(!attacking_item.use_tool(src, user, duration)) + return TRUE + switch(choice) + if("Dismantle All") + TakeApart(T) + return TRUE + if("Remove Welding Tool") + welding_tool.forceMove(T) + welding_tool = null + update_icon() + if("Remove Igniter") + igniter.forceMove(T) + igniter = null + update_icon() + return TRUE - else if(attacking_item.tool_behaviour == TOOL_SCREWDRIVER && igniter && !lit) + else if(attacking_item.tool_behaviour == TOOL_SCREWDRIVER && igniter && !lit && !is_military) + if(!attacking_item.use_tool(src, user, 1 SECOND)) + return TRUE secured = !secured to_chat(user, SPAN_NOTICE("[igniter] is now [secured ? "secured" : "unsecured"]!")) update_icon() return TRUE - else if(isigniter(attacking_item)) + else if(attacking_item.tool_behaviour == TOOL_WELDER && !is_military) + var/obj/item/weldingtool/tool = attacking_item + if(welding_tool) + balloon_alert(user, "welding tool already installed!") + return TRUE + if(!do_after(user, 1 SECOND, src)) + return FALSE + user.drop_from_inventory(tool, src) + playsound(src, 'sound/items/Deconstruct.ogg', 50, TRUE) + welding_tool = tool + processUpgrade() + update_icon() + return TRUE + + else if(isigniter(attacking_item) && !is_military) var/obj/item/assembly/igniter/I = attacking_item if(I.secured) to_chat(user, SPAN_WARNING("\The [I] is not ready to attach yet! Use a screwdriver on it first.")) @@ -157,6 +211,7 @@ to_chat(user, SPAN_WARNING("\The [src] already has an igniter installed.")) return TRUE user.drop_from_inventory(I, src) + playsound(src, 'sound/machines/click.ogg', 50, TRUE) igniter = I update_icon() return TRUE @@ -178,6 +233,19 @@ return TRUE return ..() +/obj/item/flamethrower/proc/TakeApart(turf/T) + if(welding_tool) + welding_tool.forceMove(T) + welding_tool = null + if(igniter) + igniter.forceMove(T) + igniter = null + if(fuel_container) + fuel_container.forceMove(T) + fuel_container = null + new /obj/item/stack/rods(T) + qdel(src) + return /obj/item/flamethrower/attack_self(mob/user) if(use_check_and_message(user)) @@ -260,10 +328,18 @@ var/datum/reagents/my_fraction = new(fuel_reagents.maximum_volume, src) fuel_reagents.trans_to_holder(my_fraction, FLAMETHROWER_RELEASE_AMOUNT * length(turflist)) var/fire_color = null + var/obj/effect/decal/cleanable/napalm/fire_effect = null var/highest_amount = 0 for(var/reagent in my_fraction.reagent_volumes) var/singleton/reagent/fuel = GET_SINGLETON(reagent) + fire_effect = fuel.flamethrower_effect power += fuel.accelerant_quality * FLAMETHROWER_POWER_MULTIPLIER * (my_fraction.reagent_volumes[reagent] / length(turflist)) //Flamethrowers inflate flammability compared to a pool of fuel + if(fire_effect) + if(!is_military) // Are we attempting to use a powerful fuel with a shoddy flamer? + explode_in_hand(power) + return + else if(is_military)//Military-grade flamethrowers have a 150% power increase if they do not already have a flame effect + power *= 1.5 if(my_fraction.reagent_volumes[reagent] > highest_amount && fuel.accelerant_quality > 0) highest_amount = my_fraction.reagent_volumes[reagent] fire_color = fuel.fire_color @@ -287,9 +363,13 @@ if(LinkBlocked(operator_turf, T)) continue - //Consume part of our fuel to create a fire spot - T.IgniteTurf(power, fire_color) - T.hotspot_expose(power * 3 + 380) + //If we have a flamethrower effect, use it instead of directly using a turf fire + if(fire_effect) + new fire_effect(T, power, TRUE, TRUE) + else + //Consume part of our fuel to create a fire spot + T.IgniteTurf(power, fire_color) + T.hotspot_expose(power * 3 + 380) my_fraction.remove_any(FLAMETHROWER_RELEASE_AMOUNT) sleep(0.1 SECONDS) @@ -301,6 +381,27 @@ #undef FLAMETHROWER_POWER_MULTIPLIER #undef FLAMETHROWER_RELEASE_AMOUNT +/obj/item/flamethrower/proc/explode_in_hand(power) + audible_message(SPAN_WARNING("\The [src] sputters a bit, throwing out some liquid.")) + balloon_alert_to_viewers("*pshhhhhhhhhhhhhh*") + playsound(src, 'sound/weapons/flamethrower/flamethrower_empty.ogg', 50, TRUE, -3, frequency = 22000) + visible_message(SPAN_DANGER("\The [src] shakes uncontrollably!")) + sleep(0.5 SECONDS) + // Explode in a 3x3 area + var/list/turflist = circle_view_turfs(src.loc, 1) + var/turf_amount = length(turflist) + var/power_div = power/turf_amount + visible_message(SPAN_DANGER("\The [src] explodes!")) + playsound(src, SFX_EXPLOSION, 20, TRUE, -1, frequency = 48000) + for(var/turf/T as anything in turflist) + if(T.density || istype(T, /turf/space)) + continue + T.IgniteTurf(power_div) + T.hotspot_expose(power_div * 3 + 380) + qdel(src) + + + /obj/item/flamethrower/proc/return_fuel(datum/reagents/_return, datum/reagents/_fraction) if(fuel_container) //In the event we earlied out that means some fuel goes back into tank if(_fraction.total_volume > 0) @@ -317,3 +418,43 @@ fuel_container.reagents.add_reagent(/singleton/reagent/fuel, 120) processUpgrade() return ..() + +/obj/item/flamethrower/military + name = "\improper IK-163 flamethrower" + desc = "A military-grade flamethrower by Ingkom. Capable of using a wide variety of chemicals." + desc_extended = "The IK-163 was a flamethrower developed by Ingkom well before the Interstellar War. While flamethwrowers are generally considered \ + obsolete, Zavodskoi Interstellar still markets the IK-163 for niche uses, and the occasional military leader with more ego than sense." + is_military = TRUE + secured = TRUE + range = 6 + icon = 'icons/obj/item/military_flamethrower.dmi' + icon_state = "mil_flamethrower" + item_state = "flamethrower_0" + worn_x_dimension = 48 + // Military-grade flamethrowers don't use welders + +/obj/item/flamethrower/military/Initialize(mapload, welder) + . = ..() + igniter = new /obj/item/assembly/igniter(src) + igniter.secured = FALSE + +/obj/item/flamethrower/military/update_icon() + ClearOverlays() + + if(fuel_container) + AddOverlays("ptank") + + if(lit) + AddOverlays("lit") + set_light(1.4, 2) + item_state = "flamethrower_1" + else + set_light(0) + item_state = "flamethrower_0" + + update_held_icon() + +/obj/item/flamethrower/military/full/Initialize(mapload, welder) + fuel_container = new /obj/item/reagent_containers/glass/beaker/large(src) + fuel_container.reagents.add_reagent(/singleton/reagent/fuel/napalm, 120) + return ..() diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm index c4396d621313..c33d78659516 100644 --- a/code/game/objects/items/weapons/grenades/flashbang.dm +++ b/code/game/objects/items/weapons/grenades/flashbang.dm @@ -52,9 +52,6 @@ icon = 'icons/obj/grenade.dmi' icon_state = "clusterbang" -/obj/item/grenade/flashbang/clusterbang/Destroy() - . = ..() - GC_TEMPORARY_HARDDEL /obj/item/grenade/flashbang/clusterbang/prime() var/numspawned = rand(4,8) @@ -117,6 +114,3 @@ addtimer(CALLBACK(src, PROC_REF(prime)), dettime) ..() -/obj/item/grenade/flashbang/cluster/Destroy() - . = ..() - GC_TEMPORARY_HARDDEL diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm index 3e663020f76f..3aaa17d614bf 100644 --- a/code/game/objects/items/weapons/grenades/grenade.dm +++ b/code/game/objects/items/weapons/grenades/grenade.dm @@ -19,6 +19,12 @@ var/fake = FALSE var/activation_sound = 'sound/weapons/armbomb.ogg' +/obj/item/grenade/Destroy() + // Stop all animations to prevent a hard delete. + animate(src) + walk(src, 0) + return ..() + /obj/item/grenade/feedback_hints(mob/user, distance, is_adjacent) . += ..() if(distance <= 0) diff --git a/code/game/objects/items/weapons/grenades/napalm_grenade.dm b/code/game/objects/items/weapons/grenades/napalm_grenade.dm index 0b767c2d9f9b..32811cb50c92 100644 --- a/code/game/objects/items/weapons/grenades/napalm_grenade.dm +++ b/code/game/objects/items/weapons/grenades/napalm_grenade.dm @@ -3,6 +3,7 @@ desc = "A grenade that delivers napalm. Not as classy as an airstrike, but still effective." desc_extended = "A Necropolis Industries (now known as Zavodskoi Interstellar) engineered device, this grenade is one of the most effective and destructive portable emergency sterilization \ device available, causing high-intensity sustained fires at over 2000K." + var/effect = /obj/effect/decal/cleanable/napalm /obj/item/grenade/napalm/antagonist_hints(mob/user, distance, is_adjacent) . += ..() @@ -11,7 +12,13 @@ /obj/item/grenade/napalm/prime() . = ..() - for(var/turf/turf in view(5, get_turf(src))) - new /obj/effect/decal/cleanable/liquid_fuel/napalm(turf, 100, TRUE) + for(var/turf/turf as anything in circle_view_turfs(get_turf(src), 5)) + if(turf.density) + continue + new effect(turf, 100, TRUE, TRUE) qdel(src) + + +/obj/item/grenade/napalm/zorane + effect = /obj/effect/decal/cleanable/napalm/zorane_fire diff --git a/code/game/objects/items/weapons/ipc_scanner.dm b/code/game/objects/items/weapons/ipc_scanner.dm index 272a33778300..0cda9477b081 100644 --- a/code/game/objects/items/weapons/ipc_scanner.dm +++ b/code/game/objects/items/weapons/ipc_scanner.dm @@ -1,7 +1,7 @@ /obj/item/ipc_tag_scanner name = "IPC tag scanner" desc = "A hand-held IPC tag scanner, that, when used to analyze the info of an IPC, will output its tag status and information." - icon = 'icons/obj/ipc_utilities.dmi' + icon = 'icons/obj/item/scanner.dmi' icon_state = "ipc_tag_scanner" item_state = "ipc_tag_scanner" contained_sprite = TRUE diff --git a/code/game/objects/items/weapons/manuals.dm b/code/game/objects/items/weapons/manuals.dm index 201f01f9e9bd..525219e345a0 100644 --- a/code/game/objects/items/weapons/manuals.dm +++ b/code/game/objects/items/weapons/manuals.dm @@ -1524,7 +1524,8 @@ name = "tau ceti armed forces pamphlet" desc = "A simple pamphlet containing information about the Tau Ceti Armed Forces." icon_state = "tcfl_pamphlet" - item_state = "paper" + item_state = "tcfl_pamphlet" + contained_sprite = TRUE title = "Tau Ceti Armed Forces pamphlet" author = "Tau Ceti Armed Forces recruitment center" pickup_sound = 'sound/items/drop/paper.ogg' diff --git a/code/game/objects/items/weapons/material/shards.dm b/code/game/objects/items/weapons/material/shards.dm index af0da44df471..2303abaf7044 100644 --- a/code/game/objects/items/weapons/material/shards.dm +++ b/code/game/objects/items/weapons/material/shards.dm @@ -29,10 +29,6 @@ AddElement(/datum/element/connect_loc, loc_connections) -/obj/item/material/shard/Destroy() - . = ..() - GC_TEMPORARY_HARDDEL - /obj/item/material/shard/set_material(var/new_material) ..(new_material) if(!istype(material)) diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm index 858c6c58e168..493421cf0310 100644 --- a/code/game/objects/items/weapons/storage/bags.dm +++ b/code/game/objects/items/weapons/storage/bags.dm @@ -108,7 +108,7 @@ item_state = "plasticbag" storage_slots = null w_class = WEIGHT_CLASS_BULKY - max_w_class = WEIGHT_CLASS_SMALL + storage_slots = DEFAULT_LARGEBOX_STORAGE can_hold = null // any cant_hold = list(/obj/item/disk/nuclear) drop_sound = 'sound/items/drop/wrapper.ogg' diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index cf9c825e7d62..158b20de654a 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -122,7 +122,8 @@ /obj/item/price_scanner, /obj/item/cratescanner, /obj/item/destTagger, - /obj/item/quikpay + /obj/item/quikpay, + /obj/item/paint_sprayer ) content_overlays = TRUE diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index 66870ae7552b..3c9cb261c29d 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -500,12 +500,16 @@ illustration = "firingpin" starts_with = list(/obj/item/firing_pin = 2, /obj/item/firing_pin/access = 2, /obj/item/firing_pin/implant/loyalty = 2, /obj/item/firing_pin/psionic = 1, /obj/item/firing_pin/dna = 1) -/obj/item/storage/box/psireceiver - name = "box of psionic receivers" - desc = "A box of psionic receivers, which can be surgically implanted to act as a replacement for an underdeveloped or non-existent zona bovinae. This one has a large sticker on the side reading FOR RESEARCH USE ONLY." +/obj/item/storage/box/unique/freezer/organcooler/psireceiver + name = "psionic receivers cooler" + desc = "A cooling box for psionic receivers, which can be surgically implanted to act as a replacement for an underdeveloped or non-existent zona bovinae. This one has a large sticker on the side reading FOR RESEARCH USE ONLY." color = COLOR_PURPLE_GRAY illustration = "implant" starts_with = list(/obj/item/organ/internal/augment/bioaug/psi = 4) + can_hold = list( + /obj/item/organ/internal/augment/bioaug/psi + ) + storage_slots = 4 /obj/item/storage/box/tethers name = "box of tethering devices" diff --git a/code/game/objects/items/weapons/storage/mre.dm b/code/game/objects/items/weapons/storage/mre.dm index a0d3b9dd4c29..0c8e5df35117 100644 --- a/code/game/objects/items/weapons/storage/mre.dm +++ b/code/game/objects/items/weapons/storage/mre.dm @@ -222,7 +222,7 @@ MRE Stuff starts_with = list(/obj/item/reagent_containers/food/snacks/meatbreadslice/filled = 1) /obj/item/storage/box/fancy/mrebag/menu7 - starts_with = list(/obj/item/reagent_containers/food/snacks/salad/tossedsalad = 1) + starts_with = list(/obj/item/reagent_containers/food/snacks/salad/applesalad = 1) /obj/item/storage/box/fancy/mrebag/menu8 starts_with = list(/obj/item/reagent_containers/food/snacks/hotchili = 1) diff --git a/code/game/objects/items/weapons/storage/toolbox.dm b/code/game/objects/items/weapons/storage/toolbox.dm index 973990df582a..36b557963c1a 100644 --- a/code/game/objects/items/weapons/storage/toolbox.dm +++ b/code/game/objects/items/weapons/storage/toolbox.dm @@ -113,6 +113,8 @@ force = 16 starts_with = list(\ /obj/item/clothing/gloves/yellow = 1,\ + /obj/item/clothing/gloves/yellow/specialt = 1,\ + /obj/item/clothing/gloves/yellow/specialu = 1,\ /obj/item/screwdriver = 1,\ /obj/item/wrench = 1,\ /obj/item/weldingtool = 1, diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm index 23430050db50..e871a9d65352 100644 --- a/code/game/objects/items/weapons/tanks/tanks.dm +++ b/code/game/objects/items/weapons/tanks/tanks.dm @@ -112,7 +112,7 @@ var/list/data = list() - data["tankPressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0) + data["tankPressure"] = round(XGM_PRESSURE(air_contents)) data["releasePressure"] = round(distribute_pressure ? distribute_pressure : 0) data["defaultReleasePressure"] = round(TANK_DEFAULT_RELEASE_PRESSURE) data["maxReleasePressure"] = round(TANK_MAX_RELEASE_PRESSURE) @@ -193,7 +193,7 @@ if(!air_contents) return null - var/tank_pressure = air_contents.return_pressure() + var/tank_pressure = XGM_PRESSURE(air_contents) if(tank_pressure < distribute_pressure) distribute_pressure = tank_pressure @@ -202,19 +202,23 @@ return remove_air(moles_needed) /obj/item/tank/process() - //Allow for reactions - air_contents.react() //cooking up air tanks - add phoron and oxygen, then heat above PHORON_MINIMUM_BURN_TEMPERATURE + var/tank_pressure = 0 + // we pass tank_pressure around and try not to recalc it unless we have to + // this is a very hot proc (~2M calls/hr) + if(air_contents) + tank_pressure = XGM_PRESSURE(air_contents) + air_contents.react() + tank_pressure = check_status(tank_pressure) if(gauge_icon) - update_gauge() - check_status() + update_gauge(tank_pressure) /obj/item/tank/proc/adjust_initial_gas() return -/obj/item/tank/proc/update_gauge() - var/gauge_pressure = 0 +/obj/item/tank/proc/update_gauge(gauge_pressure = 0) if(air_contents) - gauge_pressure = air_contents.return_pressure() + if(!gauge_pressure) + gauge_pressure = XGM_PRESSURE(air_contents) if(gauge_pressure > TANK_IDEAL_PRESSURE) gauge_pressure = -1 else @@ -231,16 +235,17 @@ /obj/item/tank/proc/percent() var/gauge_pressure = 0 if(air_contents) - gauge_pressure = air_contents.return_pressure() + gauge_pressure = XGM_PRESSURE(air_contents) return 100.0*gauge_pressure/TANK_IDEAL_PRESSURE -/obj/item/tank/proc/check_status() +/obj/item/tank/proc/check_status(pressure = 0) //Handle exploding, leaking, and rupturing of the tank if(!air_contents) return 0 + if(!pressure) + pressure = XGM_PRESSURE(air_contents) - var/pressure = air_contents.return_pressure() if(pressure > TANK_FRAGMENT_PRESSURE) if(!istype(src.loc,/obj/item/transfer_valve)) message_admins("Explosive tank rupture! last key to touch the tank was [src.fingerprintslast].") @@ -251,7 +256,7 @@ air_contents.react() air_contents.react() - pressure = air_contents.return_pressure() + pressure = XGM_PRESSURE(air_contents) var/range = (pressure-TANK_FRAGMENT_PRESSURE)/TANK_FRAGMENT_SCALE explosion( @@ -270,11 +275,10 @@ if(integrity <= 0) var/turf/simulated/T = get_turf(src) - if(!T) - return - T.assume_air(air_contents) - playsound(src.loc, 'sound/effects/spray.ogg', 10, 1, -3) - qdel(src) + if(T) + T.assume_air(air_contents) + playsound(src.loc, 'sound/effects/spray.ogg', 10, 1, -3) + qdel(src) else integrity-- @@ -285,16 +289,18 @@ if(integrity <= 0) var/turf/simulated/T = get_turf(src) - if(!T) - return - var/datum/gas_mixture/leaked_gas = air_contents.remove_ratio(0.25) - T.assume_air(leaked_gas) + if(T) + var/datum/gas_mixture/leaked_gas = air_contents.remove_ratio(0.25) + T.assume_air(leaked_gas) + return 0 else integrity-- else if(integrity < 3) integrity++ + return QDELETED(src) ? 0 : pressure // if we qdel'd or return 0, something changed and we gotta recalc + /obj/item/tank/proc/remove_air_by_flag(flag, amount) . = air_contents.remove_by_flag(flag, amount) update_icon() diff --git a/code/game/objects/items/weapons/teleportation.dm b/code/game/objects/items/weapons/teleportation.dm index fad2ee710fca..c837016e5860 100644 --- a/code/game/objects/items/weapons/teleportation.dm +++ b/code/game/objects/items/weapons/teleportation.dm @@ -273,7 +273,7 @@ Frequency: /obj/item/closet_teleporter name = "closet teleporter" desc = "A device that allows a user to connect two closets into a bluespace network." - icon = 'icons/obj/modular_components.dmi' + icon = 'icons/obj/modular_computers/modular_components.dmi' icon_state = "cpu_normal_photonic" obj_flags = OBJ_FLAG_CONDUCTABLE w_class = WEIGHT_CLASS_SMALL diff --git a/code/game/objects/items/weapons/towel.dm b/code/game/objects/items/weapons/towel.dm index c95920904dac..0751c3c2efae 100644 --- a/code/game/objects/items/weapons/towel.dm +++ b/code/game/objects/items/weapons/towel.dm @@ -48,6 +48,8 @@ to_chat(usr, SPAN_NOTICE("You lay out \the [src] flat on the ground.")) var/obj/item/towel_flat/T = new /obj/item/towel_flat(usr.loc) T.color = src.color + T.name = src.name + T.desc = src.desc qdel(src) /obj/item/towel_flat @@ -60,5 +62,7 @@ to_chat(user, SPAN_NOTICE("You pick up and fold \the [src].")) var/obj/item/towel/T = new /obj/item/towel(user) T.color = src.color + T.name = src.name + T.desc = src.desc user.put_in_hands(T) qdel(src) diff --git a/code/game/objects/items/weapons/vaurca_items.dm b/code/game/objects/items/weapons/vaurca_items.dm index bb79dbf6013b..a8813f4391d9 100644 --- a/code/game/objects/items/weapons/vaurca_items.dm +++ b/code/game/objects/items/weapons/vaurca_items.dm @@ -298,7 +298,7 @@ icon_state = "scout" item_state = "scout" desc = "Armor designed for K'laxan scouts, made of lightweight sturdy material that does not restrict movement." - slowdown = -1 + slowdown = -0.2 species_restricted = list(BODYTYPE_VAURCA) armor = list( diff --git a/code/game/objects/random/loot.dm b/code/game/objects/random/loot.dm index 95614cbfd749..fc2e123e91b7 100644 --- a/code/game/objects/random/loot.dm +++ b/code/game/objects/random/loot.dm @@ -567,6 +567,7 @@ var/to_delete = rand(1, length(AG.stored_ammo)) var/delete_counter = 0 for(var/obj/item/ammo_casing/AC in AG.stored_ammo) + AG.stored_ammo -= AC qdel(AC) delete_counter++ if(delete_counter > to_delete) diff --git a/code/game/objects/random/misc.dm b/code/game/objects/random/misc.dm index c644372e7664..a34f898af683 100644 --- a/code/game/objects/random/misc.dm +++ b/code/game/objects/random/misc.dm @@ -140,7 +140,9 @@ /obj/item/toy/balloon/bat = 1, /obj/item/toy/balloon/ghost = 1, /obj/item/toy/balloon/xmastree = 1, - /obj/item/toy/balloon/candycane = 1 + /obj/item/toy/balloon/candycane = 1, + /obj/item/toy/balloon/heart/red = 2, + /obj/item/toy/balloon/heart/pink = 2 ) /obj/random/desktoy diff --git a/code/game/objects/random/tech.dm b/code/game/objects/random/tech.dm index cc9abbfa91c4..4d9316fbc2c3 100644 --- a/code/game/objects/random/tech.dm +++ b/code/game/objects/random/tech.dm @@ -15,8 +15,8 @@ /obj/random/technology_scanner name = "random scanner" desc = "This is a random technology scanner." - icon = 'icons/obj/item/air_analyzer.dmi' - icon_state = "analyzer" + icon = 'icons/obj/item/scanner.dmi' + icon_state = "airanalyzer" problist = list( /obj/item/t_scanner = 5, /obj/item/radio = 2, diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm index a2a2257ee2eb..b2e2fa6bf18b 100644 --- a/code/game/objects/structures.dm +++ b/code/game/objects/structures.dm @@ -37,7 +37,7 @@ QUEUE_SMOOTH_NEIGHBORS(src) climbers = null - + material = null return ..() /obj/structure/attack_hand(mob/living/user) diff --git a/code/game/objects/structures/barsign.dm b/code/game/objects/structures/barsign.dm index 37a52275f797..de0f8a0c465d 100644 --- a/code/game/objects/structures/barsign.dm +++ b/code/game/objects/structures/barsign.dm @@ -213,9 +213,16 @@ in many places, selling a limited selection of basic items, usually with a markup." /singleton/sign/double/market/gm24 - name ="GetMore24" + name = "GetMore24" icon_state = "gm24" - desc = "The GetMore24, usually shortened to GM24, is the de-facto flagship of convenience stores. Whatever you need, whereever you need it, wheneever you need it. Get more, with Getmore." + desc = "The GetMore24, usually shortened to GM24, is the de-facto flagship of convenience stores. For the true convenience connoisseur. Get more, with Getmore." desc_extended = "Getmore was always a big player in the food industry. A logical follow-up would be to get big into retail and cut out the middle-man in distribution. Thus, the king of convenience stores was born: \ GMG24. Usually open 24 hours, 7 days a week there aren't many places in the galaxy where you aren't in walking distance of a GM24. Selling everything you need for your daily life, the selection is surprisingly big \ and affordable. This strategy catapulted Getmore into the big league of convenience stores." + +/singleton/sign/double/market/quikstop + name = "Quik Stop" + icon_state = "quikstop" + desc = "The Orion operated Quik Stop is often known to provide a wide variety at a small premium, thanks to Orion's spur spanning logistics operation. What you need, when you need it: that's the Orion Promise!" + desc_extended = "Orion's spur-wide logistics already had warehouses and sorting offices spread on hundreds of planets from the cosmopolitan Biesel to the dinkiest frontier colony. \ + It was only a matter of fittings and branding which turned many of these into Orion Quik Stops, able to fulfill the Spur's need for convenient shopping and able to tap into Orion's delivery system." diff --git a/code/game/objects/structures/carts/engicart.dm b/code/game/objects/structures/carts/engicart.dm index 45091b85eab0..d53e3fec37a4 100644 --- a/code/game/objects/structures/carts/engicart.dm +++ b/code/game/objects/structures/carts/engicart.dm @@ -75,9 +75,9 @@ update_icon() /obj/structure/cart/storage/engineeringcart/Destroy() - QDEL_NULL(my_glass) - QDEL_NULL(my_metal) - QDEL_NULL(my_plasteel) + QDEL_LIST(my_glass) + QDEL_LIST(my_metal) + QDEL_LIST(my_plasteel) QDEL_NULL(my_lightreplacer) QDEL_NULL(my_blue_toolbox) QDEL_NULL(my_yellow_toolbox) diff --git a/code/game/objects/structures/carts/parcelcart.dm b/code/game/objects/structures/carts/parcelcart.dm index d379950735db..d1c4cd000e04 100644 --- a/code/game/objects/structures/carts/parcelcart.dm +++ b/code/game/objects/structures/carts/parcelcart.dm @@ -36,7 +36,7 @@ update_icon() /obj/structure/cart/storage/parcelcart/Destroy() - QDEL_NULL(my_parcels) + QDEL_LIST(my_parcels) return ..() /obj/structure/cart/storage/parcelcart/attackby(obj/item/attacking_item, mob/user) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 6a0a8696b69b..c143390f5ea0 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -79,6 +79,9 @@ /// Used by body bags and air bubbles. var/contains_body = FALSE + /// If its a plain grey closet or crate, you can use the paint sprayer on it ONCE to change its appearance. + var/can_label = FALSE + /obj/structure/closet/mechanics_hints(mob/user, distance, is_adjacent) . += ..() . += "When closed, a welder could be used to weld the closet shut." @@ -124,6 +127,10 @@ fill() if(secure) verbs += /obj/structure/closet/proc/verb_togglelock + + // Only plain grey crates and closets can be repainted. Handle label-ability here so we don't have to deal with a ton of bespoke definition adjustments. + if(icon_state == "crate" || icon_state == "generic") + can_label = TRUE return mapload ? INITIALIZE_HINT_LATELOAD : INITIALIZE_HINT_NORMAL /obj/structure/closet/LateInitialize() @@ -492,8 +499,10 @@ attack_hand(user) else if(istype(attacking_item,/obj/item/card/id) && secure) togglelock(user) + else if(istype(attacking_item, /obj/item/paint_sprayer)) + return -// Secure locker cutting open stuff. + // Secure locker cutting open stuff. else if(!opened && secure) if(!broken && istype(attacking_item,/obj/item/material/twohanded/chainsaw)) var/obj/item/material/twohanded/chainsaw/ChainSawVar = attacking_item @@ -570,11 +579,10 @@ /obj/structure/closet/relaymove(mob/living/user, direction) . = ..() - if(user.stat || !isturf(loc)) + if(user.stat || !isturf(loc) || user.loc != src || open()) return - if(!open()) - to_chat(user, SPAN_NOTICE("It won't budge!")) + to_chat(user, SPAN_NOTICE("It won't budge!")) /obj/structure/closet/attack_hand(mob/user as mob) add_fingerprint(user) @@ -835,6 +843,21 @@ new /obj/item/stack/material/steel(get_turf(src)) qdel(src) +/obj/structure/closet/proc/paint_container(paint_color) + // Fucking engineering container sprites. Closets and crates handle their main sprite/door naming differently. + var/eng_prefix = findtext(paint_color,"eng_") + if(eng_prefix) + if(istype(src,/obj/structure/closet/crate)) + icon_state = paint_color + icon_door = "eng" + else + icon_state = "eng" + icon_door = paint_color + // And back to sanity. + else + icon_state = paint_color + can_label = FALSE + update_icon() /* ========================== Contents Scanner @@ -843,8 +866,9 @@ /obj/item/cratescanner name = "crate contents scanner" desc = "A handheld device used to scan and print a manifest of a container's contents. Does not work on locked crates, for privacy reasons." - icon = 'icons/obj/item/cratescanner.dmi' - icon_state = "cratescanner" + icon = 'icons/obj/item/scanner.dmi' + icon_state = "crate_scanner" + item_state = "crate_scanner" matter = list(DEFAULT_WALL_MATERIAL = 250, MATERIAL_GLASS = 140) w_class = WEIGHT_CLASS_SMALL obj_flags = OBJ_FLAG_CONDUCTABLE diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm index 995b15c24cec..1b9a69463801 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm @@ -86,7 +86,6 @@ // Painters new /obj/item/paint_sprayer(src) - new /obj/item/pipe_painter(src) // Atmospherics Technician /obj/structure/closet/secure_closet/atmos_personal @@ -120,7 +119,6 @@ // Painters new /obj/item/paint_sprayer(src) - new /obj/item/pipe_painter(src) // Electrical Supplies /obj/structure/closet/secure_closet/engineering_electrical diff --git a/code/game/objects/structures/crates_lockers/closets/secure/operations.dm b/code/game/objects/structures/crates_lockers/closets/secure/operations.dm index c0b512c9f1ee..5b4a2b7274e9 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/operations.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/operations.dm @@ -52,6 +52,8 @@ new /obj/item/clipboard(src) new /obj/item/storage/belt/utility(src) new /obj/item/flashlight/marshallingwand(src) + new /obj/item/flashlight/marshallingwand(src) + new /obj/item/paint_sprayer(src) // Machinist /obj/structure/closet/secure_closet/machinist diff --git a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm index 9c07436e975e..b5471413c0bc 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm @@ -44,7 +44,7 @@ new /obj/item/taperoll/science(src) new /obj/item/gun/energy/disruptorpistol/miniature(src) new /obj/item/clothing/accessory/holster/waist(src) - new /obj/item/storage/box/psireceiver(src) + new /obj/item/storage/box/unique/freezer/organcooler/psireceiver(src) new /obj/item/megaphone/sci(src) new /obj/item/taperecorder(src) new /obj/item/sampler(src) diff --git a/code/game/objects/structures/crates_lockers/crates/gear_loadout.dm b/code/game/objects/structures/crates_lockers/crates/gear_loadout.dm index 25d4f7384ab9..ad5d8a61063c 100644 --- a/code/game/objects/structures/crates_lockers/crates/gear_loadout.dm +++ b/code/game/objects/structures/crates_lockers/crates/gear_loadout.dm @@ -233,7 +233,7 @@ /obj/structure/closet/crate/secure/gear_loadout/frontier_cowboys/fill() for(var/i in 1 to 6) - var/obj/item/clothing/pants/shorts/khaki/pants = new(src) + var/obj/item/clothing/pants/shorts/black/pants = new(src) var/obj/item/clothing/under/dressshirt/rolled/shirt = new(src) var/obj/item/clothing/accessory/chaps/chaps = new(src) var/obj/item/clothing/accessory/suspenders/suspenders = new(src) @@ -255,7 +255,7 @@ new /obj/item/gun/projectile/shotgun/pump/lever_action(src) /obj/structure/closet/crate/secure/gear_loadout/frontier_cowboys/single/fill() - var/obj/item/clothing/pants/shorts/khaki/pants = new(src) + var/obj/item/clothing/pants/shorts/black/pants = new(src) var/obj/item/clothing/under/dressshirt/rolled/shirt = new(src) var/obj/item/clothing/accessory/chaps/chaps = new(src) var/obj/item/clothing/accessory/suspenders/suspenders = new(src) @@ -412,13 +412,13 @@ new /obj/item/clothing/suit/space/void/pra(src) new /obj/item/gun/projectile/automatic/rifle/adhomian(src) new /obj/item/gun/projectile/automatic/rifle/adhomian(src) - new /obj/item/ammo_magazine/boltaction(src) - new /obj/item/ammo_magazine/boltaction(src) - new /obj/item/ammo_magazine/boltaction(src) - new /obj/item/ammo_magazine/boltaction(src) - new /obj/item/ammo_magazine/boltaction(src) - new /obj/item/ammo_magazine/boltaction(src) - new /obj/item/ammo_magazine/boltaction(src) + new /obj/item/ammo_magazine/a68(src) + new /obj/item/ammo_magazine/a68(src) + new /obj/item/ammo_magazine/a68(src) + new /obj/item/ammo_magazine/a68(src) + new /obj/item/ammo_magazine/a68(src) + new /obj/item/ammo_magazine/a68(src) + new /obj/item/ammo_magazine/a68(src) new /obj/item/gun/energy/rifle/icelance(src) new /obj/item/gun/projectile/pistol/adhomai(src) new /obj/item/gun/projectile/pistol/adhomai(src) @@ -439,10 +439,10 @@ new /obj/item/clothing/head/helmet/space/void/pra(src) new /obj/item/clothing/suit/space/void/pra(src) new /obj/item/gun/projectile/automatic/rifle/adhomian(src) - new /obj/item/ammo_magazine/boltaction(src) - new /obj/item/ammo_magazine/boltaction(src) - new /obj/item/ammo_magazine/boltaction(src) - new /obj/item/ammo_magazine/boltaction(src) + new /obj/item/ammo_magazine/a68(src) + new /obj/item/ammo_magazine/a68(src) + new /obj/item/ammo_magazine/a68(src) + new /obj/item/ammo_magazine/a68(src) new /obj/item/gun/projectile/pistol/adhomai(src) new /obj/item/ammo_magazine/mc9mm(src) new /obj/item/ammo_magazine/mc9mm(src) @@ -770,9 +770,9 @@ new /obj/item/gun/projectile/automatic/rifle/shorty(src) new /obj/item/ammo_magazine/c762(src) new /obj/item/ammo_magazine/c762(src) - new /obj/item/gun/projectile/automatic/rifle/dpra/gold(src) - new /obj/item/ammo_magazine/c762/dpra(src) - new /obj/item/ammo_magazine/c762/dpra(src) + new /obj/item/gun/projectile/automatic/rifle/dpra(src) + new /obj/item/ammo_magazine/a68(src) + new /obj/item/ammo_magazine/a68(src) new /obj/item/storage/box/unathi_pirate(src) new /obj/item/voidsuit_modkit_multi/unathi_pirate/captain(src) @@ -811,12 +811,12 @@ new /obj/item/gun/projectile/automatic/rifle/dpra(src) new /obj/item/gun/projectile/automatic/rifle/dpra(src) new /obj/item/gun/projectile/automatic/rifle/dpra(src) - new /obj/item/ammo_magazine/c762/dpra(src) - new /obj/item/ammo_magazine/c762/dpra(src) - new /obj/item/ammo_magazine/c762/dpra(src) - new /obj/item/ammo_magazine/c762/dpra(src) - new /obj/item/ammo_magazine/c762/dpra(src) - new /obj/item/ammo_magazine/c762/dpra(src) + new /obj/item/ammo_magazine/a68(src) + new /obj/item/ammo_magazine/a68(src) + new /obj/item/ammo_magazine/a68(src) + new /obj/item/ammo_magazine/a68(src) + new /obj/item/ammo_magazine/a68(src) + new /obj/item/ammo_magazine/a68(src) new /obj/item/material/knife/bayonet(src) new /obj/item/material/knife/bayonet(src) new /obj/item/gun/projectile/shotgun/pump/rifle/scope(src) @@ -840,8 +840,8 @@ new /obj/item/clothing/suit/space/void/dpra(src) new /obj/item/clothing/head/helmet/space/void/dpra(src) new /obj/item/gun/projectile/automatic/rifle/dpra(src) - new /obj/item/ammo_magazine/c762/dpra(src) - new /obj/item/ammo_magazine/c762/dpra(src) + new /obj/item/ammo_magazine/a68(src) + new /obj/item/ammo_magazine/a68(src) new /obj/item/material/knife/bayonet(src) new /obj/item/gun/projectile/silenced(src) new /obj/item/ammo_magazine/c45m(src) diff --git a/code/game/objects/structures/flags_banners.dm b/code/game/objects/structures/flags_banners.dm index 075ed46f1238..083efeb4dc1a 100644 --- a/code/game/objects/structures/flags_banners.dm +++ b/code/game/objects/structures/flags_banners.dm @@ -4112,3 +4112,46 @@ /obj/structure/sign/flag/sfk/large/west/Initialize(mapload) . = ..(mapload, WEST) + +// Outer Eyes + +/obj/item/flag/outer_eyes + name = "\improper Outer Eyes flag" + desc = "The staring eyes icon of that mysterious group, the Outer Eyes." + desc_extended = "This representation of the Eyes only hints at the provost's inner circle, allowing the larger eye to dominate." + flag_path = "outer_eyes" + flag_structure = /obj/structure/sign/flag/outer_eyes + +/obj/structure/sign/flag/outer_eyes + name = "\improper Outer Eyes flag" + desc = "The staring eyes icon of that mysterious group, the Outer Eyes." + desc_extended = "This representation of the Eyes only hints at the provost's inner circle, allowing the larger eye to dominate." + flag_path = "outer_eyes" + icon_state = "outer_eyes" + flag_item = /obj/item/flag/outer_eyes + +/obj/structure/sign/flag/outer_eyes/unmovable + unmovable = TRUE + +/obj/item/flag/outer_eyes/l + name = "large Outer Eyes flag" + flag_size = TRUE + flag_structure = /obj/structure/sign/flag/outer_eyes/large + +/obj/structure/sign/flag/outer_eyes/large + icon_state = "outer_eyes_l" + flag_path = "outer_eyes" + flag_size = TRUE + flag_item = /obj/item/flag/outer_eyes/l + +/obj/structure/sign/flag/outer_eyes/large/north/Initialize(mapload) + . = ..(mapload, NORTH) + +/obj/structure/sign/flag/outer_eyes/large/south/Initialize(mapload) + . = ..(mapload, SOUTH) + +/obj/structure/sign/flag/outer_eyes/large/east/Initialize(mapload) + . = ..(mapload, EAST) + +/obj/structure/sign/flag/outer_eyes/large/west/Initialize(mapload) + . = ..(mapload, WEST) diff --git a/code/game/objects/structures/fluff/engineering/maintenance.dm b/code/game/objects/structures/fluff/engineering/maintenance.dm index 2a3741d0a905..e90e0e045a32 100644 --- a/code/game/objects/structures/fluff/engineering/maintenance.dm +++ b/code/game/objects/structures/fluff/engineering/maintenance.dm @@ -52,7 +52,7 @@ ABSTRACT_TYPE(/obj/structure/engineer_maintenance) . = ..() // Floor panels are smaller and should be layered beneath dropped objects other structures. if(panel_location == PANEL_LOCATION_FLOOR) - name = "maintenance_panel" + name = "maintenance panel" layer = EXPOSED_WIRE_TERMINAL_LAYER else name = "large maintenance panel" diff --git a/code/game/objects/structures/inflatable.dm b/code/game/objects/structures/inflatable.dm index a75056b82b09..945279cdbc1f 100644 --- a/code/game/objects/structures/inflatable.dm +++ b/code/game/objects/structures/inflatable.dm @@ -5,6 +5,8 @@ name = "inflatable" w_class = WEIGHT_CLASS_SMALL icon = 'icons/obj/item/inflatables.dmi' + item_state = "folded" + contained_sprite = TRUE var/deploy_path = null /obj/item/inflatable/mechanics_hints(mob/user, distance, is_adjacent) @@ -334,6 +336,8 @@ drop_sound = 'sound/items/drop/backpack.ogg' pickup_sound = 'sound/items/pickup/backpack.ogg' + contained_sprite = TRUE + /obj/item/storage/bag/inflatable/emergency name = "emergency inflatable barrier box" desc = "Contains inflatable walls and doors. This box has emergency labelling on it and outlines that there's only enough inflatables within to secure a small area." diff --git a/code/game/objects/structures/noticeboard.dm b/code/game/objects/structures/noticeboard.dm index 7388ee1eb2a4..18bac5a97253 100644 --- a/code/game/objects/structures/noticeboard.dm +++ b/code/game/objects/structures/noticeboard.dm @@ -28,17 +28,18 @@ //attaching papers!! /obj/structure/noticeboard/attackby(obj/item/attacking_item, mob/user) - if(istype(attacking_item, /obj/item/paper)) - if(notice_limit > notices) - attacking_item.add_fingerprint(user) - add_fingerprint(user) - user.drop_from_inventory(attacking_item,src) - notices++ - update_icon() - SSpersistence.register_track(attacking_item, ckey(usr.key)) // Add paper to persistent tracker - to_chat(user, SPAN_NOTICE("You pin the paper to the noticeboard.")) - else - to_chat(user, SPAN_NOTICE("You reach to pin your paper to the board but hesitate. You are certain your paper will not be seen among the many others already attached.")) + if(!istype(attacking_item, /obj/item/paper) || istype(attacking_item, /obj/item/paper/stickynotes)) //Stickynotes on a noticeboard are redundant and have overlapping persistence. + return + if(notice_limit > notices) + attacking_item.add_fingerprint(user) + add_fingerprint(user) + user.drop_from_inventory(attacking_item, src) + notices++ + update_icon() + SSpersistence.register_track(attacking_item, ckey(usr.key)) // Add paper to persistent tracker + to_chat(user, SPAN_NOTICE("You pin the paper to the noticeboard.")) + else + to_chat(user, SPAN_NOTICE("\The [src] is already full of papers and can not fit another.")) /obj/structure/noticeboard/attack_hand(var/mob/user) examine(user) diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm index dc731a02a079..0e7c29626508 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm @@ -609,23 +609,22 @@ if(use_check_and_message(usr)) return - set_rate: - var/amount = tgui_input_number(usr, "Set the IV drip's transfer rate.", "IV Drip", iv_transfer_rate, iv_transfer_rate_upperlimit, iv_transfer_rate_lowerlimit, round_value = FALSE) - if(!amount) - return - if ((0.001 > amount || amount > 4) && amount != 0) - to_chat(usr, SPAN_WARNING("Entered value must be between 0.001 and 4.")) - goto set_rate - if (iv_transfer_rate == 0) - iv_transfer_rate = REM - return - iv_transfer_rate = amount - to_chat(usr, SPAN_NOTICE("Transfer rate set to [src.iv_transfer_rate] u/sec.")) + + iv_transfer_rate = tgui_input_number( \ + usr, \ + "Set the IV drip's transfer rate between [iv_transfer_rate_lowerlimit] and [iv_transfer_rate_upperlimit].", \ + "IV Drip", \ + iv_transfer_rate, \ + iv_transfer_rate_upperlimit, \ + iv_transfer_rate_lowerlimit, \ + round_value = FALSE) + to_chat(usr, SPAN_NOTICE("Transfer rate set to [src.iv_transfer_rate] u/sec.")) /obj/structure/bed/roller/Move() . = ..() if(buckled) if(buckled.buckled_to == src) + buckled.set_glide_size(glide_size) buckled.forceMove(src.loc) else buckled = null diff --git a/code/game/sound/sound.dm b/code/game/sound/sound.dm index 888946f34843..7bf6ea9b051f 100644 --- a/code/game/sound/sound.dm +++ b/code/game/sound/sound.dm @@ -178,7 +178,7 @@ var/datum/gas_mixture/source_env = turf_source.return_air() if(hearer_env && source_env) - var/pressure = min(hearer_env.return_pressure(), source_env.return_pressure()) + var/pressure = min(XGM_PRESSURE(hearer_env), XGM_PRESSURE(source_env)) if(pressure < ONE_ATMOSPHERE) pressure_factor = max((pressure - SOUND_MINIMUM_PRESSURE)/(ONE_ATMOSPHERE - SOUND_MINIMUM_PRESSURE), 0) else //space diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index d0be60f5f191..3c48b4128a10 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -248,9 +248,10 @@ else step(user.pulling, get_dir(user.pulling.loc, src)) - . = handle_hand_interception(user) - if (!.) - return TRUE + // Check if objects in the turf want to slap the attacker back. + for (var/atom/target_atom in src) + SEND_SIGNAL(target_atom, COMSIG_HANDLE_HAND_INTERCEPTION, user, src) + return TRUE /// Call to move a turf from its current area to a new one @@ -291,16 +292,6 @@ /turf/proc/on_change_area(area/old_area, area/new_area) transfer_area_lighting(old_area, new_area) -/turf/proc/handle_hand_interception(var/mob/user) - var/datum/component/turf_hand/THE - for (var/atom/A in src) - var/datum/component/turf_hand/TH = A.GetComponent(/datum/component/turf_hand) - if (istype(TH) && TH.priority > THE?.priority) //Only overwrite if the new one is higher. For matching values, its first come first served - THE = TH - - if (THE) - return THE.OnHandInterception(user) - // /turf/Enter(atom/movable/mover as mob|obj, atom/forget as mob|obj|turf|area) // if(movement_disabled && usr.ckey != movement_disabled_exception) // to_chat(usr, SPAN_WARNING("Movement is admin-disabled.")) //This is to identify lag problems) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 4dd702544c0a..ca2652eb049d 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -1399,11 +1399,14 @@ var/global/enabled_spooking = 0 /datum/admins/proc/set_odyssey() set name = "Set Odyssey Type" set category = "Special Verbs" + if (!SSodyssey.initialized) + to_chat(usr, SPAN_WARNING("You must wait for the server to finish initializing.")) + return if(!check_rights(R_ADMIN)) return - if(SSticker.current_state != GAME_STATE_SETTING_UP) + if(SSticker.current_state > GAME_STATE_SETTING_UP) to_chat(usr, SPAN_WARNING("You need to use this verb while the game is still setting up!")) return diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 38278df1383a..4beb0c2c6285 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -30,7 +30,6 @@ GLOBAL_LIST_INIT(admin_verbs_admin, list( /client/proc/cmd_admin_delete, /*delete an instance/object/mob/etc*/ /client/proc/cmd_admin_check_contents, /*displays the contents of an instance*/ /datum/admins/proc/access_news_network, /*allows access of newscasters*/ - /client/proc/getserverlog, /*allows us to fetch server logs (diary) for other days*/ /client/proc/jumptocoord, /*we ghost and jump to a coordinate*/ /client/proc/jumptozlevel, /client/proc/jumptoshuttle, @@ -188,7 +187,6 @@ GLOBAL_LIST_INIT(admin_verbs_server, list( )) GLOBAL_LIST_INIT(admin_verbs_debug, list( - /client/proc/getruntimelog, // allows us to access runtime logs to somebody, /client/proc/cmd_admin_list_open_jobs, /client/proc/Debug2, /client/proc/DebugToggle, @@ -245,7 +243,8 @@ GLOBAL_LIST_INIT(admin_verbs_debug, list( /client/proc/profiler_start, /datum/admins/proc/force_initialize_weather, /datum/admins/proc/force_weather_state, - /datum/admins/proc/force_kill_weather + /datum/admins/proc/force_kill_weather, + /client/proc/check_timer_sources )) GLOBAL_LIST_INIT(admin_verbs_paranoid_debug, list( @@ -414,9 +413,7 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list( /datum/admins/proc/set_odyssey_canonicity, /client/proc/cmd_display_init_log, /client/proc/cmd_generate_lag, - /client/proc/getruntimelog, /client/proc/toggledebuglogs, - /client/proc/getserverlog, /client/proc/view_chemical_reaction_logs, /datum/admins/proc/capture_map, /turf/proc/view_chunk, @@ -489,7 +486,6 @@ GLOBAL_LIST_INIT(admin_verbs_dev, list( //will need to be altered - Ryan784 /client/proc/debug_controller, /client/proc/debug_variables, /client/proc/dsay, - /client/proc/getruntimelog, /client/proc/hide_most_verbs, /client/proc/kill_air, /client/proc/kill_airgroup, @@ -769,8 +765,8 @@ GLOBAL_LIST_INIT(admin_verbs_storyteller, list( set name = "Drop Bomb" set desc = "Cause an explosion of varying strength at your location." - var/turf/epicenter = get_turf(mob) var/choice = tgui_input_list(usr, "What size explosion would you like to produce?", "Drop Bomb", list("Small Bomb", "Medium Bomb", "Big Bomb", "Custom Bomb")) + var/turf/epicenter = get_turf(mob) switch(choice) if(null) return 0 @@ -785,6 +781,7 @@ GLOBAL_LIST_INIT(admin_verbs_storyteller, list( var/heavy_impact_range = tgui_input_number(usr, "Set the heavy impact range (in tiles).", "Heavy") var/light_impact_range = tgui_input_number(usr, "Set the light impact range (in tiles).", "Light") var/flash_range = tgui_input_number(usr, "Set the flash range (in tiles).", "Flash") + epicenter = get_turf(mob) explosion(epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range) message_admins(SPAN_NOTICE("[ckey] creating an admin explosion at [epicenter.loc].")) feedback_add_details("admin_verb","DB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/secrets/fun_secrets/ghost_mode.dm b/code/modules/admin/secrets/fun_secrets/ghost_mode.dm index ab3f81a407b6..fcd763ddb9d3 100644 --- a/code/modules/admin/secrets/fun_secrets/ghost_mode.dm +++ b/code/modules/admin/secrets/fun_secrets/ghost_mode.dm @@ -36,10 +36,10 @@ affected_mobs |= user for(var/area/AffectedArea in affected_areas) AffectedArea.power_light = 0 - AffectedArea.power_change() + SEND_SIGNAL(AffectedArea, COMSIG_AREA_POWER_CHANGE) spawn(rand(25,50)) AffectedArea.power_light = 1 - AffectedArea.power_change() + SEND_SIGNAL(AffectedArea, COMSIG_AREA_POWER_CHANGE) sleep(100) for(var/mob/M in affected_mobs) diff --git a/code/modules/admin/ticket.dm b/code/modules/admin/ticket.dm index 593586035f77..d81533f601f0 100644 --- a/code/modules/admin/ticket.dm +++ b/code/modules/admin/ticket.dm @@ -297,7 +297,7 @@ GLOBAL_LIST_EMPTY(ticket_panels) if("close") ticket.close(usr.client) if("pm") - if(check_rights(R_MOD|R_ADMIN) && ticket.owner != usr.ckey) + if(ticket.owner != usr.ckey && check_rights(R_MOD|R_ADMIN)) usr.client.cmd_admin_pm(client_by_ckey(ticket.owner), ticket = ticket) else if(ticket.status == TICKET_ASSIGNED) // manually check that the target client exists here as to not spam the usr for each logged out admin on the ticket diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index 7140a79de6e3..c659d92e4156 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -46,9 +46,10 @@ return var/receive_pm_type = "Player" + var/sender_is_ahelp_staff = check_rights(R_ADMIN|R_MOD, FALSE) //mod PMs are maroon //PMs sent from admins and mods display their rank - if(holder) + if(sender_is_ahelp_staff) if(!C.holder && holder.fakekey) receive_pm_type = "Admin" else @@ -61,12 +62,12 @@ //get message text, limit it's length.and clean/escape html // only sanitize it if we're getting it from this proc if(!msg) - msg = input(src,"Message:", "Private message to [key_name(C, 0, holder ? 1 : 0)]") as text|null + msg = input(src,"Message:", "Private message to [key_name(C, 0, sender_is_ahelp_staff ? 1 : 0)]") as text|null if(!msg) return if(!C) - if(holder) + if(sender_is_ahelp_staff) to_chat(src, SPAN_WARNING("Error: Admin-PM: Client not found.")) else to_chat(src, SPAN_WARNING("Error: Private-Message: Client not found. They may have lost connection, so try using an adminhelp!")) @@ -81,7 +82,7 @@ // searches for an open ticket, in case an outdated link was clicked // I'm paranoid about the problems that could be caused by accidentally finding the wrong ticket, which is why this is strict if(isnull(ticket)) - if(holder) + if(sender_is_ahelp_staff) ticket = get_open_ticket_by_ckey(C.ckey) // it's more likely an admin clicked a different PM link, so check admin -> player with ticket first if(isnull(ticket) && C.holder) ticket = get_open_ticket_by_ckey(src.ckey) // if still no dice, try an admin with ticket -> admin @@ -90,7 +91,7 @@ if(isnull(ticket)) // finally, accept that no ticket exists - if(holder && src != C) + if(sender_is_ahelp_staff && src != C) ticket = new /datum/ticket(C.ckey) ticket.take(src) else @@ -101,13 +102,13 @@ return // if the sender is an admin and they're not assigned to the ticket, ask them if they want to take/join it, unless the admin is responding to their own ticket - if(holder && !(src.ckey in ticket.assigned_admins)) + if(sender_is_ahelp_staff && !(src.ckey in ticket.assigned_admins)) if(src.ckey != ticket.owner && !ticket.take(src)) return var/receive_message - if(holder && !C.holder) + if(sender_is_ahelp_staff && !C.holder) receive_message = "-- Click the [receive_pm_type]'s name to reply --\n" if(C.adminhelped) to_chat(C, receive_message) @@ -126,8 +127,8 @@ adminhelp(reply) //sender has left, adminhelp instead return - var/sender_message = "" + create_text_tag("PM <-", src) + " to [get_options_bar(C, holder ? 1 : 0, holder ? 1 : 0, 1)]" - if(holder) + var/sender_message = "" + create_text_tag("PM <-", src) + " to [get_options_bar(C, sender_is_ahelp_staff ? 1 : 0, sender_is_ahelp_staff ? 1 : 0, 1)]" + if(sender_is_ahelp_staff) sender_message += " ([(ticket.status == TICKET_OPEN) ? "TAKE" : "JOIN"]) (CLOSE)" sender_message += ": [generate_ahelp_key_words(mob, msg)]" else diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index cbfd73fbf88a..84493bc85f35 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -57,7 +57,7 @@ var/t = SPAN_NOTICE("Coordinates: [T.x],[T.y],[T.z]\n") t += SPAN_WARNING("Temperature: [env.temperature]\n") - t += SPAN_WARNING("Pressure: [env.return_pressure()]kPa\n") + t += SPAN_WARNING("Pressure: [XGM_PRESSURE(env)]kPa\n") for(var/g in env.gas) t += SPAN_NOTICE("[g]: [env.gas[g]] / [env.gas[g] * R_IDEAL_GAS_EQUATION * env.temperature / env.volume]kPa\n") @@ -515,3 +515,63 @@ to_chat(src, SPAN_INFO("You can now right click to use inspect on browsers.")) winset(src, null, list("browser-options" = "+devtools")) winset(src, null, list("browser-options" = "+find")) + +/// A debug verb to check the sources of currently running timers +/client/proc/check_timer_sources() + set category = "Debug" + set name = "Check Timer Sources" + set desc = "Checks the sources of the running timers" + if (!check_rights(R_DEBUG)) + return + + var/bucket_list_output = generate_timer_source_output(SStimer.bucket_list) + var/second_queue = generate_timer_source_output(SStimer.second_queue) + var/html_body = {" +

bucket_list

+ [bucket_list_output] + +

second_queue

+ [second_queue] + "} + usr << browse(HTML_SKELETON(html_body), "window=check_timer_sources;size=700x700") + +/proc/generate_timer_source_output(list/datum/timedevent/events) + var/list/per_source = list() + + // Collate all events and figure out what sources are creating the most + for (var/_event in events) + if (!_event) + continue + var/datum/timedevent/event = _event + + do + if (event.source) + if (per_source[event.source] == null) + per_source[event.source] = 1 + else + per_source[event.source] += 1 + event = event.next + while (event && event != _event) + + // Now, sort them in order + var/list/sorted = list() + for (var/source in per_source) + sorted += list(list("source" = source, "count" = per_source[source])) + sorted = sortTim(sorted, .proc/cmp_timer_data) + + // Now that everything is sorted, compile them into an HTML output + var/output = "" + + for (var/_timer_data in sorted) + var/list/timer_data = _timer_data + output += {" + + + "} + + output += "
[timer_data["source"]][timer_data["count"]]
" + + return output + +/proc/cmp_timer_data(list/a, list/b) + return b["count"] - a["count"] diff --git a/code/modules/admin/verbs/getlogs.dm b/code/modules/admin/verbs/getlogs.dm deleted file mode 100644 index 769e68fc2f31..000000000000 --- a/code/modules/admin/verbs/getlogs.dm +++ /dev/null @@ -1,55 +0,0 @@ -/* - HOW DO I LOG RUNTIMES? - Firstly, start dreamdeamon if it isn't already running. Then select "world>Log Session" (or press the F3 key) - navigate the popup window to the data/logs/runtime/ folder from where your tgstation .dmb is located. - (you may have to make this folder yourself) - - OPTIONAL: you can select the little checkbox down the bottom to make dreamdeamon save the log everytime you - start a world. Just remember to repeat these steps with a new name when you update to a new revision! - - Save it with the name of the revision your server uses (e.g. r3459.txt). - Game Masters will now be able to grant access any runtime logs you have archived this way! - This will allow us to gather information on bugs across multiple servers and make maintaining the TG - codebase for the entire /TG/station commuity a TONNE easier :3 Thanks for your help! -*/ - -/** - * Allows a client that has this proc to download the runtime logs of the current round - */ -/client/proc/getruntimelog() - set name = ".getruntimelog" - set desc = "Retrieve any session logfiles saved by dreamdeamon." - set category = null - - var/path = LOGPATH(GLOB.config.logfiles["world_runtime_log"]) - - if(file_spam_check()) - return - - message_admins("[key_name_admin(src)] accessed file: [path]") - src << run( file(path) ) - to_chat(src, "Attempting to send file, this may take a fair few minutes if the file is very large.") - - -//This proc allows download of past server logs saved within the data/logs/ folder. -//It works similarly to show-server-log. -/** - * Allows a client that has this proc the download of a log file of the active round - * - * Assigned only to admins currently - */ -/client/proc/getserverlog() - set name = ".getserverlog" - set desc = "Fetch logfiles from data/logs" - set category = null - - var/path = browse_files(LOGPATH("")) //Prompt for which file to download, understands subfolders from files - if(!path) - return - - if(file_spam_check()) - return - - message_admins("[key_name_admin(src)] accessed file: [path]") - src << run( file(path) ) - to_chat(src, "Attempting to send file, this may take a fair few minutes if the file is very large.") diff --git a/code/modules/asset_cache/asset_cache.dm b/code/modules/asset_cache/asset_cache.dm index 1e33d367c89e..49355997d11f 100644 --- a/code/modules/asset_cache/asset_cache.dm +++ b/code/modules/asset_cache/asset_cache.dm @@ -534,6 +534,8 @@ GLOBAL_LIST_EMPTY(asset_datums) "goldenlogo_small.png" = 'html/images/factions/goldenlogo_small.png', "pvpolicelogo.png" = 'html/images/pvpolicelogo.png', "pvpolicelogo_small.png" = 'html/images/pvpolicelogo_small.png', + "outereyeslogo.png" = 'html/images/outereyeslogo.png', + "outereyeslogo_small.png" = 'html/images/outereyeslogo_small.png', //scan images that appear on sensors "no_data.png" = 'html/images/scans/no_data.png', "horizon.png" = 'html/images/scans/horizon.png', diff --git a/code/modules/atmospherics/_atmospherics_helpers.dm b/code/modules/atmospherics/_atmospherics_helpers.dm index f7ed86c60b43..4f396f1016ac 100644 --- a/code/modules/atmospherics/_atmospherics_helpers.dm +++ b/code/modules/atmospherics/_atmospherics_helpers.dm @@ -451,7 +451,7 @@ var/source_volume = source.volume * source.group_multiplier var/sink_volume = sink.volume * sink.group_multiplier - var/source_pressure = source.return_pressure() - var/sink_pressure = sink.return_pressure() + var/source_pressure = XGM_PRESSURE(source) + var/sink_pressure = XGM_PRESSURE(sink) return (source_pressure - sink_pressure)/(R_IDEAL_GAS_EQUATION * (source.temperature/source_volume + sink.temperature/sink_volume)) diff --git a/code/modules/atmospherics/atmospherics.dm b/code/modules/atmospherics/atmospherics.dm index a03ee65aec7b..ba316f2a2299 100644 --- a/code/modules/atmospherics/atmospherics.dm +++ b/code/modules/atmospherics/atmospherics.dm @@ -56,7 +56,7 @@ Pipelines + Other Objects -> Pipe network atmos_init() /obj/machinery/atmospherics/attackby(obj/item/attacking_item, mob/user) - if(istype(attacking_item, /obj/item/pipe_painter)) + if(istype(attacking_item, /obj/item/paint_sprayer)) return FALSE ..() diff --git a/code/modules/atmospherics/components/binary_devices/circulator.dm b/code/modules/atmospherics/components/binary_devices/circulator.dm index c510ad6cc790..5856613843bd 100644 --- a/code/modules/atmospherics/components/binary_devices/circulator.dm +++ b/code/modules/atmospherics/components/binary_devices/circulator.dm @@ -21,6 +21,8 @@ var/volume_capacity_used = 0 var/stored_energy = 0 var/temperature_overlay + /// When passing its status to the main Stirling generator, this informs labeling on the TGUI. + var/is_hot_loop = FALSE density = TRUE @@ -37,8 +39,8 @@ /obj/machinery/atmospherics/binary/circulator/proc/return_transfer_air() var/datum/gas_mixture/removed if(anchored && !(stat&BROKEN) && network1) - var/input_starting_pressure = air1.return_pressure() - var/output_starting_pressure = air2.return_pressure() + var/input_starting_pressure = XGM_PRESSURE(air1) + var/output_starting_pressure = XGM_PRESSURE(air2) last_pressure_delta = max(input_starting_pressure - output_starting_pressure - 5, 0) //only circulate air if there is a pressure difference (plus 5kPa kinetic, 10kPa static friction) diff --git a/code/modules/atmospherics/components/binary_devices/oxyregenerator.dm b/code/modules/atmospherics/components/binary_devices/oxyregenerator.dm index 4daeeb041409..28e30599c21c 100644 --- a/code/modules/atmospherics/components/binary_devices/oxyregenerator.dm +++ b/code/modules/atmospherics/components/binary_devices/oxyregenerator.dm @@ -103,7 +103,7 @@ last_power_draw = 0 //TODO Add overlay with F-P-R letter to display current state if (phase == "filling")//filling tank - var/pressure_delta = target_pressure - inner_tank.return_pressure() + var/pressure_delta = target_pressure - XGM_PRESSURE(inner_tank) if (pressure_delta > 0.01 && air1.temperature > 0) var/transfer_moles = calculate_transfer_moles(air1, inner_tank, pressure_delta) power_draw = pump_gas(src, air1, inner_tank, transfer_moles, power_rating*power_setting) * intake_power_efficiency @@ -112,7 +112,7 @@ use_power_oneoff(power_draw) if(network1) network1.update = 1 - if (air1.return_pressure() < 0.1 * ONE_ATMOSPHERE || inner_tank.return_pressure() >= target_pressure * 0.95)//if pipe is good as empty or tank is full + if (XGM_PRESSURE(air1) < 0.1 * ONE_ATMOSPHERE || XGM_PRESSURE(inner_tank) >= target_pressure * 0.95)//if pipe is good as empty or tank is full phase = "processing" if (phase == "processing")//processing CO2 in tank @@ -137,7 +137,7 @@ if (phase == "releasing")//releasing processed gas mix power_draw = -1 - var/pressure_delta = target_pressure - air2.return_pressure() + var/pressure_delta = target_pressure - XGM_PRESSURE(air2) if (pressure_delta > 0.01 && inner_tank.temperature > 0) var/transfer_moles = calculate_transfer_moles(inner_tank, air2, pressure_delta, (network2)? network2.volume : 0) power_draw = pump_gas(src, inner_tank, air2, transfer_moles, power_rating*power_setting) @@ -148,7 +148,7 @@ network2.update = 1 else//can't push outside harder than target pressure. Device is not intended to be used as a pump after all phase = "filling" - if (inner_tank.return_pressure() <= 0.1) + if (XGM_PRESSURE(inner_tank) <= 0.1) phase = "filling" /obj/machinery/atmospherics/binary/oxyregenerator/update_icon() @@ -162,9 +162,9 @@ data["on"] = use_power ? 1 : 0 data["powerSetting"] = power_setting data["gasProcessed"] = last_flow_rate - data["air1Pressure"] = round(air1.return_pressure()) - data["air2Pressure"] = round(air2.return_pressure()) - data["tankPressure"] = round(inner_tank.return_pressure()) + data["air1Pressure"] = round(XGM_PRESSURE(air1)) + data["air2Pressure"] = round(XGM_PRESSURE(air2)) + data["tankPressure"] = round(XGM_PRESSURE(inner_tank)) data["targetPressure"] = round(target_pressure) data["phase"] = phase if (inner_tank.total_moles > 0) diff --git a/code/modules/atmospherics/components/binary_devices/passive_gate.dm b/code/modules/atmospherics/components/binary_devices/passive_gate.dm index c73c85a17205..677b8a7bdd3b 100644 --- a/code/modules/atmospherics/components/binary_devices/passive_gate.dm +++ b/code/modules/atmospherics/components/binary_devices/passive_gate.dm @@ -116,8 +116,8 @@ if(!unlocked) return 0 - var/output_starting_pressure = air2.return_pressure() - var/input_starting_pressure = air1.return_pressure() + var/output_starting_pressure = XGM_PRESSURE(air2) + var/input_starting_pressure = XGM_PRESSURE(air1) var/pressure_delta switch (regulate_mode) @@ -203,11 +203,8 @@ unlocked = !unlocked if("set_target_pressure" in signal.data) - target_pressure = between( - 0, - text2num(signal.data["set_target_pressure"]), - max_pressure_setting - ) + var/set_pressure = text2num(signal.data["set_target_pressure"]) + target_pressure = between(0, set_pressure, max_pressure_setting) if("set_regulate_mode" in signal.data) regulate_mode = text2num(signal.data["set_regulate_mode"]) @@ -335,7 +332,7 @@ var/datum/gas_mixture/int_air = return_air() if (!loc) return FALSE var/datum/gas_mixture/env_air = loc.return_air() - if ((int_air.return_pressure()-env_air.return_pressure()) > PRESSURE_EXERTED) + if ((XGM_PRESSURE(int_air)-XGM_PRESSURE(env_air)) > PRESSURE_EXERTED) to_chat(user, SPAN_WARNING("You cannot unwrench \the [src], it too exerted due to internal pressure.")) add_fingerprint(user) return TRUE diff --git a/code/modules/atmospherics/components/binary_devices/pump.dm b/code/modules/atmospherics/components/binary_devices/pump.dm index 26a5e9856d42..e407eeb6a66e 100644 --- a/code/modules/atmospherics/components/binary_devices/pump.dm +++ b/code/modules/atmospherics/components/binary_devices/pump.dm @@ -121,7 +121,7 @@ Thus, the two variables affect pump operation are set in New(): broadcast_status_next_process = FALSE var/power_draw = -1 - var/pressure_delta = target_pressure - air2.return_pressure() + var/pressure_delta = target_pressure - XGM_PRESSURE(air2) if(pressure_delta > 0.01 && air1.temperature > 0) //Figure out how much gas to transfer to meet the target pressure. @@ -282,7 +282,7 @@ Thus, the two variables affect pump operation are set in New(): var/datum/gas_mixture/int_air = return_air() if (!loc) return FALSE var/datum/gas_mixture/env_air = loc.return_air() - if ((int_air.return_pressure()-env_air.return_pressure()) > PRESSURE_EXERTED && !istype(attacking_item, /obj/item/pipewrench)) + if ((XGM_PRESSURE(int_air)-XGM_PRESSURE(env_air)) > PRESSURE_EXERTED && !istype(attacking_item, /obj/item/pipewrench)) to_chat(user, SPAN_WARNING("You cannot unwrench this [src], it's too exerted due to internal pressure.")) add_fingerprint(user) return TRUE diff --git a/code/modules/atmospherics/components/omni_devices/_omni_extras.dm b/code/modules/atmospherics/components/omni_devices/_omni_extras.dm index 2e8c02839397..9592639782ee 100644 --- a/code/modules/atmospherics/components/omni_devices/_omni_extras.dm +++ b/code/modules/atmospherics/components/omni_devices/_omni_extras.dm @@ -46,6 +46,14 @@ air = new air.volume = 200 +/datum/omni_port/Destroy(force) + if(node) + disconnect() + QDEL_NULL(network) + node = null + master = null + . = ..() + /datum/omni_port/proc/connect() if(node) return diff --git a/code/modules/atmospherics/components/omni_devices/filter.dm b/code/modules/atmospherics/components/omni_devices/filter.dm index 1b566d396375..04795c08c607 100644 --- a/code/modules/atmospherics/components/omni_devices/filter.dm +++ b/code/modules/atmospherics/components/omni_devices/filter.dm @@ -30,6 +30,7 @@ P.air.volume = ATMOS_DEFAULT_VOLUME_FILTER /obj/machinery/atmospherics/omni/filter/Destroy() + // these get qdel'd in omni/Destroy() input = null output = null active_filters.Cut() diff --git a/code/modules/atmospherics/components/omni_devices/mixer.dm b/code/modules/atmospherics/components/omni_devices/mixer.dm index 2640168dd6b3..215c8ad39714 100644 --- a/code/modules/atmospherics/components/omni_devices/mixer.dm +++ b/code/modules/atmospherics/components/omni_devices/mixer.dm @@ -56,6 +56,7 @@ /obj/machinery/atmospherics/omni/mixer/Destroy() inputs.Cut() + // this gets qdel'd in omni/Destroy() output = null return ..() diff --git a/code/modules/atmospherics/components/omni_devices/omni_base.dm b/code/modules/atmospherics/components/omni_devices/omni_base.dm index 043a241e1009..e848f8072475 100644 --- a/code/modules/atmospherics/components/omni_devices/omni_base.dm +++ b/code/modules/atmospherics/components/omni_devices/omni_base.dm @@ -88,10 +88,10 @@ var/int_pressure = 0 for(var/datum/omni_port/P in ports) - int_pressure += P.air.return_pressure() + int_pressure += XGM_PRESSURE(P.air) if(!loc) return FALSE var/datum/gas_mixture/env_air = loc.return_air() - if ((int_pressure - env_air.return_pressure()) > PRESSURE_EXERTED) + if ((int_pressure - XGM_PRESSURE(env_air)) > PRESSURE_EXERTED) to_chat(user, SPAN_WARNING("You cannot unwrench \the [src], it is too exerted due to internal pressure.")) add_fingerprint(user) return TRUE @@ -212,15 +212,9 @@ /obj/machinery/atmospherics/omni/Destroy() loc = null - - for(var/datum/omni_port/P in ports) - if(P.node) - P.node.disconnect(src) - qdel(P.network) - P.node = null + QDEL_LIST(ports) . = ..() - GC_TEMPORARY_HARDDEL /obj/machinery/atmospherics/omni/atmos_init() for(var/datum/omni_port/P in ports) diff --git a/code/modules/atmospherics/components/portables_connector.dm b/code/modules/atmospherics/components/portables_connector.dm index 9411793a592d..dbc2ebbfd4e7 100644 --- a/code/modules/atmospherics/components/portables_connector.dm +++ b/code/modules/atmospherics/components/portables_connector.dm @@ -164,7 +164,7 @@ var/datum/gas_mixture/int_air = return_air() if(!loc) return FALSE var/datum/gas_mixture/env_air = loc.return_air() - if ((int_air.return_pressure()-env_air.return_pressure()) > PRESSURE_EXERTED) + if ((XGM_PRESSURE(int_air)-XGM_PRESSURE(env_air)) > PRESSURE_EXERTED) to_chat(user, SPAN_WARNING("You cannot unwrench \the [src], it too exerted due to internal pressure.")) add_fingerprint(user) return TRUE diff --git a/code/modules/atmospherics/components/tvalve.dm b/code/modules/atmospherics/components/tvalve.dm index 42a8db1e453e..a16be54f6884 100644 --- a/code/modules/atmospherics/components/tvalve.dm +++ b/code/modules/atmospherics/components/tvalve.dm @@ -355,7 +355,7 @@ var/datum/gas_mixture/int_air = return_air() if(!loc) return FALSE var/datum/gas_mixture/env_air = loc.return_air() - if ((int_air.return_pressure()-env_air.return_pressure()) > PRESSURE_EXERTED) + if ((XGM_PRESSURE(int_air)-XGM_PRESSURE(env_air)) > PRESSURE_EXERTED) to_chat(user, "You cannot unwrench \the [src], it too exerted due to internal pressure.") add_fingerprint(user) return TRUE diff --git a/code/modules/atmospherics/components/unary/cold_sink.dm b/code/modules/atmospherics/components/unary/cold_sink.dm index d10868266c21..aa9f0472db64 100644 --- a/code/modules/atmospherics/components/unary/cold_sink.dm +++ b/code/modules/atmospherics/components/unary/cold_sink.dm @@ -92,7 +92,7 @@ var/list/data = list() data["on"] = !!use_power - data["gasPressure"] = round(air_contents.return_pressure()) + data["gasPressure"] = round(XGM_PRESSURE(air_contents)) data["gasTemperature"] = round(air_contents.temperature) data["minGasTemperature"] = 0 data["maxGasTemperature"] = round(T20C+500) diff --git a/code/modules/atmospherics/components/unary/heat_exchanger.dm b/code/modules/atmospherics/components/unary/heat_exchanger.dm index 4766c1d3c6c1..b8a596ac0a5b 100644 --- a/code/modules/atmospherics/components/unary/heat_exchanger.dm +++ b/code/modules/atmospherics/components/unary/heat_exchanger.dm @@ -73,7 +73,7 @@ var/datum/gas_mixture/int_air = return_air() if(!loc) return FALSE var/datum/gas_mixture/env_air = loc.return_air() - if((int_air.return_pressure() - env_air.return_pressure()) > PRESSURE_EXERTED) + if((XGM_PRESSURE(int_air) - XGM_PRESSURE(env_air)) > PRESSURE_EXERTED) to_chat(user, SPAN_WARNING("You cannot unwrench \the [src], it is too exerted due to internal pressure.")) add_fingerprint(user) return TRUE diff --git a/code/modules/atmospherics/components/unary/heat_source.dm b/code/modules/atmospherics/components/unary/heat_source.dm index be4816b7741f..a5e5af6743f3 100644 --- a/code/modules/atmospherics/components/unary/heat_source.dm +++ b/code/modules/atmospherics/components/unary/heat_source.dm @@ -110,7 +110,7 @@ var/list/data = list() data["on"] = !!use_power - data["gasPressure"] = round(air_contents.return_pressure()) + data["gasPressure"] = round(XGM_PRESSURE(air_contents)) data["gasTemperature"] = round(air_contents.temperature) data["minGasTemperature"] = 0 data["maxGasTemperature"] = round(T20C + 600) diff --git a/code/modules/atmospherics/components/unary/unary_base.dm b/code/modules/atmospherics/components/unary/unary_base.dm index 7f24679fd404..39ab9d0bc2d3 100644 --- a/code/modules/atmospherics/components/unary/unary_base.dm +++ b/code/modules/atmospherics/components/unary/unary_base.dm @@ -92,15 +92,11 @@ return null -/obj/machinery/atmospherics/unary/proc/is_welded() +/obj/machinery/atmospherics/proc/is_welded() return FALSE /obj/machinery/atmospherics/unary/vent_pump/is_welded() - if (welded > 0) - return TRUE - return FALSE + return welded /obj/machinery/atmospherics/unary/vent_scrubber/is_welded() - if (welded > 0) - return TRUE - return FALSE + return welded diff --git a/code/modules/atmospherics/components/unary/vent_pump.dm b/code/modules/atmospherics/components/unary/vent_pump.dm index 100826a9b1d5..2cc6f7f3fc00 100644 --- a/code/modules/atmospherics/components/unary/vent_pump.dm +++ b/code/modules/atmospherics/components/unary/vent_pump.dm @@ -260,18 +260,18 @@ /obj/machinery/atmospherics/unary/vent_pump/proc/get_pressure_delta(datum/gas_mixture/environment) var/pressure_delta = DEFAULT_PRESSURE_DELTA - var/environment_pressure = environment.return_pressure() + var/environment_pressure = XGM_PRESSURE(environment) if(pump_direction) //internal -> external if(pressure_checks & PRESSURE_CHECK_EXTERNAL) pressure_delta = min(pressure_delta, external_pressure_bound - environment_pressure) //increasing the pressure here if(pressure_checks & PRESSURE_CHECK_INTERNAL) - pressure_delta = min(pressure_delta, air_contents.return_pressure() - internal_pressure_bound) //decreasing the pressure here + pressure_delta = min(pressure_delta, XGM_PRESSURE(air_contents) - internal_pressure_bound) //decreasing the pressure here else //external -> internal if(pressure_checks & PRESSURE_CHECK_EXTERNAL) pressure_delta = min(pressure_delta, environment_pressure - external_pressure_bound) //decreasing the pressure here if(pressure_checks & PRESSURE_CHECK_INTERNAL) - pressure_delta = min(pressure_delta, internal_pressure_bound - air_contents.return_pressure()) //increasing the pressure here + pressure_delta = min(pressure_delta, internal_pressure_bound - XGM_PRESSURE(air_contents)) //increasing the pressure here return pressure_delta @@ -349,37 +349,23 @@ if (signal.data["set_internal_pressure"] == "default") internal_pressure_bound = internal_pressure_bound_default else - internal_pressure_bound = between( - 0, - text2num(signal.data["set_internal_pressure"]), - MAX_VENT_PRESSURE - ) + var/set_pressure = text2num(signal.data["set_internal_pressure"]) + internal_pressure_bound = between(0, set_pressure, MAX_VENT_PRESSURE) if(signal.data["set_external_pressure"] != null) if (signal.data["set_external_pressure"] == "default") external_pressure_bound = external_pressure_bound_default else - external_pressure_bound = between( - 0, - text2num(signal.data["set_external_pressure"]), - MAX_VENT_PRESSURE - ) + var/set_pressure = text2num(signal.data["set_external_pressure"]) + external_pressure_bound = between(0, set_pressure, MAX_VENT_PRESSURE) if(signal.data["adjust_internal_pressure"] != null) - internal_pressure_bound = between( - 0, - internal_pressure_bound + text2num(signal.data["adjust_internal_pressure"]), - MAX_VENT_PRESSURE - ) + var/set_pressure = internal_pressure_bound + text2num(signal.data["adjust_internal_pressure"]) + internal_pressure_bound = between(0, set_pressure, MAX_VENT_PRESSURE) if(signal.data["adjust_external_pressure"] != null) - - - external_pressure_bound = between( - 0, - external_pressure_bound + text2num(signal.data["adjust_external_pressure"]), - MAX_VENT_PRESSURE - ) + var/set_pressure = external_pressure_bound + text2num(signal.data["adjust_external_pressure"]) + external_pressure_bound = between(0, set_pressure, MAX_VENT_PRESSURE) if(signal.data["init"] != null) name = signal.data["init"] @@ -452,7 +438,7 @@ var/datum/gas_mixture/int_air = return_air() var/datum/gas_mixture/env_air = loc.return_air() - if((int_air.return_pressure()-env_air.return_pressure()) > PRESSURE_EXERTED) + if((XGM_PRESSURE(int_air)-XGM_PRESSURE(env_air)) > PRESSURE_EXERTED) to_chat(user, SPAN_WARNING("You cannot unwrench \the [src], it is too exerted due to internal pressure.")) add_fingerprint(user) diff --git a/code/modules/atmospherics/components/unary/vent_scrubber.dm b/code/modules/atmospherics/components/unary/vent_scrubber.dm index d8a1a0bf6a54..28d490ad0da2 100644 --- a/code/modules/atmospherics/components/unary/vent_scrubber.dm +++ b/code/modules/atmospherics/components/unary/vent_scrubber.dm @@ -369,7 +369,7 @@ var/datum/gas_mixture/int_air = return_air() if(!loc) return FALSE var/datum/gas_mixture/env_air = loc.return_air() - if ((int_air.return_pressure()-env_air.return_pressure()) > PRESSURE_EXERTED) + if ((XGM_PRESSURE(int_air)-XGM_PRESSURE(env_air)) > PRESSURE_EXERTED) to_chat(user, SPAN_WARNING("You cannot unwrench \the [src], it is too exerted due to internal pressure.")) add_fingerprint(user) return TRUE diff --git a/code/modules/atmospherics/components/valve.dm b/code/modules/atmospherics/components/valve.dm index 5a79e98a5230..3c29f91b12e9 100644 --- a/code/modules/atmospherics/components/valve.dm +++ b/code/modules/atmospherics/components/valve.dm @@ -327,7 +327,7 @@ var/datum/gas_mixture/int_air = return_air() if (!loc) return FALSE var/datum/gas_mixture/env_air = loc.return_air() - if ((int_air.return_pressure()-env_air.return_pressure()) > PRESSURE_EXERTED) + if ((XGM_PRESSURE(int_air)-XGM_PRESSURE(env_air)) > PRESSURE_EXERTED) to_chat(user, SPAN_WARNING("You cannot unwrench \the [src], it is too exerted due to internal pressure.")) add_fingerprint(user) return TRUE diff --git a/code/modules/atmospherics/datum_pipeline.dm b/code/modules/atmospherics/datum_pipeline.dm index 8375d58f3d22..7c3532594e87 100644 --- a/code/modules/atmospherics/datum_pipeline.dm +++ b/code/modules/atmospherics/datum_pipeline.dm @@ -27,7 +27,7 @@ /datum/pipeline/process()//This use to be called called from the pipe networks //Check to see if pressure is within acceptable limits - var/pressure = air.return_pressure() + var/pressure = XGM_PRESSURE(air) if(pressure > alert_pressure) for(var/obj/machinery/atmospherics/pipe/member in members) if(!member.check_pressure(pressure)) @@ -115,24 +115,28 @@ return network /datum/pipeline/proc/mingle_with_turf(turf/simulated/target, mingle_volume) + if(!isturf(target)) + return + var/datum/gas_mixture/air_sample = air.remove_ratio(mingle_volume/air.volume) air_sample.volume = mingle_volume - if(istype(target) && target.zone) + if(target.zone) //Have to consider preservation of group statuses var/datum/gas_mixture/turf_copy = new + var/datum/gas_mixture/turf_original = new turf_copy.copy_from(target.zone.air) turf_copy.volume = target.zone.air.volume //Copy a good representation of the turf from parent group + turf_original.copy_from(turf_copy) equalize_gases(list(air_sample, turf_copy)) air.merge(air_sample) - turf_copy.subtract(target.zone.air) - + target.zone.air.remove(turf_original.total_moles) target.zone.air.merge(turf_copy) - else if(target) + else var/datum/gas_mixture/turf_air = target.return_air() equalize_gases(list(air_sample, turf_air)) diff --git a/code/modules/atmospherics/pipes.dm b/code/modules/atmospherics/pipes.dm index 95138391f06e..574b4938f1ed 100644 --- a/code/modules/atmospherics/pipes.dm +++ b/code/modules/atmospherics/pipes.dm @@ -95,7 +95,7 @@ if (istype(src, /obj/machinery/atmospherics/pipe/tank)) return ..() - if(istype(attacking_item,/obj/item/pipe_painter)) + if(istype(attacking_item,/obj/item/paint_sprayer)) return FALSE if(istype(attacking_item, /obj/item/analyzer) && Adjacent(user)) @@ -112,7 +112,7 @@ var/datum/gas_mixture/int_air = return_air() if(!loc) return FALSE var/datum/gas_mixture/env_air = loc.return_air() - if ((int_air.return_pressure()-env_air.return_pressure()) > PRESSURE_EXERTED) + if ((XGM_PRESSURE(int_air)-XGM_PRESSURE(env_air)) > PRESSURE_EXERTED) if(!istype(attacking_item, /obj/item/pipewrench)) to_chat(user, SPAN_WARNING("You cannot unwrench \the [src], it is too exerted due to internal pressure.")) add_fingerprint(user) @@ -236,7 +236,7 @@ if(!loc) return var/datum/gas_mixture/environment = loc.return_air() - var/pressure_difference = pressure - environment.return_pressure() + var/pressure_difference = pressure - XGM_PRESSURE(environment) if(pressure_difference > maximum_pressure) burst() @@ -1303,7 +1303,7 @@ return null /obj/machinery/atmospherics/pipe/tank/attackby(obj/item/attacking_item, mob/user) - if(istype(attacking_item, /obj/item/pipe_painter)) + if(istype(attacking_item, /obj/item/paint_sprayer)) return FALSE if(istype(attacking_item, /obj/item/analyzer) && in_range(user, src)) diff --git a/code/modules/atmospherics/vent_passive.dm b/code/modules/atmospherics/vent_passive.dm new file mode 100644 index 000000000000..f3c57e54b873 --- /dev/null +++ b/code/modules/atmospherics/vent_passive.dm @@ -0,0 +1,178 @@ +/obj/machinery/atmospherics/pipe/vent_passive + name = "passive vent" + desc = "" + icon = 'icons/atmos/vent_passive.dmi' + icon_state = "map_vent" + + connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER|CONNECT_TYPE_AUX|CONNECT_TYPE_FUEL //connects to all pipes except HE + + level = 1 + + volume = 250 + + dir = SOUTH + initialize_directions = SOUTH + + var/obj/machinery/atmospherics/node + var/welded = FALSE + +/obj/machinery/atmospherics/pipe/vent_passive/Initialize() + initialize_directions = dir + . = ..() + +/obj/machinery/atmospherics/pipe/vent_passive/hide(var/i) + if(istype(loc, /turf/simulated)) + set_invisibility(i ? 101 : 0) + queue_icon_update() + +/obj/machinery/atmospherics/pipe/vent_passive/mechanics_hints(mob/user, distance, is_adjacent) + . = ..() + . += "This passively outputs the contents of the attached pipe out into the atmosphere." + +/obj/machinery/atmospherics/pipe/vent_passive/feedback_hints(mob/user, distance, is_adjacent) + . = list() + if(welded) + . += "It seems welded shut." + +/obj/machinery/atmospherics/pipe/vent_passive/update_icon(safety = 0) + + var/vent_icon = "" + + if(welded) + vent_icon += "weld" + else + vent_icon += "vent" + + icon_state = vent_icon + + update_underlays() + +/obj/machinery/atmospherics/pipe/vent_passive/update_underlays() + if(..()) + underlays.Cut() + var/turf/T = get_turf(src) + if(!istype(T)) + return + if(!T.is_plating() && node && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe)) + return + else + if(node) + add_underlay(T, node, dir, node.icon_connect_type) + else + add_underlay(T,, dir) + underlays += "frame" + +/obj/machinery/atmospherics/pipe/vent_passive/process(seconds_per_tick) + if(!parent) + ..() + else + parent.mingle_with_turf(loc, volume) + +/obj/machinery/atmospherics/pipe/vent_passive/Destroy() + if(node) + node.disconnect(src) + + node = null + + return ..() + +/obj/machinery/atmospherics/pipe/vent_passive/pipeline_expansion() + return list(node) + +/obj/machinery/atmospherics/pipe/vent_passive/atmos_init() + for(var/obj/machinery/atmospherics/target in get_step(src, dir)) + if(target.initialize_directions & get_dir(target,src)) + if (check_connect_types(target,src)) + node = target + break + + atmos_initialised = TRUE + SSicon_update.add_to_queue(src) + +/obj/machinery/atmospherics/pipe/vent_passive/disconnect(obj/machinery/atmospherics/reference) + if(reference == node) + if(istype(node, /obj/machinery/atmospherics/pipe)) + qdel(parent) + node = null + + update_icon() + + return null + +/obj/machinery/atmospherics/pipe/vent_passive/attackby(obj/item/attacking_item, mob/user) + + if(attacking_item.tool_behaviour == TOOL_WELDER) + var/obj/item/weldingtool/WT = attacking_item + if (!WT.welding) + to_chat(user, SPAN_DANGER("\The [WT] must be turned on!")) + else if (WT.use(0,user)) + to_chat(user, SPAN_NOTICE("Now welding the vent.")) + if(attacking_item.use_tool(src, user, 30, volume = 50)) + if(!src || !WT.isOn()) + return TRUE + welded = !welded + update_icon() + playsound(src, 'sound/items/welder_pry.ogg', 50, 1) + user.visible_message(SPAN_NOTICE("\The [user] [welded ? "welds \the [src] shut" : "unwelds \the [src]"]."), \ + SPAN_NOTICE("You [welded ? "weld \the [src] shut" : "unweld \the [src]"]."), \ + "You hear welding.") + else + to_chat(user, SPAN_NOTICE("You fail to complete the welding.")) + else + to_chat(user, SPAN_WARNING("You need more welding fuel to complete this task.")) + return TRUE + + + else if(istype(attacking_item, /obj/item/melee/arm_blade)) + if(!welded) + to_chat(user, SPAN_WARNING("\The [attacking_item] can only be used to tear open welded air vents!")) + return TRUE + user.visible_message(SPAN_WARNING("\The [user] starts using \the [attacking_item] to hack open \the [src]!"), SPAN_NOTICE("You start hacking open \the [src] with \the [attacking_item]...")) + user.do_attack_animation(src, attacking_item) + playsound(loc, 'sound/weapons/smash.ogg', 60, TRUE) + var/cut_amount = 3 + for(var/i = 0; i <= cut_amount; i++) + if(!attacking_item || !do_after(user, 30, src)) + return TRUE + user.do_attack_animation(src, attacking_item) + user.visible_message(SPAN_WARNING("\The [user] smashes \the [attacking_item] into \the [src]!"), SPAN_NOTICE("You smash \the [attacking_item] into \the [src].")) + playsound(loc, 'sound/weapons/smash.ogg', 60, TRUE) + if(i == cut_amount) + welded = FALSE + spark(get_turf(src), 3, GLOB.alldirs) + playsound(loc, 'sound/items/welder_pry.ogg', 50, TRUE) + update_icon() + + else if(attacking_item.tool_behaviour == TOOL_WRENCH) + var/turf/T = src.loc + + if(level==1 && isturf(T) && !T.is_plating()) + to_chat(user, SPAN_WARNING("You must remove the plating first.")) + + else if(loc) + var/datum/gas_mixture/int_air = return_air() + var/datum/gas_mixture/env_air = loc.return_air() + + if((XGM_PRESSURE(int_air)-XGM_PRESSURE(env_air)) > PRESSURE_EXERTED) + to_chat(user, SPAN_WARNING("You cannot unwrench \the [src], it is too exerted due to internal pressure.")) + add_fingerprint(user) + + else + to_chat(user, SPAN_NOTICE("You begin to unfasten \the [src]...")) + + if(attacking_item.use_tool(src, user, istype(attacking_item, /obj/item/pipewrench) ? 80 : 40, volume = 50)) + user.visible_message(SPAN_NOTICE("\The [user] unfastens \the [src]."), \ + SPAN_NOTICE("You have unfastened \the [src]."), \ + "You hear a ratchet.") + new /obj/item/pipe(loc, make_from=src) + qdel(src) + + else if(istype(attacking_item, /obj/item/analyzer) && in_range(user, src)) + var/obj/item/analyzer/A = attacking_item + A.analyze_gases(src, user) + return TRUE + + return ..() + +/obj/machinery/atmospherics/pipe/vent_passive/is_welded() + return welded diff --git a/code/modules/background/citizenship/human.dm b/code/modules/background/citizenship/human.dm index 12f297f719cd..91eb08f06f64 100644 --- a/code/modules/background/citizenship/human.dm +++ b/code/modules/background/citizenship/human.dm @@ -6,6 +6,7 @@ unrest and gridlock undermine the government, and the aggressive attitude of the Sol Alliance against its former system has made many worried for the future of the Republic." consular_outfit = /obj/outfit/job/representative/consular/ceti assistant_outfit = /obj/outfit/job/diplomatic_aide/ceti + bodyguard_outfit = /obj/outfit/job/diplomatic_bodyguard/ceti job_species_blacklist = list( "Consular Officer" = list( @@ -73,6 +74,8 @@ /obj/outfit/job/diplomatic_bodyguard/ceti name = "Tau Ceti Diplomatic Bodyguard" + uniform = /obj/item/clothing/under/rank/bssb + suit = /obj/item/clothing/suit/storage/toggle/bssb backpack_contents = list( /obj/item/gun/energy/blaster/revolver ) @@ -206,6 +209,9 @@ /obj/outfit/job/diplomatic_bodyguard/sol name = "Sol Diplomatic Bodyguard" + uniform = /obj/item/clothing/under/rank/sol/army/service + shoes = /obj/item/clothing/shoes/jackboots + head = /obj/item/clothing/head/sol/army/service/garrison backpack_contents = list( /obj/item/gun/projectile/pistol/sol = 1 ) @@ -292,6 +298,8 @@ /obj/outfit/job/diplomatic_bodyguard/elyra name = "Elyra Diplomatic Bodyguard" + uniform = /obj/item/clothing/under/rank/elyran_fatigues + shoes = /obj/item/clothing/shoes/jackboots backpack_contents = list( /obj/item/gun/projectile/plasma/bolter/pistol = 1 ) diff --git a/code/modules/background/citizenship/ipc.dm b/code/modules/background/citizenship/ipc.dm index 311cd495181b..9171fd043fc6 100644 --- a/code/modules/background/citizenship/ipc.dm +++ b/code/modules/background/citizenship/ipc.dm @@ -57,6 +57,9 @@ /obj/outfit/job/diplomatic_bodyguard/golden name = "Golden Deep Diplomatic Bodyguard" + uniform = /obj/item/clothing/under/goldendeep/hoplan + head = /obj/item/clothing/head/goldendeep/hoplan + shoes = /obj/item/clothing/shoes/jackboots backpack_contents = list( /obj/item/gun/energy/pistol/goldendeep = 1 ) diff --git a/code/modules/background/citizenship/skrell.dm b/code/modules/background/citizenship/skrell.dm index 5e7d9da9c935..d6991dd7dff4 100644 --- a/code/modules/background/citizenship/skrell.dm +++ b/code/modules/background/citizenship/skrell.dm @@ -111,7 +111,7 @@ uniform = /obj/item/clothing/under/skrell backpack_contents = list( /obj/item/camera = 1, - /obj/item/storage/box/psireceiver = 1 + /obj/item/storage/box/unique/freezer/organcooler/psireceiver = 1 ) /obj/outfit/job/representative/consular/nralakk/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) @@ -133,7 +133,9 @@ /obj/outfit/job/diplomatic_bodyguard/nralakk name = "Nralakk Federation Diplomatic Bodyguard" - uniform = /obj/item/clothing/under/skrell + uniform = /obj/item/clothing/under/skrell/qukala + shoes = /obj/item/clothing/shoes/jackboots/kala + gloves = /obj/item/clothing/gloves/kala /obj/outfit/job/diplomatic_bodyguard/nralakk/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) if(H) diff --git a/code/modules/background/citizenship/tajara.dm b/code/modules/background/citizenship/tajara.dm index 5749baff6f97..34d9e7588c46 100644 --- a/code/modules/background/citizenship/tajara.dm +++ b/code/modules/background/citizenship/tajara.dm @@ -31,8 +31,7 @@ SPECIES_VAURCA_ATTENDANT, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER, - SPECIES_TAJARA_ZHAN, - SPECIES_TAJARA_MSAI + SPECIES_TAJARA_ZHAN ), "Diplomatic Aide" = list( SPECIES_HUMAN, @@ -54,8 +53,7 @@ SPECIES_VAURCA_WARRIOR, SPECIES_VAURCA_ATTENDANT, SPECIES_VAURCA_BULWARK, - SPECIES_VAURCA_BREEDER, - SPECIES_TAJARA_ZHAN + SPECIES_VAURCA_BREEDER ), "Diplomatic Bodyguard" = list( SPECIES_HUMAN, @@ -77,8 +75,7 @@ SPECIES_VAURCA_WARRIOR, SPECIES_VAURCA_ATTENDANT, SPECIES_VAURCA_BULWARK, - SPECIES_VAURCA_BREEDER, - SPECIES_TAJARA_ZHAN + SPECIES_VAURCA_BREEDER ) ) @@ -159,8 +156,7 @@ SPECIES_VAURCA_ATTENDANT, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER, - SPECIES_TAJARA_ZHAN, - SPECIES_TAJARA_MSAI + SPECIES_TAJARA_ZHAN ), "Diplomatic Aide" = list( SPECIES_HUMAN, @@ -182,8 +178,7 @@ SPECIES_VAURCA_WARRIOR, SPECIES_VAURCA_ATTENDANT, SPECIES_VAURCA_BULWARK, - SPECIES_VAURCA_BREEDER, - SPECIES_TAJARA_ZHAN + SPECIES_VAURCA_BREEDER ), "Diplomatic Bodyguard" = list( SPECIES_HUMAN, @@ -205,8 +200,7 @@ SPECIES_VAURCA_WARRIOR, SPECIES_VAURCA_ATTENDANT, SPECIES_VAURCA_BULWARK, - SPECIES_VAURCA_BREEDER, - SPECIES_TAJARA_ZHAN + SPECIES_VAURCA_BREEDER ) ) @@ -285,8 +279,7 @@ SPECIES_VAURCA_ATTENDANT, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER, - SPECIES_TAJARA_ZHAN, - SPECIES_TAJARA_MSAI + SPECIES_TAJARA_ZHAN ), "Diplomatic Aide" = list( SPECIES_HUMAN, @@ -309,6 +302,7 @@ SPECIES_VAURCA_ATTENDANT, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER, + SPECIES_TAJARA_MSAI, SPECIES_TAJARA_ZHAN ), "Diplomatic Bodyguard" = list( diff --git a/code/modules/background/education/medical.dm b/code/modules/background/education/medical.dm index 58db4c6991d3..35b7f1ec4aaa 100644 --- a/code/modules/background/education/medical.dm +++ b/code/modules/background/education/medical.dm @@ -41,23 +41,48 @@ SPECIES_SKRELL_AXIORI = 60 ) skills = list( + /singleton/skill/pharmacology = SKILL_LEVEL_PROFESSIONAL, /singleton/skill/medicine = SKILL_LEVEL_TRAINED, /singleton/skill/anatomy = SKILL_LEVEL_TRAINED ) /singleton/education/psychologist_degree - name = "Psychology PhD" - description = "You are at least 30 years of age, with a PhD from an accredited university in an applicable field." + name = "Doctor of Psychology" + description = "You are at least 30 years of age, with at least a doctorate from an accredited university in an applicable field. " \ + + "This is more of a research degree that has medical applications, as opposed to a true medical degree. " \ + + "As such, it is only tangentially involved with actual medicine. A character with only this education is not legally considered a licensed doctor." \ + + "You are however qualified to perform psychological evaluations on behalf of the SCC, as well as perform psychotherapy." jobs = list("Psychologist") minimum_character_age = list( - SPECIES_HUMAN = 25, + SPECIES_HUMAN = 30, SPECIES_SKRELL = 60, SPECIES_SKRELL_AXIORI = 60 ) skills = list( - /singleton/skill/pharmacology = SKILL_LEVEL_PROFESSIONAL, + /* Uncomment this block after finishing the Leadership skill. Psychologists should be able to give people morale bonuses as a mechanic. + /singleton/skill/leadership = SKILL_LEVEL_TRAINED, + */ + /singleton/skill/pharmacology = SKILL_LEVEL_FAMILIAR, + /singleton/skill/medicine = SKILL_LEVEL_FAMILIAR, + /singleton/skill/anatomy = SKILL_LEVEL_FAMILIAR, + /singleton/skill/research = SKILL_LEVEL_TRAINED + ) + +/singleton/education/psychiatrist_degree + name = "MD, Psychiatry Track" + description = "You are at least 30 years of age, with an applicable MD from an accredited school and you have completed 2 years of residency at an \ + accredited hospital or clinic. Unlike Psychology, this is an actual medical degree, and a character with this education is considered a licensed doctor." + jobs = list("Psychiatrist") + minimum_character_age = list( + SPECIES_HUMAN = 30, + SPECIES_SKRELL = 60, + SPECIES_SKRELL_AXIORI = 60 + ) + skills = list( + /singleton/skill/surgery = SKILL_LEVEL_FAMILIAR, /singleton/skill/medicine = SKILL_LEVEL_TRAINED, - /singleton/skill/anatomy = SKILL_LEVEL_TRAINED + /singleton/skill/anatomy = SKILL_LEVEL_TRAINED, + /singleton/skill/pharmacology = SKILL_LEVEL_TRAINED ) /singleton/education/paramedic @@ -70,6 +95,8 @@ SPECIES_SKRELL_AXIORI = 55 ) skills = list( + /* Can perform only the most basic surgeries up to arterial bleeds. */ + /singleton/skill/surgery = SKILL_LEVEL_FAMILIAR, /singleton/skill/medicine = SKILL_LEVEL_TRAINED, /singleton/skill/anatomy = SKILL_LEVEL_TRAINED ) diff --git a/code/modules/background/education/science.dm b/code/modules/background/education/science.dm index 218ff30e23e3..9651e150280b 100644 --- a/code/modules/background/education/science.dm +++ b/code/modules/background/education/science.dm @@ -26,7 +26,6 @@ skills = list( /singleton/skill/research = SKILL_LEVEL_FAMILIAR, /singleton/skill/robotics = SKILL_LEVEL_PROFESSIONAL, - /singleton/skill/surgery = SKILL_LEVEL_FAMILIAR, /singleton/skill/electrical_engineering = SKILL_LEVEL_FAMILIAR, /singleton/skill/mechanical_engineering = SKILL_LEVEL_FAMILIAR, ) @@ -44,7 +43,6 @@ skills = list( /singleton/skill/research = SKILL_LEVEL_FAMILIAR, /singleton/skill/robotics = SKILL_LEVEL_TRAINED, - /singleton/skill/surgery = SKILL_LEVEL_FAMILIAR, /singleton/skill/electrical_engineering = SKILL_LEVEL_FAMILIAR, /singleton/skill/mechanical_engineering = SKILL_LEVEL_PROFESSIONAL ) diff --git a/code/modules/background/education/security.dm b/code/modules/background/education/security.dm index ed51254aabab..8b89f4796dfd 100644 --- a/code/modules/background/education/security.dm +++ b/code/modules/background/education/security.dm @@ -1,6 +1,7 @@ /singleton/education/forensics_degree name = "Forensics Science Degree" - description = "You are 25 years of age or older, with a degree in Forensics Science. You specialize in the medical procedures required to understand why someone died." + description = "You are 25 years of age or older, with a degree in Forensics Science. You specialize in the medical procedures required to understand why someone died. " \ + + "While not necessarily a medical degree, there's not much difference in suturing a body whether or not its approaching room temperature." jobs = list("Investigator") minimum_character_age = list( SPECIES_HUMAN = 25, @@ -14,11 +15,76 @@ /singleton/skill/forensics = SKILL_LEVEL_PROFESSIONAL ) -/singleton/education/protagonist - name = "Protagonist Degree" - description = "you are the protagonist of aurora" +/singleton/education/military_basic + name = "Military Training" + description = "You have finished at least one full contract of military service. Alternatively, this could be equivalent experience from mercenary work." + minimum_character_age = list( + SPECIES_HUMAN = 25, + SPECIES_SKRELL = 60, + SPECIES_SKRELL_AXIORI = 60 + ) skills = list( /singleton/skill/unarmed_combat = SKILL_LEVEL_TRAINED, /singleton/skill/armed_combat = SKILL_LEVEL_TRAINED, /singleton/skill/firearms = SKILL_LEVEL_TRAINED ) + +/singleton/education/military_corpsman + name = "Corpsman Training" + description = "After completing basic military training, you received advanced individual training in battlefield medicine. " \ + + "Your combat skills are not as sharp as others, but you made up for it by knowing how to keep your comrades in arms from bleeding out on the battlefield. " \ + + "A character with this training is NOT legally considered a medical doctor. You're on the hook for manslaughter if you attempt and fail to save them yourself instead of taking them to a real doctor." + minimum_character_age = list( + SPECIES_HUMAN = 25, + SPECIES_SKRELL = 60, + SPECIES_SKRELL_AXIORI = 60 + ) + skills = list( + /* Significantly worse combat skills than other security educations, though not so bad they'll footgun themselves. + Alternatively, this is a plausible though less specialized alternative for paramedic training, as is common in real life. */ + /singleton/skill/armed_combat = SKILL_LEVEL_FAMILIAR, + /singleton/skill/firearms = SKILL_LEVEL_FAMILIAR, + /singleton/skill/surgery = SKILL_LEVEL_FAMILIAR, /* Only enough to repair an artery. */ + /singleton/skill/medicine = SKILL_LEVEL_FAMILIAR + ) + +/singleton/education/police_academy + name = "Police Academy Graduate" + description = "You are a police academy graduate. Your combat skills are not as stringent as actual military service, though this is made up for with more generalized training suitable for a first-responder." + minimum_character_age = list( + SPECIES_HUMAN = 25, + SPECIES_SKRELL = 60, + SPECIES_SKRELL_AXIORI = 60 + ) + skills = list( + /singleton/skill/unarmed_combat = SKILL_LEVEL_FAMILIAR, + /singleton/skill/firearms = SKILL_LEVEL_TRAINED, + /singleton/skill/forensics = SKILL_LEVEL_FAMILIAR, /* Very basic crime investigation skills. */ + /singleton/skill/medicine = SKILL_LEVEL_FAMILIAR /* Police are also trained in basic first aid. */ + ) + +/singleton/education/military_aviator + name = "Combat Aviator" + description = "You have formal training in piloting military spacecraft, along with a fast tracked form of basic training." + minimum_character_age = list( + SPECIES_HUMAN = 30, + SPECIES_SKRELL = 60, + SPECIES_SKRELL_AXIORI = 60 + ) + skills = list( + /singleton/skill/pilot_spacecraft = SKILL_LEVEL_TRAINED, + /singleton/skill/firearms = SKILL_LEVEL_TRAINED + ) + +/singleton/education/military_tanker + name = "Mech Tanker" + description = "You are a graduate of the spur's modern day equivalent to Tanker School, and can call yourself a Mech-warrior." + minimum_character_age = list( + SPECIES_HUMAN = 25, + SPECIES_SKRELL = 60, + SPECIES_SKRELL_AXIORI = 60 + ) + skills = list( + /singleton/skill/pilot_mechs = SKILL_LEVEL_TRAINED, + /singleton/skill/firearms = SKILL_LEVEL_TRAINED, /* Actually needed for firing mech guns oddly enough. */ + ) diff --git a/code/modules/background/education/service.dm b/code/modules/background/education/service.dm index 33c2327f559b..732fbf158df9 100644 --- a/code/modules/background/education/service.dm +++ b/code/modules/background/education/service.dm @@ -9,7 +9,7 @@ SPECIES_SKRELL_AXIORI = 50 ) skills = list( - /singleton/skill/mixing = SKILL_LEVEL_PROFESSIONAL, + /singleton/skill/bartending = SKILL_LEVEL_PROFESSIONAL, ) /singleton/education/cooking_degree diff --git a/code/modules/background/origins/_origins.dm b/code/modules/background/origins/_origins.dm index cc81cef7d164..ceb0319d87af 100644 --- a/code/modules/background/origins/_origins.dm +++ b/code/modules/background/origins/_origins.dm @@ -34,7 +34,7 @@ if(!istype(OI)) crash_with("Invalid culture supplied: [OI]!") culture = OI - if(old_culture && culture != old_culture) + if(old_culture) old_culture.on_remove(src) OI.on_apply(src) @@ -43,7 +43,7 @@ if(!istype(OI)) crash_with("Invalid origin supplied: [OI]!") origin = OI - if(old_origin && origin != old_origin) + if(old_origin) old_origin.on_remove(src) OI.on_apply(src) diff --git a/code/modules/background/origins/origins/tajara/offworld.dm b/code/modules/background/origins/origins/tajara/offworld.dm index 9cceaff7cc41..21317d647f14 100644 --- a/code/modules/background/origins/origins/tajara/offworld.dm +++ b/code/modules/background/origins/origins/tajara/offworld.dm @@ -27,10 +27,13 @@ /singleton/origin_item/origin/little_adhomai name = "Little Adhomai" - desc = "Little Adhomai is the largest off-world Tajaran community. Situated in Mendell City, District Six is the home of most Tajara living in the Republic of Tau Ceti. Because of its relatively short existence, discrimination, and other barriers present in Tau Ceti, the Tajara of Little Adhomai still clings to their native culture. Even the few individuals born here carry a great Adhomian influence, usually identifying themselves with their family's origins. Despite this influence, District Six is also home to its own cultural expressions." + desc = "Little Adhomai is the largest off-world Tajaran community. Situated in Mendell City, District Six is the home of most Tajara living in the Republic of Biesel. Because of its relatively short existence, discrimination, and other barriers present in Tau Ceti, the Tajara of Little Adhomai still clings to their native culture. Even the few individuals born here carry a great Adhomian influence, usually identifying themselves with their family's origins. Despite this influence, District Six is also home to its own cultural expressions." + important_information = "This origin is intended for tajara who were either born on Biesel or immigrated there at a young age. Tajara with Republic of Biesel citizenship must ICly hold citizenship of one of the Adhomian nations as well." possible_accents = list(ACCENT_REPUBICLANSIIK, ACCENT_NAZIRASIIK, ACCENT_CREVAN, ACCENT_DASNRRASIIK, ACCENT_HIGHHARRSIIK, ACCENT_LOWHARRSIIK, ACCENT_AMOHDASIIK, ACCENT_NORTHRASNRR, ACCENT_DINAKK) - possible_citizenships = CITIZENSHIPS_ADHOMAI + possible_citizenships = list(CITIZENSHIP_PRA, CITIZENSHIP_DPRA, CITIZENSHIP_NKA, CITIZENSHIP_BIESEL) possible_religions = RELIGIONS_ADHOMAI + origin_traits = list(TRAIT_ORIGIN_HOT_RESISTANCE) + origin_traits_descriptions = list("are more acclimatised to the heat.") /singleton/origin_item/origin/little_adhomai/zhan possible_accents = list(ACCENT_REPUBICLANSIIK, ACCENT_NAZIRASIIK, ACCENT_CREVAN, ACCENT_DASNRRASIIK, ACCENT_HIGHHARRSIIK, ACCENT_LOWHARRSIIK, ACCENT_AMOHDASIIK, ACCENT_NORTHRASNRR, ACCENT_DINAKK, ACCENT_HARRNRRI, ACCENT_RURALDELVAHHI) diff --git a/code/modules/cargo/bounties/chef.dm b/code/modules/cargo/bounties/chef.dm index f1e16ec7adf1..bfa269734b11 100644 --- a/code/modules/cargo/bounties/chef.dm +++ b/code/modules/cargo/bounties/chef.dm @@ -271,6 +271,8 @@ wanted_types = list(/obj/item/reagent_containers/food/snacks/adhomian_porridge, /obj/item/reagent_containers/food/snacks/adhomian_sausage, /obj/item/reagent_containers/food/snacks/avah, + /obj/item/reagent_containers/food/snacks/sliceable/cheesebake, + /obj/item/reagent_containers/food/snacks/cheese_twig, /obj/item/reagent_containers/food/snacks/chipplate/crownfurter, /obj/item/reagent_containers/food/snacks/chipplate/miniavah_basket, /obj/item/reagent_containers/food/snacks/chocolate_rikazu, @@ -402,3 +404,17 @@ /obj/item/reagent_containers/food/snacks/sliceable/ylpharoulade, /obj/item/reagent_containers/food/snacks/sliceable/koisroulade ) + +/datum/bounty/item/chef/colorful_desserts + name = "Colorful desserts" + description = "'Bring your offspring to work' day is upon us and we want to grab the attention of future employees! Let's make sure the office is stocked with the most trendy, gaudy, eye-catching, disgustingly sugary desserts so the little brats show it to all of their friends! Blitz shakes, Elatas, chocolate pizzas, cake pops, whatever!" + reward_low = 90 + reward_high = 150 + required_count = 4 + random_count = 1 + wanted_types = list( + /obj/item/reagent_containers/food/snacks/elata, + /obj/item/reagent_containers/food/snacks/blitz_shake, + /obj/item/reagent_containers/food/snacks/sliceable/pizza/chocolate_pizza, + /obj/item/storage/box/fancy/food/cakepopjar + ) diff --git a/code/modules/cargo/bounties/engineer.dm b/code/modules/cargo/bounties/engineer.dm index 6d2f9653fcc8..a23281735f74 100644 --- a/code/modules/cargo/bounties/engineer.dm +++ b/code/modules/cargo/bounties/engineer.dm @@ -25,7 +25,7 @@ /datum/bounty/item/engineer/solar name = "Solar Assemblies or Trackers" - description = "A meteor shower ruined some backup solar arrays on the %DOCKNAME; ship us some assemblies or tracker electronics so we can expedite repairs." + description = "Owing to the ongoing phoron scarcity, additional hardware has been requested by several facilities within our region of influence for the expansion of their solar arrays." reward_low = 650 reward_high = 870 required_count = 6 @@ -116,7 +116,7 @@ return FALSE if(!istype(O)) return FALSE - if(O.air_contents.return_pressure() >= 500) + if(XGM_PRESSURE(O.air_contents) >= 500) return TRUE return FALSE diff --git a/code/modules/cargo/bounties/special.dm b/code/modules/cargo/bounties/special.dm index cd93c05f49bb..9ee872250389 100644 --- a/code/modules/cargo/bounties/special.dm +++ b/code/modules/cargo/bounties/special.dm @@ -41,13 +41,3 @@ if(!applies_to(O)) return shipped_count += O.amount - -/datum/bounty/item/solar_array - name = "Assembled Solar Panels" - description = "Owing to the phoron shortage continuing for over a year, longer than projected, we have decided to use solar arrays to power various facilities across our region of influence." - reward_low = 280 - reward_high = 400 - required_count = 6 - random_count = 2 // 4 to 8 - wanted_types = list(/obj/machinery/power/solar) - high_priority = TRUE diff --git a/code/modules/cargo/bounty.dm b/code/modules/cargo/bounty.dm index a6902bd1b9f4..5917a72c83b0 100644 --- a/code/modules/cargo/bounty.dm +++ b/code/modules/cargo/bounty.dm @@ -31,7 +31,7 @@ // Displayed on bounty UI screen. /datum/bounty/proc/reward_string() - return "[reward] Credits" + return "[reward]电" /datum/bounty/proc/can_claim() return !claimed @@ -209,7 +209,7 @@ if(prob(60)) //phoron bounties - var/datum/bounty/item/phoron_bounty = pick(/datum/bounty/item/phoron_sheet, /datum/bounty/item/solar_array) + var/datum/bounty/item/phoron_bounty = pick(/datum/bounty/item/phoron_sheet, /datum/bounty/item/engineer/solar) try_add_bounty(new phoron_bounty) else var/datum/bounty/B = pick(bounties_list) diff --git a/code/modules/cargo/export_scanner.dm b/code/modules/cargo/export_scanner.dm index 751253eac0f0..b7420a7a565c 100644 --- a/code/modules/cargo/export_scanner.dm +++ b/code/modules/cargo/export_scanner.dm @@ -1,8 +1,10 @@ /obj/item/export_scanner name = "export scanner" desc = "A device used to check objects against NanoTrasen exports and bounty database." - icon = 'icons/obj/item/export_scanner.dmi' + icon = 'icons/obj/item/scanner.dmi' icon_state = "export_scanner" + item_state = "export_scanner" + contained_sprite = TRUE slot_flags = SLOT_BELT item_flags = ITEM_FLAG_NO_BLUDGEON w_class = WEIGHT_CLASS_SMALL @@ -15,7 +17,7 @@ var/price = SScargo.export_item_and_contents(O, FALSE, FALSE, dry_run=TRUE) if(price) - to_chat(user, SPAN_NOTICE("Scanned [O], value: [price] credits[O.contents.len ? " (contents included)" : ""].")) + to_chat(user, SPAN_NOTICE("Scanned [O], value: [price]电[O.contents.len ? " (contents included)" : ""].")) else to_chat(user, SPAN_WARNING("Scanned [O], no export value.")) if(SScargo.bounty_ship_item_and_contents(O, dry_run=TRUE)) diff --git a/code/modules/cargo/exports.dm b/code/modules/cargo/exports.dm index 26893c0fb5a8..00cee153ac8a 100644 --- a/code/modules/cargo/exports.dm +++ b/code/modules/cargo/exports.dm @@ -132,7 +132,7 @@ then the player gets the profit from selling his own wasted time. /datum/export/proc/total_printout(contr = 0, emag = 0) if(!total_cost && !total_amount) return "" - var/msg = "[total_cost] credits: Received [total_amount] " + var/msg = "[total_cost]电: Received [total_amount]电 " if(total_cost > 0) msg = "+" + msg diff --git a/code/modules/cargo/items/atmos.dm b/code/modules/cargo/items/atmos.dm index 4598d62480ce..0e26be3bc2f9 100644 --- a/code/modules/cargo/items/atmos.dm +++ b/code/modules/cargo/items/atmos.dm @@ -208,14 +208,14 @@ groupable = FALSE spawn_amount = 1 -/singleton/cargo_item/pipepainter +/singleton/cargo_item/paint_sprayer category = "atmos" - name = "pipe painter" + name = "paint sprayer" supplier = "hephaestus" description = "Its said that green pipes are safe to travel through." price = 25 items = list( - /obj/item/pipe_painter + /obj/item/paint_sprayer ) access = ACCESS_ENGINE container_type = "crate" diff --git a/code/modules/cargo/items/hospitality.dm b/code/modules/cargo/items/hospitality.dm index 8e4373cc4aa1..883e4fcf3922 100644 --- a/code/modules/cargo/items/hospitality.dm +++ b/code/modules/cargo/items/hospitality.dm @@ -1519,7 +1519,7 @@ /singleton/cargo_item/assunzione_wine category = "hospitality" - name = "\improper Assunzioni Sera Stellata di Dalyan Wine" + name = "Assunzioni Sera Stellata di Dalyan Wine" supplier = "getmore" description = "A bottle of velvety smooth red wine from the underground vineyards of Dalyan, Assunzione." price = 50 diff --git a/code/modules/cargo/items/medical.dm b/code/modules/cargo/items/medical.dm index 57ff3ed4956d..4fea8507f1eb 100644 --- a/code/modules/cargo/items/medical.dm +++ b/code/modules/cargo/items/medical.dm @@ -240,12 +240,40 @@ groupable = TRUE spawn_amount = 1 +/singleton/cargo_item/tricordrazine + category = "medical" + name = "tricordrazine bottle" + supplier = "nanotrasen" + description = "A bottle of tricordrazine, a medicine used to treat various wounds." + price = 175 + items = list( + /obj/item/reagent_containers/glass/bottle/tricordrazine + ) + access = 0 + container_type = "crate" + groupable = TRUE + spawn_amount = 1 + +/singleton/cargo_item/bicaridine_bottle + category = "medical" + name = "bicaridine bottle" + supplier = "nanotrasen" + description = "A bottle of bicaridine, a medicine used to treat trauma." + price = 250 + items = list( + /obj/item/reagent_containers/glass/bottle/bicaridine + ) + access = ACCESS_MEDICAL + container_type = "crate" + groupable = TRUE + spawn_amount = 1 + /singleton/cargo_item/butazoline_bottle category = "medical" name = "butazoline bottle" - supplier = "nanotrasen" + supplier = "zeng_hu" description = "A bottle of butazoline, a medicine used to treat severe trauma." - price = 250 + price = 525 items = list( /obj/item/reagent_containers/glass/bottle/butazoline ) @@ -258,7 +286,7 @@ category = "medical" name = "kelotane bottle" supplier = "nanotrasen" - description = "A bottle of kelotane, a medicine used to treat severe burns." + description = "A bottle of kelotane, a medicine used to treat burns." price = 250 items = list( /obj/item/reagent_containers/glass/bottle/kelotane @@ -268,6 +296,20 @@ groupable = TRUE spawn_amount = 1 +/singleton/cargo_item/dermaline_bottle + category = "medical" + name = "dermaline bottle" + supplier = "zeng_hu" + description = "A bottle of dermaline, a medicine used to treat severe burns." + price = 525 + items = list( + /obj/item/reagent_containers/glass/bottle/dermaline + ) + access = ACCESS_MEDICAL + container_type = "crate" + groupable = TRUE + spawn_amount = 1 + /singleton/cargo_item/dylovene_bottle category = "medical" name = "dylovene bottle" diff --git a/code/modules/cargo/items/supply.dm b/code/modules/cargo/items/supply.dm index a07b271bafa1..0ee37193cf00 100644 --- a/code/modules/cargo/items/supply.dm +++ b/code/modules/cargo/items/supply.dm @@ -180,6 +180,20 @@ groupable = TRUE spawn_amount = 1 +/singleton/cargo_item/stickypad + category = "supply" + name = "stickynote pad" + supplier = "nanotrasen" + description = "A wad of stickynotes." + price = 10 + items = list( + /obj/item/paper/stickynotes/pad + ) + access = 0 + container_type = "crate" + groupable = TRUE + spawn_amount = 1 + /singleton/cargo_item/pen category = "supply" name = "pen" diff --git a/code/modules/cargo/items/weaponry.dm b/code/modules/cargo/items/weaponry.dm index 106a72f2c8b4..5d759f30507e 100644 --- a/code/modules/cargo/items/weaponry.dm +++ b/code/modules/cargo/items/weaponry.dm @@ -208,6 +208,20 @@ groupable = TRUE spawn_amount = 1 +/singleton/cargo_item/prarifle + category = "weaponry" + name = "Tsarrayut'yan automatic rifle" + supplier = "zharkov" + description = "An Adhomian assault rifle from the People's Republic of Adhomai." + price = 1450 + items = list( + /obj/item/gun/projectile/automatic/rifle/adhomian + ) + access = ACCESS_ARMORY + container_type = "crate" + groupable = TRUE + spawn_amount = 1 + /singleton/cargo_item/derringer category = "weaponry" name = "derringer" @@ -406,6 +420,48 @@ groupable = TRUE spawn_amount = 1 +/singleton/cargo_item/clip_68 + category = "weaponry" + name = "rifle clip (6.8mm)" + supplier = "zharkov" + description = "A clip of 6.8mm for Adhomian rifles." + price = 30 + items = list( + /obj/item/ammo_magazine/boltaction/adhomai + ) + access = ACCESS_SECURITY + container_type = "crate" + groupable = TRUE + spawn_amount = 1 + +/singleton/cargo_item/magazine_68 + category = "weaponry" + name = "rifle magazine (6.8mm)" + supplier = "zharkov" + description = "A 6.8mm rifle magazine." + price = 65 + items = list( + /obj/item/ammo_magazine/a68 + ) + access = ACCESS_SECURITY + container_type = "crate" + groupable = TRUE + spawn_amount = 1 + +/singleton/cargo_item/magazine_68ap + category = "weaponry" + name = "sniper rifle magazine (6.8mm AP)" + supplier = "zharkov" + description = "An AP 6.8mm rifle magazine." + price = 70 + items = list( + /obj/item/ammo_magazine/a68/hotaki + ) + access = ACCESS_SECURITY + container_type = "crate" + groupable = TRUE + spawn_amount = 1 + /singleton/cargo_item/magazine_9 category = "weaponry" name = "pistol magazine (9mm)" @@ -511,7 +567,7 @@ description = "A box of 40mm AP ammo for the francisca rotary cannon." price = 850 items = list( - /obj/item/ship_ammunition/grauwolf_bundle/ap + /obj/item/ship_ammunition/francisca/ap ) access = ACCESS_CARGO container_type = "crate" @@ -525,7 +581,21 @@ description = "A box of 40mm FMJ ammo for a Francisca-type rotary cannon." price = 800 items = list( - /obj/item/ship_ammunition/grauwolf_bundle + /obj/item/ship_ammunition/francisca + ) + access = ACCESS_CARGO + container_type = "crate" + groupable = TRUE + spawn_amount = 1 + +/singleton/cargo_item/franciscafmjammo + category = "weaponry" + name = "francisca rotary cannon fragmentation ammunition box" + supplier = "zavodskoi" + description = "A box of 40mm fragmentation ammo for a Francisca-type rotary cannon." + price = 800 + items = list( + /obj/item/ship_ammunition/francisca/frag ) access = ACCESS_CARGO container_type = "crate" diff --git a/code/modules/cargo/random_stock/t1_common.dm b/code/modules/cargo/random_stock/t1_common.dm index 4fc2f7acfe23..91cc2b4810f3 100644 --- a/code/modules/cargo/random_stock/t1_common.dm +++ b/code/modules/cargo/random_stock/t1_common.dm @@ -210,7 +210,6 @@ STOCK_ITEM_COMMON(gloves, 3.3) var/list/exclusion = list( /obj/item/clothing/gloves, - /obj/item/clothing/gloves/fluff, /obj/item/clothing/gloves/swat/bst, /obj/item/clothing/gloves/powerfist, /obj/item/clothing/gloves/claws, @@ -219,7 +218,6 @@ STOCK_ITEM_COMMON(gloves, 3.3) exclusion += typesof(/obj/item/clothing/gloves/rig) exclusion += typesof(/obj/item/clothing/gloves/lightrig) exclusion += typesof(/obj/item/clothing/wrists/watch) - exclusion += typesof(/obj/item/clothing/gloves/fluff) exclusion += typesof(/obj/item/clothing/gloves/ballistic) exclusion += typesof(/obj/item/clothing/gloves/unathi/ancient) allgloves -= exclusion diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 12334fafcafa..4158a27a9740 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -406,7 +406,7 @@ GLOBAL_LIST_INIT(localhost_addresses, list( send_resources() if(!winexists(src, "asset_cache_browser")) // The client is using a custom skin, tell them. - to_chat(src, SPAN_WARNING("Unable to access asset cache browser, if you are using a custom skin file, please allow DS to download the updated version, if you are not, then make a bug report. This is not a critical issue but can cause issues with resource downloading, as it is impossible to know when extra resources arrived to you.")) + to_chat_immediate(src, SPAN_WARNING("Unable to access asset cache browser, if you are using a custom skin file, please allow DS to download the updated version, if you are not, then make a bug report. This is not a critical issue but can cause issues with resource downloading, as it is impossible to know when extra resources arrived to you.")) Master.UpdateTickRate() fully_created = TRUE diff --git a/code/modules/client/preference_setup/loadout/items/augments.dm b/code/modules/client/preference_setup/loadout/items/augments.dm index cc8c4c9d0b31..ed0f10833b62 100644 --- a/code/modules/client/preference_setup/loadout/items/augments.dm +++ b/code/modules/client/preference_setup/loadout/items/augments.dm @@ -353,29 +353,26 @@ description = "A fluff based bioaug that can be renamed/redescribed to appear as something else for RP purposes." path = /obj/item/organ/internal/augment/bioaug/head_fluff flags = GEAR_HAS_NAME_SELECTION | GEAR_HAS_DESC_SELECTION - origin_restriction = list(/singleton/origin_item/origin/galatea) - whitelisted = list(SPECIES_HUMAN, SPECIES_HUMAN_OFFWORLD) + whitelisted = list(SPECIES_HUMAN, SPECIES_HUMAN_OFFWORLD, SPECIES_SKRELL, SPECIES_SKRELL_AXIORI, SPECIES_DIONA, SPECIES_DIONA_COEUS, SPECIES_VAURCA_WORKER, SPECIES_VAURCA_WARRIOR, SPECIES_VAURCA_ATTENDANT, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER, SPECIES_UNATHI) + /datum/gear/augment/bio_chest_fluff display_name = "custom chest bioaug" description = "A fluff based bioaug that can be renamed/redescribed to appear as something else for RP purposes." path = /obj/item/organ/internal/augment/bioaug/head_fluff/chest_fluff flags = GEAR_HAS_NAME_SELECTION | GEAR_HAS_DESC_SELECTION - origin_restriction = list(/singleton/origin_item/origin/galatea) - whitelisted = list(SPECIES_HUMAN, SPECIES_HUMAN_OFFWORLD) + whitelisted = list(SPECIES_HUMAN, SPECIES_HUMAN_OFFWORLD, SPECIES_SKRELL, SPECIES_SKRELL_AXIORI, SPECIES_DIONA, SPECIES_DIONA_COEUS, SPECIES_VAURCA_WORKER, SPECIES_VAURCA_WARRIOR, SPECIES_VAURCA_ATTENDANT, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER, SPECIES_UNATHI) /datum/gear/augment/bio_rhand_fluff display_name = "custom right hand bioaug" description = "A fluff based bioaug that can be renamed/redescribed to appear as something else for RP purposes." path = /obj/item/organ/internal/augment/bioaug/head_fluff/rhand_fluff flags = GEAR_HAS_NAME_SELECTION | GEAR_HAS_DESC_SELECTION - origin_restriction = list(/singleton/origin_item/origin/galatea) - whitelisted = list(SPECIES_HUMAN, SPECIES_HUMAN_OFFWORLD) + whitelisted = list(SPECIES_HUMAN, SPECIES_HUMAN_OFFWORLD, SPECIES_SKRELL, SPECIES_SKRELL_AXIORI, SPECIES_DIONA, SPECIES_DIONA_COEUS, SPECIES_VAURCA_WORKER, SPECIES_VAURCA_WARRIOR, SPECIES_VAURCA_ATTENDANT, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER, SPECIES_UNATHI) /datum/gear/augment/bio_lhand_fluff display_name = "custom left hand bioaug" description = "A fluff based bioaug that can be renamed/redescribed to appear as something else for RP purposes." path = /obj/item/organ/internal/augment/bioaug/head_fluff/lhand_fluff flags = GEAR_HAS_NAME_SELECTION | GEAR_HAS_DESC_SELECTION - origin_restriction = list(/singleton/origin_item/origin/galatea) - whitelisted = list(SPECIES_HUMAN, SPECIES_HUMAN_OFFWORLD) + whitelisted = list(SPECIES_HUMAN, SPECIES_HUMAN_OFFWORLD, SPECIES_SKRELL, SPECIES_SKRELL_AXIORI, SPECIES_DIONA, SPECIES_DIONA_COEUS, SPECIES_VAURCA_WORKER, SPECIES_VAURCA_WARRIOR, SPECIES_VAURCA_ATTENDANT, SPECIES_VAURCA_BULWARK, SPECIES_VAURCA_BREEDER, SPECIES_UNATHI) diff --git a/code/modules/client/preference_setup/loadout/items/pants.dm b/code/modules/client/preference_setup/loadout/items/pants.dm index 52a99739f6c6..e5fa56ccf685 100644 --- a/code/modules/client/preference_setup/loadout/items/pants.dm +++ b/code/modules/client/preference_setup/loadout/items/pants.dm @@ -16,11 +16,7 @@ ABSTRACT_TYPE(/datum/gear/pants) pants["classic jeans"] = /obj/item/clothing/pants/classic pants["mustang jeans"] = /obj/item/clothing/pants/mustang pants["black jeans"] = /obj/item/clothing/pants/jeansblack - pants["white pants"] = /obj/item/clothing/pants/white pants["black pants"] = /obj/item/clothing/pants/black - pants["red pants"] = /obj/item/clothing/pants/red - pants["tan pants"] = /obj/item/clothing/pants/tan - pants["khaki pants"] = /obj/item/clothing/pants/khaki pants["track pants"] = /obj/item/clothing/pants/track pants["blue track pants"] = /obj/item/clothing/pants/track/blue pants["green track pants"] = /obj/item/clothing/pants/track/green @@ -35,8 +31,6 @@ ABSTRACT_TYPE(/datum/gear/pants) // Shorts pants["black shorts"] = /obj/item/clothing/pants/shorts/black pants["black short shorts"] = /obj/item/clothing/pants/shorts/black/short - pants["khaki shorts"] = /obj/item/clothing/pants/shorts/khaki - pants["khaki short shorts"] = /obj/item/clothing/pants/shorts/khaki/short // Jeans Shorts pants["jeans shorts"] = /obj/item/clothing/pants/shorts/jeans diff --git a/code/modules/client/preference_setup/loadout/items/utility.dm b/code/modules/client/preference_setup/loadout/items/utility.dm index cc5617817154..ed08f8f1be0a 100644 --- a/code/modules/client/preference_setup/loadout/items/utility.dm +++ b/code/modules/client/preference_setup/loadout/items/utility.dm @@ -55,6 +55,12 @@ path = /obj/item/journal/notepad/filled flags = GEAR_HAS_NAME_SELECTION | GEAR_HAS_DESC_SELECTION | GEAR_HAS_COLOR_SELECTION +/datum/gear/utility/stickynote + display_name = "sticky note pad" + description = "A pad full of sticky notes, to stick notes to places with." + path = /obj/item/paper/stickynotes/pad + flags = GEAR_HAS_COLOR_SELECTION + /datum/gear/utility/fountainpen display_name = "fountain pen selection" description = "A selection of fountain pens." @@ -209,5 +215,6 @@ music_cartridges["Spacer Classics Vol. 1"] = /obj/item/music_cartridge/ss13 music_cartridges["Indulgence EP (X-Rock)"] = /obj/item/music_cartridge/xanu_rock music_cartridges["Electro-Swing of Adhomai"] = /obj/item/music_cartridge/adhomai_swing + music_cartridges["Adhomai Vibes"] = /obj/item/music_cartridge/adhomai_vibes music_cartridges["Europa: Best of the 50s"] = /obj/item/music_cartridge/europa_various gear_tweaks += new /datum/gear_tweak/path(music_cartridges) diff --git a/code/modules/client/preference_setup/loadout/items/xeno/tajara.dm b/code/modules/client/preference_setup/loadout/items/xeno/tajara.dm index 2bcbdc586c37..8ae3a5018db9 100644 --- a/code/modules/client/preference_setup/loadout/items/xeno/tajara.dm +++ b/code/modules/client/preference_setup/loadout/items/xeno/tajara.dm @@ -20,7 +20,7 @@ ABSTRACT_TYPE(/datum/gear/shoes/tajara) boots["grey workboots"] = /obj/item/clothing/shoes/workboots/tajara/grey boots["dark workboots"] = /obj/item/clothing/shoes/workboots/tajara/dark boots["adhomian boots"] = /obj/item/clothing/shoes/workboots/tajara/adhomian_boots - boots["native tajaran footwear"] = /obj/item/clothing/shoes/tajara/footwraps + boots["kah'romra wraps"] = /obj/item/clothing/shoes/tajara/footwraps boots["fancy adhomian shoes"] = /obj/item/clothing/shoes/tajara/fancy boots["saddle shoes, black"] = /obj/item/clothing/shoes/sneakers/black/tajara boots["high-heeled adhomian shoes, black"] = /obj/item/clothing/shoes/heels/tajara @@ -162,6 +162,7 @@ ABSTRACT_TYPE(/datum/gear/shoes/tajara) coat["fine brown coat"] = /obj/item/clothing/suit/storage/tajaran/finecoat coat["fine blue coat"] = /obj/item/clothing/suit/storage/tajaran/finecoat/blue coat["fancy royalist jacket"] = /obj/item/clothing/suit/storage/tajaran/fancy + coat["adhomian hunting coat"] = /obj/item/clothing/suit/storage/tajaran/hunting gear_tweaks += new /datum/gear_tweak/path(coat) /datum/gear/suit/tajaran_labcoat @@ -175,7 +176,7 @@ ABSTRACT_TYPE(/datum/gear/shoes/tajara) display_name = "adhomian surgeon garb" path = /obj/item/clothing/suit/storage/hooded/tajaran/surgery whitelisted = list(SPECIES_TAJARA, SPECIES_TAJARA_ZHAN, SPECIES_TAJARA_MSAI) - allowed_roles = list("Chief Medical Officer", "Physician", "Surgeon", "Xenobiologist", "Roboticist", "Medical Intern", "Medical Personnel") + allowed_roles = list("Chief Medical Officer", "Physician", "Surgeon", "Xenobiologist", "Machinist", "Medical Intern", "Medical Personnel") sort_category = "Xenowear - Tajara" // Cloaks @@ -568,6 +569,14 @@ ABSTRACT_TYPE(/datum/gear/shoes/tajara) whitelisted = list(SPECIES_TAJARA, SPECIES_TAJARA_ZHAN, SPECIES_TAJARA_MSAI) sort_category = "Xenowear - Tajara" +/datum/gear/accessory/tajara_dogtags + display_name = "adhomian dogtags" + description = "An engraved metal identification tag. The description you assign to the dogtags will carry over to both halves when separated." + path = /obj/item/clothing/accessory/dogtags/adhomai + whitelisted = list(SPECIES_TAJARA, SPECIES_TAJARA_ZHAN, SPECIES_TAJARA_MSAI) + sort_category = "Xenowear - Tajara" + flags = GEAR_HAS_NAME_SELECTION | GEAR_HAS_DESC_SELECTION + // Hats, masks and earrings /datum/gear/head/tajara @@ -759,6 +768,13 @@ ABSTRACT_TYPE(/datum/gear/shoes/tajara) sort_category = "Xenowear - Tajara" flags = GEAR_HAS_DESC_SELECTION +/datum/gear/tajara_camera_film + display_name = "adhomian film canister" + description = "Spare film for the Adhomian camera." + path = /obj/item/camera_film/taj_film + whitelisted = list(SPECIES_TAJARA, SPECIES_TAJARA_ZHAN, SPECIES_TAJARA_MSAI) + flags = GEAR_HAS_NAME_SELECTION | GEAR_HAS_DESC_SELECTION + /datum/gear/typewriter display_name = "adhomian portable typewriter" whitelisted = list(SPECIES_TAJARA, SPECIES_TAJARA_ZHAN, SPECIES_TAJARA_MSAI) @@ -766,5 +782,20 @@ ABSTRACT_TYPE(/datum/gear/shoes/tajara) path = /obj/item/typewriter_case flags = GEAR_HAS_DESC_SELECTION +/datum/gear/prrama + display_name = "p'rrama" + whitelisted = list(SPECIES_TAJARA, SPECIES_TAJARA_ZHAN, SPECIES_TAJARA_MSAI) + sort_category = "Xenowear - Tajara" + path = /obj/item/synthesized_instrument/guitar/prrama + flags = GEAR_HAS_NAME_SELECTION | GEAR_HAS_DESC_SELECTION + allowed_roles = list("Off-Duty Crew Member", "Passenger") + +/datum/gear/maikahar + display_name = "maikahar" + whitelisted = list(SPECIES_TAJARA, SPECIES_TAJARA_ZHAN, SPECIES_TAJARA_MSAI) + sort_category = "Xenowear - Tajara" + path = /obj/item/cane/maikahar + flags = GEAR_HAS_NAME_SELECTION | GEAR_HAS_DESC_SELECTION + // All the rest diff --git a/code/modules/client/preference_setup/occupation/occupation.dm b/code/modules/client/preference_setup/occupation/occupation.dm index bcbd86fcc695..16e1edc90d84 100644 --- a/code/modules/client/preference_setup/occupation/occupation.dm +++ b/code/modules/client/preference_setup/occupation/occupation.dm @@ -219,6 +219,26 @@ if(C.name in job.blacklisted_citizenship) dat += "[dispRank] \[BACKGROUND RESTRICTED]" continue + + // Skill requirement handling. + var/skills_length = length(job.skill_requirements) + var/skill_index = 0 + var/missing_skills = "" + for (var/key,value in job.skill_requirements) + skill_index++ + if (!key || pref.skills[key] >= value) + continue + + var/singleton/skill/skill = GET_SINGLETON(key) + missing_skills += "[skill.name] [value]" + if (skill_index != skills_length) + missing_skills += "\n" + + if (missing_skills != "") + dat += "[dispRank] MISSING SKILLS: [missing_skills]" + continue + // End of skill requirement handling. + if(job.alt_titles && (LAZYLEN(pref.GetValidTitles(job)) > 1)) dispRank = " \[[pref.GetPlayerAltTitle(job)]\]" if((pref.job_civilian_low & ASSISTANT) && (rank != "Assistant")) @@ -462,11 +482,16 @@ if (!job) return var/choices = list(job.title) + job.alt_titles - for(var/t in choices) - if(!isnull(job.alt_factions)) + if(!isnull(job.alt_factions)) + for(var/t in choices) if (src.faction in job.alt_factions[t]) continue choices -= t + if(!isnull(job.alt_citizenships)) + for(var/t in choices) + if (src.citizenship in job.alt_citizenships[t]) + continue + choices -= t if((GLOB.all_species[src.species].spawn_flags & NO_AGE_MINIMUM)) return choices for(var/t in choices) diff --git a/code/modules/client/preference_setup/other/01_incidents.dm b/code/modules/client/preference_setup/other/01_incidents.dm index af4a62a892a8..b152305bac13 100644 --- a/code/modules/client/preference_setup/other/01_incidents.dm +++ b/code/modules/client/preference_setup/other/01_incidents.dm @@ -78,7 +78,7 @@ if (I.fine == 0) dat += "
Brig Sentence: [I.getBrigSentence()]
" else - dat += "Fine: [I.fine] Credits
" + dat += "Fine: [I.fine]电
" dat += "Notes:
" if (I.notes != "") dat += nl2br(I.notes) diff --git a/code/modules/client/preference_setup/skills/skills.dm b/code/modules/client/preference_setup/skills/skills.dm index 1eff73a7bb2c..1ce674f3afc7 100644 --- a/code/modules/client/preference_setup/skills/skills.dm +++ b/code/modules/client/preference_setup/skills/skills.dm @@ -56,16 +56,23 @@ var/before = pref.skills var/loaded_skills try - loaded_skills = json_decode(pref.skills) + loaded_skills = pref.skills catch (var/exception/e) log_debug("SKILLS: Caught [e]. Initial value: [before]") pref.skills = list() pref.skills = list() - for(var/new_skill in loaded_skills) - var/singleton/skill/skill = GET_SINGLETON(text2path(new_skill)) + for(var/key in SSskills.required_skills) + var/singleton/skill/skill = GET_SINGLETON(key) + if (istype(skill)) + pref.skills[skill.type] = SKILL_LEVEL_UNFAMILIAR + + for(var/key,value in loaded_skills) + if (!key) + continue + var/singleton/skill/skill = GET_SINGLETON(key) if(istype(skill)) - pref.skills[skill.type] = loaded_skills[new_skill] + pref.skills[skill.type] = value /datum/category_item/player_setup_item/skills/sanitize_character(var/sql_load = 0) //todomatt @@ -124,7 +131,8 @@ dat += "" dat += "[skill.name]" - var/current_level = pref.skills[skill.type] + var/level_from_pref = pref.skills[skill.type] + var/current_level = level_from_pref ? level_from_pref : SKILL_LEVEL_UNFAMILIAR var/maximum_skill_level = get_maximum_skill_level(skill, education) for(var/i = SKILL_LEVEL_UNFAMILIAR, i <= skill.maximum_level, i++) @@ -154,7 +162,7 @@ if(effective_level <= 0) return "" - var/level_name = SSskills.skill_level_map[effective_level] + var/level_name = skill.skill_level_map[effective_level] var/cost = skill.get_cost(effective_level) var/button_label = "[level_name] ([cost])" var/given_skill = FALSE @@ -224,11 +232,11 @@ var/dat = "
[skill_to_show.name]
" dat += "
[skill_to_show.description]
" if(skill_to_show.uneducated_skill_cap) - dat += "Without the relevant education, you may only reach the [SSskills.skill_level_map[skill_to_show.uneducated_skill_cap]] level.
" + dat += "Without the relevant education, you may only reach the [skill_to_show.skill_level_map[skill_to_show.uneducated_skill_cap]] level.
" dat += "
" var/skill_level = (skill_to_show.type in pref.skills) ? pref.skills[skill_to_show.type] : SKILL_LEVEL_UNFAMILIAR - dat += "Your current level in this skill is [SPAN_BOLD(SSskills.skill_level_map[skill_level])].
" - dat += SPAN_NOTICE("[skill_to_show.skill_level_descriptions[skill_level]]") + dat += "Your current level in this skill is [SPAN_BOLD(skill_to_show.skill_level_map[skill_level])].
" + dat += "[skill_to_show.skill_level_descriptions[skill_level]]" dat += "" skill_window.set_content(dat) skill_window.open() @@ -240,10 +248,7 @@ return var/new_skill_value = text2num(href_list["newvalue"]) - if(new_skill_value == SKILL_LEVEL_UNFAMILIAR) - pref.skills -= new_skill.type - else - pref.skills[new_skill.type] = text2num(new_skill_value) + pref.skills[new_skill.type] = text2num(new_skill_value) return TOPIC_REFRESH else if(href_list["open_education_menu"]) @@ -276,7 +281,7 @@ for(var/skill in education.skills) var/singleton/skill/new_skill = GET_SINGLETON(skill) pref.skills[new_skill.type] = education.skills[new_skill.type] - to_chat(user, SPAN_NOTICE("Added the [new_skill.name] skill at level [SSskills.skill_level_map[education.skills[new_skill.type]]].")) + to_chat(user, SPAN_NOTICE("Added the [new_skill.name] skill at level [new_skill.skill_level_map[education.skills[new_skill.type]]].")) sanitize_character() return TOPIC_REFRESH @@ -294,7 +299,7 @@ var/list/skills_to_show = list() for(var/skill in ED.skills) var/singleton/skill/S = GET_SINGLETON(skill) - skills_to_show += "[S.name] ([SPAN_DANGER(SSskills.skill_level_map[ED.skills[S.type]])])" + skills_to_show += "[S.name] ([SPAN_DANGER(S.skill_level_map[ED.skills[S.type]])])" dat += "[english_list(skills_to_show)].
" dat += "
\[Select\]
" dat += "" diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index c1138a4b9b96..9b91daa693ea 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -528,7 +528,9 @@ GLOBAL_LIST_EMPTY_TYPED(preferences_datums, /datum/preferences) if(istype(P) && (P.ability_flags & PSI_FLAG_CANON)) P.apply(character) - character.skills.set_skills_from_pref(src) + for(var/skill_type in skills) + var/singleton/skill/skill = GET_SINGLETON(skill_type) + skill.on_spawn(character, skills[skill.type]) if(icon_updates) character.force_update_limbs() diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index fef3b23cf915..195b8f7a934d 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -1359,7 +1359,7 @@ else item_state_slots[slot_w_uniform_str] = "[worn_state]_d" if(user) - to_chat(user, SPAN_NOTICE("You roll up \the [src].")) + to_chat(user, SPAN_NOTICE("You roll down \the [src].")) else body_parts_covered = initial(body_parts_covered) if(contained_sprite || !LAZYLEN(item_state_slots)) @@ -1370,7 +1370,7 @@ else item_state_slots[slot_w_uniform_str] = "[worn_state]" if(user) - to_chat(user, SPAN_NOTICE("You roll down \the [src].")) + to_chat(user, SPAN_NOTICE("You roll up \the [src].")) update_clothing_icon() /obj/item/clothing/under/proc/rollsleeves() diff --git a/code/modules/clothing/ears/earphones.dm b/code/modules/clothing/ears/earphones.dm index da84f52eec1f..cb218a74a2c9 100644 --- a/code/modules/clothing/ears/earphones.dm +++ b/code/modules/clothing/ears/earphones.dm @@ -1,20 +1,13 @@ -/* - Earphones that use our sound_player system to play sounds from a music cartridge to their wearer. - - Current Features: - - All earphones have a cartridge slot. Cartridges can be inserted by clicking an earphone, and removed via an eject_music_cartridge() verb. - - Inserting a cartridge will load a playlist containing /datum/tracks, where track names and sound files are loaded. - - Alt+Clicking will Start/Stop a playlist, creating or deleting an active sound_player token. - - attack_self will eject the music cartridge. Ejecting a music cartridge also terminates the sound_player token. - - Volume controllable via verb. - - Missing features i am too weak to figure out: - - There is no auto—next song, and a user must manually use next_song() or previous_song() verbs to iterate through a playlist. - - Part and parcel with no auto-next: Tracks automatically loop due to using the PlayLoopingSound() proc. Ideally, tracks should not loop. - - There is no accomodation for user-uploaded sound files. - - There are no UI implementations of earphone controls, which could be more user friendly. -*/ - +/** + * Earphones that use our sound_player system to play sounds from a music cartridge to their wearer. + * + * Current Features: + * - All earphones have a cartridge slot. Cartridges can be inserted by clicking an earphone, and removed via an eject_music_cartridge() verb. + * - Inserting a cartridge will load a playlist containing /datum/tracks, where track names and sound files are loaded. + * - Alt+Clicking will Start/Stop a playlist, creating or deleting an active sound_player token. + * - attack_self will eject the music cartridge. Ejecting a music cartridge also terminates the sound_player token. + * - Volume controllable via verb. + */ /obj/item/clothing/ears/earphones name = "earphones" desc = "A pair of wireless earphones. Includes a little slot for a music cartridge." @@ -135,7 +128,7 @@ if(!soundplayer_token) if(current_playlist && (current_playlist.len > 0)) var/sound/sound_to_play = current_playlist[playlist_index].song_path - soundplayer_token = GLOB.sound_player.PlayNonloopingSound(src, src, sound_to_play, volume, range, 20, prefer_mute = FALSE, sound_type = ASFX_MUSIC) + soundplayer_token = GLOB.sound_player.PlayLoopingSound(src, src, sound_to_play, volume, range, 20, prefer_mute = FALSE, sound_type = ASFX_MUSIC) // Queue the next_song() proc when the current song ends. Clean up handled under next_song() which also calls stopplaying() to end this token autoplay_timeleft = current_playlist[playlist_index].song_length @@ -496,6 +489,18 @@ Earphone Variants /obj/item/music_cartridge/adhomai_swing/demo hardcoded = TRUE +/obj/item/music_cartridge/adhomai_vibes + name = "Adhomai vibes" + desc = "A red music cartridge holding various music considered to fit the vibe of Adhomai." + icon_state = "adhomai" + + tracks = list( + new/datum/track("Adhomai Vibes #1", 'sound/music/lobby/adhomai/adhomai-1.ogg', 4 MINUTES + 15 SECONDS, /obj/item/music_cartridge/adhomai_vibes), + new/datum/track("Adhomai Vibes #2", 'sound/music/lobby/adhomai/adhomai-2.ogg', 3 MINUTES + 55 SECONDS, /obj/item/music_cartridge/adhomai_vibes), + new/datum/track("Adhomai Vibes #3", 'sound/music/lobby/adhomai/adhomai-3.ogg', 5 MINUTES + 50 SECONDS, /obj/item/music_cartridge/adhomai_vibes), + new/datum/track("Adhomai Vibes #4", 'sound/music/lobby/adhomai/adhomai-4.ogg', 4 MINUTES + 24 SECONDS, /obj/item/music_cartridge/adhomai_vibes) + ) + /obj/item/music_cartridge/europa_various name = "Europa: Best of the 50s" desc = "A music cartridge storing the best tracks to listen to on a submarine dive." diff --git a/code/modules/clothing/head/soft_caps.dm b/code/modules/clothing/head/soft_caps.dm index a5bd71af7d84..541e78700cf1 100644 --- a/code/modules/clothing/head/soft_caps.dm +++ b/code/modules/clothing/head/soft_caps.dm @@ -27,6 +27,7 @@ icon_state = "[initial(icon_state)][flipped ? "_flipped" : ""]" item_state = icon_state to_chat(usr, "You flip the hat [flipped ? "backwards" : "forwards"].") + update_icon() update_clothing_icon() // So our mob-overlays update. /obj/item/clothing/head/softcap/colorable diff --git a/code/modules/clothing/pants/pants.dm b/code/modules/clothing/pants/pants.dm index 52689fb9fcde..c8f6e6530056 100644 --- a/code/modules/clothing/pants/pants.dm +++ b/code/modules/clothing/pants/pants.dm @@ -54,36 +54,12 @@ ABSTRACT_TYPE(/obj/item/clothing/pants) /********** Pants Start **********/ // Pants -/obj/item/clothing/pants/white - name = "white pants" - desc = "Plain boring white pants." - icon_state = "whitepants" - item_state = "whitepants" - /obj/item/clothing/pants/black name = "black pants" desc = "A pair of plain black pants." icon_state = "blackpants" item_state = "blackpants" -/obj/item/clothing/pants/red - name = "red pants" - desc = "Bright red pants." - icon_state = "redpants" - item_state = "redpants" - -/obj/item/clothing/pants/tan - name = "tan pants" - desc = "Some tan pants. You look like a white collar worker with these on." - icon_state = "tanpants" - item_state = "tanpants" - -/obj/item/clothing/pants/khaki - name = "tan pants" - desc = "A pair of dust beige khaki pants." - icon_state = "khaki" - item_state = "khaki" - /obj/item/clothing/pants/camo name = "camouflage pants" desc = "A pair of woodland camouflage pants. Probably not the best choice for a space station." @@ -99,8 +75,8 @@ ABSTRACT_TYPE(/obj/item/clothing/pants) /obj/item/clothing/pants/dress/belt name = "dress pants" desc = "A pair of suit trousers. Comes with a belt, to secure your burdens." - icon_state = "dresspants_belt" - item_state = "dresspants_belt" + build_from_parts = TRUE + worn_overlay = "belt" /obj/item/clothing/pants/striped name = "striped pants" diff --git a/code/modules/clothing/pants/shorts.dm b/code/modules/clothing/pants/shorts.dm index 0005631b5c66..6315c9e33fb8 100644 --- a/code/modules/clothing/pants/shorts.dm +++ b/code/modules/clothing/pants/shorts.dm @@ -35,16 +35,6 @@ icon_state = "shorts_s_black" item_state = "shorts_s_black" -/obj/item/clothing/pants/shorts/khaki - name = "khaki shorts" - desc = "For that island getaway. It's five o'clock somewhere, right?" - icon_state = "shorts_khaki" - item_state = "shorts_khaki" - -/obj/item/clothing/pants/shorts/khaki/short - name = "khaki short shorts" - icon_state = "shorts_s_khaki" - item_state = "shorts_s_khaki" /********** Shorts End **********/ /********** Jeans Shorts Start **********/ diff --git a/code/modules/clothing/shoes/cowboy.dm b/code/modules/clothing/shoes/cowboy.dm index 93a8b80b77bb..d45de5b15509 100644 --- a/code/modules/clothing/shoes/cowboy.dm +++ b/code/modules/clothing/shoes/cowboy.dm @@ -8,6 +8,7 @@ permeability_coefficient = 0.05 //these are quite tall drop_sound = 'sound/items/drop/leather.ogg' pickup_sound = 'sound/items/pickup/leather.ogg' + can_hold_knife = TRUE /obj/item/clothing/shoes/cowboy/classic name = "classic cowboy boots" diff --git a/code/modules/clothing/shoes/sandals.dm b/code/modules/clothing/shoes/sandals.dm index 19303703b48f..a3d3ce724e4d 100644 --- a/code/modules/clothing/shoes/sandals.dm +++ b/code/modules/clothing/shoes/sandals.dm @@ -9,6 +9,7 @@ contained_sprite = TRUE icon_auto_adapt = TRUE icon_supported_species_tags = list("taj") + color = WOOD_COLOR_GENERIC /obj/item/clothing/shoes/sandals/geta name = "geta" diff --git a/code/modules/clothing/shoes/xeno/tajara.dm b/code/modules/clothing/shoes/xeno/tajara.dm index 59a9fef546ec..97e8d05db36a 100644 --- a/code/modules/clothing/shoes/xeno/tajara.dm +++ b/code/modules/clothing/shoes/xeno/tajara.dm @@ -1,5 +1,5 @@ /obj/item/clothing/shoes/tajara/footwraps - name = "native tajaran foot-wear" + name = "kah'romra" desc = "Native foot and leg wear worn by Tajara, completely covering the legs in wraps and the feet in adhomian fabric." icon = 'icons/obj/tajara_items.dmi' icon_state = "adhomai_shoes" @@ -8,11 +8,11 @@ species_restricted = list(BODYTYPE_TAJARA) contained_sprite = TRUE move_trail = null - desc_extended = "Today the fashion that dominates Adhomai shares few similarities to the clothing of old Furs, linen, hemp, silk and other such fabrics were traded for \ - synthetic versions, creating a massive boom in the nylon industry and textile industry in the cities. Jeans, overcoats, army uniforms, parade uniforms, flags, pants, shirts, ties, \ - suspenders, overalls are now the fashion of every Tajara from Nal'Tor to Kaltir. The protests of \"Old fashion\" supporters can't stand against how undeniably effective and cheap \ - to produce Human clothes are. There are a few notable branches, the long-coat and fedora \"gangster style\". Leather jacket wearing \"Greaser\" or the popular amongst females, short \ - and colorful dress wearing \"Flapper\" variety of clothing." + desc_extended = "Kahriye Romra, often shortened to Kah'Romra or just Romra, are a traditional set of Adhomian fabrics \ + and leathers that wrap the legs and feet. The style of footwear has existed on Adhomai for longer than recorded history \ + and continues to survive well into the modern eras of Tajaran history. The combination of tough leathers on the feet, and \ + insulating fabrics and furs along the legs combine the warmth and protection needed to cross Adhomai's rugged terrain. \ + Modern Kah'Romra utilize treated fabrics and leathers for increased durability." // Flats. // since everything except the onmob is a carbon copy, we just add another onmob sprite with the proper suffix and the species restriction to avoid bloat diff --git a/code/modules/clothing/spacesuits/rig/modules/utility.dm b/code/modules/clothing/spacesuits/rig/modules/utility.dm index 0266a0805a68..5e8b9f7c0396 100644 --- a/code/modules/clothing/spacesuits/rig/modules/utility.dm +++ b/code/modules/clothing/spacesuits/rig/modules/utility.dm @@ -292,7 +292,7 @@ if(target_mob != user) to_chat(user, SPAN_NOTICE("You inject [target_mob] with [chems_to_use] unit\s of [charge.display_name].")) - if(!target_mob.is_physically_disabled()) + if(!target_mob.incapacitated(INCAPACITATION_DISABLED)) to_chat(target_mob, SPAN_NOTICE("You feel a rushing in your veins as [chems_to_use] unit\s of [charge.display_name] [chems_to_use == 1 ? "is" : "are"] injected.")) target_mob.reagents.add_reagent(charge.product_type, chems_to_use) diff --git a/code/modules/clothing/spacesuits/rig/suits/light.dm b/code/modules/clothing/spacesuits/rig/suits/light.dm index ccc4a6821ac1..e28de0b202bc 100644 --- a/code/modules/clothing/spacesuits/rig/suits/light.dm +++ b/code/modules/clothing/spacesuits/rig/suits/light.dm @@ -15,7 +15,7 @@ BOMB = ARMOR_BOMB_PADDED ) emp_protection = 100 - slowdown = -1 + slowdown = -0.3 species_restricted = list(BODYTYPE_HUMAN, BODYTYPE_UNATHI, BODYTYPE_SKRELL, BODYTYPE_VAURCA) item_flags = ITEM_FLAG_THICK_MATERIAL offline_slowdown = 0 @@ -260,7 +260,7 @@ BIO = ARMOR_BIO_SHIELDED, RAD = ARMOR_RAD_SHIELDED ) - slowdown = -1 + slowdown = -0.3 offline_slowdown = 0 airtight = 1 offline_vision_restriction = TINT_HEAVY diff --git a/code/modules/clothing/spacesuits/void/void.dm b/code/modules/clothing/spacesuits/void/void.dm index e2ee768481d6..e45eed4e3fd8 100644 --- a/code/modules/clothing/spacesuits/void/void.dm +++ b/code/modules/clothing/spacesuits/void/void.dm @@ -96,7 +96,7 @@ part_list += "\a [I]" . += "\The [src] has [english_list(part_list)] installed." if(tank && distance <= 1) - . += SPAN_NOTICE("The wrist-mounted pressure gauge reads [max(round(tank.air_contents.return_pressure()),0)] kPa remaining in \the [tank].") + . += SPAN_NOTICE("The wrist-mounted pressure gauge reads [max(round(XGM_PRESSURE(tank.air_contents)),0)] kPa remaining in \the [tank].") if (cooler && distance <= 1) . += SPAN_NOTICE("The mounted cooler's battery charge reads [round(cooler.cell.percent())]%") diff --git a/code/modules/clothing/suits/hazardvests.dm b/code/modules/clothing/suits/hazardvests.dm index 8e6d31aa9b43..e3bb76fdb620 100644 --- a/code/modules/clothing/suits/hazardvests.dm +++ b/code/modules/clothing/suits/hazardvests.dm @@ -6,7 +6,7 @@ item_state = "hazard" contained_sprite = TRUE blood_overlay_type = "armor" - allowed = list (/obj/item/analyzer, /obj/item/flashlight, /obj/item/multitool, /obj/item/pipe_painter, /obj/item/radio, /obj/item/t_scanner, \ + allowed = list (/obj/item/analyzer, /obj/item/flashlight, /obj/item/multitool, /obj/item/paint_sprayer, /obj/item/radio, /obj/item/t_scanner, \ /obj/item/crowbar, /obj/item/screwdriver, /obj/item/weldingtool, /obj/item/wirecutters, /obj/item/wrench, /obj/item/tank/emergency_oxygen, \ /obj/item/clothing/mask/gas, /obj/item/taperoll/engineering, /obj/item/storage/bag/inflatable) body_parts_covered = UPPER_TORSO diff --git a/code/modules/clothing/suits/xeno/tajara.dm b/code/modules/clothing/suits/xeno/tajara.dm index 38b59a215ddb..d91d526a0c40 100644 --- a/code/modules/clothing/suits/xeno/tajara.dm +++ b/code/modules/clothing/suits/xeno/tajara.dm @@ -182,6 +182,9 @@ /obj/item/healthanalyzer, /obj/item/flashlight, /obj/item/radio, /obj/item/tank/emergency_oxygen, /obj/item/breath_analyzer, /obj/item/reagent_containers/blood) species_restricted = list(BODYTYPE_TAJARA) desc_extended = null + armor = list( + bio = ARMOR_BIO_STRONG, + ) /obj/item/clothing/head/winterhood/hoodie/taj_scrubs name = "adhomian surgeon mask" @@ -191,6 +194,12 @@ item_state = "tajscrubs_hood" contained_sprite = TRUE species_restricted = list(BODYTYPE_TAJARA) + body_parts_covered = FACE|HEAD + gas_transfer_coefficient = 0.90 + permeability_coefficient = 0.01 + armor = list( + BIO = ARMOR_BIO_RESISTANT + ) /obj/item/clothing/suit/storage/hooded/tajaran/amohda name = "amohdan cloak" @@ -332,7 +341,7 @@ BOMB = ARMOR_BOMB_MINOR ) siemens_coefficient = 0.50 - allowed = list(/obj/item/gun/projectile/shotgun/pump/rifle, /obj/item/ammo_magazine/boltaction, /obj/item/gun/projectile/automatic/rifle/adhomian, /obj/item/flashlight) + allowed = list(/obj/item/gun/projectile/shotgun/pump/rifle, /obj/item/ammo_magazine/boltaction/adhomai, /obj/item/ammo_magazine/a68, /obj/item/gun/projectile/automatic/rifle/adhomian, /obj/item/flashlight) /obj/item/clothing/suit/storage/tajaran/dpra_jacket name = "al'mariist jacket" diff --git a/code/modules/clothing/under/accessories/storage.dm b/code/modules/clothing/under/accessories/storage.dm index 32f8609b41c0..00c3c8d8f065 100644 --- a/code/modules/clothing/under/accessories/storage.dm +++ b/code/modules/clothing/under/accessories/storage.dm @@ -178,6 +178,7 @@ /obj/item/clothing/accessory/storage/pouches/colour icon_state = "thigh_colour" + item_state = "thigh_colour" /obj/item/clothing/accessory/storage/knifeharness name = "decorated harness" diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index 028f495c2307..1c98c8a92291 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -617,7 +617,6 @@ /obj/item/clothing/under/rank/elyran_fatigues name = "elyran navy uniform" desc = "An utility uniform worn by Elyran navy staff serving aboard ships and in the field." - icon = "" icon_state = "elyran_fatigues" item_state = "elyran_fatigues" armor = list( diff --git a/code/modules/cooking/machinery/commissary.dm b/code/modules/cooking/machinery/commissary.dm index b7b719b360fb..dba823d2beb9 100644 --- a/code/modules/cooking/machinery/commissary.dm +++ b/code/modules/cooking/machinery/commissary.dm @@ -40,6 +40,7 @@ ) display_tiers = 5 display_tier_amt = 3 + has_emissive = FALSE /obj/machinery/smartfridge/tradeshelf/clothing name = "clothing shelf" @@ -48,7 +49,9 @@ contents_path = "-clothing" accepted_items = list(/obj/item/storage/backpack, /obj/item/storage/belt, - /obj/item/clothing + /obj/item/clothing, + /obj/item/storage/briefcase, + /obj/item/cane ) display_tiers = 3 display_tier_amt = 5 @@ -82,6 +85,7 @@ ) display_tiers = 4 display_tier_amt = 5 + has_emissive = TRUE /obj/machinery/smartfridge/tradeshelf/toy name = "toy shelf" @@ -105,7 +109,8 @@ /obj/item/gun/projectile/revolver/capgun, /obj/item/gun/bang, /obj/item/eightball, - /obj/item/bikehorn + /obj/item/bikehorn, + /obj/item/camera_film ) display_tiers = 4 display_tier_amt = 5 @@ -128,7 +133,7 @@ user.visible_message("[user] loads [src] with [P].", SPAN_NOTICE("You load [src] with [P].")) if(length(P.contents) > 0) to_chat(user, SPAN_NOTICE("Some items are refused.")) - update_overlays() + update_icon() return TRUE . = ..() @@ -145,6 +150,7 @@ var/receipt = "" var/destinationact = "Operations" var/credit = 100 + var/shop_name = "Commissary" storage_type = null /obj/structure/cash_register/commissary/mechanics_hints(mob/user, distance, is_adjacent) @@ -153,6 +159,7 @@ . += "Alt click with credits in hand, to deposit them." . += "Alt click while having operations access, to withdraw credits from it." . += "Items can be paid for with id cards, charge cards or physical credits, and a receipt will be printed." + . += "The register can print a paper which can be used to quickly fill it out in the future by using it on the register." /obj/structure/cash_register/commissary/Initialize() . = ..() @@ -176,7 +183,7 @@ return I = user.GetIdCard() if(istype(I) && (ACCESS_CARGO in I.access)) - var/price_guess = text2num(sanitizeSafe( tgui_input_text(user, "How much do you wish to withdraw? Remaining cash: [credit]", "QuikPay", 0, 10), 10)) + var/price_guess = text2num(sanitizeSafe( tgui_input_text(user, "How much do you wish to withdraw? Remaining credits: [credit]电", "QuikPay", 0, 10), 10)) if(isnull(price_guess) || price_guess == 0) return price_guess = max(0, round(price_guess, 0.01)) @@ -187,21 +194,25 @@ return /obj/structure/cash_register/commissary/proc/print_receipt() - var/obj/item/paper/R = new(loc) + var/obj/item/paper/notepad/receipt/R = new(loc) var/receiptname = "Receipt: [machine_id]" R.set_content_unsafe(receiptname, receipt, sum) //stamp the paper var/image/stampoverlay = image('icons/obj/bureaucracy.dmi') - stampoverlay.icon_state = "paper_stamp-cent" + stampoverlay.icon_state = "paper_stamp-hop" if(!R.stamped) R.stamped = new R.stamped += /obj/item/stamp R.AddOverlays(stampoverlay) R.stamps += "
This paper has been stamped by the Idris Quik-Pay Register." usr.put_in_any_hand_if_possible(R) + R.ripped = TRUE /obj/structure/cash_register/commissary/attackby(obj/item/attacking_item, mob/user) + if(istype(attacking_item, /obj/item/paper)) + read_paper_list(attacking_item, user) + return if(sum == 0) return if (istype(attacking_item, /obj/item/spacecash/ewallet)) @@ -253,9 +264,9 @@ if(transaction) to_chat(user, SPAN_NOTICE("[icon2html(src, user)][transaction].")) else - playsound(src, 'sound/machines/chime.ogg', 50, 1) - visible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] chimes.")) visible_message("\The [user] swipes a card on \the [src]." ) + audible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] chimes.")) + playsound(src, 'sound/machines/chime.ogg', 50, 1) print_receipt() sum = 0 receipt = "" @@ -273,8 +284,8 @@ E.worth -= transaction_amount visible_message("\The [user] swipes a card on \the [src]." ) + audible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] chimes.")) playsound(src, 'sound/machines/chime.ogg', 50, 1) - src.audible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] chimes.")) print_receipt() sum = 0 receipt = "" @@ -284,6 +295,18 @@ to_chat(user, SPAN_WARNING("[icon2html(src, user)]\The [E] doesn't have that much money!")) return +/obj/structure/cash_register/commissary/proc/read_paper_list(obj/item/paper/R, mob/user) + if(!editmode) + balloon_alert(user, "device locked!") + return FALSE + var/result = read_paper_price_list(R) + for(var/item in result) + items += list(list("name" = item["name"], "price" = item["price"])) + items_to_price[item["name"]] += item["price"] + +/obj/structure/cash_register/commissary/proc/print_price(mob/user) + return print_price_to_paper(shop_name, items, loc, user) + /obj/structure/cash_register/commissary/attack_hand(mob/living/user) . = ..() ui_interact(user) @@ -314,7 +337,7 @@ switch(action) if("add") if(!editmode) - to_chat(usr, SPAN_WARNING("Device locked.")) + balloon_alert(usr, "device locked!") return FALSE items += list(list("name" = new_item, "price" = new_price)) @@ -323,7 +346,7 @@ if("remove") if(!editmode) - to_chat(usr, SPAN_NOTICE("Device locked.")) + balloon_alert(usr, "device locked!") return FALSE var/index = 0 for(var/list/L in items) @@ -363,14 +386,21 @@ . = TRUE if("confirm") + // Ensuring it is clear, in case the button is clicked multiple times + receipt = "" + sum = 0 + var/obj/item/card/id/id_card = usr.GetIdCard() + var/cashier = id_card? id_card.registered_name : "Unknown" + receipt = "

[shop_name] receipt

Today's date: [worlddate2text()]
Cashier: [cashier]

Purchased items:
    " for(var/list/bought_item in buying) var/item_name = bought_item["name"] var/item_amount = bought_item["amount"] var/item_price = items_to_price[item_name] - receipt += "[item_name]: x[item_amount] at [item_price]cr each
    " + receipt += "
  • [item_name]: [item_amount] x [item_price]电: [item_amount * item_price]电
    " sum += item_price * item_amount - receipt += "Total: [sum]cr
    " + + receipt += "

Total: [sum]电
" playsound(src, 'sound/machines/ping.ogg', 25, 1) audible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] pings.")) . = TRUE @@ -378,7 +408,7 @@ if("locking") if(editmode) editmode = FALSE - to_chat(usr, SPAN_NOTICE("Device locked.")) + balloon_alert(usr, "device locked!") else if(!editmode) var/obj/item/card/id/I = usr.GetIdCard() @@ -386,19 +416,26 @@ return if(check_access(I)) editmode = !editmode - to_chat(usr, SPAN_NOTICE("Device [editmode ? "un" : ""]locked.")) + balloon_alert(usr, "device [editmode ? "un" : ""]locked") . = TRUE if("accountselect") if(!editmode) - to_chat(usr, SPAN_WARNING("Device locked.")) + balloon_alert(usr, "device locked!") return FALSE var/dest = tgui_input_list(usr, "What account would you like to select?", "Destination Account", assoc_to_keys(SSeconomy.department_accounts)) if(!dest) return FALSE destinationact = dest - return TRUE + . = TRUE + + if("print_dsv") + if(!editmode) + balloon_alert(usr, "device locked!") + return FALSE + print_price(usr) + . = TRUE /obj/structure/cash_register/commissary/proc/clear_order() buying.Cut() @@ -582,6 +619,7 @@ // Tajara /obj/item/reagent_containers/food/drinks/cans/hrozamal_soda = 5, /obj/item/reagent_containers/food/drinks/cans/adhomai_milk = 3, + /obj/item/reagent_containers/food/drinks/cans/earthen_juice = 3, // Milk /obj/item/reagent_containers/food/drinks/cans/beetle_milk = 5, /obj/item/reagent_containers/food/drinks/carton/small/milk = 5, diff --git a/code/modules/cooking/machinery/smartfridge.dm b/code/modules/cooking/machinery/smartfridge.dm index 19bb8bdd9f93..31957f5890e9 100644 --- a/code/modules/cooking/machinery/smartfridge.dm +++ b/code/modules/cooking/machinery/smartfridge.dm @@ -22,6 +22,11 @@ var/machineselect = 0 var/list/accepted_items = list(/obj/item/reagent_containers/food/snacks/grown, /obj/item/seeds, /obj/item/mollusc) + /// List of items that the machine starts with upon spawn + var/list/initial_contents + + /// Is this smartfridge going to have a glowing screen? (Drying Racks are not) + var/has_emissive = TRUE var/cooling = 0 //Whether or not to vend products at the cooling temperature var/heating = 0 //Whether or not to vend products at the heating temperature @@ -43,6 +48,8 @@ var/datum/wires/smartfridge/wires = null atmos_canpass = CANPASS_DENSITY + VAR_PRIVATE/static/list/base64_cache = list() + /obj/machinery/smartfridge/secure is_secure = 1 @@ -95,13 +102,22 @@ for(var/obj/item/reagent_containers/food/snacks/grown/g in contents) item_quants[g.name]++ update_overlays() + update_static_data_for_all_viewers() -/obj/machinery/smartfridge/Initialize() +/obj/machinery/smartfridge/Initialize(mapload) . = ..() if(is_secure) wires = new/datum/wires/smartfridge/secure(src) else wires = new(src) + if(islist(initial_contents)) + for(var/obj/item/typekey as anything in initial_contents) + var/amount = initial_contents[typekey] + if(isnull(amount)) + amount = 1 + for(var/i in 1 to amount) + new typekey(src) + item_quants[typekey.name]++ update_icon() /obj/machinery/smartfridge/Destroy() @@ -167,6 +183,12 @@ /obj/item/reagent_containers/hypospray/autoinjector, /obj/item/personal_inhaler) +//Variant of medical fridge, but with some starting gear +/obj/machinery/smartfridge/secure/medbay/horizon + initial_contents = list(/obj/item/reagent_containers/glass/bottle/bicaridine = 1, + /obj/item/reagent_containers/glass/bottle/kelotane = 1, + /obj/item/reagent_containers/glass/bottle/dexalin = 1) + /obj/machinery/smartfridge/secure/virology name = "\improper Refrigerated Virus Storage" desc = "A refrigerated storage unit for storing viral material." @@ -210,6 +232,7 @@ icon_state = "drying_rack" accepted_items = list(/obj/item/reagent_containers/food/snacks) contents_path = null + has_emissive = FALSE /obj/machinery/smartfridge/drying_rack/accept_check(var/obj/item/O) if(!..()) @@ -230,6 +253,10 @@ if(S.on_dry(src)) //Drying rack keeps the item but changes the name. This prevents pre-dried item lingering in the UI as vendable item_quants[S.name]++ item_quants[old_name]-- + if(item_quants[old_name] <= 0 || item_quants[S.name] == 1) + update_static_data_for_all_viewers() + if(item_quants[old_name] <= 0) + item_quants -= old_name return /obj/machinery/smartfridge/drying_rack/update_overlays() @@ -285,10 +312,12 @@ if(panel_open) AddOverlays("[initial(icon_state)]-panel") var/list/shown_contents = contents - component_parts - if(contents_path && shown_contents.len > 0) - var/contents_icon_state = change_display(shown_contents.len - 1) + if(contents_path && length(shown_contents) > 0) + var/contents_icon_state = change_display(length(shown_contents) - 1) AddOverlays("[initial(icon_state)][contents_path][contents_icon_state]") AddOverlays("[initial(icon_state)]-glass[(stat & BROKEN) ? "-broken" : ""]") + if(has_emissive && powered() && !(stat & BROKEN)) + AddOverlays(emissive_appearance(icon, "[initial(icon_state)]-light-mask", src, alpha = src.alpha)) /obj/machinery/smartfridge/proc/change_display(var/length) var/tier = clamp((floor(length / display_tier_amt) + 1), 1, display_tiers) @@ -360,25 +389,32 @@ user.remove_from_mob(attacking_item) attacking_item.forceMove(src) item_quants[attacking_item.name]++ + if(item_quants[attacking_item.name] == 1) + update_static_data_for_all_viewers() user.visible_message("[user] adds \a [attacking_item] to [src].", SPAN_NOTICE("You add [attacking_item] to [src].")) update_overlays() - return + return TRUE if(istype(attacking_item, /obj/item/storage)) var/obj/item/storage/P = attacking_item var/plants_loaded = 0 + var/update_static_data = FALSE for(var/obj/G in P.contents) if(accept_check(G)) if(length(contents) >= max_n_of_items) break P.remove_from_storage(G,src) item_quants[G.name]++ + if(item_quants[G.name] == 1) + update_static_data = TRUE plants_loaded++ if(plants_loaded) user.visible_message("[user] loads [src] with [P].", SPAN_NOTICE("You load [src] with [P].")) if(length(P.contents) > 0) to_chat(user, SPAN_NOTICE("Some items are refused.")) update_overlays() + if(update_static_data) + update_static_data_for_all_viewers() return TRUE to_chat(user, SPAN_NOTICE("[src] smartly refuses [attacking_item].")) return TRUE @@ -416,22 +452,59 @@ /obj/machinery/smartfridge/ui_data(mob/user) var/list/data = list() - data["contents"] = null data["electrified"] = seconds_electrified > 0 data["shoot_inventory"] = shoot_inventory data["locked"] = locked data["secure"] = is_secure data["sort_alphabetically"] = ui_sort_alphabetically - var/list/items = list() - for (var/i = 1 to length(item_quants)) + var/list/stocks + for (var/i in 1 to length(item_quants)) var/K = item_quants[i] var/count = item_quants[K] if(count > 0) - items.Add(list(list("display_name" = capitalize(K), "vend" = i, "quantity" = count))) + LAZYADDASSOC(stocks, capitalize(K), count) + + data["stocks"] = stocks + + return data + +/obj/machinery/smartfridge/ui_static_data(mob/user) + var/list/data = list() + data["contents"] = null + + var/list/items = list() + for (var/i = 1 to length(item_quants)) + var/K = item_quants[i] + var/obj/item/item_used = null + for (var/obj/item/O in contents - component_parts) + if(O.name == K) + item_used = O + break + + if(!item_used) + continue + + var/final_icon = base64_cache["[K]_[item_used.type]_[item_used.icon_state]"] + if(!final_icon) + var/icon/item_icon + if(istype(item_used, /obj/item/seeds)) + var/obj/item/seeds/S = item_used + item_icon = S.update_appearance(TRUE) + else + item_icon = getFlatIcon(item_used) + final_icon = icon2base64(item_icon) + base64_cache["[K]_[item_used.type]_[item_used.icon_state]"] = final_icon + + items.Add(list(list( + "display_name" = capitalize(K), + "vend" = i, + "icon" = final_icon, + ))) if(length(items) > 0) data["contents"] = items + return data /obj/machinery/smartfridge/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) @@ -472,6 +545,10 @@ update_overlays() if(i <= 0) break + + if(item_quants[K] <= 0) + update_static_data_for_all_viewers() + item_quants -= K if("switch_sort_alphabetically") ui_sort_alphabetically = !ui_sort_alphabetically @@ -485,6 +562,7 @@ for (var/O in item_quants) if(item_quants[O] <= 0) //Try to use a record that actually has something to dump. + item_quants -= O continue item_quants[O]-- @@ -493,6 +571,10 @@ T.forceMove(loc) throw_item = T break + + if(item_quants[O] <= 0) + update_static_data_for_all_viewers() + item_quants -= O break if(!throw_item) return FALSE @@ -519,6 +601,7 @@ icon = 'icons/obj/structure/urban/restaurant.dmi' icon_state = "buffet" contents_path = null + has_emissive = FALSE /obj/machinery/smartfridge/foodheater/buffet/Initialize() . = ..() diff --git a/code/modules/cooking/recipes/cultural/recipes_human.dm b/code/modules/cooking/recipes/cultural/recipes_human.dm index 4d09176eb83f..5533b0121740 100644 --- a/code/modules/cooking/recipes/cultural/recipes_human.dm +++ b/code/modules/cooking/recipes/cultural/recipes_human.dm @@ -221,6 +221,12 @@ result = /obj/item/reagent_containers/food/snacks/jambalaya reagent_mix = RECIPE_REAGENT_REPLACE //Simplify end product +/singleton/recipe/churros + appliance = FRYER + reagents = list(/singleton/reagent/nutriment/coating/batter = 5, /singleton/reagent/sugar = 5) + reagent_mix = RECIPE_REAGENT_REPLACE + result = /obj/item/reagent_containers/food/snacks/chipplate/churros + // Konyang /singleton/recipe/mossbowl @@ -460,7 +466,7 @@ /obj/item/reagent_containers/food/snacks/breadslice, /obj/item/reagent_containers/food/snacks/bacon ) - result = /obj/item/reagent_containers/food/snacks/clams_casino + result = /obj/item/reagent_containers/food/snacks/bowl/clams_casino reagent_mix = RECIPE_REAGENT_REPLACE //Simplify and replace /singleton/recipe/lady_lulaine @@ -544,7 +550,7 @@ reagents = list(/singleton/reagent/blackpepper = 2, /singleton/reagent/spacespice = 2, /singleton/reagent/alcohol/beer = 5) items = list( /obj/item/reagent_containers/food/snacks/fish/fishfillet, - /obj/item/reagent_containers/food/snacks/clam, + /obj/item/reagent_containers/food/snacks/fish/mollusc, /obj/item/reagent_containers/food/snacks/crabmeat ) @@ -654,3 +660,45 @@ ) reagent_mix = RECIPE_REAGENT_REPLACE result = /obj/item/reagent_containers/food/snacks/bowl/belinas + +//Venus + +/singleton/recipe/elata + appliance = MIX + reagents = list(/singleton/reagent/drink/berryjuice = 5, /singleton/reagent/drink/ice = 5, /singleton/reagent/drink/milk/cream = 5, /singleton/reagent/nutriment/vanilla = 5, /singleton/reagent/sugar = 10) + items = list( + /obj/item/reagent_containers/food/snacks/whitechocolate + ) + reagent_mix = RECIPE_REAGENT_REPLACE + result = /obj/item/reagent_containers/food/snacks/elata + +/singleton/recipe/filet_cabaret + appliance = SKILLET + fruit = list ("garlic" = 1) + reagents = list(/singleton/reagent/alcohol/wine/assunzione = 5, /singleton/reagent/drink/milk/cream = 5, /singleton/reagent/blackpepper = 1, /singleton/reagent/sodiumchloride = 1) + items = list( + /obj/item/reagent_containers/food/snacks/rawcutlet, + /obj/item/reagent_containers/food/snacks/spreads/butter + ) + reagent_mix = RECIPE_REAGENT_REPLACE + result = /obj/item/reagent_containers/food/snacks/filet_cabaret + +/singleton/recipe/embassy_strips + appliance = SKILLET + fruit = list ("lemon" = 1, "soybeans" = 1, "dyn leaf" = 1) + reagents = list(/singleton/reagent/enzyme = 5, /singleton/reagent/nutriment/mayonnaise = 5) + items = list( + /obj/item/reagent_containers/food/snacks/fish + ) + reagent_mix = RECIPE_REAGENT_REPLACE + result = /obj/item/reagent_containers/food/snacks/embassy_strips + +/singleton/recipe/blitz_shake + appliance = MIX + reagents = list(/singleton/reagent/drink/shake_strawberry = 30, /singleton/reagent/nutriment/sprinkles = 3, /singleton/reagent/drink/milk/cream = 5) + items = list( + /obj/item/reagent_containers/food/snacks/candy, + /obj/item/reagent_containers/food/snacks/donut + ) + reagent_mix = RECIPE_REAGENT_REPLACE + result = /obj/item/reagent_containers/food/snacks/blitz_shake diff --git a/code/modules/cooking/recipes/cultural/recipes_tajara.dm b/code/modules/cooking/recipes/cultural/recipes_tajara.dm index 3cbd304a1796..9acab270fa62 100644 --- a/code/modules/cooking/recipes/cultural/recipes_tajara.dm +++ b/code/modules/cooking/recipes/cultural/recipes_tajara.dm @@ -171,7 +171,7 @@ reagents = list(/singleton/reagent/drink/milk/adhomai = 5, /singleton/reagent/sugar = 5) items = list( /obj/item/reagent_containers/food/snacks/dough, - /obj/item/reagent_containers/food/snacks/cheesewedge + /obj/item/reagent_containers/food/snacks/adhomian_cheese_wedge ) result = /obj/item/reagent_containers/food/snacks/avah @@ -415,3 +415,25 @@ reagents = list(/singleton/reagent/nutriment/gelatin = 5, /singleton/reagent/water = 5, /singleton/reagent/spacespice = 1) reagent_mix = RECIPE_REAGENT_REPLACE result = /obj/item/reagent_containers/food/snacks/chipplate/crownfurter + +/singleton/recipe/cheesebake + appliance = OVEN + fruit = list("dirtberries" = 1, "earthenroot" = 1) + items = list( + /obj/item/reagent_containers/food/snacks/tajaran_bread, + /obj/item/reagent_containers/food/snacks/adhomian_cheese_wedge, + /obj/item/reagent_containers/food/snacks/adhomian_cheese_wedge + ) + reagent_mix = RECIPE_REAGENT_REPLACE + result = /obj/item/reagent_containers/food/snacks/sliceable/cheesebake + +/singleton/recipe/cheese_twig + appliance = OVEN + reagents = list(/singleton/reagent/sodiumchloride = 2) + items = list( + /obj/item/reagent_containers/food/snacks/tajaran_bread, + /obj/item/reagent_containers/food/snacks/adhomian_cheese_wedge + ) + result_quantity = 2 + reagent_mix = RECIPE_REAGENT_REPLACE + result = /obj/item/reagent_containers/food/snacks/cheese_twig diff --git a/code/modules/cooking/recipes/cultural/recipes_unathi.dm b/code/modules/cooking/recipes/cultural/recipes_unathi.dm index 2740b0ff7795..a2631744e25c 100644 --- a/code/modules/cooking/recipes/cultural/recipes_unathi.dm +++ b/code/modules/cooking/recipes/cultural/recipes_unathi.dm @@ -41,7 +41,7 @@ /singleton/recipe/father_breakfast items = list( /obj/item/reagent_containers/food/snacks/sausage, - /obj/item/reagent_containers/food/snacks/omelette, + /obj/item/reagent_containers/food/snacks/omelette/fromage, /obj/item/reagent_containers/food/snacks/meatsteak ) result = /obj/item/reagent_containers/food/snacks/father_breakfast @@ -81,7 +81,7 @@ /obj/item/reagent_containers/food/snacks/meatball, /obj/item/reagent_containers/food/snacks/meatball, /obj/item/reagent_containers/food/snacks/meatball, - /obj/item/reagent_containers/food/snacks/omelette + /obj/item/reagent_containers/food/snacks/omelette/fromage ) result = /obj/item/reagent_containers/food/snacks/egg_pancake diff --git a/code/modules/cooking/recipes/recipes_eggs.dm b/code/modules/cooking/recipes/recipes_eggs.dm index a3b782aa609a..1e56c216bfd8 100644 --- a/code/modules/cooking/recipes/recipes_eggs.dm +++ b/code/modules/cooking/recipes/recipes_eggs.dm @@ -40,6 +40,19 @@ result = /obj/item/reagent_containers/food/snacks/bacon_and_eggs /singleton/recipe/omelette + appliance = SKILLET + reagents = list(/singleton/reagent/nutriment/protein/egg = 6, /singleton/reagent/drink/milk = 5) + reagent_mix = RECIPE_REAGENT_REPLACE + result = /obj/item/reagent_containers/food/snacks/omelette + +/singleton/recipe/omelette_veggie + appliance = SKILLET + fruit = list("onion" = 1) //if herbs ever get added to the game please add them to this recipe + reagents = list(/singleton/reagent/nutriment/protein/egg = 3, /singleton/reagent/drink/milk = 5) + reagent_mix = RECIPE_REAGENT_REPLACE + result = /obj/item/reagent_containers/food/snacks/omelette/veggie + +/singleton/recipe/omelette_du_fromage appliance = SKILLET items = list( /obj/item/reagent_containers/food/snacks/cheesewedge, @@ -47,7 +60,7 @@ ) reagents = list(/singleton/reagent/nutriment/protein/egg = 6) reagent_mix = RECIPE_REAGENT_REPLACE - result = /obj/item/reagent_containers/food/snacks/omelette + result = /obj/item/reagent_containers/food/snacks/omelette/fromage /singleton/recipe/poachedegg appliance = SKILLET | SAUCEPAN diff --git a/code/modules/cooking/recipes/recipes_fryer.dm b/code/modules/cooking/recipes/recipes_fryer.dm index fccbdd8dc8a3..de32765d9b70 100644 --- a/code/modules/cooking/recipes/recipes_fryer.dm +++ b/code/modules/cooking/recipes/recipes_fryer.dm @@ -109,6 +109,15 @@ ) result = /obj/item/reagent_containers/food/snacks/fried_pickles +/singleton/recipe/poutine + appliance = MIX + reagents = list(/singleton/reagent/condiment/gravy = 5) + items = list( + /obj/item/reagent_containers/food/snacks/fries, + /obj/item/reagent_containers/food/snacks/cheesewedge + ) + result = /obj/item/reagent_containers/food/snacks/poutine + //Fishy Recipes //================== /singleton/recipe/fishandchips diff --git a/code/modules/cooking/recipes/recipes_ingredients.dm b/code/modules/cooking/recipes/recipes_ingredients.dm index e2012795387d..ea5599379440 100644 --- a/code/modules/cooking/recipes/recipes_ingredients.dm +++ b/code/modules/cooking/recipes/recipes_ingredients.dm @@ -32,3 +32,9 @@ reagents = list(/singleton/reagent/enzyme = 5) result = /obj/item/reagent_containers/food/snacks/pickle reagent_mix = RECIPE_REAGENT_REPLACE + +/singleton/recipe/dough //A vegan alternative to the eggs and flour method + appliance = MIX + reagents = list(/singleton/reagent/nutriment/flour = 10, /singleton/reagent/water = 5) + result = /obj/item/reagent_containers/food/snacks/dough + reagent_mix = RECIPE_REAGENT_REPLACE diff --git a/code/modules/cooking/recipes/recipes_mix.dm b/code/modules/cooking/recipes/recipes_mix.dm index 13240419a407..1e7bcb626f9f 100644 --- a/code/modules/cooking/recipes/recipes_mix.dm +++ b/code/modules/cooking/recipes/recipes_mix.dm @@ -44,9 +44,9 @@ // Salads -/singleton/recipe/tossedsalad +/singleton/recipe/applesalad fruit = list("cabbage" = 2, "tomato" = 1, "carrot" = 1, "apple" = 1) - result = /obj/item/reagent_containers/food/snacks/salad/tossedsalad + result = /obj/item/reagent_containers/food/snacks/salad/applesalad /singleton/recipe/aesirsalad fruit = list("goldapple" = 1, "ambrosiadeus" = 1) diff --git a/code/modules/cooking/recipes/recipes_pizza.dm b/code/modules/cooking/recipes/recipes_pizza.dm index 0d76ca6c808b..0da8410f37ff 100644 --- a/code/modules/cooking/recipes/recipes_pizza.dm +++ b/code/modules/cooking/recipes/recipes_pizza.dm @@ -104,6 +104,18 @@ ) result = /obj/item/reagent_containers/food/snacks/bacon_flatbread +/singleton/recipe/chocolate_pizza + appliance = OVEN + reagents = list(/singleton/reagent/nutriment/sprinkles = 2) + items = list( + /obj/item/reagent_containers/food/snacks/sliceable/flatdough, + /obj/item/reagent_containers/food/snacks/chocolatebar, + /obj/item/reagent_containers/food/snacks/chocolatebar, + /obj/item/reagent_containers/food/snacks/candy + ) + reagent_mix = RECIPE_REAGENT_REPLACE + result = /obj/item/reagent_containers/food/snacks/sliceable/pizza/chocolate_pizza + //Deep Dish /singleton/recipe/deepdish_margherita diff --git a/code/modules/cooking/recipes/recipes_processed.dm b/code/modules/cooking/recipes/recipes_processed.dm index 54b404129385..a69a1ff36d65 100644 --- a/code/modules/cooking/recipes/recipes_processed.dm +++ b/code/modules/cooking/recipes/recipes_processed.dm @@ -3,6 +3,30 @@ fruit = list("corn" = 1) result = /obj/item/reagent_containers/food/snacks/popcorn +/singleton/recipe/popcorn_chocolate + appliance = MIX + reagents = list(/singleton/reagent/condiment/syrup_chocolate = 5) + items = list( + /obj/item/reagent_containers/food/snacks/popcorn + ) + result = /obj/item/reagent_containers/food/snacks/popcorn/chocolate + +/singleton/recipe/popcorn_caramel + appliance = MIX + reagents = list(/singleton/reagent/condiment/syrup_caramel = 5) + items = list( + /obj/item/reagent_containers/food/snacks/popcorn + ) + result = /obj/item/reagent_containers/food/snacks/popcorn/caramel + +/singleton/recipe/popcorn_cheese + appliance = MIX + reagents = list(/singleton/reagent/nutriment/protein/cheese = 5) + items = list( + /obj/item/reagent_containers/food/snacks/popcorn + ) + result = /obj/item/reagent_containers/food/snacks/popcorn/cheese + // Jellies /singleton/recipe/amanitajelly appliance = SAUCEPAN | MICROWAVE diff --git a/code/modules/custom_ka/core.dm b/code/modules/custom_ka/core.dm index 0860db6acde2..83e4c261c3e0 100644 --- a/code/modules/custom_ka/core.dm +++ b/code/modules/custom_ka/core.dm @@ -241,7 +241,7 @@ if(T) var/datum/gas_mixture/environment = T.return_air() - var/pressure = (environment)? environment.return_pressure() : 0 + var/pressure = SAFE_XGM_PRESSURE(environment) if(ispath(installed_barrel.projectile_type, /obj/projectile/kinetic)) var/obj/projectile/kinetic/shot_projectile = new installed_barrel.projectile_type(get_turf(src)) shot_projectile.damage = damage_increase diff --git a/code/modules/custom_ka/projectiles.dm b/code/modules/custom_ka/projectiles.dm index 58cd35294dd3..453e1b8d0387 100644 --- a/code/modules/custom_ka/projectiles.dm +++ b/code/modules/custom_ka/projectiles.dm @@ -30,7 +30,7 @@ /obj/projectile/kinetic/proc/do_damage(var/turf/T, var/living_damage = 1, var/mineral_damage = 1) if(!istype(T)) return var/datum/gas_mixture/environment = T.return_air() - living_damage *= max(1 - (environment.return_pressure() / 100) * 0.75, 0) + living_damage *= max(1 - (XGM_PRESSURE(environment) / 100) * 0.75, 0) new /obj/effect/overlay/temp/kinetic_blast(T) for(var/mob/living/L in T) L.take_overall_damage(min(living_damage, 50)) diff --git a/code/modules/customitems/imogen_guiltymen.txt b/code/modules/customitems/imogen_guiltymen.txt deleted file mode 100644 index 6fe7ccd391b7..000000000000 --- a/code/modules/customitems/imogen_guiltymen.txt +++ /dev/null @@ -1,18 +0,0 @@ -...on one side a resurgent Sol, on the other an expanding Biesel, and the last an imperious Dominia. We are Isolated and alone, led here through the failures, and sins of Guilty Men. -...we were victorious! At the peak of its power and glory, Sol found itself humbled through the efforts of the people of the frontier, with nothing but retrofitted freighters, and a handful of defectors. Look at where we find ourselves today, what would the victors of Xansan think of what we’ve done with that hard-won freedom? -If our noble Coalition is ever to falter, and stumble it will be our own fault. When we needed most to change, to adapt, we instead bickered with one-another over the smallest of details as the shadows closed in... -Leaders? And what leadership have they shown us? Through their inaction they have shrugged that responsibility from their shoulders, and we the people suffer the consequences. I ask again, what leaders? -And what if the Strelitz had faced the Grand Army in Fisanduh? Would we face that petty gaggle of tyrants, and despots from across the Badlands? The answer is obvious, yet now we must reap the bounty of our inaction. -Mictlan, Port Antilles, and how many others now suffer under the yolk of corporate tyranny rather than flourishing amidst the freedom of the frontier? Is this what our forefathers fought for? Passivity and inaction? -..I think the argument has been laid plain, the evidence held bare. Now we all might agree it is time for the Guilty Men to retire, and allow the ship of state to be steered by those more able. -And who might the blame be laid upon for these crimes? Chief Sianne, First-Speaker Helminen, Presiden Afza and dozens more whose sins will be laid bare in these pages … -...at what point might we finally admit that the tepid response of diplomats might have a limit? When might we finally realize that our values might need defense with blood, and force-of-arms, not words? -...so I ask, how much longer might we gaze across the frontier and utter ‘Not our business’ as those theocrats, and warlords in Dominia ransack free colonies? How many worlds will we abandon to the whims of these petty despots? -...should our Coalition continue upon its current path; that of inaction, of delay, wrapped in the cloak of political theater, then we will come to a precipice. That is not alarmism, it is a reality we will have to face, within our own lifetimes. -In mankind’s history, it has been the indifference of those that have known better; the silence of the voice of justice when it mattered the utmost, that has made possible for the great evils of our people to arise. We can ill afford more silence. -...On our horizon lies a gathering storm. The sky above dark and frightening, looming over us with ill intent, engulfing all hope within its smothering embrace. The earth below shudders with unrestrained fury, our feet unsteady, and weak in its wake. Yet we needn’t have been set upon this path, had steadier hands steered our course... -...there is nothing in the universe with a shorter half-life than a politician's memory for inconvenient facts. Yet their unwillingness to face these inconvenient truths does nothing to shield us from them, if they do nothing, we must find those who will. -Some might label those who come to believe as we do, know as we do, as extremists. Yet it is imperative to remember that our society has had decades to seek a less drastic course, and instead it has done nothing. As we near a precipice, radical action must be considered. -Those who look upon this book, and the solutions offered within with scorn must face one simple, elegant truth. Not one man, woman, or child within this Spur can make the truth untrue, simply because it is painful to face. -Given the foes that look upon us with malice, greed, and hate from every corner of the Spur, I think it time to consider that in measures such as foreign policy, and military operations, the decentralized nature of our Coalition has failed us. A federal structure might serve us on the interstellar stage, and allow us to defend ourselves abroad, while preserving our liberty at home... -...And too we must see to change within our great Coalition. A hundred member states feud at times with a hundred more, we must take action! So that when the time comes, our foes face a united Coalition, bound with amity, held together with common need, and common purpose... \ No newline at end of file diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm index 9fbf73a4d95d..c56bb7d1bd5e 100644 --- a/code/modules/customitems/item_defines.dm +++ b/code/modules/customitems/item_defines.dm @@ -5,16 +5,6 @@ Add custom items to this file, their sprites into their own dmi. in the icons/ob All custom items with worn sprites must follow the contained sprite system: http://forums.aurorastation.org/viewtopic.php?f=23&t=6798 */ -/obj/item/clothing/suit/armor/vest/fluff/zubari_jacket //Fancy Jacket - Zubari Akenzua - filthyfrankster - name = "fancy jacket" - desc = "A well tailored unathi styled armored jacket, fitted for one too." - icon = 'icons/obj/custom_items/zubari_jacket.dmi' - icon_override = 'icons/obj/custom_items/zubari_jacket.dmi' - icon_state = "zubari_jacket" - item_state = "zubari_jacket" - contained_sprite = TRUE - - /obj/item/implanter/fluff //snowflake implanters for snowflakes var/allowed_ckey = "" var/implant_type = null @@ -84,25 +74,6 @@ All custom items with worn sprites must follow the contained sprite system: http contained_sprite = TRUE -/obj/item/clothing/head/det/fluff/leo_hat //Tagged brown hat - Leo Wyatt - keinto - name = "tagged brown hat" - desc = "A worn mid 20th century brown hat. If you look closely at the back, you can see a an embedded tag from the \"Museum of Terran Culture and Technology\"." - icon = 'icons/obj/custom_items/leo_coat.dmi' - icon_override = 'icons/obj/custom_items/leo_coat.dmi' - icon_state = "leo_hat" - item_state = "leo_hat" - contained_sprite = TRUE - -/obj/item/clothing/suit/storage/det_trench/fluff/leo_coat //Tagged brown coat - Leo Wyatt - keinto - name = "tagged brown coat" - desc = "A worn mid 20th century brown trenchcoat. If you look closely at bottom of the back, you can see an embedded tag from the \"Museum of Terran Culture and Technology\"." - icon = 'icons/obj/custom_items/leo_coat.dmi' - icon_override = 'icons/obj/custom_items/leo_coat.dmi' - icon_state = "leo_coat" - item_state = "leo_coat" - contained_sprite = TRUE - - /obj/item/reagent_containers/glass/beaker/teapot/fluff/brianne_teapot //Ceramic Teapot - Sean Brianne - zelmana name = "ceramic teapot" desc = "A blue ceramic teapot, gilded with the abbreviation for NanoTrasen." @@ -149,54 +120,6 @@ All custom items with worn sprites must follow the contained sprite system: http . += "It is [active ? "on" : "off"]." -/obj/item/clothing/suit/storage/fluff/vira_coat //Designer Military Coat - Vira Bolivar - scheveningen - name = "designer military coat" - desc = "A dark funnel neck designer military-style dress coat, specially fitted on commission, clearly designed for a woman's figure. \ - A skillfully stitched 'NT' pattern is laden above a chest pocket, the phrase \"15 years of loyal service to the Corp\" below the insignia, followed by the personal signature of \"Vira Bolivar Taryk\"." - icon = 'icons/obj/custom_items/vira_coat.dmi' - icon_override = 'icons/obj/custom_items/vira_coat.dmi' - icon_state = "vira_coat" - item_state = "vira_coat" - contained_sprite = TRUE - - -/obj/item/clothing/suit/fluff/leo_scarf //Scarf - Leo Wyatt - keinto - name = "striped scarf" - desc = "A soft scarf striped in black and blue." - icon = 'icons/obj/custom_items/leo_scarf.dmi' - icon_override = 'icons/obj/custom_items/leo_scarf.dmi' - icon_state = "leo_scarf" - item_state = "leo_scarf" - contained_sprite = TRUE - - -/obj/item/clothing/wrists/watch/fluff/rex_watch //Engraved Wristwatch - Rex Winters - tailson - name = "engraved wristwatch" - desc = "A fine gold watch. On the inside is an engraving that reads \"Happy birthday dad, thinking of you always\"." - icon = 'icons/obj/custom_items/rex_watch.dmi' - icon_override = 'icons/obj/custom_items/rex_watch.dmi' - icon_state = "rex_watch" - - -/obj/item/camera/fluff/hadley_camera //Hadley's Camera - Hadley Dawson - fekkor - name = "customized camera" - desc = "A early 2450's Sunny camera with an adjustable lens, this one has a sticker with the name \"Hadley\" on the back." - icon = 'icons/obj/custom_items/hadley_camera.dmi' - icon_override = 'icons/obj/custom_items/hadley_camera.dmi' - icon_state = "hadley_camera" - icon_on = "hadley_camera" - icon_off = "hadley_camera_off" - - -/obj/item/clothing/accessory/holster/thigh/fluff/rifler_holster //Rifler's Holster - Sophie Rifler - shodan43893 - name = "tan leather thigh holster" - desc = "A version of the security thigh holster done up in tan leather - this one appears to have the word \"Rifler\" engraved down the side. It appears to be rather well made and hard wearing; more of a worker's holster than a show piece." - icon = 'icons/obj/custom_items/rifler_holster.dmi' - icon_override = 'icons/obj/custom_items/rifler_holster.dmi' - icon_state = "rifler_holster" - contained_sprite = TRUE - - /obj/item/storage/backpack/satchel/fluff/xerius_bag //Tote Bag - Shiur'izzi Xerius - witchebells name = "tote bag" desc = "A sackcloth bag with an image of Moghes printed onto it. Floating above the planet are the words \"Save Moghes!\"." @@ -207,27 +130,6 @@ All custom items with worn sprites must follow the contained sprite system: http contained_sprite = TRUE -/obj/item/clothing/mask/fluff/ird_mask //Titanium Faceplate - IRD - kyres1 - name = "titanium faceplate" - desc = "An odd mask seeming to mimic the face of a Human with some artistic liberties taken. Small lights keep it dimly illuminated from within with holographic projectors emulating two bright blue eyes. \ - Its rigid frame is composed of what looks like polished titanium." - icon = 'icons/obj/custom_items/ird_face.dmi' - icon_override = 'icons/obj/custom_items/ird_face.dmi' - icon_state = "ird_mask" - item_state = "ird_mask" - contained_sprite = TRUE - flags_inv = HIDEEARS|HIDEFACE - body_parts_covered = FACE - w_class = WEIGHT_CLASS_NORMAL - - -/obj/item/flame/lighter/zippo/fluff/nikit_zippo //Vasili Mine Zippo - Nikit Vasili - sampletex - desc = "An old looking zippo lighter with Vasili Mine Logo engraved on it. \"Good Luck Nikit\" is crudely scratched on under the logo in small writing." - icon = 'icons/obj/custom_items/nikit_zippo.dmi' - icon_override = 'icons/obj/custom_items/nikit_zippo.dmi' - icon_state = "nikit_zippo" - - /obj/item/clothing/accessory/locket/fluff/klavdiya_amulet //Moon Shaped Amulet - Klavdiya Tikhomirov - alberyk name = "moon shaped amulet" desc = "A metalic necklace that bears a silver moon shapped pendant." @@ -237,35 +139,6 @@ All custom items with worn sprites must follow the contained sprite system: http contained_sprite = TRUE -/obj/item/clothing/suit/storage/toggle/fluff/talon_coat //Embroidered Coat - Talon Hatfield - dronzthewolf - name = "embroidered coat" - desc = " Martian long coat, made to fend off dust storms and other unpleasantries. This one has a few patches sewn into it depicting: A Solarian flag, a Batallion number, and a large sun." - icon = 'icons/obj/custom_items/talon_coat.dmi' - icon_override = 'icons/obj/custom_items/talon_coat.dmi' - icon_state = "talon_coat" - item_state = "talon_coat" - contained_sprite = TRUE - - -/obj/item/storage/backpack/cloak/fluff/ryn_cloak //Security Tunnel Cloak - Za'Akaix'Ryn Zo'ra - jamchop23334 - name = "security tunnel cloak" - desc = "A blue, tailor-made tunnel cloak with paltry storage options. The fabric is smoother and less abrasive than regular tunnel cloaks, though it looks difficult to wear." - icon = 'icons/obj/custom_items/ryn_clothing.dmi' - icon_override = 'icons/obj/custom_items/ryn_clothing.dmi' - icon_state = "ryn_cloak" - item_state = "ryn_cloak" - contained_sprite = TRUE - -/obj/item/clothing/head/fluff/ryn_hood //Security Tunnel Hood - Za'Akaix'Ryn Zo'ra - jamchop23334 - name = "security tunnel hood" - desc = "A silky smooth blue hood, though its more of a headwrap. You're having a hard time wrapping your head around how to wear this." - icon = 'icons/obj/custom_items/ryn_clothing.dmi' - icon_override = 'icons/obj/custom_items/ryn_clothing.dmi' - icon_state = "ryn_hood" - item_state = "ryn_hood" - contained_sprite = TRUE - - /obj/item/sign/fluff/tokash_sign //Shark Jaw Trophy - Suvek Tokash - evandorf name = "shark jaw trophy" desc = "A pair of jaws from what must have been a large and impressive shark." @@ -274,18 +147,6 @@ All custom items with worn sprites must follow the contained sprite system: http w_class = WEIGHT_CLASS_SMALL -/obj/item/clothing/head/fluff/aavs_mask //Reflective Mask - Aavs Guwan - dronzthewolf - name = "reflective mask" - desc = "This odd mask and hood combination covers the wearer, and seems to be made of a one-way dome mirror and some old cloth or rope." - icon = 'icons/obj/custom_items/aavs_mask.dmi' - icon_override = 'icons/obj/custom_items/aavs_mask.dmi' - icon_state = "aavs_mask" - item_state = "aavs_mask" - contained_sprite = TRUE - flags_inv = HIDEEARS|HIDEFACE|BLOCKHAIR|BLOCKHEADHAIR - body_parts_covered = HEAD|FACE|EYES - - /obj/item/cane/fluff/qrqil_cane //Energy Cane - Qrqil Qrrzix - yonnimer name = "energy cane" desc = "This silver-handled cane has letters carved into the sides." @@ -322,35 +183,6 @@ All custom items with worn sprites must follow the contained sprite system: http item_state = icon_state -/obj/item/clothing/accessory/poncho/fluff/djar_cape //Zandiziite Cape - D'Jar Sa'Kuate - firstact - name = "zandiziite cape" - desc = "A dominian cape, with a clasp bearing the symbol of a champion Zandiziite wrestler. It looks well worn, of the finest material." - icon = 'icons/obj/custom_items/djar_cape.dmi' - icon_override = 'icons/obj/custom_items/djar_cape.dmi' - icon_state = "djar_cape" - item_state = "djar_cape" - contained_sprite = TRUE - - -/obj/item/clothing/suit/chaplain_hoodie/fluff/hidemichi_robes //Zen Monk Robes - Yoshihama Hidemichi - dobhranthedruid - name = "zen monk robes" - desc = "A traditional Soto Zen buddhist robes for meditation and services" - icon = 'icons/obj/custom_items/hidemichi_items.dmi' - icon_override = 'icons/obj/custom_items/hidemichi_items.dmi' - icon_state = "hidemichi_robes" - item_state = "hidemichi_robes" - contained_sprite = TRUE - -/obj/item/clothing/head/fluff/hidemichi_hat //Takuhatsugasa - Yoshihama Hidemichi - dobhranthedruid - name = "takuhatsugasa" - desc = "A dome shaped rice hat, this one is dyed a darker color." - icon = 'icons/obj/custom_items/hidemichi_items.dmi' - icon_override = 'icons/obj/custom_items/hidemichi_items.dmi' - icon_state = "hidemichi_hat" - item_state = "hidemichi_hat" - contained_sprite = TRUE - - /obj/item/radio/headset/fluff/resolve_headset //Antennae - Decisive Resolve - itanimulli name = "antennae" desc = "Collapsible spherical antennae designed to interface with an IPC." @@ -480,66 +312,6 @@ All custom items with worn sprites must follow the contained sprite system: http item_state = "khasan_helmet" contained_sprite = TRUE - -/obj/item/synthesized_instrument/guitar/multi/fluff/akinyi_symphette //Holo-symphette - Akinyi Idowu - kyres1 - name = "holo-symphette" - desc = "A cheap, collapsible musical instrument which utilizes holographic projections to generate a rough noise. It's shaped like a small harp, and seems to be \ - able to be tuned to mimic several old stringed Solarian instruments with some distorted audio. It's still got its price tag sticker on it." - icon = 'icons/obj/custom_items/akinyi_symphette.dmi' - icon_override = 'icons/obj/custom_items/akinyi_symphette.dmi' - icon_state = "akinyi_symphette" - item_state = "akinyi_symphette" - w_class = WEIGHT_CLASS_NORMAL - slot_flags = SLOT_BACK - contained_sprite = TRUE - var/deployed = FALSE - -/obj/item/synthesized_instrument/guitar/multi/fluff/akinyi_symphette/update_icon() - if(deployed) - icon_state = "akinyi_symphette_on" - item_state = "akinyi_symphette_on" - else - icon_state = "akinyi_symphette" - item_state = "akinyi_symphette" - -/obj/item/synthesized_instrument/guitar/multi/fluff/akinyi_symphette/AltClick(var/mob/user) - deployed = !deployed - to_chat(user, SPAN_NOTICE("You [deployed ? "expand" : "collapse"] \the [src].")) - update_icon() - user.update_inv_l_hand() - user.update_inv_r_hand() - -/obj/item/reagent_containers/glass/beaker/teapot/fluff/thea_teapot //Bronze Teapot - Thea Reeves - shestrying - name = "bronze teapot" - desc = "A round-bottomed, well-used teapot. It looks as though it's been carefully maintained." - icon = 'icons/obj/custom_items/thea_tea.dmi' - icon_override = 'icons/obj/custom_items/thea_tea.dmi' - icon_state = "thea_teapot" - center_of_mass = list("x"=16, "y"=13) - -/obj/item/reagent_containers/food/drinks/fluff/thea_teacup //Bonze Teacup - Thea Reeves - shestrying - name = "bronze teacup" - desc = "A shallow, bronze teacup. Looks heavy." - icon = 'icons/obj/custom_items/thea_tea.dmi' - icon_override = 'icons/obj/custom_items/thea_tea.dmi' - icon_state = "thea_teacup" - volume = 20 - center_of_mass = list("x"=16, "y"=12) - -/obj/item/storage/box/fluff/thea_teabox //Tea Box - Thea Reeves - shestrying - desc = "A black, wooden box, the edges softened with transport and use." - icon = 'icons/obj/custom_items/thea_tea.dmi' - icon_override = 'icons/obj/custom_items/thea_tea.dmi' - icon_state = "thea_teabox" - foldable = null - can_hold = list(/obj/item/reagent_containers/glass/beaker/teapot/fluff/thea_teapot, /obj/item/reagent_containers/food/drinks/fluff/thea_teacup) - make_exact_fit = TRUE - -/obj/item/storage/box/fluff/thea_teabox/fill() - new /obj/item/reagent_containers/glass/beaker/teapot/fluff/thea_teapot(src) - for(var/i in 1 to 4) - new /obj/item/reagent_containers/food/drinks/fluff/thea_teacup(src) - /obj/item/fluff/fraseq_journal //Fraseq's Journal of Mysteries - Quorrdash Fraseq - kingoftheping name = "leather journal" desc = "An old, worn out journal made out of leather. It has a lot of lose pages stuck in it, it surely has seen better days. The front just says \"Fraseq\"." @@ -548,7 +320,6 @@ All custom items with worn sprites must follow the contained sprite system: http icon_state = "fraseq_journal" w_class = WEIGHT_CLASS_NORMAL - /obj/item/clothing/accessory/poncho/fluff/ioraks_cape //Iorakian Cape - Kuhserze Ioraks - geeves name = "iorakian cape" desc = "A tough leather cape, with neat colours of the Ioraks clan threaded through the seams." @@ -559,18 +330,6 @@ All custom items with worn sprites must follow the contained sprite system: http contained_sprite = TRUE -/obj/item/clothing/suit/storage/fluff/strauss_jacket //Custom Firesuit - Lena Strauss - oddbomber3768 - name = "modified firesuit" - desc = "An old industrial firesuit belonging to a defunct and forgotten company. The wearer has sawn off both of the arms, added two buttons on the front and replaced the back name \ - tag with one reading \"FIREAXE\". Doesn't look really fire resistant anymore" - icon = 'icons/obj/custom_items/strauss_jacket.dmi' - icon_override = 'icons/obj/custom_items/strauss_jacket.dmi' - icon_state = "strauss_jacket" - item_state = "strauss_jacket" - contained_sprite = TRUE - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS - - /obj/item/clothing/suit/storage/toggle/labcoat/fluff/likho_labcoat //Terraneus Diagnostics Labcoat - Likho - neworiginalschwann name = "terraneus diagnostics labcoat" desc = "A well-worn labcoat that marks its wearer as an employee of Terraneus Diagnostics, a subsidiary corporation of Einstein Engines. Text on the labcoat's breast pocket marks \ @@ -581,45 +340,6 @@ All custom items with worn sprites must follow the contained sprite system: http item_state = "likho_labcoat" -/obj/item/clothing/suit/storage/toggle/para_jacket/fluff/ramit_jacket //Winter paramedic Jacket - Ra'mit Ma'zaira - sampletex - name = "winter paramedic jacket" - desc = "A custom made paramedic coat. Inside is a warm fabric with the name \"Ra'Mit Ma'zaira\" sewn in by the collar." - icon = 'icons/obj/custom_items/ramit_jacket.dmi' - icon_override = 'icons/obj/custom_items/ramit_jacket.dmi' - icon_state = "ramit_jacket" - item_state = "ramit_jacket" - contained_sprite = TRUE - - -/obj/item/clothing/glasses/sunglasses/blindfold/fluff/nai_fold //Starvoice - Nai Eresh'Wake - jamchop23334 - name = "starvoid blindfold" - desc = "An ethereal purple blindfold, woven from an incredibly soft yet durable silk. The faintest of light shines through, shading your darkened vision in a haze of purple." - icon = 'icons/obj/custom_items/nai_items.dmi' - icon_override = 'icons/obj/custom_items/nai_items.dmi' - icon_state = "nai_fold" - item_state = "nai_fold" - contained_sprite = TRUE - tint = TINT_BLIND - drop_sound = 'sound/items/drop/gloves.ogg' - pickup_sound = 'sound/items/pickup/gloves.ogg' - -/obj/item/clothing/glasses/sunglasses/blindfold/fluff/nai_fold/equipped(mob/M as mob, slot) - if (M.ckey == "jamchop23334" && M.name == "Nai Eresh'Wake") - tint = TINT_NONE - else - tint = TINT_BLIND - ..() - -/obj/item/clothing/gloves/fluff/nai_gloves //Starvoid Gloves - Nai Eresh'Wake - jamchop23334 - name = "starvoid gloves" - desc = "An ethereal purple set of fingerless evening gloves, secured at the middle finger by a lace, with the palms exposed. The fabric is soft silk of some kind." - icon = 'icons/obj/custom_items/nai_items.dmi' - icon_override = 'icons/obj/custom_items/nai_items.dmi' - icon_state = "nai_gloves" - item_state = "nai_gloves" - contained_sprite = TRUE - - /obj/item/clothing/head/fluff/djikstra_hood //Stellar Hood - Msizi Djikstra - happyfox name = "stellar hood" desc = "A more encompassing version of the Starveil, made from a resilient xeno-silk, intended to protect not just the eyes but also the soul of the wearer." @@ -651,53 +371,6 @@ All custom items with worn sprites must follow the contained sprite system: http contained_sprite = TRUE -/obj/item/clothing/suit/fluff/naali_blanket //Fuzzy Pink Blanket - Naali'Xiiux Qu-Uish - shestrying - name = "fuzzy pink blanket" - desc = "A rather large, pink, fluffy blanket. It feels quite heavy, and smells slightly of saltwater." - icon = 'icons/obj/custom_items/naali_blanket.dmi' - icon_override = 'icons/obj/custom_items/naali_blanket.dmi' - icon_state = "naali_blanket" - item_state = "naali_blanket" - body_parts_covered = UPPER_TORSO|LOWER_TORSO - contained_sprite = TRUE - - -/obj/item/storage/box/fancy/fluff/sentiment_bouquet //Bouquet of Chrysanthemums - IRU-Sentiment - niennab - name = "bouquet of chrysanthemums" - desc = "A bouquet of white artificial chrysanthemum flowers wrapped in a sheet of newsprint." - icon = 'icons/obj/custom_items/sentiment_bouquet.dmi' - icon_override = 'icons/obj/custom_items/sentiment_bouquet.dmi' - icon_state = "sentiment_bouquet" - item_state = "sentiment_bouquet" - can_hold = list(/obj/item/clothing/accessory/fluff/sentiment_flower) - starts_with = list(/obj/item/clothing/accessory/fluff/sentiment_flower = 6) - storage_slots = 6 - contained_sprite = TRUE - drop_sound = 'sound/items/drop/gloves.ogg' - pickup_sound = 'sound/items/pickup/gloves.ogg' - use_sound = 'sound/items/storage/wrapper.ogg' - -/obj/item/storage/box/fancy/fluff/sentiment_bouquet/fill() - . = ..() - update_icon() - -/obj/item/storage/box/fancy/fluff/sentiment_bouquet/update_icon() - icon_state = "[initial(icon_state)]_[contents.len]" - if(contents.len) - item_state = initial(item_state) - else - item_state = "[initial(item_state)]_e" - -/obj/item/clothing/accessory/fluff/sentiment_flower //Artificial Chrysanthemum - IRU-Sentiment - niennab - name = "artificial chrysanthemum" - desc = "An artificial white chrysanthemum flower." - icon = 'icons/obj/custom_items/sentiment_bouquet.dmi' - icon_override = 'icons/obj/custom_items/sentiment_bouquet.dmi' - icon_state = "sentiment_flower" - item_state = "sentiment_flower" - contained_sprite = TRUE - - /obj/item/clothing/head/welding/fluff/ioraks_mask //Iorakian Welding Mask - Kuhserze Ioraks - geeves name = "iorakian welding mask" desc = "A modified version of the standard issue NanoTrasen Engineering Corps welding mask, hand-painted into the colours of the Ioraks clan. Various alterations are clearly \ @@ -787,118 +460,6 @@ All custom items with worn sprites must follow the contained sprite system: http to_chat(user, SPAN_NOTICE("You pick out a song in the folder and read the lyrics: [pick(lyrics)]")) -/obj/item/clothing/accessory/poncho/fluff/ozuha_cape //Victory Cape - Skavoss Ozuha - dronzthewolf - name = "victory cape" - desc = "A finely crafted cape that combines Ozuha clan colors and Izweski nation colors, with inscriptions on the decorative brass paldrons reading something in Sinta'Unathi." - icon = 'icons/obj/custom_items/ozuha_cape.dmi' - icon_override = 'icons/obj/custom_items/ozuha_cape.dmi' - icon_state = "ozuha_cape" - item_state = "ozuha_cape" - contained_sprite = TRUE - - -/obj/item/megaphone/fluff/akinyi_mic //Resonance Microphone - Akinyi Idowu - kyres1 - name = "resonance microphone" - desc = "A rather costly voice amplifier disguised as a microphone. A button on the side permits the user to dial their vocal volume with ease." - icon = 'icons/obj/custom_items/akinyi_symphette.dmi' - icon_override = 'icons/obj/custom_items/akinyi_symphette.dmi' - icon_state = "akinyi_mic" - item_state = "akinyi_mic" - w_class = WEIGHT_CLASS_SMALL - contained_sprite = TRUE - activation_sound = null - needs_user_location = FALSE - -/obj/item/fluff/akinyi_stand //Telescopic Mic Stand - Akinyi Idowu - kyres1 - name = "telescopic mic stand" - desc = "A fold-able telescopic microphone with a built in battery to keep your fancy science fiction microphone charged on the go." - icon = 'icons/obj/custom_items/akinyi_symphette.dmi' - icon_override = 'icons/obj/custom_items/akinyi_symphette.dmi' - icon_state = "akinyi_stand-collapsed" - item_state = "akinyi_stand-collapsed" - w_class = WEIGHT_CLASS_SMALL - contained_sprite = TRUE - var/obj/item/megaphone/fluff/akinyi_mic/mic - var/collapsed = TRUE - -/obj/item/fluff/akinyi_stand/attackby(obj/item/attacking_item, mob/user, params) - if(istype(attacking_item, /obj/item/megaphone/fluff/akinyi_mic)) - if(!mic && !collapsed) - user.unEquip(attacking_item) - attacking_item.forceMove(src) - mic = attacking_item - to_chat(user, SPAN_NOTICE("You place \the [attacking_item] on \the [src].")) - update_icon() - -/obj/item/fluff/akinyi_stand/mouse_drop_dragged(atom/over, mob/user, src_location, over_location, params) - if((over == user && (!use_check(over))) && (over.contents.Find(src) || in_range(src, over))) - if(ishuman(over)) - var/mob/living/carbon/human/H = over - forceMove(get_turf(H)) - H.put_in_hands(src) - update_icon() - -/obj/item/fluff/akinyi_stand/attack_hand(mob/user) - if(!isturf(loc)) //so if you want to play the use the board, you need to put it down somewhere - ..() - else - if(mic && !collapsed) - mic.attack_self(user) - -/obj/item/fluff/akinyi_stand/attack_self(mob/user as mob) - if(mic) - mic.forceMove(get_turf(src)) - user.put_in_hands(mic) - mic = null - update_icon() - return - - if(collapsed) - w_class = WEIGHT_CLASS_BULKY - collapsed = FALSE - else - w_class = WEIGHT_CLASS_SMALL - collapsed = TRUE - - update_icon() - user.update_inv_l_hand() - user.update_inv_r_hand() - -/obj/item/fluff/akinyi_stand/update_icon() - if(collapsed) - icon_state = "akinyi_stand-collapsed" - item_state = "akinyi_stand-collapsed" - else - if(mic) - icon_state = "akinyi_stand-1" - item_state = "akinyi_stand-1" - else - icon_state = "akinyi_stand-0" - item_state = "akinyi_stand-0" - -/obj/item/storage/fluff/akinyi_case //Instrument Case - Akinyi Idowu - kyres1 - name = "instrument case" - desc = "A chunky white leather case, with lots of space inside for holding your delicate musical instruments." - icon = 'icons/obj/custom_items/akinyi_symphette.dmi' - icon_override = 'icons/obj/custom_items/akinyi_symphette.dmi' - icon_state = "akinyi_case" - item_state = "akinyi_case" - w_class = WEIGHT_CLASS_BULKY - contained_sprite = TRUE - storage_slots = 3 - max_w_class = WEIGHT_CLASS_NORMAL - can_hold = list( - /obj/item/megaphone/fluff/akinyi_mic, - /obj/item/fluff/akinyi_stand, - /obj/item/synthesized_instrument/guitar/multi/fluff/akinyi_symphette - ) - starts_with = list( - /obj/item/megaphone/fluff/akinyi_mic = 1, - /obj/item/fluff/akinyi_stand = 1, - /obj/item/synthesized_instrument/guitar/multi/fluff/akinyi_symphette = 1 - ) - - /obj/item/clothing/accessory/poncho/fluff/amos_vest //Ouerean Vest - Amos Zhujian - dronzthewolf name = "ourean vest" desc = "A thin vest made of separate colors, this one is brown and turquoise, with something written in Sinta'Unathi on the right breast. While this is a traditional cut vest, it's made of modern machine-woven fabrics as is commonly done on Ouerea, and sized to fit a human." @@ -919,14 +480,6 @@ All custom items with worn sprites must follow the contained sprite system: http contained_sprite = TRUE species_restricted = list(BODYTYPE_TAJARA) -/obj/item/clothing/suit/storage/toggle/para_jacket/fluff/akila_jacket //Reflective paramedic Jacket - Akila Aksha'Shalwariran - shestrying - name = "reflective paramedic jacket" - desc = "A jacket in an eye-blinding yellow, with flourescent green, light-reflective striping along the cuffs and bottom edge. A bright red cross rests on the front, over the heart." - icon = 'icons/obj/custom_items/akila_jacket.dmi' - icon_override = 'icons/obj/custom_items/akila_jacket.dmi' - icon_state = "akila_jacket" - item_state = "akila_jacket" - contained_sprite = TRUE /obj/item/voidsuit_modkit/fluff/rajka_suit name = "HEV-3 voidsuit kit" @@ -956,207 +509,6 @@ All custom items with worn sprites must follow the contained sprite system: http species_restricted = list(BODYTYPE_TAJARA) -/obj/item/fluff/holoconsole // Holoconsole - Qoi Liuiq - shestrying - name = "holoconsole" - desc = "A game console capable of displaying a three-dimensional, holographic image of the player's game of choice. It's pink!" - icon = 'icons/obj/custom_items/qoi_console.dmi' - icon_override = 'icons/obj/custom_items/qoi_console.dmi' - icon_state = "console" - - var/on = FALSE - var/obj/item/fluff/holoconsole_controller/left_controller - var/obj/item/fluff/holoconsole_controller/r/right_controller - var/mutable_appearance/screen - - var/sound_delay = 0.5 SECONDS // so we don't deafen everyone by spam clicking - var/last_sound = 0 - -/obj/item/fluff/holoconsole/Initialize() - . = ..() - left_controller = new /obj/item/fluff/holoconsole_controller(src) - right_controller = new /obj/item/fluff/holoconsole_controller/r(src) - verbs += /obj/item/fluff/holoconsole/proc/remove_left - verbs += /obj/item/fluff/holoconsole/proc/remove_right - screen = mutable_appearance(icon, "screen") - update_icon() - -/obj/item/fluff/holoconsole/Destroy() - QDEL_NULL(left_controller) - QDEL_NULL(right_controller) - return ..() - -/obj/item/fluff/holoconsole/update_icon() - icon_state = "console[left_controller ? "_l" : ""][right_controller ? "_r" : ""]" - -/obj/item/fluff/holoconsole/attack_self(mob/user) - if(on && !(world.time < last_sound + sound_delay)) - playsound(loc, SFX_ARCADE, 60) - last_sound = world.time - return - return ..() - -/obj/item/fluff/holoconsole/attackby(obj/item/attacking_item, mob/user, params) - switch(attacking_item.type) - if(/obj/item/fluff/holoconsole_controller) - if(left_controller) - to_chat(user, SPAN_WARNING("\The [src] already has its left controller connected!")) - return - user.visible_message("[user] slots \the [attacking_item] back into to \the [src].", SPAN_NOTICE("You slot \the [attacking_item] back into \the [src].")) - user.drop_from_inventory(attacking_item, src) - left_controller = attacking_item - left_controller.parent_console = null - verbs += /obj/item/fluff/holoconsole/proc/remove_left - update_icon() - return - if(/obj/item/fluff/holoconsole_controller/r) - if(right_controller) - to_chat(user, SPAN_WARNING("\The [src] already has its right controller connected!")) - return - user.visible_message("[user] slots \the [attacking_item] back into to \the [src].", SPAN_NOTICE("You slot \the [attacking_item] back into \the [src].")) - user.drop_from_inventory(attacking_item, src) - right_controller = attacking_item - right_controller.parent_console = null - verbs += /obj/item/fluff/holoconsole/proc/remove_right - update_icon() - return - return ..() - -/obj/item/fluff/holoconsole/verb/toggle_on() - set name = "Toggle On" - set category = "Object" - set src in view(1) - - on = !on - usr.visible_message("[usr] turns \the [src] [on ? "on" : "off"].", SPAN_NOTICE("You turn \the [src] [on ? "on" : "off"].")) - if(on) - playsound(loc, 'sound/machines/synth_yes.ogg', 50) - AddOverlays(screen) - else - playsound(loc, 'sound/machines/synth_no.ogg', 50) - CutOverlays(screen) - update_icon() - -/obj/item/fluff/holoconsole/proc/remove_left() - set name = "Remove Left Controller" - set category = "Object" - set src in view(1) - - usr.visible_message("[usr] removes the left controller from \the [src], flicking it open.", SPAN_NOTICE("You remove the left controller from \the [src], flicking it open.")) - usr.put_in_hands(left_controller) - left_controller.parent_console = WEAKREF(src) - left_controller = null - verbs -= /obj/item/fluff/holoconsole/proc/remove_left - update_icon() - -/obj/item/fluff/holoconsole/proc/remove_right() - set name = "Remove Right Controller" - set category = "Object" - set src in view(1) - - usr.visible_message("[usr] removes the right controller from \the [src], flicking it open.", SPAN_NOTICE("You remove the right controller from \the [src], flicking it open.")) - usr.put_in_hands(right_controller) - right_controller.parent_console = WEAKREF(src) - right_controller = null - verbs -= /obj/item/fluff/holoconsole/proc/remove_right - update_icon() - -/obj/item/fluff/holoconsole_controller // Holoconsole - Qoi Liuiq - shestrying - name = "left holoconsole controller" - desc = "A controller for the Holoconsole, capable of folding in half and re-attaching to the machine. It's pink!" - icon = 'icons/obj/custom_items/qoi_console.dmi' - icon_override = 'icons/obj/custom_items/qoi_console.dmi' - icon_state = "controller" - - var/datum/weakref/parent_console - var/sound_delay = 0.5 SECONDS // so we don't deafen everyone by spam clicking - var/last_sound = 0 - -/obj/item/fluff/holoconsole_controller/attack_self(mob/user) - if(world.time < last_sound + sound_delay) - return - - var/obj/item/fluff/holoconsole/H = parent_console.resolve() - if(H?.on) - playsound(H.loc, SFX_ARCADE, 60) - last_sound = world.time - -/obj/item/fluff/holoconsole_controller/r // Holoconsole - Qoi Liuiq - shestrying - name = "right holoconsole controller" - -/obj/item/fluff/holocase // Holoconsole Case - Qoi Liuiq - shestrying - name = "holoconsole case" - desc = "A case for the Holoconsole. This one is made of fabric, with various iron-on patches attached to it. It's pink!" - icon = 'icons/obj/custom_items/qoi_console.dmi' - icon_override = 'icons/obj/custom_items/qoi_console.dmi' - icon_state = "case" - - var/spinned = FALSE - var/obj/item/fluff/holoconsole/contained_console - -/obj/item/fluff/holocase/Initialize() - . = ..() - contained_console = new /obj/item/fluff/holoconsole(src) - -/obj/item/fluff/holocase/Destroy() - QDEL_NULL(contained_console) - return ..() - -/obj/item/fluff/holocase/update_icon() - if(!contained_console) - icon_state = "case_o" - return - icon_state = spinned ? "case_b" : "case" - -/obj/item/fluff/holocase/attack_self(mob/user) - if(!contained_console) - to_chat(user, SPAN_WARNING("\The [src] doesn't have a console inside it! Insert it before trying to spin \the [src] around.")) - return - spinned = !spinned - user.visible_message("[usr] deftly spins \the [src], showing its [spinned ? "back" : "front"].", SPAN_NOTICE("You deftly spin \the [src], showing its [spinned ? "back" : "front"].")) - update_icon() - -/obj/item/fluff/holocase/attack_hand(mob/user) - if(contained_console && src == user.get_inactive_hand()) - user.visible_message("[usr] removes \the [contained_console] from \the [src].", SPAN_NOTICE("You remove \the [contained_console] from \the [src].")) - user.put_in_hands(contained_console) - contained_console = null - update_icon() - return - return ..() - -/obj/item/fluff/holocase/attackby(obj/item/attacking_item, mob/user, params) - if(istype(attacking_item, /obj/item/fluff/holoconsole)) - if(contained_console) - to_chat(user, SPAN_WARNING("\The [src] already contains a holoconsole!")) - return - user.drop_from_inventory(attacking_item, src) - contained_console = attacking_item - user.visible_message("[usr] puts \the [contained_console] into \the [src], zipping it back up.", SPAN_NOTICE("You put \the [contained_console] into \the [src], zipping it back up.")) - update_icon() - return - return ..() - -/obj/item/clothing/accessory/poncho/dominia_cape/fluff/godard_cape //House godard cape - Pierre Godard - desven - name = "house godard cape" - desc = "This is a cape in the style of Dominian nobility. This one is in the colours of House Godard." - icon = 'icons/obj/custom_items/godard_cape.dmi' - icon_override = 'icons/obj/custom_items/godard_cape.dmi' - icon_state = "godard_cape" - item_state = "godard_cape" - contained_sprite = TRUE - - -/obj/item/clothing/glasses/spiffygogs/fluff/andersen_goggles //Red Goggles - Adam Andersen - cybercide - name = "red goggles" - desc = " A pair of worn black goggles with red tinted lenses, both the Kevlar strap and polycarbonate lenses have some scuffs and scratches but they still hold up nicely. \ - There appears to be a Zavodskoi Interstellar insignia on the strap." - icon = 'icons/obj/custom_items/andersen_goggles.dmi' - icon_override = 'icons/obj/custom_items/andersen_goggles.dmi' - icon_state = "andersen_goggles" - item_state = "andersen_goggles" - contained_sprite = TRUE - - /obj/item/clothing/glasses/welding/fluff/mahir_glasses //Hephaestus Auto-darkening Welding Glasses - Mahir Rrhamrare - veterangary name = "hephaestus auto-darkening welding glasses" desc = "A pair of Hephaestus produced safety glasses with the prototype incorporation of liquid crystal lenses that polarize intense light present in arc-welding." @@ -1167,35 +519,6 @@ All custom items with worn sprites must follow the contained sprite system: http contained_sprite = TRUE -/obj/item/clothing/accessory/poncho/tajarancloak/fancy/fluff/valetzrhonaja_cloak //Nayrragh'Rakhan Cloak - Valetzrhonaja Nayrragh'Rakhan - ramke - name = "nayrragh'rakhan cloak" - desc = " A worn, black cloak with golden adornments decorating the edges of the fabric. The insignia of the Nayrragh'Rakhan family is embedded into the custom pin holding the cloak \ - together, and each shoulder is decorated by the representation of a yellow or blue sun - the symbols of S'rendarr and Messa. The fabric is faded, having clearly been tested by time." - icon = 'icons/obj/custom_items/valetzrhonaja_cloak.dmi' - icon_override = 'icons/obj/custom_items/valetzrhonaja_cloak.dmi' - icon_state = "valetzrhonaja_cloak" - item_state = "valetzrhonaja_cloak" - contained_sprite = TRUE - -/obj/item/flag/fluff/bian_flag //Coalition Fisanduh Unity Flag - Bian Quy Le - persephoneq - name = "large coalition fisanduh unity flag" - desc = "A well-loved flag often seen hung by those advocating for Fisanduh's legitimization and acceptance into the Coalition of Colonies." - icon = 'icons/obj/custom_items/bian_flag.dmi' - icon_override = 'icons/obj/custom_items/bian_flag.dmi' - icon_state = "bian_flag" - flag_path = "fisanduh_coalition" - flag_size = TRUE - flag_structure = /obj/structure/sign/flag/fisanduh_coalition - -/obj/structure/sign/flag/fisanduh_coalition - name = "large coalition fisanduh unity flag" - desc = "A well-loved flag often seen hung by those advocating for Fisanduh's legitimization and acceptance into the Coalition of Colonies." - icon = 'icons/obj/custom_items/bian_flag.dmi' - flag_path = "fisanduh_coalition" - flag_item = /obj/item/flag/fluff/bian_flag - flag_size = TRUE - - /obj/item/clothing/under/fluff/rajjurl_uniform //Tajaran Noble's Suit - Rajjurl Al-Thaalzir - abigbear name = "tajaran noble's suit" desc = "A dark, older suit refurbished with new additions and golden buttons, embroidery, and trim. Made with silken fabric, crimson epaulette, and matching sleeve cuffs this suit is a remnant of an older time on Adhomai made new again with recent restorations." @@ -1275,20 +598,6 @@ All custom items with worn sprites must follow the contained sprite system: http canremove = FALSE contained_sprite = TRUE -/obj/item/organ/internal/augment/synthetic_cords/voice/fluff/marc //Old Synthetic Vocal Cords - Marc Hardy - dekser - name = "old synthetic vocal cords" - desc = "A set of Old Age Synthetic Vocal Cords. They look barely functional." - -/obj/item/clothing/suit/storage/toggle/fluff/leonid_chokha //Old Rebel's Chokha - Leonid Myagmar - lucaken - name = "old rebel's chokha" - desc = "A not-so traditional Vysokan Chokha made out of beat-up gurmori leathers, worn-out to the point of seeming ancient. Though it might have been a Host-boy's garment once, it is now \ - swarmed with dozens of patches all with varying colours and origins - the most prominent of which is a large image of a crimson snake on a white plain, curled around a fire. It's the oldest \ - out of all the adornments." - icon = 'icons/obj/custom_items/leonid_chokha.dmi' - icon_override = 'icons/obj/custom_items/leonid_chokha.dmi' - icon_state = "leonid_chokha" - item_state = "leonid_chokha" - contained_sprite = TRUE /obj/item/clothing/suit/storage/toggle/fluff/sezrak_coat //Red Domelkoan Coat - Sezrak Han'san - captaingecko name = "red Domelkoan Coat" @@ -1424,28 +733,7 @@ All custom items with worn sprites must follow the contained sprite system: http contained_sprite = TRUE -/obj/item/clothing/accessory/poncho/shouldercape/qeblak/zeng/fluff/eden_cloak // Zeng-Hu Nralakk division cloak - Eden Li - huntime - name = "\improper Zeng-Hu cloak: Nralakk division" - desc = "A cloak worn by Zeng-Hu personnel who worked with or in the Nralakk Federation." - icon = 'icons/obj/custom_items/eden_cloak.dmi' - icon_override = 'icons/obj/custom_items/eden_cloak.dmi' - icon_state = "ZH_cape_custom" - item_state = "ZH_cape_custom" - - -/obj/item/clothing/head/welding/fluff/akara_mask //Steel Face Mask - Akara Seuseisak - aticius - name = "steel face mask" - desc = "A slab of steel that has been hammered into the shape of a full-face mask with crude tools. It seems quite old and an appreciable layer of rust has built up." - icon = 'icons/obj/custom_items/akara_mask.dmi' - icon_override = 'icons/obj/custom_items/akara_mask.dmi' - icon_state = "akara_mask" - item_state = "akara_mask" - contained_sprite = TRUE - action_button_name = "Adjust mask" - flash_protection = FLASH_PROTECTION_NONE - tint = TINT_NONE - -/obj/item/clothing/suit/storage/toggle/leather_jacket/flight/fluff/iliasz_jacket //Naval Pilot's Jacket - Iliasz Jajszczyk - dansemacabre +/obj/item/clothing/suit/storage/toggle/leather_jacket/flight/fluff/iliasz_jacket //Naval Pilot's Jacket - Iliasz Jajszczyk - kintsugi name = "naval pilot's jacket" desc = "A sturdy grey-green neonomex-lined jacket, flame-resistant and sleek. A garment of choice for anyone who might be in the cockpit of something with a risk of catching fire. \ There's a name patch sewn onto the breast of this one, reading \"JAJSZCZYK\". It seems to be more rugged than a typical flight jacket, and also appears to have some waterproofing. \ @@ -1456,189 +744,6 @@ All custom items with worn sprites must follow the contained sprite system: http item_state = "iliasz_jacket" contained_sprite = TRUE -/obj/item/clothing/accessory/poncho/tajarancloak/fluff/dekel_smock // Corporate Smock - Dekel Mrrhazrughan - veterangary - name = "corporate smock" - desc = "A dark coloured surplus winter smock repurposed for interstellar use that has a hood shaded with corporate colors. A traditional Stellar Corporate Conglomerate star is embroidered on the back." - icon = 'icons/obj/custom_items/dekel_smock.dmi' - icon_override = 'icons/obj/custom_items/dekel_smock.dmi' - icon_state = "seccloak" - item_state = "seccloak" - contained_sprite = TRUE - var/hoodtype = /obj/item/clothing/head/winterhood/fluff/dekel_hood - -/obj/item/clothing/accessory/poncho/tajarancloak/fluff/dekel_smock/Initialize() - . = ..() - new hoodtype(src) - -/obj/item/clothing/head/winterhood/fluff/dekel_hood - name = "corporate hood" - desc = "A hood attached to a corporate smock." - icon = 'icons/obj/custom_items/dekel_smock.dmi' - icon_override = 'icons/obj/custom_items/dekel_smock.dmi' - icon_state = "seccloak_hood" - item_state = "seccloak_hood" - contained_sprite = TRUE - flags_inv = HIDEEARS | BLOCKHAIR - -/obj/item/clothing/accessory/poncho/tajarancloak/fluff/dekel_smock/on_attached(obj/item/clothing/S, mob/user as mob) - ..() - has_suit.verbs += /obj/item/clothing/accessory/poncho/tajarancloak/fluff/dekel_smock/verb/change_hood - -/obj/item/clothing/accessory/poncho/tajarancloak/fluff/dekel_smock/on_removed(mob/user as mob) - if(has_suit) - has_suit.verbs -= /obj/item/clothing/accessory/poncho/tajarancloak/fluff/dekel_smock/verb/change_hood - ..() - -/obj/item/clothing/accessory/poncho/tajarancloak/fluff/dekel_smock/verb/change_hood() - set name = "Toggle Hood" - set category = "Object.Equipped" - set src in usr - - if(use_check_and_message(usr)) - return - - var/obj/item/clothing/accessory/poncho/tajarancloak/fluff/dekel_smock/D = get_accessory(/obj/item/clothing/accessory/poncho/tajarancloak/fluff/dekel_smock) - if(!D) - return - - SEND_SIGNAL(D, COMSIG_ITEM_UPDATE_STATE, D) - - -/obj/item/fluff/nasira_burner //Adhomian Incense Burner - Nasira Nahnikh - ramke - name = "adhomian incense burner" - desc = "A traditional Adhomian incense burner with blue and yellow suns depicted on the front. The metal cover is blackened from use, and there appear to be unclear etchings on the inside." - icon = 'icons/obj/custom_items/nasira_burner.dmi' - icon_state = "burner" - drop_sound = 'sound/items/drop/glass.ogg' - pickup_sound = 'sound/items/pickup/glass.ogg' - var/matchmsg = "USER lights NAME with their FLAME." - var/lightermsg = "USER manages to awkwardly light NAME with FLAME." - var/zippomsg = "With a flick of their wrist, USER lights NAME with their FLAME." - var/weldermsg = "USER lights NAME with FLAME. That looked rather unsafe!" - var/ignitermsg = "USER fiddles with FLAME, and eventually manages to light NAME." - var/genericmsg = "USER lights NAME with their FLAME." - var/lit = FALSE - -/obj/item/fluff/nasira_burner/Destroy() - STOP_PROCESSING(SSprocessing, src) - return ..() - -/obj/item/fluff/nasira_burner/get_examine_text(mob/user, distance, is_adjacent, infix, suffix) - . = ..() - if(lit) - . += "\The [src] is currently lit." - -/obj/item/fluff/nasira_burner/proc/light(var/lighting_text) - if(!lit) - lit = TRUE - playsound(src, 'sound/items/cigs_lighters/cig_light.ogg', 75, 1, -1) - if(lighting_text) - var/turf/T = get_turf(src) - T.visible_message(SPAN_NOTICE(lighting_text)) - set_light(2, 0.25, "#E38F46") - icon_state = "burner_lit" - START_PROCESSING(SSprocessing, src) - -/obj/item/fluff/nasira_burner/attack_self(mob/user as mob) - if(lit) - lit = FALSE - var/turf/T = get_turf(src) - T.visible_message(SPAN_NOTICE("[user] extinguishes \the [src].")) - set_light(0) - icon_state = initial(icon_state) - STOP_PROCESSING(SSprocessing, src) - -/obj/item/fluff/nasira_burner/attackby(obj/item/attacking_item, mob/user, params) - ..() - if(attacking_item.isFlameSource()) - var/text = matchmsg - if(istype(attacking_item, /obj/item/flame/match)) - text = matchmsg - else if(istype(attacking_item, /obj/item/flame/lighter/zippo)) - text = zippomsg - else if(istype(attacking_item, /obj/item/flame/lighter)) - text = lightermsg - else if(attacking_item.tool_behaviour == TOOL_WELDER) - text = weldermsg - else if(istype(attacking_item, /obj/item/assembly/igniter)) - text = ignitermsg - else - text = genericmsg - text = replacetext(text, "USER", "\the [user]") - text = replacetext(text, "NAME", "\the [name]") - text = replacetext(text, "FLAME", "\the [attacking_item.name]") - light(text) - -/obj/item/fluff/nasira_burner/process() - if(prob(10)) - var/lit_message - - lit_message = pick( "The smell of ceremonial incense reaches your nose.", - "Adhomian incense permeates the air around you.", - "The soft glow of the incense burner illuminates the vicinity.") - - if(lit_message) - visible_message(SPAN_NOTICE(lit_message), range = 3) - -/obj/item/clothing/suit/vaurca/fluff/bells_zora_cloak //Tailored Hive Cloak - Ka'Akaix'Bells Zo'ra - shestrying - name = "tailored hive cloak" - desc = "A typical-looking Vaurca hive cloak design, tailored from what looks to be labcoat material." - icon = 'icons/obj/custom_items/bells_zora_items.dmi' - icon_override = 'icons/obj/custom_items/bells_zora_items.dmi' - icon_state = "bells_zora_cloak" - item_state = "bells_zora_cloak" - contained_sprite = TRUE - -/obj/item/storage/box/fancy/fluff/bells_zora_box //Taffy Basket - Ka'Akaix'Bells Zo'ra - shestrying - name = "taffy basket" - desc = "A round, wicker basket full to the brim with taffy! " - icon = 'icons/obj/custom_items/bells_zora_items.dmi' - icon_override = 'icons/obj/custom_items/bells_zora_items.dmi' - icon_state = "bells_zora_box_full" - item_state = "bells_zora_box_full" - can_hold = list(/obj/item/reagent_containers/food/snacks/fluff/taffy) - starts_with = list(/obj/item/reagent_containers/food/snacks/fluff/taffy = 6, /obj/item/reagent_containers/food/snacks/fluff/taffy/pink = 6, /obj/item/reagent_containers/food/snacks/fluff/taffy/blue = 6) - storage_slots = 18 - contained_sprite = TRUE - drop_sound = 'sound/items/drop/gloves.ogg' - pickup_sound = 'sound/items/pickup/gloves.ogg' - use_sound = 'sound/items/storage/wrapper.ogg' - -/obj/item/storage/box/fancy/fluff/bells_zora_box/fill() - . = ..() - update_icon() - -/obj/item/storage/box/fancy/fluff/bells_zora_box/update_icon() - if(contents.len == 0) - icon_state = "bells_zora_box_empty" - desc = " A round, wicker basket. There's some colorful crumbs on the bottom of the linen lining. " - else if(contents.len <= 11) - icon_state = "bells_zora_box_half" - desc = "A round, wicker basket with some taffy inside!" - else if(contents.len >= 12) - icon_state = "bells_zora_box_full" - desc = "A round, wicker basket full to the brim with taffy!" - - -/obj/item/reagent_containers/food/snacks/fluff/taffy - name = "orange taffy" - desc = "A piece of handmade taffy, rolled up in a cute spiral!" - icon = 'icons/obj/custom_items/bells_zora_items.dmi' - icon_state = "orange_taffy" - reagents_to_add = list(/singleton/reagent/nutriment = 3) - reagent_data = list(/singleton/reagent/nutriment = list("bittersweetness, insect meat and regret" = 1)) - bitesize = 1 - -/obj/item/reagent_containers/food/snacks/fluff/taffy/pink - name = "pink taffy" - icon_state = "pink_taffy" - reagent_data = list(/singleton/reagent/nutriment = list("sweetness and a hint of strawberry" = 1)) - -/obj/item/reagent_containers/food/snacks/fluff/taffy/blue - name = "blue taffy" - icon_state = "blue_taffy" - reagent_data = list(/singleton/reagent/nutriment = list("salty-sweet, tangy taffy" = 1)) - /obj/item/clothing/suit/storage/fluff/aheke_coat //Hengsha Thermal Coat - Aheke Han'san - hawkington name = "hengsha thermal coat" @@ -1688,107 +793,6 @@ All custom items with worn sprites must follow the contained sprite system: http contained_sprite = TRUE -/obj/item/fluff/ielia_tarot //Starfinder - Ielia Aliori-Quis'Naala - shestrying - name = "starfinder" - desc = "A small, bronze ball. It is heavy in the hand and seems to have no switches or buttons on it. " - icon = 'icons/obj/custom_items/ielia_tarot.dmi' - icon_override = 'icons/obj/custom_items/ielia_tarot.dmi' - icon_state = "ielia_tarot" - contained_sprite = TRUE - w_class = WEIGHT_CLASS_SMALL - var/list/possible_cards = list("Island","Hatching Egg","Star Chanter","Jiu'x'klua","Stormcloud","Gnarled Tree","Poet","Bloated Toad","Void","Qu'Poxii","Fisher","Mountain","Sraso","Nioh") - var/activated = FALSE - var/first_card - var/second_card - var/third_card - -/obj/item/fluff/ielia_tarot/attack_self(var/mob/user) - if(activated) - reset_starfinder() - else - start_starfinder() - -/obj/item/fluff/ielia_tarot/AltClick(mob/user) - attack_self(user) - -/obj/item/fluff/ielia_tarot/verb/start_starfinder() - set name = "Start the Starfinder" - set category = "Object" - set src in view(1) - - if(activated) - return - - if(use_check_and_message(usr, USE_DISALLOW_SILICONS)) - return - - first_card = null - second_card = null - third_card = null - - icon_state = "ielia_tarot_on" - ClearOverlays() - - usr.visible_message("\The [usr] activates the [src].") - flick ("card_spawn",src) - activated = TRUE - - icon_state = "card_spin" - AddOverlays("card_spin_fx") - addtimer(CALLBACK(src, PROC_REF(finish_selection), usr), 3 SECONDS) - -/obj/item/fluff/ielia_tarot/get_examine_text(mob/user, distance, is_adjacent, infix, suffix) - . = ..() - if(distance <= 1) - if(first_card && second_card && third_card) - . += "The following constellations are displayed on the starfinder: [first_card], [second_card], and [third_card]." - -/obj/item/fluff/ielia_tarot/proc/finish_selection(var/mob/user) - ClearOverlays() - flick("card_spin_stop",src) - icon_state = "ielia_tarot_on" - for(var/i = 1 to 3) - var/P = pick(possible_cards) - if(!first_card) - first_card = P - else if(first_card && !second_card) - second_card = P - else if(first_card && second_card) - third_card = P - - ClearOverlays() - AddOverlays("card_display_fx") - AddOverlays("card_display") - - var/image/first_card_overlay = image(icon, src, first_card) - first_card_overlay.pixel_x = -8 - AddOverlays(first_card_overlay) - - var/image/second_card_overlay = image(icon, src, second_card) - AddOverlays(second_card_overlay) - - var/image/third_card_overlay = image(icon, src, third_card) - third_card_overlay.pixel_x = 8 - AddOverlays(third_card_overlay) - -/obj/item/fluff/ielia_tarot/proc/reset_starfinder() - if(!activated) - return - ClearOverlays() - icon_state = "ielia_tarot" - activated = FALSE - - -/obj/item/clothing/suit/storage/fluff/osborne_suit //Dominian Officers Trench Coat - Osborne Strelitz - sirtoast - name = "dominian officer's trench coat" - desc = "An Imperial Army trench coat that is used by Dominian officers in colder environments. This one is missing the unit insignia and has the symbol of a military count on its rank collar." - icon = 'icons/obj/custom_items/osborne_suit.dmi' - icon_override = 'icons/obj/custom_items/osborne_suit.dmi' - icon_state = "osborne_suit" - item_state = "osborne_suit" - contained_sprite = TRUE - - /obj/item/storage/box/fancy/cigarettes/cigar/brianne_cigarettes //Martian Cigarette Case - Sean Brianne - zelmana name = "martian cigarette case" desc = "A small, personal cigarette tin. It holds cigarettes similar to a cigarette packet but has some nice flair." @@ -1802,26 +806,6 @@ All custom items with worn sprites must follow the contained sprite system: http contained_sprite = TRUE -/obj/item/clothing/glasses/sunglasses/fluff/lyod_snowglasses //Lyod snowglasses - Ravna Surtaeva - sycmos - name = "\improper Lyod snowglasses" - desc = "A pair of protective glasses hand-sculpted of reindeer antler, intended for use in arctic climates to protect from snow blindness." - icon = 'icons/obj/custom_items/ravna_items.dmi' - icon_override = 'icons/obj/custom_items/ravna_items.dmi' - icon_state = "ravna_sunglasses" - item_state = "ravna_sunglasses" - contained_sprite = TRUE - flash_protection = FLASH_PROTECTION_NONE - -/obj/item/clothing/suit/storage/toggle/fluff/prejoroub_fur_longcoat //Prejoroub Fur Longcoat - Ravna Surtaeva - sycmos - name = "prejoroub fur longcoat" - desc = "A dense and heavy longcoat of dyed tenelote leather, with a liner and collar of prejoroub fur and decorative trimming throughout." - icon = 'icons/obj/custom_items/ravna_items.dmi' - icon_override = 'icons/obj/custom_items/ravna_items.dmi' - icon_state = "ravna_coat" - item_state = "ravna_coat" - contained_sprite = TRUE - - /obj/item/clothing/suit/armor/carrier/fluff/abbasi_carrier //Medinan Mercenary's Plate Carrier - Shirin Abbasi - persephoneq name = "medinan mercenary's plate carrier" desc = "A flashy and apparently well-made plate carrier. This one seems well-maintained, if quite worn-in. It's design is reminiscent of the ornate and intricate patterns of \ @@ -1846,24 +830,6 @@ All custom items with worn sprites must follow the contained sprite system: http item_state = "freedom_coat" contained_sprite = TRUE -/obj/item/clothing/head/fluff/schlosser_hat // National Defense Force Schiffchen - Schlosser - NewOriginalSchwann - name = "national defense force schiffchen" - desc = "A side cap known as a Schiffchen on Visegrad, a term roughly translating to \"little boat\" in Basic, which is commonly worn by members of the Visegradi National Defense Force. The NDF’s symbol – a silver fortress standing upon a crimson background – is prominently featured on the Schiffchen’s badge. “Totschlager” has been written on the inside of the band by somebody with a marker." - desc_extended = "The Schiffchen has a long, storied, and somewhat controversial history upon Visegrad, which dates back to its initial colonization. The planet’s first security service, the Visegradi People’s Security Service, used the Schiffchen as its standard headwear for security personnel in an effort to invoke \ - the Warsaw Pact’s security services. Following its dissolution the National Defense Force continued to use the Schiffchen as headwear, and it remains a common sight on Visegrad today even if the NDF, which was dissolved by the Navy shortly after the Solarian Collapse, no longer exists." - icon = 'icons/obj/custom_items/schlosser_hat.dmi' - icon_override = 'icons/obj/custom_items/schlosser_hat.dmi' - icon_state = "schlosser_hat" - item_state = "schlosser_hat" - contained_sprite = TRUE - -/obj/item/clothing/suit/storage/toggle/konyang/dbjacket/provenance_jacket // Double-Breasted Cropped Jacket - Z.I Provenance - niennab - name = "double-breasted cropped jacket" - desc = "Styled after the latest fashion trends on Konyang, this hybrid leather and polyester mesh jacket was built with the planet’s humid climate in mind. This particular jacket appears to be emblematic of Konyang's stylings but hand-made, sporting a distinctive fur collar." - icon = 'icons/obj/custom_items/provenance_jacket.dmi' - icon_override = 'icons/obj/custom_items/provenance_jacket.dmi' - icon_state = "provenance_coat" - item_state = "provenance_coat" /obj/item/voidsuit_modkit/fluff/ashkii_suit name = "Squall voidsuit kit" @@ -1908,16 +874,6 @@ All custom items with worn sprites must follow the contained sprite system: http item_state = "ashkii_cloak" contained_sprite = TRUE -/obj/item/versebook/fluff/guilty_men - name = "Guilty Men" - desc = "A leather bound book bearing a burning Coalition of Colonies flag. \"Guilty Men\" and \"How the Coalition of Colonies and its leaders failed the Frontier\" are engraved on golden plaques on either side of the flag. A controversial book published several years ago, \"Guilty Men\" is acclaimed by some as a scathing rebuke of failed Coalition policies, and their intolerable results, and condemned by others as a radical break from traditional Coalition attitudes and values. This example is worn, with its pages dog-eared and torn in numerous places, while the leather binding has begun to crack and discolor under frequent handling." - icon = 'icons/obj/custom_items/imogen_items.dmi' - icon_state = "Guilty_Men" - item_state = "book" - -/obj/item/versebook/fluff/guilty_men/Initialize() - . = ..() - randomquip = file2list("code/modules/customitems/imogen_guiltymen.txt") /obj/item/rig/light/offworlder/fluff/aayun name = "command exo-stellar skeleton module" @@ -2087,6 +1043,38 @@ All custom items with worn sprites must follow the contained sprite system: http else collapse() +/obj/item/organ/internal/augment/fluff/kath_legbrace/Initialize() + . = ..() + if(!owner) + return + RegisterSignal(owner, COMSIG_BEGIN_SURGERY, PROC_REF(negate_healing), override = TRUE) + var/obj/item/organ/external/parent = owner.get_organ(parent_organ) + parent.fracture(TRUE) + +/obj/item/organ/internal/augment/fluff/kath_legbrace/replaced() + . = ..() + if(!owner) + return + RegisterSignal(owner, COMSIG_BEGIN_SURGERY, PROC_REF(negate_healing), override = TRUE) + var/obj/item/organ/external/parent = owner.get_organ(parent_organ) + parent.fracture(TRUE) + +/obj/item/organ/internal/augment/fluff/kath_legbrace/removed() + if(!owner) + return ..() + UnregisterSignal(owner, COMSIG_BEGIN_SURGERY) + return ..() + +/obj/item/organ/internal/augment/fluff/kath_legbrace/proc/negate_healing(var/owner, var/canceled, var/obj/item/organ/external/affected, var/mob/living/user, var/singleton/surgery_step/surgery) + SIGNAL_HANDLER + if(!istype(surgery, /singleton/surgery_step/glue_bone) && !istype(surgery, /singleton/surgery_step/set_bone)) + return + if(affected.limb_name != parent_organ) + return + *canceled = TRUE + user.visible_message(SPAN_WARNING("[user] seems to be unable to set the bone in [owner]'s [affected.name]."), \ + SPAN_WARNING("The bone in [owner]'s [affected.name] appears to be impossible to set correctly!")) + /obj/item/organ/internal/augment/fluff/kath_legbrace/proc/collapse(var/prob_chance = 20, var/weaken_strength = 2, var/pain_strength = 40) if(prob(prob_chance)) var/obj/item/organ/external/E = owner.organs_by_name[parent_organ] @@ -2124,13 +1112,13 @@ All custom items with worn sprites must follow the contained sprite system: http /obj/item/clothing/accessory/poncho/tajarancloak/fluff/kathira_cloak/update_icon(var/hooded = FALSE) var/obj/item/clothing/accessory/poncho/tajarancloak/fluff/kathira_cloak/K = get_accessory(/obj/item/clothing/accessory/poncho/tajarancloak/fluff/kathira_cloak) - K.icon_state = "[K.changed ? K.style : initial(K.icon_state)]" SEND_SIGNAL(K, COMSIG_ITEM_STATE_CHECK, args) + . = ..() + K.icon_state = "[K.changed ? K.style : initial(K.icon_state)]" K.item_state = "[K.icon_state][hooded ? "_up" : ""]" K.name = "[K.changed ? K.name2 : initial(K.name)]" K.desc = "[K.changed ? K.desc2 : initial(K.desc)]" K.accessory_mob_overlay = null - . = ..() SEND_SIGNAL(K, COMSIG_ITEM_ICON_UPDATE) if(usr) usr.update_inv_w_uniform() diff --git a/code/modules/customitems/item_spawning.dm b/code/modules/customitems/item_spawning.dm index 500d121da565..0b424483271e 100644 --- a/code/modules/customitems/item_spawning.dm +++ b/code/modules/customitems/item_spawning.dm @@ -64,7 +64,7 @@ GLOBAL_LIST_INIT(custom_items, list()) var/list/loaded_items = list() var/item_id = 0 try - loaded_items = json_decode(return_file_text("config/custom_items.json")) + loaded_items = json_decode(file2text("config/custom_items.json")) catch(var/exception/e) log_module_customitems("Failed to load custom_items.json: [e]") diff --git a/code/modules/economy/ATM.dm b/code/modules/economy/ATM.dm index b1c622cd0380..83fdf599aaf3 100644 --- a/code/modules/economy/ATM.dm +++ b/code/modules/economy/ATM.dm @@ -306,7 +306,7 @@ if("balance_statement") if(authenticated_account) - var/obj/item/paper/R = new() + var/obj/item/paper/notepad/receipt/R = new() var/pname = "Account balance: [authenticated_account.owner_name]" var/info = "Idris Automated Teller Account Statement

" info += "Account holder: [authenticated_account.owner_name]
" @@ -318,12 +318,13 @@ //stamp the paper var/image/stampoverlay = image('icons/obj/bureaucracy.dmi') - stampoverlay.icon_state = "paper_stamp-cent" + stampoverlay.icon_state = "paper_stamp-hop" if(!R.stamped) R.stamped = new R.stamped += /obj/item/stamp R.AddOverlays(stampoverlay) R.stamps += "
This paper has been stamped by the Automatic Teller Machine." + R.ripped = TRUE print(R, user = usr) release_held_id(usr) // printing ends the ATM session similar to real life + prevents spam @@ -332,7 +333,7 @@ playsound(loc, SFX_PRINT, 50, 1) if ("print_transaction") if(authenticated_account) - var/obj/item/paper/R = new() + var/obj/item/paper/notepad/receipt/R = new() var/pname = "Transaction logs: [authenticated_account.owner_name]" var/info = "Transaction logs
" info += "Account holder: [authenticated_account.owner_name]
" @@ -369,6 +370,7 @@ R.stamped += /obj/item/stamp R.AddOverlays(stampoverlay) R.stamps += "
This paper has been stamped by the Automatic Teller Machine." + R.ripped = TRUE print(R, user = usr) playsound(loc, SFX_PRINT, 50, 1) diff --git a/code/modules/economy/EFTPOS.dm b/code/modules/economy/EFTPOS.dm index b3c06666744a..a05857e51b88 100644 --- a/code/modules/economy/EFTPOS.dm +++ b/code/modules/economy/EFTPOS.dm @@ -50,18 +50,18 @@ //stamp the paper var/image/stampoverlay = image('icons/obj/bureaucracy.dmi') - stampoverlay.icon_state = "paper_stamp-cent" + stampoverlay.icon_state = "paper_stamp-hop" if(!R.stamped) R.stamped = new R.offset_x += 0 R.offset_y += 0 - R.ico += "paper_stamp-cent" + R.ico += "paper_stamp-hop" R.stamped += /obj/item/stamp R.AddOverlays(stampoverlay) R.stamps += "
This paper has been stamped by the EFTPOS device." /obj/item/eftpos/proc/print_reference() - var/obj/item/paper/R = new(src.loc) + var/obj/item/paper/notepad/receipt/R = new(src.loc) var/pname = "Reference: [eftpos_name]" var/info = "[eftpos_name] reference

" info += "Access code: [access_code]

" @@ -70,7 +70,7 @@ //stamp the paper var/image/stampoverlay = image('icons/obj/bureaucracy.dmi') - stampoverlay.icon_state = "paper_stamp-cent" + stampoverlay.icon_state = "paper_stamp-hop" if(!R.stamped) R.stamped = new R.stamped += /obj/item/stamp diff --git a/code/modules/economy/OrderTerminal.dm b/code/modules/economy/OrderTerminal.dm index 035ad232ab2c..9df4983d1a66 100644 --- a/code/modules/economy/OrderTerminal.dm +++ b/code/modules/economy/OrderTerminal.dm @@ -63,12 +63,12 @@ ui.open() /obj/machinery/orderterminal/proc/print_receipt() // Print the receipt followed by the order ticket - var/obj/item/paper/R = new(usr.loc) + var/obj/item/paper/notepad/receipt/R = new(usr.loc) var/receiptname = "Receipt: [machine_id]" R.set_content_unsafe(receiptname, receipt, sum) stamp_receipt(R) // And now we do it but for the ticket. - var/obj/item/paper/T = new(usr.loc) + var/obj/item/paper/notepad/receipt/T = new(usr.loc) var/tickettname = "Order ticket: [ticket_number]" ticket_number++ T.set_content_unsafe(tickettname, ticket, sum) @@ -76,12 +76,13 @@ /obj/machinery/orderterminal/proc/stamp_receipt(obj/item/paper/R) // Stamps the papers, made into a proc to avoid copy pasting too much var/image/stampoverlay = image('icons/obj/bureaucracy.dmi') - stampoverlay.icon_state = "paper_stamp-cent" + stampoverlay.icon_state = "paper_stamp-hop" if(!R.stamped) R.stamped = new R.stamped += /obj/item/stamp R.AddOverlays(stampoverlay) R.stamps += "
This paper has been stamped by the Idris Ordering Terminal." + R.ripped = TRUE /obj/machinery/orderterminal/attackby(obj/item/attacking_item, mob/user) var/obj/item/card/id/I = attacking_item.GetID() @@ -180,8 +181,8 @@ var/item_price = items_to_price[item_name] sum += item_price - receipt += "[name]: [item_name] x[item_amount] at [item_price]cr each
" - ticket += "[name]: [item_name] x[item_amount] at [item_price]cr each
" + receipt += "[name]: [item_name] x[item_amount] at [item_price]电 each
" + ticket += "[name]: [item_name] x[item_amount] at [item_price]电 each
" receipt += "
Total: [sum]电" ticket += "
Total: [sum]电" sum = sum diff --git a/code/modules/economy/cash.dm b/code/modules/economy/cash.dm index b57dcbb85134..3348dded99fd 100644 --- a/code/modules/economy/cash.dm +++ b/code/modules/economy/cash.dm @@ -1,6 +1,6 @@ /obj/item/spacecash name = "0 credit chip" - desc = "It's worth 0 credits." + desc = "It's worth 0电." gender = PLURAL icon = 'icons/obj/cash.dmi' icon_state = "spacecash1" @@ -38,7 +38,7 @@ h_user.drop_from_inventory(src) h_user.drop_from_inventory(bundle) h_user.put_in_hands(bundle) - to_chat(user, SPAN_NOTICE("You add [src.worth] credits worth of money to the bundles.
It holds [bundle.worth] credits now.")) + to_chat(user, SPAN_NOTICE("You add [src.worth]电 to the bundles.
It holds [bundle.worth]电 now.")) qdel(src) /proc/coin_typepath_suffix(var/amount) @@ -55,7 +55,7 @@ name = "credit chips" icon_state = "" gender = PLURAL - desc = "They are worth 0 credits." + desc = "They are worth 0电." worth = 0 /obj/item/spacecash/bundle/update_icon() @@ -97,7 +97,7 @@ AddOverlays(ovr) UpdateOverlays() // The delay looks weird, so we force an update immediately. - src.desc = "A bundle of Biesel Standard Credits. Combined, this is worth [worth] credits." + src.desc = "A bundle of Biesel Standard Credits. Combined, this is worth [worth]电." /obj/item/spacecash/bundle/attack_self(mob/user as mob) var/amount = tgui_input_number(user, "How many credits do you want to take out? (0 to [src.worth])", "Take Money", 5, worth, 0, 0, round_value = FALSE) @@ -171,49 +171,49 @@ /obj/item/spacecash/c5 name = "5 credit chip" icon_state = "spacecash5" - desc = "A Biesel Standard Credit chip, used for transactions large and small. This one is worth 5 credits." + desc = "A Biesel Standard Credit chip, used for transactions large and small. This one is worth 5电." worth = 5 /obj/item/spacecash/c10 name = "10 credit chip" icon_state = "spacecash10" - desc = "A Biesel Standard Credit chip, used for transactions large and small. This one is worth 10 credits." + desc = "A Biesel Standard Credit chip, used for transactions large and small. This one is worth 10电." worth = 10 /obj/item/spacecash/c20 name = "20 credit chip" icon_state = "spacecash20" - desc = "A Biesel Standard Credit chip, used for transactions large and small. This one is worth 20 credits." + desc = "A Biesel Standard Credit chip, used for transactions large and small. This one is worth 20电." worth = 20 /obj/item/spacecash/c50 name = "50 credit chip" icon_state = "spacecash50" - desc = "A Biesel Standard Credit chip, used for transactions large and small. This one is worth 50 credits." + desc = "A Biesel Standard Credit chip, used for transactions large and small. This one is worth 50电." worth = 50 /obj/item/spacecash/c100 name = "100 credit chip" icon_state = "spacecash100" - desc = "A Biesel Standard Credit chip, used for transactions large and small. This one is worth 100 credits." + desc = "A Biesel Standard Credit chip, used for transactions large and small. This one is worth 100电." worth = 100 /obj/item/spacecash/c200 name = "200 credit chip" icon_state = "spacecash200" - desc = "A Biesel Standard Credit chip, used for transactions large and small. This one is worth 200 credits." + desc = "A Biesel Standard Credit chip, used for transactions large and small. This one is worth 200电." worth = 200 /obj/item/spacecash/c500 name = "500 credit chip" icon_state = "spacecash500" - desc = "A Biesel Standard Credit chip, used for transactions large and small. This one is worth 500 credits." + desc = "A Biesel Standard Credit chip, used for transactions large and small. This one is worth 500电." worth = 500 /obj/item/spacecash/c1000 name = "1000 credit chip" icon_state = "spacecash1000" - desc = "A Biesel Standard Credit chip, used for transactions large and small. This one is worth 1000 credits." + desc = "A Biesel Standard Credit chip, used for transactions large and small. This one is worth 1000电." worth = 1000 /obj/item/spacecash/coin @@ -238,25 +238,25 @@ /obj/item/spacecash/coin/c001 name = "1 cent unie coin" icon_state = "spacecash0.01" - desc = "A Biesel Standard Credit coin, called a 'unie'. This is worth 0.01 credits." + desc = "A Biesel Standard Credit coin, called a 'unie'. This is worth 0.01电." worth = 0.01 /obj/item/spacecash/coin/c005 name = "5 cent quin coin" icon_state = "spacecash0.05" - desc = "A Biesel Standard Credit coin, called a 'quin'. This is worth 0.05 credits." + desc = "A Biesel Standard Credit coin, called a 'quin'. This is worth 0.05电." worth = 0.05 /obj/item/spacecash/coin/c010 name = "10 cent dece coin" icon_state = "spacecash0.10" - desc = "A Biesel Standard Credit coin, called a 'dece'. This is worth 0.10 credits." + desc = "A Biesel Standard Credit coin, called a 'dece'. This is worth 0.10电." worth = 0.10 /obj/item/spacecash/coin/c025 name = "25 cent quarter coin" icon_state = "spacecash0.25" - desc = "A Biesel Standard Credit coin, called a 'quarter'. This is worth 0.25 credits." + desc = "A Biesel Standard Credit coin, called a 'quarter'. This is worth 0.25电." worth = 0.25 /proc/spawn_money(var/sum, spawnloc, mob/living/carbon/human/human_user as mob) diff --git a/code/modules/economy/quikpay.dm b/code/modules/economy/quikpay.dm index c8451d392272..a3c3c01c6675 100644 --- a/code/modules/economy/quikpay.dm +++ b/code/modules/economy/quikpay.dm @@ -18,6 +18,7 @@ var/editmode = FALSE var/receipt = "" var/destinationact = "Service" + var/shop_name = "Quikpay" /obj/item/quikpay/Initialize() . = ..() @@ -57,20 +58,25 @@ SStgui.update_uis(src) /obj/item/quikpay/proc/print_receipt() - var/obj/item/paper/R = new(usr.loc) + var/obj/item/paper/notepad/receipt/R = new(usr.loc) var/receiptname = "Receipt: [machine_id]" R.set_content_unsafe(receiptname, receipt, sum) //stamp the paper var/image/stampoverlay = image('icons/obj/bureaucracy.dmi') - stampoverlay.icon_state = "paper_stamp-cent" + stampoverlay.icon_state = "paper_stamp-hop" if(!R.stamped) R.stamped = new R.stamped += /obj/item/stamp R.AddOverlays(stampoverlay) R.stamps += "
This paper has been stamped by the Quik-Pay device." + R.ripped = TRUE + usr.put_in_any_hand_if_possible(R) /obj/item/quikpay/attackby(obj/item/attacking_item, mob/user) + if(istype(attacking_item, /obj/item/paper)) + read_paper_list(attacking_item, user) + return if (istype(attacking_item, /obj/item/spacecash/ewallet)) var/obj/item/spacecash/ewallet/E = attacking_item var/transaction_amount = sum @@ -78,8 +84,8 @@ var/transaction_terminal = machine_id if(transaction_amount <= E.worth) + audible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] chimes.")) playsound(src, 'sound/machines/chime.ogg', 50, 1) - src.visible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] chimes.")) SSeconomy.charge_to_account(SSeconomy.get_department_account(destinationact)?.account_number, E.owner_name, transaction_purpose, transaction_terminal, transaction_amount) E.worth -= transaction_amount @@ -104,13 +110,25 @@ if(transaction) to_chat(user, SPAN_NOTICE("[icon2html(src, user)][transaction].")) else + audible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] chimes.")) playsound(src, 'sound/machines/chime.ogg', 50, 1) - visible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] chimes.")) print_receipt() sum = 0 receipt = "" to_chat(user, SPAN_NOTICE("Transaction completed, please return to the home screen.")) +/obj/item/quikpay/proc/read_paper_list(obj/item/paper/R, mob/user) + if(!editmode) + balloon_alert(user, "device locked!") + return FALSE + var/result = read_paper_price_list(R) + for(var/item in result) + items += list(list("name" = item["name"], "price" = item["price"])) + items_to_price[item["name"]] += item["price"] + +/obj/item/quikpay/proc/print_price(mob/user) + return print_price_to_paper(shop_name, items, loc, user) + /obj/item/quikpay/attack_self(var/mob/user) ui_interact(user) @@ -141,7 +159,7 @@ switch(action) if("add") if(!editmode) - to_chat(usr, SPAN_WARNING("Device locked.")) + balloon_alert(usr, "device locked!") return FALSE items += list(list("name" = new_item, "price" = new_price)) @@ -150,7 +168,7 @@ if("remove") if(!editmode) - to_chat(usr, SPAN_NOTICE("Device locked.")) + balloon_alert(usr, "device locked!") return FALSE var/index = 0 for(var/list/L in items) @@ -190,19 +208,29 @@ . = TRUE if("confirm") + // Ensuring it is clear, in case the button is clicked multiple times + receipt = "" + sum = 0 + var/obj/item/card/id/id_card = usr.GetIdCard() + var/cashier = id_card? id_card.registered_name : "Unknown" + receipt = "

[shop_name] receipt

Today's date: [worlddate2text()]
Cashier: [cashier]

Purchased items:
    " for(var/list/bought_item in buying) var/item_name = bought_item["name"] var/item_amount = bought_item["amount"] var/item_price = items_to_price[item_name] - receipt += "[name]: [item_name] x[item_amount] at [item_price]cr each
    " - sum += item_price + receipt += "
  • [item_name]: [item_amount] x [item_price]电: [item_amount * item_price]电
    " + sum += item_price * item_amount + + receipt += "

Total: [sum]电
" + playsound(src, 'sound/machines/ping.ogg', 25, 1) + audible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] pings.")) . = TRUE if("locking") if(editmode) editmode = FALSE - to_chat(usr, SPAN_NOTICE("Device locked.")) + balloon_alert(usr, "device locked!") else if(!editmode) var/obj/item/card/id/I = usr.GetIdCard() @@ -215,14 +243,21 @@ if("accountselect") if(!editmode) - to_chat(usr, SPAN_WARNING("Device locked.")) + balloon_alert(usr, "device locked!") return FALSE var/dest = tgui_input_list(usr, "What account would you like to select?", "Destination Account", assoc_to_keys(SSeconomy.department_accounts)) if(!dest) return FALSE destinationact = dest - return TRUE + . = TRUE + + if("print_dsv") + if(!editmode) + balloon_alert(usr, "device locked!") + return FALSE + print_price(usr) + . = TRUE /obj/item/quikpay/proc/clear_order() buying.Cut() @@ -247,5 +282,6 @@ price_guess = max(0, round(price_guess, 0.01)) items += list(list("name" = "[name_guess]", "price" = price_guess)) + items_to_price[name_guess] = price_guess to_chat(user, SPAN_NOTICE("[src]: added '[name_guess]' for [price_guess].")) diff --git a/code/modules/effects/map_effects/mob_spawner.dm b/code/modules/effects/map_effects/mob_spawner.dm index 63ddf00f4517..00c12a29603f 100644 --- a/code/modules/effects/map_effects/mob_spawner.dm +++ b/code/modules/effects/map_effects/mob_spawner.dm @@ -24,15 +24,24 @@ /obj/effect/fauna_spawner/Initialize() . = ..() var/obj/effect/landmark/mob_waypoint/W = locate(/obj/effect/landmark/mob_waypoint) in world - RegisterSignal(GLOB, COMSIG_GLOB_MOB_DEATH, PROC_REF(mob_died)) + RegisterSignal(SSdcs, COMSIG_GLOB_MOB_DEATH, PROC_REF(mob_died)) if (W && W.z == src.z) waypoint = W if(!islist(GLOB.fauna_spawners)) GLOB.fauna_spawners = list() GLOB.fauna_spawners |= src + return INITIALIZE_HINT_LATELOAD + +/obj/effect/fauna_spawner/LateInitialize() + waypoint = LAZYACCESS(GLOB.mob_waypoints, z) + if(!istype(waypoint)) + qdel(src) /obj/effect/fauna_spawner/Destroy() UnregisterSignal(GLOB, COMSIG_GLOB_MOB_DEATH, PROC_REF(mob_died)) + for(var/mob/m in active_mobs) + UnregisterSignal(m, COMSIG_QDELETING) + active_mobs.Cut() if(islist(GLOB.fauna_spawners)) GLOB.fauna_spawners -= src return ..() @@ -71,7 +80,7 @@ if (!new_mob) return active_mobs += new_mob - RegisterSignal(new_mob, COMSIG_GLOB_MOB_DEATH, PROC_REF(mob_died)) + RegisterSignal(new_mob, COMSIG_QDELETING, PROC_REF(mob_died)) if (src.waypoint && istype(new_mob, /mob/living/simple_animal/hostile)) var/mob/living/simple_animal/hostile/H = new_mob H.target_waypoint = src.waypoint @@ -80,6 +89,8 @@ GLOB.move_manager.move_towards(H, src.waypoint.loc, move_speed, TRUE) /obj/effect/fauna_spawner/proc/mob_died(var/mob/living/mob_ref, gibbed) + SIGNAL_HANDLER + UnregisterSignal(mob_ref, COMSIG_QDELETING) for (var/i = length(active_mobs); i >= 1; i--) var/mob/living/M = active_mobs[i] if (!M || QDELETED(M) || M.stat == DEAD) @@ -171,7 +182,7 @@ var/mob/living/new_mob = new mob_type(T) active_mobs += new_mob - RegisterSignal(new_mob, COMSIG_GLOB_MOB_DEATH, PROC_REF(mob_died)) + RegisterSignal(new_mob, COMSIG_QDELETING, PROC_REF(mob_died)) if(src.waypoint && istype(new_mob, /mob/living/simple_animal/hostile)) var/mob/living/simple_animal/hostile/H = new_mob H.target_waypoint = src.waypoint @@ -206,3 +217,15 @@ /obj/effect/landmark/mob_waypoint name = "mob waypoint" + +/obj/effect/landmark/mob_waypoint/Initialize(mapload) + . = ..() + var/list/z_levels = GetConnectedZlevels(z) + for(var/i in z_levels) + LAZYADDASSOCLIST(GLOB.mob_waypoints, "[i]", src) + +/obj/effect/landmark/mob_waypoint/Destroy() + var/list/z_levels = GetConnectedZlevels(z) + for(var/i in z_levels) + LAZYREMOVEASSOC(GLOB.mob_waypoints, "[i]", src) + return ..() diff --git a/code/modules/events/money_lotto.dm b/code/modules/events/money_lotto.dm index 3454f0c7b0ee..071c123763f3 100644 --- a/code/modules/events/money_lotto.dm +++ b/code/modules/events/money_lotto.dm @@ -28,8 +28,8 @@ var/author = "[SSatlas.current_map.company_name] Editor" var/channel = "Tau Ceti Daily" - var/body = "Tau Ceti Daily wishes to congratulate [winner_name] for recieving the Tau Ceti Stellar Slam Lottery, and receiving the out of this world sum of [winner_sum] credits!" + var/body = "Tau Ceti Daily wishes to congratulate [winner_name] for recieving the Tau Ceti Stellar Slam Lottery, and receiving the out of this world sum of [winner_sum]电!" if(!deposit_success) - body += "
Unfortunately, we were unable to verify the account details provided, so we were unable to transfer the money. Send a cheque containing the sum of 5000 credits to ND 'Stellar Slam' office on the Tau Ceti gateway containing updated details, and your winnings'll be re-sent within the month." + body += "
Unfortunately, we were unable to verify the account details provided, so we were unable to transfer the money. Send a cheque containing the sum of 5000电 to ND 'Stellar Slam' office on the Tau Ceti gateway containing updated details, and your winnings'll be re-sent within the month." var/datum/feed_channel/ch = SSnews.GetFeedChannel(channel) SSnews.SubmitArticle(body, author, ch, null, 1) diff --git a/code/modules/fabrication/designs/general/designs_general.dm b/code/modules/fabrication/designs/general/designs_general.dm index 3ed2b6102030..f8d61afb1757 100644 --- a/code/modules/fabrication/designs/general/designs_general.dm +++ b/code/modules/fabrication/designs/general/designs_general.dm @@ -30,6 +30,10 @@ ABSTRACT_TYPE(/singleton/fabricator_recipe/general) name = "tape recorder" path = /obj/item/taperecorder +/singleton/fabricator_recipe/general/spotlight + name = "spotlight light tube" + path = /obj/item/light/tube/large + /singleton/fabricator_recipe/general/tube name = "light tube" path = /obj/item/light/tube diff --git a/code/modules/fabrication/designs/general/designs_tools.dm b/code/modules/fabrication/designs/general/designs_tools.dm index 5646c16958b1..564cfa1f6b1a 100644 --- a/code/modules/fabrication/designs/general/designs_tools.dm +++ b/code/modules/fabrication/designs/general/designs_tools.dm @@ -45,3 +45,7 @@ ABSTRACT_TYPE(/singleton/fabricator_recipe/tools) /singleton/fabricator_recipe/tools/minihoe name = "mini hoe" path = /obj/item/material/minihoe + +/singleton/fabricator_recipe/tools/hammer + name = "hammer" + path = /obj/item/hammer diff --git a/code/modules/ghostroles/spawner/base.dm b/code/modules/ghostroles/spawner/base.dm index 3cd6583ba000..69984f8fefee 100644 --- a/code/modules/ghostroles/spawner/base.dm +++ b/code/modules/ghostroles/spawner/base.dm @@ -77,6 +77,11 @@ if(!isnull(enable_chance)) enabled = prob(enable_chance) +/datum/ghostspawner/proc/spawn_atom_deleted(atom/spawn_atom) + SIGNAL_HANDLER + spawn_atoms -= spawn_atom + UnregisterSignal(spawn_atom, COMSIG_QDELETING) + //Return a error message if the user CANT see the ghost spawner. Otherwise FALSE /datum/ghostspawner/proc/cant_see(mob/user) //If the user can see the spawner in the menu if(req_perms) //Only those with the correct flags can see restricted roles diff --git a/code/modules/ghostroles/spawner/human/pra.dm b/code/modules/ghostroles/spawner/human/pra.dm index e91ee59c9dd8..314aa326fd99 100644 --- a/code/modules/ghostroles/spawner/human/pra.dm +++ b/code/modules/ghostroles/spawner/human/pra.dm @@ -43,7 +43,7 @@ id = /obj/item/card/id/syndicate accessory = /obj/item/clothing/accessory/badge/hadii_card belt_contents = list( - /obj/item/ammo_magazine/boltaction = 3, + /obj/item/ammo_magazine/a68 = 3, /obj/item/grenade/smokebomb = 2, /obj/item/plastique = 1, /obj/item/gun/projectile/pistol/adhomai = 1, diff --git a/code/modules/heavy_vehicle/components/body.dm b/code/modules/heavy_vehicle/components/body.dm index b082c77ba7f9..90397a0b26ea 100644 --- a/code/modules/heavy_vehicle/components/body.dm +++ b/code/modules/heavy_vehicle/components/body.dm @@ -106,7 +106,7 @@ cockpit.equalize(T.return_air()) changed = TRUE else if(air_supply) - var/env_pressure = cockpit.return_pressure() + var/env_pressure = XGM_PRESSURE(cockpit) var/pressure_delta = air_supply.release_pressure - env_pressure if((air_supply.air_contents.temperature > 0) && (pressure_delta > 0)) var/transfer_moles = calculate_transfer_moles(air_supply.air_contents, cockpit, pressure_delta) diff --git a/code/modules/heavy_vehicle/components/legs.dm b/code/modules/heavy_vehicle/components/legs.dm index 1b4e2b257182..4309203d00c2 100644 --- a/code/modules/heavy_vehicle/components/legs.dm +++ b/code/modules/heavy_vehicle/components/legs.dm @@ -3,8 +3,34 @@ center_of_mass = list("x"=24, "y"=4) icon_state = "loader_legs" power_use = 75 + /// Movement delay added when moving in any direction. var/move_delay = 5 + + /// Movement delay added when turning, cumulative with move_delay. var/turn_delay = 5 + + /// Extra movement delay added when using reverse throttle. + var/reverse_delay = 10 + + /// Extra movement delay added when strafing. + var/strafe_delay_modifier = 1.5 + + /// Whether or not the legs allow strafing at all. + var/can_strafe = TRUE + + /** + * Extra movement delay added based on the ratio of the legs current damage to its maximum damage. + * IE: If your max is 100, and you've taken 50 damage to the legs, this delay should come out to +5. + * At 0 damage, the delay from this is also 0. So it linearly scales with leg damage. + */ + var/damaged_delay = 10 + + /** + * Linear slope of a mech's damage delay characteristics, EG how "fast" it linearly scales. + * This allows floating points, and can technically be a negative number. EG: "Rage mechanic where being damaged makes the mech faster" + */ + var/damaged_delay_slope = 1.0 + var/obj/item/robot_parts/robot_component/actuator/motivator var/mech_turn_sound = 'sound/mecha/mechturn.ogg' var/mech_step_sound = 'sound/mecha/mechstep.ogg' diff --git a/code/modules/heavy_vehicle/components/remote.dm b/code/modules/heavy_vehicle/components/remote.dm index 44b8cfb42c7f..06b3f536f14b 100644 --- a/code/modules/heavy_vehicle/components/remote.dm +++ b/code/modules/heavy_vehicle/components/remote.dm @@ -1,7 +1,7 @@ /obj/item/remote_mecha name = "standard exosuit remote upgrade" desc = "A device that, when inserted into an exosuit, allows it to be remotely piloted." - icon = 'icons/obj/modular_components.dmi' + icon = 'icons/obj/modular_computers/modular_components.dmi' icon_state = "aislot" origin_tech = list(TECH_BLUESPACE = 3, TECH_MATERIAL = 4, TECH_DATA = 4) w_class = WEIGHT_CLASS_SMALL diff --git a/code/modules/heavy_vehicle/mech_helpers.dm b/code/modules/heavy_vehicle/mech_helpers.dm index 6356742d8c2b..2c3d5c796f89 100644 --- a/code/modules/heavy_vehicle/mech_helpers.dm +++ b/code/modules/heavy_vehicle/mech_helpers.dm @@ -1,5 +1,4 @@ -/mob/living/heavy_vehicle/proc/can_move(var/mob/user) - . = 0 +/mob/living/heavy_vehicle/proc/can_move(var/mob/user, delay_modifier) if(world.time < next_mecha_move) return @@ -12,13 +11,85 @@ next_mecha_move = world.time + 3 // Just to stop them from getting spammed with messages. return - if(!legs.motivator || legs.total_damage > 45) + if(!legs.motivator || legs.total_damage != 0 && legs.total_damage >= legs.max_damage) if(user) - to_chat(user, SPAN_WARNING("Your motivators are damaged! You can't move!")) + to_chat(user, SPAN_WARNING("Your motivators are destroyed! You can't move!")) next_mecha_move = world.time + 15 return - next_mecha_move = world.time + (incorporeal_move ? legs.move_delay / 2 : legs.move_delay) + if(maintenance_protocols) + if(user) + to_chat(user, SPAN_WARNING("Maintenance protocols are in effect.")) + return + + var/obj/item/cell/C = get_cell() + if(!C || !C.check_charge(legs.power_use * CELLRATE)) + if(user) + to_chat(user, SPAN_WARNING("The power indicator flashes briefly.")) + return + + + next_mecha_move = delay_modifier + world.time + (incorporeal_move ? legs.move_delay / 2 : legs.move_delay) + (legs.damaged_delay * (legs.total_damage / legs.max_damage) * legs.damaged_delay_slope) + return TRUE + +/mob/living/heavy_vehicle/proc/can_turn(var/mob/user, delay_modifier) + if(world.time < next_mecha_turn) + return + + if(incapacitated() || (user && user.incapacitated()) || lockdown) + return + + if(!legs) + if(user) + to_chat(user, SPAN_WARNING("\The [src] has no means of propulsion!")) + next_mecha_turn = world.time + 3 // Just to stop them from getting spammed with messages. + return + + if(!legs.motivator || legs.total_damage != 0 && legs.total_damage >= legs.max_damage) + if(user) + to_chat(user, SPAN_WARNING("Your motivators are destroyed! You can't turn!")) + next_mecha_turn = world.time + 15 + return + + if(maintenance_protocols) + if(user) + to_chat(user, SPAN_WARNING("Maintenance protocols are in effect.")) + return + + var/obj/item/cell/C = get_cell() + if(!C || !C.check_charge(legs.power_use * CELLRATE)) + if(user) + to_chat(user, SPAN_WARNING("The power indicator flashes briefly.")) + return + + + next_mecha_turn = delay_modifier + world.time + legs.turn_delay + (legs.damaged_delay * (legs.total_damage / legs.max_damage) * legs.damaged_delay_slope) + return TRUE + +/mob/living/heavy_vehicle/proc/can_strafe(var/mob/user, delay_modifier) + if (world.time < next_mecha_move) + return + + if(incapacitated() || (user && user.incapacitated()) || lockdown) + return + + if(!legs) + if(user) + to_chat(user, SPAN_WARNING("\The [src] has no means of propulsion!")) + next_mecha_move = world.time + 3 // Just to stop them from getting spammed with messages. + return + + if(!legs.can_strafe) + if(user) + to_chat(user, SPAN_WARNING("Your motivators are not capable of strafing!")) + next_mecha_move = world.time + 15 + return + + if(!legs.motivator || legs.total_damage != 0 && legs.total_damage >= legs.max_damage) + if(user) + to_chat(user, SPAN_WARNING("Your motivators are destroyed! You can't strafe!")) + next_mecha_move = world.time + 15 + return if(maintenance_protocols) if(user) @@ -31,6 +102,7 @@ to_chat(user, SPAN_WARNING("The power indicator flashes briefly.")) return + next_mecha_move = world.time + ((legs.move_delay + (legs.damaged_delay * (legs.total_damage / legs.max_damage) * legs.damaged_delay_slope)) * legs.strafe_delay_modifier) return TRUE /mob/living/heavy_vehicle/get_standard_pixel_x() diff --git a/code/modules/heavy_vehicle/mech_interaction.dm b/code/modules/heavy_vehicle/mech_interaction.dm index b7f251cae555..7ea50f785524 100644 --- a/code/modules/heavy_vehicle/mech_interaction.dm +++ b/code/modules/heavy_vehicle/mech_interaction.dm @@ -228,6 +228,8 @@ user.forceMove(src) LAZYDISTINCTADD(pilots, user) RegisterSignal(user, COMSIG_MOB_FACEDIR, PROC_REF(handle_user_turn)) + RegisterSignal(user, COMSIG_INPUT_KEY_QUICK_EQUIP, PROC_REF(strafe_left)) + RegisterSignal(user, COMSIG_INPUT_KEY_DROP, PROC_REF(strafe_right)) playsound(src, 'sound/machines/windowdoor.ogg', 50, 1) if(user.client) user.client.screen |= hud_elements LAZYDISTINCTADD(user.additional_vision_handlers, src) @@ -260,61 +262,123 @@ set_intent(I_HURT) LAZYREMOVE(pilots, user) UnregisterSignal(user, COMSIG_MOB_FACEDIR) + UnregisterSignal(user, COMSIG_INPUT_KEY_QUICK_EQUIP) + UnregisterSignal(user, COMSIG_INPUT_KEY_DROP) UNSETEMPTY(pilots) /mob/living/heavy_vehicle/proc/handle_user_turn(var/mob/living/user, var/direction) SIGNAL_HANDLER INVOKE_ASYNC(src, TYPE_PROC_REF(/atom, relaymove), user, direction, TRUE) +/mob/living/heavy_vehicle/proc/strafe_left(var/mob/user, var/cancelled) + SIGNAL_HANDLER + // Stop the pilot from attempting to drop the item in their hands, we're replacing it with a strafe input. + *cancelled = TRUE + strafe_move(user, angle2dir(dir2angle(dir) + 90)) + +/mob/living/heavy_vehicle/proc/strafe_right(var/mob/user, var/cancelled) + SIGNAL_HANDLER + // Stop the pilot from attempting to drop the item in their hands, we're replacing it with a strafe input. + *cancelled = TRUE + strafe_move(user, angle2dir(dir2angle(dir) + 270)) + /mob/living/heavy_vehicle/relaymove(mob/living/user, direction, var/turn_only = FALSE) . = ..() - if(!can_move(user)) - return + var/delay_modifier = 0 + SEND_SIGNAL(user, COMSIG_MECH_MOVE_WASD, &direction, &delay_modifier) if(hallucination >= EMP_MOVE_DISRUPT && prob(30)) direction = pick(GLOB.cardinals) - var/do_strafe = !isnull(user.facing_dir) && (legs.turn_delay <= legs.move_delay) - if(!do_strafe && dir != direction) + // Convert keyboard inputs to Battletech-style controls. + switch (direction) + if (NORTH) // "Throttle Forwards" + throttle_move(user, dir, FALSE, delay_modifier) + if (SOUTH) // "Throttle Reverse" + throttle_move(user, angle2dir(dir2angle(dir) + 180), TRUE, delay_modifier) + if (EAST) // "Turn Right" + rotate_by_angle(user, angle2dir(dir2angle(dir) + 90), delay_modifier) + if (WEST) // "Turn Left" + rotate_by_angle(user, angle2dir(dir2angle(dir) + 270), delay_modifier) + +/mob/living/heavy_vehicle/proc/throttle_move(mob/living/user, direction, reverse, delay_modifier) + if (!legs || !can_move(user, delay_modifier)) + return + + // Get the tile in the direction. + var/turf/target_loc = get_step(src, direction) + if(!legs.can_move_on(loc, target_loc)) + return + + if (reverse) + next_mecha_move += legs.reverse_delay + + // Then send a move command + if(incorporeal_move) + if(legs.mech_step_sound) + playsound(src.loc,legs.mech_step_sound,40,1) use_cell_power(legs.power_use * CELLRATE) - if(legs && legs.mech_turn_sound) - playsound(src.loc,legs.mech_turn_sound,40,1) - if(world.time + legs.turn_delay > next_mecha_move) - next_mecha_move = world.time + legs.turn_delay - set_dir(direction) - for(var/mob/pilot in pilots) - pilot.set_dir(direction) - if(istype(hardpoints[HARDPOINT_BACK], /obj/item/mecha_equipment/shield)) - var/obj/item/mecha_equipment/shield/S = hardpoints[HARDPOINT_BACK] - if(S.aura) - S.aura.dir = direction - if(S.aura.dir == NORTH) - S.aura.layer = MOB_LAYER - else - S.aura.layer = ABOVE_HUMAN_LAYER - update_icon() + user.client.Process_Incorpmove(direction, src) + else + Move(target_loc, direction, 0, FALSE) - if(!turn_only) - var/turf/target_loc = get_step(src, direction) - if(!legs.can_move_on(loc, target_loc)) - return - if(incorporeal_move) - if(legs && legs.mech_step_sound) - playsound(src.loc,legs.mech_step_sound,40,1) - use_cell_power(legs.power_use * CELLRATE) - user.client.Process_Incorpmove(direction, src) - else - var/new_direction = do_strafe ? user.facing_dir || direction : direction - Move(target_loc, new_direction) +/mob/living/heavy_vehicle/proc/strafe_move(mob/user, direction) + if (!legs) + return -/mob/living/heavy_vehicle/Move() + var/delay_modifier = 0 + SEND_SIGNAL(user, COMSIG_MECH_MOVE_STRAFE, &direction, &delay_modifier) + + if (!can_strafe(user, delay_modifier)) + return + + // Get the tile in the direction. + var/turf/target_loc = get_step(src, direction) + if(!legs.can_move_on(loc, target_loc)) + return + + // Then send a move command + if(incorporeal_move) + if(legs.mech_step_sound) + playsound(src.loc,legs.mech_step_sound,40,1) + use_cell_power(legs.power_use * CELLRATE) + user.client.Process_Incorpmove(direction, src) + else + Move(target_loc, direction, 0, FALSE) + +/mob/living/heavy_vehicle/proc/rotate_by_angle(mob/living/user, direction, delay_modifier) + if (!legs || !can_turn(user, delay_modifier)) + return + + use_cell_power(legs.power_use * CELLRATE) + if(legs && legs.mech_turn_sound) + playsound(src.loc,legs.mech_turn_sound,40,1) + + set_dir(direction) + for(var/mob/pilot in pilots) + pilot.set_dir(direction) + if(istype(hardpoints[HARDPOINT_BACK], /obj/item/mecha_equipment/shield)) + var/obj/item/mecha_equipment/shield/S = hardpoints[HARDPOINT_BACK] + if(S.aura) + S.aura.dir = direction + if(S.aura.dir == NORTH) + S.aura.layer = MOB_LAYER + else + S.aura.layer = ABOVE_HUMAN_LAYER + update_icon() + Move(src.loc, direction, 0, TRUE) + +/mob/living/heavy_vehicle/Move(atom/newloc, direct, glide_size_override = 0, update_dir = TRUE) + // They shouldn't get to this proc without legs in the first place, but its okay to guard here. + if (!legs) + return . = ..() + set_glide_size(DELAY_TO_GLIDE_SIZE(next_mecha_move - world.time)) if(. && !istype(loc, /turf/space)) - if(legs) - if(legs.mech_step_sound) - playsound(src.loc, legs.mech_step_sound, 40, TRUE) - use_cell_power(legs.power_use * CELLRATE) + if(legs.mech_step_sound) + playsound(src.loc, legs.mech_step_sound, 40, TRUE) + use_cell_power(legs.power_use * CELLRATE) update_icon() /mob/living/heavy_vehicle/Post_Incorpmove() diff --git a/code/modules/heavy_vehicle/mecha.dm b/code/modules/heavy_vehicle/mecha.dm index f02841c18862..c68c8420cbf0 100644 --- a/code/modules/heavy_vehicle/mecha.dm +++ b/code/modules/heavy_vehicle/mecha.dm @@ -9,7 +9,7 @@ mob_push_flags = ALLMOBS can_be_buckled = FALSE accent = ACCENT_TTS - appearance_flags = KEEP_TOGETHER + appearance_flags = KEEP_TOGETHER | DEFAULT_APPEARANCE_FLAGS | TILE_BOUND | LONG_GLIDE pass_flags_self = PASSVEHICLE var/decal @@ -76,7 +76,16 @@ var/use_air = FALSE // Interface stuff. + + /// The next world tick that the mech has to wait for before it can change its Throttle (forward and backward movement). var/next_mecha_move = 0 + + /// The next world tick that the mech has to wait for before it can turn. + var/next_mecha_turn = 0 + + /// The next world tick that the mech has to wait for before it can strafe. + var/next_mecha_strafe = 0 + var/list/hud_elements = list() var/list/hardpoint_hud_elements = list() var/atom/movable/screen/mecha/health/hud_health @@ -254,6 +263,13 @@ /// `var/remote` can be set to TRUE to have proc adjust where messages and hud elements are presented /// If `remote` is TRUE, messages and other hud elements are called on the exosuit itself to prevent wierdness, and errors are handled in `handle_hear_say()` /mob/living/heavy_vehicle/proc/toggle_power(var/mob/user, var/remote = FALSE) + var/cancelled = FALSE + var/delay = 0 + SEND_SIGNAL(user, COMSIG_MECH_TOGGLE_POWER, &cancelled, &delay) + if (cancelled || delay && !do_after(user, delay)) + to_chat(user, SPAN_WARNING("There's just too many buttons! You fail to find the power switch!")) + return + // if remotely called, send these messages to the exosuit, not the person calling this proc var/reciever = user if(remote) diff --git a/code/modules/heavy_vehicle/premade/combat.dm b/code/modules/heavy_vehicle/premade/combat.dm index 2e948dc65aad..970a79690cdd 100644 --- a/code/modules/heavy_vehicle/premade/combat.dm +++ b/code/modules/heavy_vehicle/premade/combat.dm @@ -33,6 +33,9 @@ max_damage = 100 power_use = 2500 trample_damage = 35 + // Dedicated combat chassis is highly resistant to mobility loss until a full "mobility kill" + damaged_delay = 3 + damaged_delay_slope = 0.5 /obj/item/mech_component/sensors/combat name = "combat sensors" diff --git a/code/modules/heavy_vehicle/premade/cult.dm b/code/modules/heavy_vehicle/premade/cult.dm index 19b038b32d73..ca4fbbb14e58 100644 --- a/code/modules/heavy_vehicle/premade/cult.dm +++ b/code/modules/heavy_vehicle/premade/cult.dm @@ -38,6 +38,11 @@ power_use = 2500 trample_damage = 45 + // Uniquely increases speed when damaged. Fragile, but good for melee. + // It can become faster than a light mech, but only when on the verge of death. + damaged_delay = 4 + damaged_delay_slope = -1 + /obj/item/mech_component/sensors/cult name = "daemon sensors" desc = "A hard shell to protect those that follow the Great One, these sensors assist in the slaughter." diff --git a/code/modules/heavy_vehicle/premade/heavy.dm b/code/modules/heavy_vehicle/premade/heavy.dm index 74949de7f68f..5757bd6a2dc2 100644 --- a/code/modules/heavy_vehicle/premade/heavy.dm +++ b/code/modules/heavy_vehicle/premade/heavy.dm @@ -33,6 +33,7 @@ max_damage = 200 power_use = 2500 trample_damage = 45 + damaged_delay = 5 /obj/item/mech_component/sensors/heavy name = "heavy sensors" diff --git a/code/modules/heavy_vehicle/premade/hoverpod.dm b/code/modules/heavy_vehicle/premade/hoverpod.dm index 80c136255290..adb7e97f1b38 100644 --- a/code/modules/heavy_vehicle/premade/hoverpod.dm +++ b/code/modules/heavy_vehicle/premade/hoverpod.dm @@ -8,6 +8,8 @@ max_damage = 150 move_delay = 5 turn_delay = 2 + strafe_delay_modifier = 1.2 // minimal delay on strafing. + reverse_delay = 10 power_use = 2500 trample_damage = 0 hover = TRUE @@ -20,4 +22,6 @@ max_damage = 75 move_delay = 2 turn_delay = 2 + strafe_delay_modifier = 1.2 // minimal delay on strafing. + reverse_delay = 5 power_use = 2000 diff --git a/code/modules/heavy_vehicle/premade/light.dm b/code/modules/heavy_vehicle/premade/light.dm index ef42515577ba..d69dafbc7f79 100644 --- a/code/modules/heavy_vehicle/premade/light.dm +++ b/code/modules/heavy_vehicle/premade/light.dm @@ -29,6 +29,7 @@ icon_state = "light_legs" move_delay = 2 turn_delay = 2 + damaged_delay = 4 max_damage = 100 power_use = 1500 desc = "The electrical systems driving these legs are almost totally silent. Unfortunately slamming a plate of metal against the ground is not." diff --git a/code/modules/heavy_vehicle/premade/military.dm b/code/modules/heavy_vehicle/premade/military.dm index 4964d6f16c31..79d3f691d593 100644 --- a/code/modules/heavy_vehicle/premade/military.dm +++ b/code/modules/heavy_vehicle/premade/military.dm @@ -16,6 +16,8 @@ desc = "Four utterly goliath stump-like pistons hold this propulsion mechanism together." icon_state = "strider_legs" move_delay = 5 + damaged_delay = 5 + damaged_delay_slope = 0.5 max_damage = 650 power_use = 2500 trample_damage = 45 diff --git a/code/modules/heavy_vehicle/premade/misc.dm b/code/modules/heavy_vehicle/premade/misc.dm index cad77053eb8b..fd75befc8463 100644 --- a/code/modules/heavy_vehicle/premade/misc.dm +++ b/code/modules/heavy_vehicle/premade/misc.dm @@ -6,6 +6,9 @@ max_damage = 160 move_delay = 4 turn_delay = 1 + reverse_delay = 1 // Faster than usual reverse for legs + strafe_delay_modifier = 1 // Uniquely the only chassis without a strafe delay + damaged_delay = 4 power_use = 1250 trample_damage = 10 @@ -16,6 +19,7 @@ icon_state = "spiderlegs-industrial" max_damage = 250 move_delay = 5 + damaged_delay = 5 turn_delay = 1 power_use = 3500 trample_damage = 25 @@ -27,8 +31,11 @@ icon_state = "tracks" max_damage = 450 move_delay = 2 //Its fast + damaged_delay = 2 turn_delay = 7 + reverse_delay = 0 // Uniquely the only chassis without a reverse delay. power_use = 3500 color = COLOR_WHITE mech_step_sound = 'sound/mecha/tanktread.ogg' trample_damage = 25 + can_strafe = FALSE diff --git a/code/modules/heavy_vehicle/premade/pra.dm b/code/modules/heavy_vehicle/premade/pra.dm index bffc82719872..8468fb05e7d2 100644 --- a/code/modules/heavy_vehicle/premade/pra.dm +++ b/code/modules/heavy_vehicle/premade/pra.dm @@ -28,6 +28,7 @@ desc = "Strong legs adapted for the Adhomian rought terrain." icon_state = "egg_legs" move_delay = 3 + damaged_delay = 3 turn_delay = 3 max_damage = 100 power_use = 2500 diff --git a/code/modules/hydroponics/seed.dm b/code/modules/hydroponics/seed.dm index 91e96979c106..28bc309bbf4a 100644 --- a/code/modules/hydroponics/seed.dm +++ b/code/modules/hydroponics/seed.dm @@ -59,6 +59,9 @@ var/force_layer var/hydrotray_only + /// The amount of time it takes to harvest this plant. + var/harvest_time = 2 SECONDS + /datum/seed/proc/setup_traits() /datum/seed/New() @@ -322,7 +325,7 @@ health_change += missing_gas * HYDRO_SPEED_MULTIPLIER // Process it. - var/pressure = environment.return_pressure() + var/pressure = XGM_PRESSURE(environment) if(pressure < GET_SEED_TRAIT(src, TRAIT_LOWKPA_TOLERANCE)|| pressure > GET_SEED_TRAIT(src, TRAIT_HIGHKPA_TOLERANCE)) health_change += rand(1,3) * HYDRO_SPEED_MULTIPLIER @@ -773,13 +776,28 @@ /// Place the plant products at the feet of the user. /datum/seed/proc/harvest(var/mob/user,var/yield_mod,var/harvest_sample,var/force_amount,var/stunted_status = FALSE) - if(!user) + if(!istype(user)) + return + + var/total_yield = 0 + var/cancelled = FALSE + var/doafter = harvest_time + // Check if any components on the user wish to modify the harvest. + SEND_SIGNAL(user, COMSIG_PLANT_HARVESTER, src, &total_yield, &cancelled, &doafter) + // And check if any components on the plant wish to modify the harvest. + SEND_SIGNAL(src, COMSIG_PLANT_HARVESTED, user, &total_yield, &cancelled, &doafter) + if (cancelled) + return + + user.visible_message(SPAN_WARNING("[user] starts harvesting \the [display_name]")) + if (doafter > 0 && !do_after(user, doafter, src)) + to_chat(user, SPAN_DANGER("You were interrupted while trying to harvest \the [display_name]")) return if(!force_amount && GET_SEED_TRAIT(src, TRAIT_YIELD) == 0 && !harvest_sample) - if(istype(user)) to_chat(user, SPAN_DANGER("You fail to harvest anything useful.")) + to_chat(user, SPAN_DANGER("You fail to harvest anything useful.")) else - if(istype(user)) to_chat(user, "You [harvest_sample ? "take a sample" : "harvest"] from the [display_name].") + to_chat(user, "You [harvest_sample ? "take a sample" : "harvest"] from the [display_name].") //This may be a new line. Update the global if it is. if(name == "new line" || !(name in SSplants.seeds)) @@ -793,16 +811,15 @@ seeds.update_seed() return - var/total_yield = 0 if(!isnull(force_amount)) total_yield = force_amount else if(GET_SEED_TRAIT(src, TRAIT_YIELD) > -1) if(isnull(yield_mod) || yield_mod < 1) yield_mod = 0 - total_yield = GET_SEED_TRAIT(src, TRAIT_YIELD) + total_yield += GET_SEED_TRAIT(src, TRAIT_YIELD) else - total_yield = GET_SEED_TRAIT(src, TRAIT_YIELD) + rand(yield_mod) + total_yield += GET_SEED_TRAIT(src, TRAIT_YIELD) + rand(yield_mod) total_yield = max(1,total_yield) // If the plant is stunted, you get half the yield. diff --git a/code/modules/hydroponics/seed_machines.dm b/code/modules/hydroponics/seed_machines.dm index cb48dede9ef3..11673255d245 100644 --- a/code/modules/hydroponics/seed_machines.dm +++ b/code/modules/hydroponics/seed_machines.dm @@ -5,7 +5,9 @@ icon_state = "disk" w_class = WEIGHT_CLASS_TINY + /// The current gene data on the disk. var/list/genes = list() + /// The player-facing name of the gene's source. var/genesource = "unknown" /obj/item/disk/botany/New() @@ -35,22 +37,28 @@ /obj/machinery/botany icon = 'icons/obj/hydroponics_machines.dmi' icon_state = "hydrotray3" - density = 1 - anchored = 1 - - var/obj/item/seeds/seed // Currently loaded seed packet. - var/obj/item/disk/botany/loaded_disk //Currently loaded data disk. - - var/open = 0 - var/active = 0 + density = TRUE + anchored = TRUE + + /// Currently loaded seed packet. + var/obj/item/seeds/seed + /// Currently loaded data disk. + var/obj/item/disk/botany/loaded_disk + /// Is the machine current performing a task? + var/active = FALSE + /// Duration the task requires for completion. var/action_time = 5 + /// World time when the last action was queued. var/last_action = 0 - var/eject_disk = 0 - var/failed_task = 0 - var/disk_needs_genes = 0 - + /// Whether the currently queued task should eject the current disk, if present. + var/eject_disk = FALSE + /// Whether the task has failed or not. + var/failed_task = FALSE + /// Helps determine whether or not a given operation requires a disk to be loaded with genes or to be empty. + var/disk_needs_genes = FALSE + +/// Gets run every process tick. /obj/machinery/botany/process() - ..() if(!active) return @@ -95,11 +103,11 @@ return if(attacking_item.tool_behaviour == TOOL_SCREWDRIVER) - open = !open - to_chat(user, SPAN_NOTICE("You [open ? "open" : "close"] the maintenance panel.")) + panel_open = !panel_open + to_chat(user, SPAN_NOTICE("You [panel_open ? "open" : "close"] the maintenance panel.")) return - if(open) + if(panel_open) if(attacking_item.tool_behaviour == TOOL_CROWBAR) dismantle() return @@ -127,7 +135,52 @@ return ..() -// Allows for a trait to be extracted from a seed packet, destroying that seed. +/// UI data shared between both editor and extractor machinery. +/obj/machinery/botany/ui_data(mob/user) + var/list/data = list() + + data["activity"] = active + data["loadedSeed"] = seed ? "[seed.name]" : null + data["disk"] = loaded_disk ? TRUE : FALSE + + return data + +/// UI action behavior shared between both editor and extractor machinery. +/obj/machinery/botany/ui_act(action, params) + . = ..() + if(.) + return + + switch(action) + if("eject_packet") + if(!seed) + return FALSE + + seed.forceMove(get_turf(src)) + + if(seed.seed.name == "new line" || isnull(SSplants.seeds[seed.seed.name])) + seed.seed.uid = SSplants.seeds.len + 1 + seed.seed.name = "[seed.seed.uid]" + SSplants.seeds[seed.seed.name] = seed.seed + + seed.update_seed() + visible_message("[icon2html(src, viewers(get_turf(src)))] [src] beeps and spits out [seed].") + seed = null + + if("eject_disk") + if(!loaded_disk) + return FALSE + + loaded_disk.forceMove(get_turf(src)) + visible_message("[icon2html(src, viewers(get_turf(src)))] [src] beeps and spits out [loaded_disk].") + loaded_disk = null + + else + return FALSE + + return TRUE + +/// Allows for a trait to be extracted from a seed packet, destroying that seed. /obj/machinery/botany/extractor name = "lysis-isolation centrifuge" icon_state = "centrifuge" @@ -136,194 +189,142 @@ /obj/item/stock_parts/manipulator = 3, /obj/item/stock_parts/scanning_module = 1 ) + /// Currently scanned seed genetic structure. + var/datum/seed/genetics + /// Increments with each scan, stops allowing gene mods after a certain point. + var/degradation = 0 - var/datum/seed/genetics // Currently scanned seed genetic structure. - var/degradation = 0 // Increments with each scan, stops allowing gene mods after a certain point. - -/obj/machinery/botany/extractor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - +/obj/machinery/botany/extractor/ui_interact(mob/user, datum/tgui/ui) if(!user) return - var/list/data = list() + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "BotanyIsolator", "Lysis-Isolation Centrifuge") + ui.open() - var/list/geneMasks = SSplants.gene_masked_list - data["geneMasks"] = geneMasks +/obj/machinery/botany/extractor/ui_data(mob/user) + var/list/data = ..() - data["activity"] = active data["degradation"] = degradation - - if(loaded_disk) - data["disk"] = 1 - else - data["disk"] = 0 - - if(seed) - data["loaded"] = "[seed.name]" - else - data["loaded"] = 0 + data["geneMasks"] = SSplants.gene_masked_list if(genetics) - data["hasGenetics"] = 1 + data["hasGeneticsData"] = TRUE data["sourceName"] = genetics.display_name if(!genetics.roundstart) data["sourceName"] += " (variety #[genetics.uid])" - else - data["hasGenetics"] = 0 - data["sourceName"] = 0 - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "botany_isolator.tmpl", "Lysis-isolation Centrifuge UI", 470, 450) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -/obj/machinery/botany/Topic(href, href_list) - - if(..()) - return 1 - if(href_list["eject_packet"]) - if(!seed) return - seed.forceMove(get_turf(src)) + data["loadedseed"] = seed ? "[seed.name]" : "Unknown" + data["disk"] = loaded_disk ? TRUE : FALSE - if(seed.seed.name == "new line" || isnull(SSplants.seeds[seed.seed.name])) - seed.seed.uid = SSplants.seeds.len + 1 - seed.seed.name = "[seed.seed.uid]" - SSplants.seeds[seed.seed.name] = seed.seed + return data - seed.update_seed() - visible_message("[icon2html(src, viewers(get_turf(src)))] [src] beeps and spits out [seed].") +/obj/machinery/botany/extractor/ui_act(action, params) + switch(action) + if("scan_genome") + if(!seed) + return FALSE - seed = null + last_action = world.time + active = TRUE - if(href_list["eject_disk"]) - if(!loaded_disk) return - loaded_disk.forceMove(get_turf(src)) - visible_message("[icon2html(src, viewers(get_turf(src)))] [src] beeps and spits out [loaded_disk].") - loaded_disk = null + if(seed && seed.seed) + genetics = seed.seed + degradation = 0 - usr.set_machine(src) - src.add_fingerprint(usr) + qdel(seed) + seed = null -/obj/machinery/botany/extractor/Topic(href, href_list) + return TRUE - if(..()) - return 1 - - usr.set_machine(src) - src.add_fingerprint(usr) - - if(href_list["scan_genome"]) - - if(!seed) return - - last_action = world.time - active = 1 - - if(seed && seed.seed) - genetics = seed.seed - degradation = 0 + if("get_gene") + if(!genetics || !loaded_disk) + return TRUE - qdel(seed) - seed = null + var/gene_tag = params["gene"] + if(!gene_tag) + return TRUE - if(href_list["get_gene"]) + last_action = world.time + active = TRUE - if(!genetics || !loaded_disk) return + var/datum/plantgene/P = genetics.get_gene(gene_tag) + if(!P) + return TRUE - last_action = world.time - active = 1 + loaded_disk.genes += P - var/datum/plantgene/P = genetics.get_gene(href_list["get_gene"]) - if(!P) return - loaded_disk.genes += P + loaded_disk.genesource = "[genetics.display_name]" + if(!genetics.roundstart) + loaded_disk.genesource += " (variety #[genetics.uid])" - loaded_disk.genesource = "[genetics.display_name]" - if(!genetics.roundstart) - loaded_disk.genesource += " (variety #[genetics.uid])" + loaded_disk.name += " ([SSplants.gene_tag_masks[gene_tag]], #[genetics.uid])" + loaded_disk.desc += " The label reads 'gene [SSplants.gene_tag_masks[gene_tag]], sampled from [genetics.display_name]'." + eject_disk = TRUE - loaded_disk.name += " ([SSplants.gene_tag_masks[href_list["get_gene"]]], #[genetics.uid])" - loaded_disk.desc += " The label reads \'gene [SSplants.gene_tag_masks[href_list["get_gene"]]], sampled from [genetics.display_name]\'." - eject_disk = 1 + degradation += rand(20,60) + if(degradation >= 100) + failed_task = TRUE + genetics = null + degradation = 0 + return TRUE - degradation += rand(20,60) - if(degradation >= 100) - failed_task = 1 + if("clear_buffer") + if(!genetics) + return genetics = null degradation = 0 + return TRUE - if(href_list["clear_buffer"]) - if(!genetics) return - genetics = null - degradation = 0 + return ..() - src.updateUsrDialog() - return - -// Fires an extracted trait into another packet of seeds with a chance -// of destroying it based on the size/complexity of the plasmid. +/// Injects an extracted trait into another packet of seeds with a chance of destroying it based on the size/complexity of the plasmid. /obj/machinery/botany/editor name = "bioballistic delivery system" icon_state = "traitgun" - disk_needs_genes = 1 + disk_needs_genes = TRUE component_types = list( /obj/item/circuitboard/botany_editor, /obj/item/stock_parts/manipulator = 3, /obj/item/stock_parts/scanning_module = 1 ) -/obj/machinery/botany/editor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - +/obj/machinery/botany/editor/ui_interact(mob/user, datum/tgui/ui) if(!user) return - var/list/data = list() + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "BotanyEditor", "Bioballistic Delivery System") + ui.open() - data["activity"] = active +/obj/machinery/botany/editor/ui_data(mob/user) + var/list/data = ..() - if(seed) - data["degradation"] = seed.modified - else - data["degradation"] = 0 + data["degradation"] = seed ? seed.modified : 0 + data["disk"] = !!loaded_disk if(loaded_disk && loaded_disk.genes.len) - data["disk"] = 1 data["sourceName"] = loaded_disk.genesource data["locus"] = "" for(var/datum/plantgene/P in loaded_disk.genes) - if(data["locus"] != "") data["locus"] += ", " + if(data["locus"] != "") + data["locus"] += ", " data["locus"] += "[SSplants.gene_tag_masks[P.genetype]]" - else - data["disk"] = 0 - data["sourceName"] = 0 - data["locus"] = 0 - - if(seed) - data["loaded"] = "[seed.name]" - else - data["loaded"] = 0 + data["loadedseed"] = seed ? "[seed.name]" : null - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "botany_editor.tmpl", "Bioballistic Delivery UI", 470, 450) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) + return data -/obj/machinery/botany/editor/Topic(href, href_list) - - if(..()) - return 1 - - if(href_list["apply_gene"]) - if(!loaded_disk || !seed) return +/obj/machinery/botany/editor/ui_act(action, params) + if(action == "apply_gene") + if(!loaded_disk || !seed) + return TRUE last_action = world.time - active = 1 + active = TRUE if(!isnull(SSplants.seeds[seed.seed.name])) seed.seed = seed.seed.diverge(1) @@ -331,15 +332,16 @@ seed.update_seed() if(prob(seed.modified)) - failed_task = 1 + failed_task = TRUE seed.modified = 101 for(var/datum/plantgene/gene in loaded_disk.genes) seed.seed.apply_gene(gene) seed.modified += rand(5,10) - usr.set_machine(src) - src.add_fingerprint(usr) + return TRUE + + return ..() /obj/item/circuitboard/botany_extractor name = T_BOARD("lysis-isolation centrifuge") diff --git a/code/modules/hydroponics/trays/tray_tools.dm b/code/modules/hydroponics/trays/tray_tools.dm index b454938b0005..6ba1f885a1ee 100644 --- a/code/modules/hydroponics/trays/tray_tools.dm +++ b/code/modules/hydroponics/trays/tray_tools.dm @@ -25,7 +25,7 @@ /// Like a health analyzer, but for plants! Tells you everything you need to know. /obj/item/analyzer/plant_analyzer name = "plant analyzer" - icon = 'icons/obj/item/plant_analyzer.dmi' + icon = 'icons/obj/item/scanner.dmi' icon_state = "hydro" item_state = "hydro" var/form_title diff --git a/code/modules/integrated_electronics/passive/power.dm b/code/modules/integrated_electronics/passive/power.dm index a42608816f31..55cede7cc9ec 100644 --- a/code/modules/integrated_electronics/passive/power.dm +++ b/code/modules/integrated_electronics/passive/power.dm @@ -201,15 +201,16 @@ if(should_act) // We're gonna give or take from the net. if(drawing) var/to_transfer = min(throughput, (assembly.battery.maxcharge - assembly.battery.charge) / CELLRATE) // So we don't need to draw 10kW if the cell needs much less. - var/amount = IO.draw_power(to_transfer) + var/amount = POWER_DRAW(IO, to_transfer) + DRAW_POWER(IO, amount) assembly.give_power(amount) else var/amount = assembly.draw_power(throughput) - IO.add_avail(amount) + ADD_TO_POWERNET(IO, amount) - set_pin_data(IC_OUTPUT, 1, IO.avail()) - set_pin_data(IC_OUTPUT, 2, IO.surplus()) - set_pin_data(IC_OUTPUT, 3, -IO.surplus()-IO.avail()) // we don't have a viewload() proc on machines and i'm lazy + set_pin_data(IC_OUTPUT, 1, POWER_AVAIL(IO)) + set_pin_data(IC_OUTPUT, 2, POWER_SURPLUS(IO)) + set_pin_data(IC_OUTPUT, 3, POWER_LOAD(IO)) // Internal power machine for interacting with the powernet. // It needs a bit of special code since base /machinery/power assumes loc will be a tile. diff --git a/code/modules/integrated_electronics/subtypes/input.dm b/code/modules/integrated_electronics/subtypes/input.dm index ab60a3a13db6..057f23486a3a 100644 --- a/code/modules/integrated_electronics/subtypes/input.dm +++ b/code/modules/integrated_electronics/subtypes/input.dm @@ -629,7 +629,7 @@ return var/datum/gas_mixture/environment = T.return_air() - var/pressure = environment.return_pressure() + var/pressure = XGM_PRESSURE(environment) var/total_moles = environment.total_moles if (total_moles) @@ -707,7 +707,7 @@ return var/datum/gas_mixture/environment = T.return_air() - var/pressure = environment.return_pressure() + var/pressure = XGM_PRESSURE(environment) var/total_moles = environment.total_moles if (total_moles) diff --git a/code/modules/law/incident.dm b/code/modules/law/incident.dm index 5d2ae9f4c933..754b9db0543b 100644 --- a/code/modules/law/incident.dm +++ b/code/modules/law/incident.dm @@ -171,7 +171,7 @@ else . += "\tBRIG: [brig_sentence] minutes
" else if ( fine != 0 ) - . += "As decided by the arbiter(s), they have been fined [fine] credits.
" + . += "As decided by the arbiter(s), they have been fined [fine]电.
" else . += "As decided by the arbiter(s), they will serve no time for their crimes.
" . += "
" diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm index e0571a03e981..88c05cad0611 100644 --- a/code/modules/library/lib_machines.dm +++ b/code/modules/library/lib_machines.dm @@ -500,6 +500,7 @@ b.dat = paper.info b.name = "blank book" b.icon_state = "book[rand(1,7)]" + b.item_state = icon_state qdel(paper) return diff --git a/code/modules/materials/material_recipes.dm b/code/modules/materials/material_recipes.dm index 77833aefef16..eb9e529d81e6 100644 --- a/code/modules/materials/material_recipes.dm +++ b/code/modules/materials/material_recipes.dm @@ -9,37 +9,37 @@ // If is_brittle() returns true, these are only good for a single strike. recipes += new /datum/stack_recipe_list("generic crafts", list( - new /datum/stack_recipe("[display_name] baseball bat", /obj/item/material/twohanded/baseballbat, 10, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("[display_name] sword hilt", /obj/item/material/sword_hilt, 10, time = 100, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("[display_name] sword blade", /obj/item/material/sword_blade, 15, time = 100, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("[display_name] ring", /obj/item/clothing/ring/material, 1, on_floor = 1, supplied_material = "[name]", required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("[display_name] armor plating", /obj/item/material/armor_plating, 3, time = 20, on_floor = 1, supplied_material = "[name]", required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)) + new /datum/stack_recipe("[display_name] baseball bat", /obj/item/material/twohanded/baseballbat, 10, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("[display_name] sword hilt", /obj/item/material/sword_hilt, 10, time = 100, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("[display_name] sword blade", /obj/item/material/sword_blade, 15, time = 100, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("[display_name] ring", /obj/item/clothing/ring/material, 1, on_floor = 1, supplied_material = "[name]", required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("[display_name] armor plating", /obj/item/material/armor_plating, 3, time = 20, on_floor = 1, supplied_material = "[name]", required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)) )) if(integrity >= 50) recipes += new /datum/stack_recipe_list("generic construction", list( - new /datum/stack_recipe("[display_name] door", /obj/structure/simple_door, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("[display_name] blocker", /obj/structure/blocker, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("[display_name] railing", /obj/structure/railing, BUILD_AMT, time = 25, one_per_turf = FALSE, on_floor = TRUE, supplied_material = "[name]", required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("[display_name] stool", /obj/structure/bed/stool, BUILD_AMT, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("[display_name] chair", /obj/structure/bed/stool/chair, BUILD_AMT, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("[display_name] bed", /obj/structure/bed, BUILD_AMT, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("[display_name] lock", /obj/item/material/lock_construct, 1, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("[display_name] urn", /obj/item/material/urn, 10, time = 30, one_per_turf = FALSE, on_floor = 1, supplied_material = "[name]", required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)) + new /datum/stack_recipe("[display_name] door", /obj/structure/simple_door, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)), + new /datum/stack_recipe("[display_name] blocker", /obj/structure/blocker, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)), + new /datum/stack_recipe("[display_name] railing", /obj/structure/railing, BUILD_AMT, time = 25, one_per_turf = FALSE, on_floor = TRUE, supplied_material = "[name]", required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)), + new /datum/stack_recipe("[display_name] stool", /obj/structure/bed/stool, BUILD_AMT, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)), + new /datum/stack_recipe("[display_name] chair", /obj/structure/bed/stool/chair, BUILD_AMT, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)), + new /datum/stack_recipe("[display_name] bed", /obj/structure/bed, BUILD_AMT, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)), + new /datum/stack_recipe("[display_name] lock", /obj/item/material/lock_construct, 1, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)), + new /datum/stack_recipe("[display_name] urn", /obj/item/material/urn, 10, time = 30, one_per_turf = FALSE, on_floor = 1, supplied_material = "[name]", required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)) )) var/list/hardness_craftables = list() if(hardness >= 10) - hardness_craftables += new /datum/stack_recipe("[display_name] ashtray", /obj/item/material/ashtray, 2, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)) + hardness_craftables += new /datum/stack_recipe("[display_name] ashtray", /obj/item/material/ashtray, 2, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)) if(hardness > 50) - hardness_craftables += new /datum/stack_recipe("[display_name] fork", /obj/item/material/kitchen/utensil/fork/plastic, 1, on_floor = 1, supplied_material = "[name]", required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_FAMILIAR)) - hardness_craftables += new /datum/stack_recipe("[display_name] spoon", /obj/item/material/kitchen/utensil/spoon/plastic, 1, on_floor = 1, supplied_material = "[name]", required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_FAMILIAR)) - hardness_craftables += new /datum/stack_recipe("[display_name] knife", /obj/item/material/kitchen/utensil/knife/plastic, 1, on_floor = 1, supplied_material = "[name]", required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_FAMILIAR)) - hardness_craftables += new /datum/stack_recipe("[display_name] blade", /obj/item/material/butterflyblade, 6, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)) - hardness_craftables += new /datum/stack_recipe("[display_name] spearhead", /obj/item/material/spearhead, 6, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)) - hardness_craftables += new /datum/stack_recipe("[display_name] drill head", /obj/item/material/drill_head, 6, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)) + hardness_craftables += new /datum/stack_recipe("[display_name] fork", /obj/item/material/kitchen/utensil/fork/plastic, 1, on_floor = 1, supplied_material = "[name]", required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)) + hardness_craftables += new /datum/stack_recipe("[display_name] spoon", /obj/item/material/kitchen/utensil/spoon/plastic, 1, on_floor = 1, supplied_material = "[name]", required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)) + hardness_craftables += new /datum/stack_recipe("[display_name] knife", /obj/item/material/kitchen/utensil/knife/plastic, 1, on_floor = 1, supplied_material = "[name]", required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)) + hardness_craftables += new /datum/stack_recipe("[display_name] blade", /obj/item/material/butterflyblade, 6, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)) + hardness_craftables += new /datum/stack_recipe("[display_name] spearhead", /obj/item/material/spearhead, 6, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)) + hardness_craftables += new /datum/stack_recipe("[display_name] drill head", /obj/item/material/drill_head, 6, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)) if(length(hardness_craftables)) recipes += new /datum/stack_recipe_list("generic miscellaneous", hardness_craftables) @@ -48,91 +48,91 @@ ..() recipes += new /datum/stack_recipe_list("construction recipes", list( - new /datum/stack_recipe("regular floor tile", /obj/item/stack/tile/floor, 1, 4, 20, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("full regular floor tile", /obj/item/stack/tile/mono, 1, 4, 20, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("metal rod", /obj/item/stack/rods, 1, 2, 60, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_FAMILIAR)), - new /datum/stack_recipe("steel barricade", /obj/structure/barricade/metal, BUILD_AMT, time = 10 SECONDS, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("barbed wire", /obj/item/stack/barbed_wire, 1, 2, 20, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("wall girders", /obj/structure/girder, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("steel window frame", /obj/structure/window_frame/unanchored, BUILD_AMT, time = 25, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("computer frame", /obj/structure/computerframe, BUILD_AMT, time = 25, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("machine blueprint", /obj/machinery/constructable_frame/machine_frame, 2, time = 25, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_FAMILIAR)), - new /datum/stack_recipe("light fixture frame", /obj/item/frame/light, 2, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_FAMILIAR)), - new /datum/stack_recipe("floor light fixture frame", /obj/item/floor_frame/light, 2, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_FAMILIAR)), - new /datum/stack_recipe("small light fixture frame", /obj/item/frame/light/small, 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_FAMILIAR)), - new /datum/stack_recipe("small floor light fixture frame", /obj/item/floor_frame/light/small, 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_FAMILIAR)), - new /datum/stack_recipe("spotlight fixture frame", /obj/item/frame/light/spot, 3, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("apc frame", /obj/item/frame/apc, 2, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("air alarm frame", /obj/item/frame/air_alarm, 2, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("fire alarm frame", /obj/item/frame/fire_alarm, 2, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("fuel port", /obj/item/fuel_port, 2, time = 2 SECONDS, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)) + new /datum/stack_recipe("regular floor tile", /obj/item/stack/tile/floor, 1, 4, 20, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("full regular floor tile", /obj/item/stack/tile/mono, 1, 4, 20, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("metal rod", /obj/item/stack/rods, 1, 2, 60, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)), + new /datum/stack_recipe("steel barricade", /obj/structure/barricade/metal, BUILD_AMT, time = 10 SECONDS, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("barbed wire", /obj/item/stack/barbed_wire, 1, 2, 20, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("wall girders", /obj/structure/girder, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("steel window frame", /obj/structure/window_frame/unanchored, BUILD_AMT, time = 25, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("computer frame", /obj/structure/computerframe, BUILD_AMT, time = 25, one_per_turf = 1, on_floor = 1, required_skills_hard = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("machine blueprint", /obj/machinery/constructable_frame/machine_frame, 2, time = 25, one_per_turf = 1, on_floor = 1, required_skills_hard = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)), + new /datum/stack_recipe("light fixture frame", /obj/item/frame/light, 2, required_skills_hard = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)), + new /datum/stack_recipe("floor light fixture frame", /obj/item/floor_frame/light, 2, required_skills_hard = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)), + new /datum/stack_recipe("small light fixture frame", /obj/item/frame/light/small, 1, required_skills_hard = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)), + new /datum/stack_recipe("small floor light fixture frame", /obj/item/floor_frame/light/small, 1, required_skills_hard = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)), + new /datum/stack_recipe("spotlight fixture frame", /obj/item/frame/light/spot, 3, required_skills_hard = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("apc frame", /obj/item/frame/apc, 2, required_skills_hard = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("air alarm frame", /obj/item/frame/air_alarm, 2, required_skills_hard = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("fire alarm frame", /obj/item/frame/fire_alarm, 2, required_skills_hard = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("fuel port", /obj/item/fuel_port, 2, time = 2 SECONDS, required_skills_hard = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)) )) recipes += new /datum/stack_recipe_list("miscellaneous construction", list( - new /datum/stack_recipe("key", /obj/item/key, 1, time = 10, one_per_turf = 0, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_FAMILIAR)), - new /datum/stack_recipe("custodial cart", /obj/structure/cart/storage/janitorialcart, BUILD_AMT, time = 120, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("engineering cart", /obj/structure/cart/storage/engineeringcart, BUILD_AMT, time = 120, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("parcel cart", /obj/structure/cart/storage/parcelcart, BUILD_AMT, time = 120, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("steel closet", /obj/structure/closet, BUILD_AMT, time = 15, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_FAMILIAR)), - new /datum/stack_recipe("canister", /obj/machinery/portable_atmospherics/canister, 10, time = 15, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("target stake", /obj/structure/target_stake, BUILD_AMT, time = 15, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("shooting target", /obj/item/target, 5, time = 10, one_per_turf = 0, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("dark office chair", /obj/structure/bed/stool/chair/office/dark, BUILD_AMT, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("light office chair", /obj/structure/bed/stool/chair/office/light, BUILD_AMT, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("steel chair (fancy)", /obj/structure/bed/stool/chair/fancy, BUILD_AMT, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("sofa (middle)", /obj/structure/bed/stool/chair/sofa, BUILD_AMT, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("sofa (left)", /obj/structure/bed/stool/chair/sofa/left, BUILD_AMT, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("sofa (right)", /obj/structure/bed/stool/chair/sofa/right, BUILD_AMT, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("sofa (corner, concave)", /obj/structure/bed/stool/chair/sofa/corner/concave, BUILD_AMT, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("sofa (corner, convex)", /obj/structure/bed/stool/chair/sofa/corner/convex, BUILD_AMT, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("key", /obj/item/key, 1, time = 10, one_per_turf = 0, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)), + new /datum/stack_recipe("custodial cart", /obj/structure/cart/storage/janitorialcart, BUILD_AMT, time = 120, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("engineering cart", /obj/structure/cart/storage/engineeringcart, BUILD_AMT, time = 120, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("parcel cart", /obj/structure/cart/storage/parcelcart, BUILD_AMT, time = 120, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("steel closet", /obj/structure/closet, BUILD_AMT, time = 15, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)), + new /datum/stack_recipe("canister", /obj/machinery/portable_atmospherics/canister, 10, time = 15, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("target stake", /obj/structure/target_stake, BUILD_AMT, time = 15, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("shooting target", /obj/item/target, 5, time = 10, one_per_turf = 0, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("dark office chair", /obj/structure/bed/stool/chair/office/dark, BUILD_AMT, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("light office chair", /obj/structure/bed/stool/chair/office/light, BUILD_AMT, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("steel chair (fancy)", /obj/structure/bed/stool/chair/fancy, BUILD_AMT, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("sofa (middle)", /obj/structure/bed/stool/chair/sofa, BUILD_AMT, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("sofa (left)", /obj/structure/bed/stool/chair/sofa/left, BUILD_AMT, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("sofa (right)", /obj/structure/bed/stool/chair/sofa/right, BUILD_AMT, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("sofa (corner, concave)", /obj/structure/bed/stool/chair/sofa/corner/concave, BUILD_AMT, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("sofa (corner, convex)", /obj/structure/bed/stool/chair/sofa/corner/convex, BUILD_AMT, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), new /datum/stack_recipe("steel crate", /obj/structure/closet/crate, BUILD_AMT, time = 50, one_per_turf = 1) )) recipes += new /datum/stack_recipe_list("airlock assemblies", list( - new /datum/stack_recipe("generic airlock assembly", /obj/structure/door_assembly/door_assembly_generic, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("maintenance airlock assembly", /obj/structure/door_assembly/door_assembly_mai, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("external airlock assembly", /obj/structure/door_assembly/door_assembly_ext, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("airtight hatch assembly", /obj/structure/door_assembly/door_assembly_hatch, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("maintenance hatch assembly", /obj/structure/door_assembly/door_assembly_mhatch, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("high security airlock assembly", /obj/structure/door_assembly/door_assembly_highsecurity, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1), required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED), - new /datum/stack_recipe("emergency shutter", /obj/structure/firedoor_assembly, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("multi-tile airlock assembly", /obj/structure/door_assembly/multi_tile, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)) + new /datum/stack_recipe("generic airlock assembly", /obj/structure/door_assembly/door_assembly_generic, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("maintenance airlock assembly", /obj/structure/door_assembly/door_assembly_mai, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("external airlock assembly", /obj/structure/door_assembly/door_assembly_ext, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("airtight hatch assembly", /obj/structure/door_assembly/door_assembly_hatch, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("maintenance hatch assembly", /obj/structure/door_assembly/door_assembly_mhatch, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("high security airlock assembly", /obj/structure/door_assembly/door_assembly_highsecurity, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1), required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED), + new /datum/stack_recipe("emergency shutter", /obj/structure/firedoor_assembly, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("multi-tile airlock assembly", /obj/structure/door_assembly/multi_tile, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)) )) recipes += new /datum/stack_recipe_list("turret frames", list( - new /datum/stack_recipe("light turret frame", /obj/machinery/porta_turret_construct, 5, time = 25, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("dark turret frame", /obj/machinery/porta_turret_construct/dark, 5, time = 25, one_per_turf = 1, on_floor = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)) + new /datum/stack_recipe("light turret frame", /obj/machinery/porta_turret_construct, 5, time = 25, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("dark turret frame", /obj/machinery/porta_turret_construct/dark, 5, time = 25, one_per_turf = 1, on_floor = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)) )) recipes += new /datum/stack_recipe_list("modular computers", list( - new /datum/stack_recipe("modular console frame", /obj/item/modular_computer/console, 20, time = 25, one_per_turf = TRUE, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("modular laptop frame", /obj/item/modular_computer/laptop, 10, time = 25, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("modular tablet frame", /obj/item/modular_computer/handheld, 5, time = 25, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)) + new /datum/stack_recipe("modular console frame", /obj/item/modular_computer/console, 20, time = 25, one_per_turf = TRUE, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("modular laptop frame", /obj/item/modular_computer/laptop, 10, time = 25, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("modular tablet frame", /obj/item/modular_computer/handheld, 5, time = 25, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)) )) recipes += new /datum/stack_recipe_list("[display_name] weaponry", list( - new /datum/stack_recipe("makeshift magazine (5.56mm)", /obj/item/ammo_magazine/a556/makeshift/empty, 5, time = 20, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("grenade casing", /obj/item/grenade/chem_grenade, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("firearm receiver", /obj/item/receivergun, 15, time = 25, one_per_turf = 0, on_floor = 0, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("shield fittings", /obj/item/material/shieldbits, 10, time = 25, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_UNFAMILIAR)), - new /datum/stack_recipe("cannon frame", /obj/item/cannonframe, 10, time = 15, one_per_turf = 0, on_floor = 0, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_FAMILIAR)), - new /datum/stack_recipe("large trap foundation", /obj/item/large_trap_foundation, 4, time = 40, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_FAMILIAR)) + new /datum/stack_recipe("makeshift magazine (5.56mm)", /obj/item/ammo_magazine/a556/makeshift/empty, 5, time = 20, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("grenade casing", /obj/item/grenade/chem_grenade, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("firearm receiver", /obj/item/receivergun, 15, time = 25, one_per_turf = 0, on_floor = 0, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("shield fittings", /obj/item/material/shieldbits, 10, time = 25, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_UNFAMILIAR)), + new /datum/stack_recipe("cannon frame", /obj/item/cannonframe, 10, time = 15, one_per_turf = 0, on_floor = 0, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)), + new /datum/stack_recipe("large trap foundation", /obj/item/large_trap_foundation, 4, time = 40, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)) )) /material/plasteel/generate_recipes() ..() recipes += new /datum/stack_recipe_list("[display_name] recipes", list( - new /datum/stack_recipe("AI core", /obj/structure/AIcore, BUILD_AMT, time = 50, one_per_turf = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("plateel barricade", /obj/structure/barricade/plasteel, BUILD_AMT, time = 12 SECONDS, one_per_turf = 1, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_TRAINED)), - new /datum/stack_recipe("knife grip", /obj/item/material/butterflyhandle, 4, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_FAMILIAR)), - new /datum/stack_recipe("dark floor tile", /obj/item/stack/tile/floor_dark, 1, 4, 20, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_FAMILIAR)), - new /datum/stack_recipe("full dark floor tile", /obj/item/stack/tile/floor_dark/full, 1, 4, 20, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_FAMILIAR)) + new /datum/stack_recipe("AI core", /obj/structure/AIcore, BUILD_AMT, time = 50, one_per_turf = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("plateel barricade", /obj/structure/barricade/plasteel, BUILD_AMT, time = 12 SECONDS, one_per_turf = 1, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_TRAINED)), + new /datum/stack_recipe("knife grip", /obj/item/material/butterflyhandle, 4, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)), + new /datum/stack_recipe("dark floor tile", /obj/item/stack/tile/floor_dark, 1, 4, 20, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)), + new /datum/stack_recipe("full dark floor tile", /obj/item/stack/tile/floor_dark/full, 1, 4, 20, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)) )) /material/plastic/generate_recipes() @@ -163,9 +163,9 @@ new /datum/stack_recipe("wood circlet", /obj/item/woodcirclet, 1), new /datum/stack_recipe("wood floor tile", /obj/item/stack/tile/wood, 1, 4, 20), new /datum/stack_recipe("wooden chair", /obj/structure/bed/stool/chair/wood, BUILD_AMT, time = 10, one_per_turf = 1, on_floor = 1), - new /datum/stack_recipe("crossbow frame", /obj/item/crossbowframe, 5, time = 25, one_per_turf = 0, on_floor = 0, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_FAMILIAR)), + new /datum/stack_recipe("crossbow frame", /obj/item/crossbowframe, 5, time = 25, one_per_turf = 0, on_floor = 0, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)), new /datum/stack_recipe("coffin", /obj/structure/closet/crate/coffin, BUILD_AMT, time = 15, one_per_turf = 1, on_floor = 1), - new /datum/stack_recipe("rifle stock", /obj/item/stock, 10, time = 25, one_per_turf = 0, on_floor = 0, required_skills = list(/singleton/skill/mechanical_engineering = SKILL_LEVEL_FAMILIAR)), + new /datum/stack_recipe("rifle stock", /obj/item/stock, 10, time = 25, one_per_turf = 0, on_floor = 0, required_skills_soft = alist(MECHANICAL_ENGINEERING_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR)), new /datum/stack_recipe("beehive assembly", /obj/item/beehive_assembly, 4), new /datum/stack_recipe("beehive frame", /obj/item/honey_frame, 1), new /datum/stack_recipe("book shelf", /obj/structure/bookcase, BUILD_AMT, time = 15, one_per_turf = 1, on_floor = 1), diff --git a/code/modules/materials/material_sheets.dm b/code/modules/materials/material_sheets.dm index f30672082e18..48a3ce8e72ab 100644 --- a/code/modules/materials/material_sheets.dm +++ b/code/modules/materials/material_sheets.dm @@ -317,7 +317,6 @@ /obj/item/stack/material/plasteel/Destroy() . = ..() - GC_TEMPORARY_HARDDEL /obj/item/stack/material/plasteel/full/Initialize() . = ..() diff --git a/code/modules/mining/drilling/drill.dm b/code/modules/mining/drilling/drill.dm index fda7d17b0b5f..947dc4f368b2 100644 --- a/code/modules/mining/drilling/drill.dm +++ b/code/modules/mining/drilling/drill.dm @@ -117,6 +117,8 @@ /obj/machinery/mining/drill/Destroy() QDEL_NULL(attached_satchel) QDEL_NULL(spark_system) + QDEL_NULL(cell) + QDEL_NULL_LIST(stored_ores) return ..() /obj/machinery/mining/drill/proc/update_ore_count() diff --git a/code/modules/mining/drilling/scanner.dm b/code/modules/mining/drilling/scanner.dm index f21ee09c9346..9c53c4e0fda3 100644 --- a/code/modules/mining/drilling/scanner.dm +++ b/code/modules/mining/drilling/scanner.dm @@ -1,7 +1,7 @@ /obj/item/mining_scanner name = "deep ore scanner" desc = "A complex device used to locate ore deep underground." - icon = 'icons/obj/item/mining_scanner.dmi' + icon = 'icons/obj/item/scanner.dmi' icon_state = "manual_mining" item_state = "manual_mining" contained_sprite = TRUE diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm index 219309ce1ada..b0aad7f71f67 100644 --- a/code/modules/mining/mine_items.dm +++ b/code/modules/mining/mine_items.dm @@ -1069,7 +1069,7 @@ GLOBAL_LIST_INIT_TYPED(total_extraction_beacons, /obj/structure/extraction_point if(!istype(proj_turf)) return var/datum/gas_mixture/environment = proj_turf.return_air() - var/pressure = environment.return_pressure() + var/pressure = XGM_PRESSURE(environment) if(pressure < 50) name = "strong resonance field" resonance_damage = 60 diff --git a/code/modules/mining/ore_detector.dm b/code/modules/mining/ore_detector.dm index 7bca37a9c6cd..c73599cc25f0 100644 --- a/code/modules/mining/ore_detector.dm +++ b/code/modules/mining/ore_detector.dm @@ -9,8 +9,10 @@ /obj/item/ore_detector name = "ore detector" desc = "A device capable of locating and displaying ores to the average untrained hole explorer." - icon = 'icons/obj/item/adv_mining_scanner.dmi' - icon_state = "advmining0" + icon = 'icons/obj/item/scanner.dmi' + icon_state = "mining_adv0" + item_state = "mining_adv" + contained_sprite = TRUE w_class = WEIGHT_CLASS_SMALL slot_flags = SLOT_BELT force = 1 @@ -40,7 +42,7 @@ return ..() /obj/item/ore_detector/update_icon() - icon_state = "advmining[active]" + icon_state = "mining_adv[active]" /obj/item/ore_detector/attack_self(mob/user) ui_interact(user) @@ -128,7 +130,7 @@ found_ores = TRUE if(found_ores) - var/image/ore_ping = image(icon = 'icons/obj/item/adv_mining_scanner.dmi', icon_state = "signal_overlay", loc = anchor, layer = UNDER_HUD_LAYER) + var/image/ore_ping = image(icon = 'icons/obj/item/scanner.dmi', icon_state = "signal_overlay", loc = anchor, layer = UNDER_HUD_LAYER) ore_ping.appearance_flags |= KEEP_APART|RESET_ALPHA|RESET_COLOR|RESET_TRANSFORM ore_ping.pixel_x = rand(-6, 6) ore_ping.pixel_y = rand(-6, 6) diff --git a/code/modules/mob/abstract/freelook/ai/eye.dm b/code/modules/mob/abstract/freelook/ai/eye.dm index 5bb99282f4cb..c2c5bbabe7dd 100644 --- a/code/modules/mob/abstract/freelook/ai/eye.dm +++ b/code/modules/mob/abstract/freelook/ai/eye.dm @@ -10,6 +10,10 @@ . = ..() visualnet = GLOB.cameranet +/mob/abstract/eye/freelook/Destroy() + visualnet = null + . = ..() + /datum/click_handler/eye/freelook/OnDblClick(atom/A, params) var/mob/abstract/eye = user.eyeobj if(!eye) //Something has broken, ensure the click handler doesn't stick around diff --git a/code/modules/mob/abstract/freelook/visualnet.dm b/code/modules/mob/abstract/freelook/visualnet.dm index 4df284e49231..48f77780992a 100644 --- a/code/modules/mob/abstract/freelook/visualnet.dm +++ b/code/modules/mob/abstract/freelook/visualnet.dm @@ -75,8 +75,8 @@ c.add_eye(eye) /datum/visualnet/proc/remove_eye(mob/abstract/eye/freelook/eye) - for(var/chunk in eye.visibleChunks) - var/datum/chunk/c = chunk + for(var/chunk in chunks) + var/datum/chunk/c = chunks[chunk] c.remove_eye(eye) // Updates the chunks that the turf is located in. Use this when obstacles are destroyed or when doors open. diff --git a/code/modules/mob/abstract/ghost/ghost.dm b/code/modules/mob/abstract/ghost/ghost.dm index 86da2ead88e3..d06f26e5afec 100644 --- a/code/modules/mob/abstract/ghost/ghost.dm +++ b/code/modules/mob/abstract/ghost/ghost.dm @@ -132,13 +132,12 @@ set category = "Ghost" set desc = "Follow and haunt a mob." - var/datum/tgui_module/follow_menu/GM = new /datum/tgui_module/follow_menu(usr) - GM.ui_interact(usr) + GLOB.follow_menu.ui_interact(src) // This is the ghost's follow verb with an argument /mob/abstract/ghost/proc/ManualFollow(var/atom/movable/target) if(!target) - return + return FALSE //Stops orbit if there's any; TG doesn't do this, but if you don't it breaks the orbiting reference //if you are jumping from one mob to another, hence why we're doing it here @@ -154,6 +153,7 @@ to_chat(src, SPAN_NOTICE("Now following \the [target].")) update_sight() + return TRUE /mob/abstract/ghost/proc/update_sight() //if they are on a restricted level, then set the ghost vision for them. @@ -192,7 +192,7 @@ var/datum/gas_mixture/environment = loc.return_air() - var/pressure = environment.return_pressure() + var/pressure = XGM_PRESSURE(environment) var/total_moles = environment.total_moles to_chat(src, SPAN_NOTICE("Results:")) diff --git a/code/modules/mob/abstract/ghost/observer/observer.dm b/code/modules/mob/abstract/ghost/observer/observer.dm index a360afa2762b..ab84dec686ff 100644 --- a/code/modules/mob/abstract/ghost/observer/observer.dm +++ b/code/modules/mob/abstract/ghost/observer/observer.dm @@ -188,7 +188,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost, you won't be able to play this round for another [GLOB.config.respawn_delay] minutes! You can't change your mind so choose wisely!)", "Are you sure you want to ghost?", "Ghost", "Stay in body") if(response != "Ghost") return - resting = 1 + if(!istype(usr, /mob/living/simple_animal/hostile/giant_spider/nurse/spider_queen)) + resting = 1 var/turf/location = get_turf(src) message_admins("[key_name_admin(usr)] has ghosted. (JMP)") log_game("[key_name_admin(usr)] has ghosted.") diff --git a/code/modules/mob/abstract/new_player/menu.dm b/code/modules/mob/abstract/new_player/menu.dm index fe1353e011dc..8f41463be03c 100644 --- a/code/modules/mob/abstract/new_player/menu.dm +++ b/code/modules/mob/abstract/new_player/menu.dm @@ -138,9 +138,11 @@ ABSTRACT_TYPE(/atom/movable/screen/new_player) icon_state = pick(SSatlas.current_map.lobby_screens) return - if(length(SSatlas.current_map.lobby_screens) >= 2) + var/num_lobby_screens = length(SSatlas.current_map.lobby_screens) + + if(num_lobby_screens >= 2) //Advance to the next icon - lobby_screen_index = max(++lobby_screen_index % length(SSatlas.current_map.lobby_screens), 1) + lobby_screen_index = (lobby_screen_index % num_lobby_screens) + 1 animate(src, alpha = 0, time = 1 SECOND) diff --git a/code/modules/mob/abstract/new_player/new_player.dm b/code/modules/mob/abstract/new_player/new_player.dm index c1ea0c6b02f5..26b32ec48025 100644 --- a/code/modules/mob/abstract/new_player/new_player.dm +++ b/code/modules/mob/abstract/new_player/new_player.dm @@ -242,37 +242,31 @@ INITIALIZE_IMMEDIATE(/mob/abstract/new_player) /mob/abstract/new_player/proc/IsJobAvailable(rank) var/datum/job/job = SSjobs.GetJob(rank) - if (!job) + // Check if the job is open in-round. + if (!job || !job.is_position_available() \ + /* check for job bans */\ + || jobban_isbanned(src,rank) \ + /* check for species blacklists */\ + || (job.blacklisted_species && (GLOB.all_species[client.prefs.species].name in job.blacklisted_species)) \ + /* check for citizenship restrictions */\ + || job.blacklisted_citizenship && (astype(SSrecords.citizenships[client.prefs.citizenship], /datum/citizenship).name in job.blacklisted_citizenship)) return FALSE - if (!job.is_position_available()) - return FALSE - if (jobban_isbanned(src,rank)) - return FALSE - - if(job.blacklisted_species) // check for restricted species - var/datum/species/S = GLOB.all_species[client.prefs.species] - if(S.name in job.blacklisted_species) - return FALSE - - if(job.blacklisted_citizenship) - var/datum/citizenship/C = SSrecords.citizenships[client.prefs.citizenship] - if(C.name in job.blacklisted_citizenship) - return FALSE + // Checks for faction requirements. var/datum/faction/faction = SSjobs.name_factions[client.prefs.faction] || SSjobs.default_faction var/list/faction_allowed_roles = unpacklist(faction.allowed_role_types) - if (!(job.type in faction_allowed_roles)) - return FALSE - - if(!faction.can_select(client.prefs,src)) + if (!(job.type in faction_allowed_roles) \ + || !faction.can_select(client.prefs,src) \ + || !(client.prefs.GetPlayerAltTitle(job) in client.prefs.GetValidTitles(job))) return FALSE - if(!(client.prefs.GetPlayerAltTitle(job) in client.prefs.GetValidTitles(job))) // does age/species check for us! - return FALSE + // Checks for skill requirements. + for (var/key,value in job.skill_requirements) + if (key && client.prefs.skills[key] < value) + return FALSE return TRUE - /mob/abstract/new_player/proc/AttemptLateSpawn(rank,var/spawning_at) if(src != usr) return 0 diff --git a/code/modules/mob/abstract/new_player/sprite_accessories.dm b/code/modules/mob/abstract/new_player/sprite_accessories.dm index 7ac04f3ede68..b979d1d7a703 100644 --- a/code/modules/mob/abstract/new_player/sprite_accessories.dm +++ b/code/modules/mob/abstract/new_player/sprite_accessories.dm @@ -3330,6 +3330,54 @@ Follow by example and make good judgement based on length which list to include length = 2 chatname = "bangs" +/datum/sprite_accessory/hair/taj_ears/taj_ears_ponytail_one + name = "Tajara Ponytail 1" + icon_state = "hair_ponytail1" + length = 2 + chatname = "ponytail" + +/datum/sprite_accessory/hair/taj_ears/taj_ears_ponytail_two + name = "Tajara Ponytail 2" + icon_state = "hair_ponytail2" + length = 2 + chatname = "ponytail" + +/datum/sprite_accessory/hair/taj_ears/taj_ears_ponytail_spiky + name = "Tajara Ponytail, Spiky" + icon_state = "hair_ponytail_spiky" + length = 2 + chatname = "ponytail" + +/datum/sprite_accessory/hair/taj_ears/taj_ears_ponytail_wisp + name = "Tajara Ponytail, Wisp" + icon_state = "hair_ponytail_wisp" + length = 3 + chatname = "ponytail" + +/datum/sprite_accessory/hair/taj_ears/taj_ears_ponytail_zieglertail + name = "Tajara Ponytail, Zieglertail" + icon_state = "hair_ponytail_ziegler" + length = 2 + chatname = "ponytail" + +/datum/sprite_accessory/hair/taj_ears/taj_ears_longfringe + name = "Tajara Long Fringe" + icon_state = "hair_longfringe" + length = 3 + chatname = "long mane" + +/datum/sprite_accessory/hair/taj_ears/taj_ears_longfringe_longer + name = "Tajara Long Fringe, Longer" + icon_state = "hair_longfringe_longer" + length = 4 + chatname = "long mane" + +/datum/sprite_accessory/hair/taj_ears/taj_ears_long_wavy + name = "Tajara Long Wavy" + icon_state = "hair_long_wavy" + length = 3 + chatname = "long mane" + //msai hair, longer ears /datum/sprite_accessory/hair/msai_ears icon = 'icons/mob/human_face/msai_hair.dmi' @@ -3627,6 +3675,54 @@ Follow by example and make good judgement based on length which list to include length = 2 chatname = "bangs" +/datum/sprite_accessory/hair/msai_ears/msai_ears_ponytail_one + name = "M'sai Ponytail 1" + icon_state = "msai_ponytail1" + length = 2 + chatname = "ponytail" + +/datum/sprite_accessory/hair/msai_ears/msai_ears_ponytail_two + name = "M'sai Ponytail 2" + icon_state = "msai_ponytail2" + length = 2 + chatname = "ponytail" + +/datum/sprite_accessory/hair/msai_ears/msai_ears_ponytail_spiky + name = "M'sai Ponytail, Spiky" + icon_state = "msai_ponytail_spiky" + length = 2 + chatname = "ponytail" + +/datum/sprite_accessory/hair/msai_ears/msai_ears_ponytail_wisp + name = "M'sai Ponytail, Wisp" + icon_state = "msai_ponytail_wisp" + length = 3 + chatname = "ponytail" + +/datum/sprite_accessory/hair/msai_ears/msai_ears_ponytail_zieglertail + name = "M'sai Ponytail, Zieglertail" + icon_state = "msai_ponytail_ziegler" + length = 2 + chatname = "ponytail" + +/datum/sprite_accessory/hair/msai_ears/msai_ears_longfringe + name = "M'sai Long Fringe" + icon_state = "msai_longfringe" + length = 3 + chatname = "long mane" + +/datum/sprite_accessory/hair/msai_ears/msai_ears_longfringe_longer + name = "M'sai Long Fringe, Longer" + icon_state = "msai_longfringe_longer" + length = 4 + chatname = "long mane" + +/datum/sprite_accessory/hair/msai_ears/msai_ears_long_wavy + name = "M'sai Long Wavy" + icon_state = "msai_long_wavy" + length = 3 + chatname = "long mane" + //tesla rejuvenation suit hair /datum/sprite_accessory/hair/tesla_ears icon = 'icons/mob/human_face/tesla_body_hair.dmi' @@ -5300,33 +5396,45 @@ Follow by example and make good judgement based on length which list to include name = "Mecha Chest" icon = 'icons/mob/human_races/markings_vaurca.dmi' icon_state = "mecha_chest" - do_colouration = FALSE + do_colouration = TRUE body_parts = list(BP_CHEST) species_allowed = list(/datum/species/bug, /datum/species/bug/type_b, /datum/species/bug/type_b/type_bb) + icon_blend_mode = ICON_MULTIPLY + +/datum/sprite_accessory/marking/vaurca_augs/chest_lights + name = "Mecha Chest Lights" + icon_state = "mecha_chest_lights" + do_colouration = TRUE + icon_blend_mode = ICON_MULTIPLY /datum/sprite_accessory/marking/vaurca_augs/mecha_abdomen name = "Mecha Abdomen" icon_state = "mecha_abdomen" + do_colouration = FALSE /datum/sprite_accessory/marking/vaurca_augs/mecha_spine name = "Mecha Spine" icon_state = "mecha_spine" + do_colouration = TRUE body_parts = list(BP_HEAD, BP_CHEST) + icon_blend_mode = ICON_MULTIPLY /datum/sprite_accessory/marking/vaurca_augs/chest_tubes name = "Chest Tubes" icon_state = "chest_tubes" + do_colouration = FALSE /datum/sprite_accessory/marking/vaurca_augs/chest_wires name = "Chest Wires" icon_state = "chest_wires" + do_colouration = FALSE /datum/sprite_accessory/marking/vaurca_augs/mecha_eye name = "Mecha Eye (Faceplate, Right)" icon_state = "mecha_eye_r" body_parts = list(BP_HEAD) - do_colouration = FALSE species_allowed = list(/datum/species/bug, /datum/species/bug/type_b/type_bb) + icon_blend_mode = ICON_MULTIPLY /datum/sprite_accessory/marking/vaurca_augs/mecha_eye/warrior name = "Mecha Eye (Faceplate, Right, Warrior)" @@ -5347,6 +5455,7 @@ Follow by example and make good judgement based on length which list to include name = "Mecha Eye (Overlay, Right)" icon_state = "mecha_eyeoverlay_r" body_parts = list(BP_HEAD) + icon_blend_mode = ICON_MULTIPLY /datum/sprite_accessory/marking/vaurca_augs/mecha_eye/mecha_eyeoverlay_l name = "Mecha Eye (Overlay, Left)" @@ -5369,54 +5478,38 @@ Follow by example and make good judgement based on length which list to include name = "Lower Mecha Eye (Overlay, Left)" icon_state = "mecha_lowereyeoverlay_l" -/datum/sprite_accessory/marking/vaurca_augs/mecha_eye_l - name = "Mecha Eye (Faceplate, Right, Large)" - icon_state = "mecha_eye_r_l" - body_parts = list(BP_HEAD) - do_colouration = FALSE - species_allowed = list(/datum/species/bug, /datum/species/bug/type_b, /datum/species/bug/type_b/type_bb) - -/datum/sprite_accessory/marking/vaurca_augs/mecha_eye_l/warrior - name = "Mecha Eye (Faceplate, Right, Large, Warrior)" - icon_state = "mecha_eye_warrior_r_l" - body_parts = list(BP_HEAD) - do_colouration = FALSE - species_allowed = list(/datum/species/bug/type_b) - -/datum/sprite_accessory/marking/vaurca_augs/mecha_eye_l/mecha_eye_r_l - name = "Mecha Eye (Faceplate, Left, Large)" - icon_state = "mecha_eye_l_l" - species_allowed = list(/datum/species/bug, /datum/species/bug/type_b/type_bb) - -/datum/sprite_accessory/marking/vaurca_augs/mecha_eye_l/mecha_eye_r_l/warrior - name = "Mecha Eye (Faceplate, Left, Large, Warrior)" - icon_state = "mecha_eye_warrior_l_l" - species_allowed = list(/datum/species/bug/type_b) - -/datum/sprite_accessory/marking/vaurca_augs/mecha_eyeoverlay_l - name = "Mecha Eye (Overlay, Right, Large)" - icon_state = "mecha_eyeoverlay_r_l" - body_parts = list(BP_HEAD) - -/datum/sprite_accessory/marking/vaurca_augs/mecha_eye_l/mecha_eye_l_r - name = "Mecha Eye (Overlay, Left, Large)" - icon_state = "mecha_eyeoverlay_l_l" - /datum/sprite_accessory/marking/vaurca_augs/mandible name = "Mecha Mandibles" icon_state = "mecha_mandibles" body_parts = list(BP_HEAD) do_colouration = FALSE + icon_blend_mode = ICON_MULTIPLY /datum/sprite_accessory/marking/vaurca_augs/hand_panel_r name = "Hand Panel (Right)" icon_state = "hand_panel_r" body_parts = list(BP_R_HAND) + do_colouration = FALSE + +/datum/sprite_accessory/marking/vaurca_augs/hand_panel_light_r + name = "Hand Panel Light (Right)" + icon_state = "hand_panel_light_r" + body_parts = list(BP_R_HAND) + do_colouration = TRUE + icon_blend_mode = ICON_MULTIPLY /datum/sprite_accessory/marking/vaurca_augs/hand_panel_l name = "Hand Panel (Left)" icon_state = "hand_panel_l" body_parts = list(BP_L_HAND) + do_colouration = FALSE + +/datum/sprite_accessory/marking/vaurca_augs/hand_panel_light_l + name = "Hand Panel Light(Left)" + icon_state = "hand_panel_light_l" + body_parts = list(BP_L_HAND) + do_colouration = TRUE + icon_blend_mode = ICON_MULTIPLY /datum/sprite_accessory/marking/bulwark_augs icon = 'icons/mob/human_races/markings_vaurcae.dmi' diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm index 49527a26c34b..9b353df7e4e4 100644 --- a/code/modules/mob/hear_say.dm +++ b/code/modules/mob/hear_say.dm @@ -23,7 +23,7 @@ if(T && !vacuum_proof) //Ghosts can hear even in vacuum. var/datum/gas_mixture/environment = T.return_air() - var/pressure = (environment)? environment.return_pressure() : 0 + var/pressure = SAFE_XGM_PRESSURE(environment) var/distance_to_speaker = get_dist(speaker, src) if(pressure < SOUND_MINIMUM_PRESSURE && distance_to_speaker > 1) // Yeah, this isn't quite realistic to be able to see if someone is talking through, say, an opaque mask, but for gameplay purposes it should help indicate that you're not bugged. diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index ca85d213ac5f..1401a939e941 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -239,7 +239,7 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( // Removes an item from inventory and places it in the target atom. // If canremove or other conditions need to be checked then use unEquip instead. -/mob/proc/drop_from_inventory(var/obj/item/W, var/atom/target) +/mob/proc/drop_from_inventory(var/obj/item/W, var/atom/target, update_icons = TRUE, force = FALSE) if(W) remove_from_mob(W) if(!(W && W.loc)) @@ -247,7 +247,8 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( if(target) W.forceMove(target) W.do_drop_animation(src) - update_icon() + if(update_icons) + update_icon() return TRUE return FALSE @@ -527,7 +528,7 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( /mob/proc/delete_inventory(var/include_carried = FALSE) for(var/obj/item/I as anything in get_equipped_items(include_carried ? INCLUDE_POCKETS|INCLUDE_HELD : 0)) - drop_from_inventory(I) + drop_from_inventory(I, null, FALSE) qdel(I) /mob/proc/get_covering_equipped_items(var/body_parts) diff --git a/code/modules/mob/living/bot/medbot.dm b/code/modules/mob/living/bot/medbot.dm index 4a3c202fb42f..b141ae957267 100644 --- a/code/modules/mob/living/bot/medbot.dm +++ b/code/modules/mob/living/bot/medbot.dm @@ -127,7 +127,7 @@ if(!underlays.len) underlays += image(firstaid_item.icon, firstaid_item.icon_state) var/matrix/M = matrix() - var/image/ha_image = image('icons/obj/item/healthanalyzer.dmi', "health") + var/image/ha_image = image('icons/obj/item/scanner.dmi', "healthanalyzer") M.Translate(5, 0) ha_image.transform = M underlays += ha_image @@ -376,7 +376,7 @@ to_chat(user, SPAN_NOTICE("You add the health sensor to [src].")) name = "first-aid/robot arm/health analyzer assembly" var/matrix/M = matrix() - var/image/ha_image = image('icons/obj/item/healthanalyzer.dmi', "health") + var/image/ha_image = image('icons/obj/item/scanner.dmi', "health") M.Translate(5, 0) ha_image.transform = M underlays += ha_image diff --git a/code/modules/mob/living/carbon/alien/diona/diona_nymph.dm b/code/modules/mob/living/carbon/alien/diona/diona_nymph.dm index 7f0d7acdaf32..12b25d1bbab6 100644 --- a/code/modules/mob/living/carbon/alien/diona/diona_nymph.dm +++ b/code/modules/mob/living/carbon/alien/diona/diona_nymph.dm @@ -91,7 +91,6 @@ ClearOverlays() . = ..() - GC_TEMPORARY_HARDDEL /mob/living/carbon/alien/diona/get_ingested_reagents() return ingested diff --git a/code/modules/mob/living/carbon/breathe.dm b/code/modules/mob/living/carbon/breathe.dm index d69357e0d58f..f2ac2335857c 100644 --- a/code/modules/mob/living/carbon/breathe.dm +++ b/code/modules/mob/living/carbon/breathe.dm @@ -96,7 +96,7 @@ //Handle possble chem smoke effect /mob/living/carbon/proc/handle_chemical_smoke(var/datum/gas_mixture/environment) - if(species && environment.return_pressure() < species.breath_pressure/5) + if(species && XGM_PRESSURE(environment) < species.breath_pressure/5) return //pressure is too low to even breathe in. if(wear_mask && (wear_mask.item_flags & ITEM_FLAG_BLOCK_GAS_SMOKE_EFFECT)) return diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index bbdfc331c2c9..cb01f89d5210 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -43,8 +43,10 @@ QDEL_NULL(bloodstr) QDEL_NULL(dna) QDEL_NULL(breathing) - for(var/guts in internal_organs) - qdel(guts) + // Delete and null a direct list of references to our internal organs (such as brain, lungs, heart, etc). + QDEL_LIST(internal_organs) + // Null an Associative list of String = Reference to the same organs. + internal_organs_by_name = null return ..() /mob/living/carbon/rejuvenate() @@ -414,11 +416,6 @@ usr.sleeping = 20 // Short nap. usr.eye_blurry = 20 -/mob/living/carbon/sleeps_horizontal() - if(species && species.sleeps_upright) - return FALSE - return ..() - /verb/toggle_indefinite_sleep() set name = "Toggle Indefinite Sleep" set category = "IC" diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index c30ca732347f..5ff5ff873976 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -109,9 +109,9 @@ var/datum/sprite_accessory/hair/hair = GLOB.hair_styles_list[h_style] var/datum/sprite_accessory/facial_hair/facial = GLOB.facial_hair_styles_list[f_style] - if(!facial.keep_as_skeleton && f_style) + if(facial && !facial.keep_as_skeleton) f_style = "Shaved" - if(!hair.keep_as_skeleton && h_style) + if(hair && !hair.keep_as_skeleton) h_style = "Bald" update_hair(0) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 0c429921ca33..15dc486d52eb 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -9,11 +9,14 @@ var/pronouns = NEUTER - var/species_items_equipped // used so species that need special items (autoinhalers for vaurca/RMT for offworlders) don't get them twice when they shouldn't. + /// Used so species that need special items (autoinhalers for vaurca/RMT for offworlders) don't get them twice when they shouldn't. + var/species_items_equipped var/list/hud_list[11] - var/embedded_flag //To check if we've need to roll for damage on movement while an item is imbedded in us. - var/obj/item/rig/wearing_rig // This is very not good, but it's much much better than calling get_rig() every update_canmove() call. + /// To check if we've need to roll for damage on movement while an item is imbedded in us. + var/embedded_flag + /// This is very not good, but it's much much better than calling get_rig() every update_canmove() call. + var/obj/item/rig/wearing_rig /// Pref holder for the speech bubble style. var/speech_bubble_type @@ -111,9 +114,10 @@ GLOB.human_mob_list -= src GLOB.intent_listener -= src + // This is apparently a different list entirely from the list of organs on /mob/living/carbon. + // It's actually the set of all Limbs (left arm, head, leg leg, etc) we have. We Qdel and null the set of all limbs, which is unique to /human. QDEL_LIST(organs) - internal_organs_by_name = null - internal_organs = null + // Then also null the associative list of those same limbs, which contains the same references. organs_by_name = null bad_internal_organs = null bad_external_organs = null @@ -135,6 +139,9 @@ QDEL_NULL(s_store) QDEL_NULL(wear_suit) QDEL_NULL(wear_mask) + QDEL_NULL(back) + QDEL_NULL(l_hand) + QDEL_NULL(r_hand) // Do this last so the mob's stuff doesn't drop on del. QDEL_NULL(w_uniform) @@ -230,6 +237,7 @@ if(A.area_blurb) . += "[A.area_blurb]" . += "" + . += "Intent: [a_intent]" . += "Move Mode: [m_intent]" if(is_diona() && DS) @@ -245,7 +253,7 @@ qdel(internal) else . += "Internal Atmosphere Info: [internal.name]" - . += "Tank Pressure: [internal.air_contents.return_pressure()]" + . += "Tank Pressure: [XGM_PRESSURE(internal.air_contents)]" . += "Distribution Pressure: [internal.distribute_pressure]" var/obj/item/organ/internal/machine/power_core/IC = internal_organs_by_name[BP_CELL] @@ -435,8 +443,7 @@ mob_win.set_content(dat) mob_win.open() -// called when something steps onto a human -// this handles vehicles +/// Called when something steps onto a human. This handles vehicles /mob/living/carbon/human/on_entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs) ..() @@ -444,7 +451,7 @@ var/obj/vehicle/V = arrived V.RunOver(src) -// Get rank from ID, ID inside PDA, PDA, ID in wallet, etc. +/// Get rank from ID, ID inside PDA, PDA, ID in wallet, etc. /mob/living/carbon/human/proc/get_authentification_rank(var/if_no_id = "No id", var/if_no_job = "No job") var/obj/item/card/id/id = GetIdCard() if(!istype(id)) @@ -452,8 +459,7 @@ else return id.rank ? id.rank : if_no_job -//gets assignment from ID or ID inside PDA or PDA itself -//Useful when player do something with computers +/// Gets assignment from ID or ID inside PDA or PDA itself. Useful when player does something with computers. /mob/living/carbon/human/proc/get_assignment(var/if_no_id = "No ID", var/if_no_job = "No Job") var/obj/item/card/id/I = GetIdCard() if(istype(I)) @@ -461,8 +467,7 @@ else return if_no_id -//gets name from ID or ID inside PDA or PDA itself -//Useful when player do something with computers +/// Gets name from ID or ID inside PDA or PDA itself. Useful when player does something with computers. /mob/living/carbon/human/proc/get_authentification_name(var/if_no_id = "Unknown") var/obj/item/card/id/I = GetIdCard() if(istype(I)) @@ -470,7 +475,7 @@ else return if_no_id -//repurposed proc. Now it combines get_id_name() and get_face_name() to determine a mob's name variable. Made into a seperate proc as it'll be useful elsewhere +/// Repurposed proc. Now it combines get_id_name() and get_face_name() to determine a mob's name variable. /mob/living/carbon/human/proc/get_visible_name() if( wear_mask && (wear_mask.flags_inv&HIDEFACE) ) //Wearing a mask which hides our face, use id-name if possible return get_id_name("Unknown") @@ -482,15 +487,14 @@ return "[face_name] (as [id_name])" return face_name -//Returns "Unknown" if facially disfigured and real_name if not. Useful for setting name when polyacided or when updating a human's name variable +/// Returns "Unknown" if facially disfigured and real_name if not. Useful for setting name when polyacided or when updating a human's name variable /mob/living/carbon/human/proc/get_face_name() var/obj/item/organ/external/head = get_organ(BP_HEAD) if(!head || head.disfigured || head.is_stump() || !real_name || (mutations & HUSK)) //disfigured. use id-name if possible return "Unknown" return real_name -//gets name from ID or PDA itself, ID inside PDA doesn't matter -//Useful when player is being seen by other mobs +/// Gets name from ID or PDA itself, ID inside PDA doesn't matter. Useful when player is being seen by other mobs /mob/living/carbon/human/proc/get_id_name(var/if_no_id = "Unknown") . = if_no_id var/obj/item/card/id/I = GetIdCard() @@ -498,7 +502,7 @@ return I.registered_name return -//gets ID card object from special clothes slot or null. +/// Gets ID card object from special clothes slot or null. /mob/living/carbon/human/proc/get_idcard() if(wear_id) return wear_id.GetID() @@ -758,7 +762,6 @@ var/message = "Medical Records: [R.name]\n\n" \ + "Name: [R.name] Blood Type: [R.medical.blood_type]\n" \ + "DNA: [R.medical.blood_dna]\n" \ - + "Disabilities: [R.medical.disabilities]\n" \ + "Notes: [R.medical.notes]\n" \ + "\[View Comment Log\]" to_chat(usr, EXAMINE_BLOCK_DEEP_CYAN(message)) @@ -882,8 +885,8 @@ ..() return -///eyecheck() -///Returns a number between -1 to 2 + +/// Returns a number between -1 to 2 /mob/living/carbon/human/get_flash_protection(ignore_inherent = FALSE) //Ling @@ -915,8 +918,10 @@ if(prob(20)) to_chat(src, SPAN_NOTICE("Something bright flashes in the corner of your vision!")) -//Used by various things that knock people out by applying blunt trauma to the head. -//Checks that the species has a BP_HEAD (brain containing organ) and that hit_zone refers to it. +/** + * Used by various things that knock people out by applying blunt trauma to the head. + * Checks that the species has a BP_HEAD (brain containing organ) and that hit_zone refers to it. + */ /mob/living/carbon/human/proc/headcheck(var/target_zone, var/brain_tag = BP_BRAIN) if(!species.has_organ[brain_tag]) return 0 @@ -1104,7 +1109,7 @@ sleep(350) //wait 35 seconds before next volley lastpuke = FALSE -// A damaged stomach can put blood in your vomit. +/// A damaged stomach can put blood in your vomit. /mob/living/carbon/human/handle_additional_vomit_reagents(obj/effect/decal/cleanable/vomit/vomit) ..() if(should_have_organ(BP_STOMACH)) @@ -1373,7 +1378,7 @@ var/obj/item/organ/internal/lungs/L = internal_organs_by_name[species_organ] return L && L.rescued -//returns 1 if made bloody, returns 0 otherwise +/// Returns 1 if made bloody, returns 0 otherwise /mob/living/carbon/human/add_blood(mob/living/carbon/C as mob) if (!..()) return FALSE @@ -1464,7 +1469,7 @@ self = 1 if ((src.species.flags & NO_BLOOD) || (status_flags & FAKEDEATH)) - to_chat(usr, SPAN_WARNING(self ? "You have no pulse." : "[src] has no pulse!")) + to_chat(usr, SPAN_WARNING("[self ? "You have" : "[src] has"] no pulse!")) return if(!self) @@ -1887,10 +1892,10 @@ playsound(src.loc, SFX_FRACTURE, 50, 1, -2) current_limb.undislocate() -/mob/living/carbon/human/drop_from_inventory(var/obj/item/W, var/atom/target = null) - if(W in organs) +/mob/living/carbon/human/drop_from_inventory(obj/item/W, atom/target, update_icons = TRUE, force = FALSE) + if(!force && (W in organs)) return - ..() + return ..() /mob/living/carbon/human/reset_view(atom/A, update_hud = 1) ..() @@ -1900,15 +1905,15 @@ eyeobj.remove_visual(src) -/mob/living/carbon/human/can_stand_overridden() +/mob/living/carbon/human/proc/can_stand_overridden() if(wearing_rig && wearing_rig.ai_can_move_suit(check_for_ai = 1)) // Actually missing a leg will screw you up. Everything else can be compensated for. for(var/limbcheck in list(BP_L_LEG,BP_R_LEG)) var/obj/item/organ/affecting = get_organ(limbcheck) if(!affecting) - return 0 - return 1 - return 0 + return FALSE + return TRUE + return FALSE /mob/living/carbon/human/proc/can_drink(var/obj/item/I) if(should_have_organ(BP_REACTOR)) @@ -2302,7 +2307,7 @@ look_up_open_space(get_turf(src)) /mob/living/proc/look_up_open_space(var/turf/T) - if(client && !is_physically_disabled()) + if(client && !MOB_IS_INCAPACITATED(INCAPACITATION_DISABLED)) if(z_eye) reset_view(null) QDEL_NULL(z_eye) @@ -2325,7 +2330,7 @@ look_down_open_space(get_turf(src)) /mob/living/proc/look_down_open_space(var/turf/T) - if(client && !is_physically_disabled()) + if(client && !MOB_IS_INCAPACITATED(INCAPACITATION_DISABLED)) if(z_eye) reset_view(null) QDEL_NULL(z_eye) diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index a099831b667d..14758139ae67 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -172,6 +172,16 @@ var/hit_zone = H.zone_sel.selecting var/obj/item/organ/external/affecting = get_organ(hit_zone) + // Check both "attacker" and "defender" for component based responses to unarmed attacks. + var/attacker_skill_level = SKILL_LEVEL_UNFAMILIAR // Lacking any component responses, treat the attacker as 'rank 1' + var/defender_skill_level = SKILL_LEVEL_UNFAMILIAR // Lacking any component responses, treat the defender as 'rank 1' + var/miss_chance = 15 // Base chance for melee attacks targeting body parts other than the torso to fail. + var/block_chance = 20 // Chance to block incoming attacks when in Harm or Grab intent. + SEND_SIGNAL(H, COMSIG_UNARMED_HARM_ATTACKER, src, &attacker_skill_level, &miss_chance, &rand_damage, &block_chance) + SEND_SIGNAL(src, COMSIG_UNARMED_HARM_DEFENDER, H, &defender_skill_level, &miss_chance, &rand_damage, &block_chance) + if (miss_chance < 1) + accurate = TRUE + if(!affecting || affecting.is_stump()) to_chat(M, SPAN_DANGER("They are missing that limb!")) return 1 @@ -183,7 +193,7 @@ accurate = 1 if(I_HURT, I_GRAB) // We're in a fighting stance, there's a chance we block - if(src.canmove && src!=H && prob(20)) + if(src.canmove && src!=H && block_chance >= 1 && prob(block_chance)) block = 1 if (M.grabbed_by.len) @@ -225,18 +235,9 @@ if(prob(80)) hit_zone = ran_zone(hit_zone) - var/melee_skill_level = H.get_skill_level(/singleton/skill/unarmed_combat) - var/miss_chance = 15 - switch(melee_skill_level) - if(SKILL_LEVEL_UNFAMILIAR) - miss_chance = 25 - if(SKILL_LEVEL_FAMILIAR) - miss_chance = 20 - - var/skill_difference = H.get_skill_difference(src, /singleton/skill/unarmed_combat) if(prob(miss_chance) && hit_zone != BP_CHEST) // Missed! if(!src.lying) - attack_message = "[H] attempted to strike [src], [skill_difference < -1 ? "but [src] [pick("dodged", "ducked")] out of the way!" : "but missed!"]" + attack_message = "[H] attempted to strike [src], [attacker_skill_level - defender_skill_level <= -1 ? "but [src] [pick("dodged", "ducked")] out of the way!" : "but missed!"]" else attack_message = "[H] attempted to strike [src], but [src.get_pronoun("he")] rolled out of the way!" src.set_dir(pick(GLOB.cardinals)) @@ -315,15 +316,17 @@ to_chat(M, SPAN_NOTICE("You don't want to risk hurting [src]!")) return FALSE - var/melee_skill_level = H.get_skill_level(/singleton/skill/unarmed_combat) - var/skill_difference = H.get_skill_difference(src, /singleton/skill/unarmed_combat) - var/disarm_cost - var/obj/item/organ/internal/machine/power_core/cell = M.internal_organs_by_name[BP_CELL] - var/obj/item/cell/potato - if(cell) - potato = cell.cell + var/attacker_skill_level = SKILL_LEVEL_UNFAMILIAR + var/defender_skill_level = SKILL_LEVEL_UNFAMILIAR + var/disarm_cost = 0 + var/push_chance = 25 + var/disarm_chance = 25 + SEND_SIGNAL(H, COMSIG_UNARMED_DISARM_ATTACKER, src, &attacker_skill_level, &disarm_cost, &push_chance, &disarm_chance) + SEND_SIGNAL(src, COMSIG_UNARMED_DISARM_DEFENDER, H, &defender_skill_level, &disarm_cost, &push_chance, &disarm_chance) + var/skill_difference = attacker_skill_level - defender_skill_level if(isipc(M)) + var/obj/item/cell/potato = astype(M.internal_organs_by_name[BP_CELL], /obj/item/organ/internal/machine/power_core)?.cell disarm_cost = potato.maxcharge / 24 if(potato.charge < disarm_cost) to_chat(M, SPAN_DANGER("You don't have enough charge to disarm someone!")) @@ -389,7 +392,7 @@ return W.afterattack(target,src) else if(M.Adjacent(src)) - visible_message(SPAN_DANGER("[src] retaliates against [M]'s [melee_skill_level == SKILL_LEVEL_UNFAMILIAR ? "inexperienced shoving" : "disarm attempt"] with [W]!")) + visible_message(SPAN_DANGER("[src] retaliates against [M]'s [attacker_skill_level == SKILL_LEVEL_UNFAMILIAR ? "inexperienced shoving" : "disarm attempt"] with [W]!")) return M.attackby(W,src) var/randn = rand(1, 100) @@ -421,8 +424,6 @@ forceMove(GET_TURF_ABOVE(current_turf)) //We use GET_TURF_ABOVE so people can't cheese it by turning their sprite. return - var/push_chance = 25 - push_chance += -(skill_difference * 5) if(randn <= push_chance) if(H.gloves && istype(H.gloves,/obj/item/clothing/gloves/force)) apply_effect(6, WEAKEN) @@ -444,8 +445,6 @@ playsound(loc, 'sound/weapons/push.ogg', 50, 1, -1) return - var/disarm_chance = 25 - disarm_chance += -(skill_difference * 5) if(randn <= disarm_chance) if(H.gloves && istype(H.gloves, /obj/item/clothing/gloves/force)) playsound(loc, 'sound/weapons/push_connect.ogg', 50, 1, -1) @@ -477,13 +476,14 @@ //No return here is intentional, as it will then try to disarm other items, and/or play a failed disarm message playsound(loc, SFX_PUNCH_MISS, 25, 1, -1) - visible_message(SPAN_DANGER("[M] [melee_skill_level == SKILL_LEVEL_UNFAMILIAR ? "[pick("inexpertly", "clumsily")] disarm" : "disarm"] attempted to disarm [src]!")) + visible_message(SPAN_DANGER("[M] [attacker_skill_level == SKILL_LEVEL_UNFAMILIAR ? "[pick("inexpertly", "clumsily")] disarm" : "disarm"] attempted to disarm [src]!")) return /mob/living/carbon/human/proc/cpr(mob/living/carbon/human/H, var/starting = FALSE, var/cpr_mode) var/obj/item/main_hand = H.get_active_hand() var/obj/item/off_hand = H.get_inactive_hand() - var/medicine_skill = H.get_skill_level(/singleton/skill/medicine) + var/datum/component/skill/medicine/medicine_component = H.GetComponent(MEDICINE_SKILL_COMPONENT) + var/medicine_skill = medicine_component ? medicine_component.skill_level : SKILL_LEVEL_TRAINED if(istype(main_hand) || istype(off_hand)) cpr = FALSE to_chat(H, SPAN_NOTICE("You cannot perform CPR with anything in your hands.")) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 602517c98af9..6269b73c4154 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -13,7 +13,7 @@ emp_act if(species_check) return species_check - if(!is_physically_disabled()) + if(!MOB_IS_INCAPACITATED(INCAPACITATION_DISABLED)) var/deflection_chance = check_martial_deflection_chance() if(prob(deflection_chance)) visible_message(SPAN_WARNING("\The [src] deftly dodges \the [hitting_projectile]!"), SPAN_NOTICE("You deftly dodge \the [hitting_projectile]!")) diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index eec74a169455..fc14e29f0704 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -38,7 +38,6 @@ var/size_multiplier = 1 //multiplier for the mob's icon size var/damage_multiplier = 1 //multiplies melee combat damage - var/icon_update = 1 //whether icon updating shall take place var/default_lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index fe8fbe30f97e..386028d36a56 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -122,9 +122,9 @@ /mob/living/carbon/human/set_dir(var/new_dir, ignore_facing_dir = FALSE) . = ..() if(. && tail_style) - update_tail_showing(1) + update_tail_showing(!lying) if(lying) - update_icon(forceDirUpdate = TRUE) + update_icon(TRUE) /mob/living/carbon/human/Move() . = ..() diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm index 0b9a0db1da3a..d16844dd3fd7 100644 --- a/code/modules/mob/living/carbon/human/human_organs.dm +++ b/code/modules/mob/living/carbon/human/human_organs.dm @@ -30,18 +30,6 @@ for(var/obj/item/organ/external/Ex in organs) bad_external_organs |= Ex - //processing internal organs is pretty cheap, do that first. - for(var/obj/item/organ/I in internal_organs) - if (QDELETED(I)) - LOG_DEBUG("Organ [DEBUG_REF(src)] was not properly removed from its parent!") - internal_organs -= I - continue - - if(I.status & ORGAN_DEAD) - continue - - I.process(seconds_per_tick) - handle_stance() handle_grasp() @@ -55,7 +43,6 @@ bad_external_organs -= E continue else - E.process() number_wounds += E.number_wounds if (!lying && !buckled_to && world.time - l_move_time < 15) @@ -66,7 +53,7 @@ I.take_damage(rand(3,5)) //Moving makes open wounds get infected much faster - for(var/datum/wound/W in E.wounds) + for(var/datum/wound/W as anything in E.wounds) if (W.infection_check()) W.germ_level += 1 diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index ea0dddcfdba7..8f97826f736f 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -7,6 +7,11 @@ This saves us from having to call add_fingerprint() any time something is put in set name = "quick-equip" set hidden = 1 + var/cancelled = FALSE + SEND_SIGNAL(src, COMSIG_INPUT_KEY_QUICK_EQUIP, &cancelled) + if (cancelled) + return + if(ishuman(src)) var/mob/living/carbon/human/H = src var/obj/item/I = H.get_active_hand() diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 8722d6f0de87..c9ed32b003ee 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -59,7 +59,7 @@ //Organs handle_organs(seconds_per_tick) - stabilize_body_temperature() //Body temperature adjusts itself (self-regulation) + stabilize_body_temperature(seconds_per_tick) //Body temperature adjusts itself (self-regulation) //Random events (vomiting etc) handle_random_events() @@ -296,14 +296,14 @@ if(breath) //exposure to extreme pressures can rupture lungs - var/check_pressure = breath.return_pressure() + var/check_pressure = XGM_PRESSURE(breath) if(check_pressure < ONE_ATMOSPHERE / 5 || check_pressure > ONE_ATMOSPHERE * 5) if(!is_lung_ruptured() && prob(5)) rupture_lung() return breath -/mob/living/carbon/human/handle_environment(datum/gas_mixture/environment) +/mob/living/carbon/human/handle_environment(datum/gas_mixture/environment, seconds_per_tick) ..() if(!environment) @@ -313,7 +313,7 @@ species.handle_environment_special(src) //Moved pressure calculations here for use in skip-processing check. - var/pressure = environment.return_pressure() + var/pressure = XGM_PRESSURE(environment) var/adjusted_pressure = calculate_affecting_pressure(pressure) if (consume_nutrition_from_air) @@ -330,8 +330,10 @@ if(bodytemperature > (0.1 * HUMAN_HEAT_CAPACITY/(HUMAN_EXPOSED_SURFACE_AREA*STEFAN_BOLTZMANN_CONSTANT))**(1/4) + COSMIC_RADIATION_TEMPERATURE) //Thermal radiation into space var/heat_loss = HUMAN_EXPOSED_SURFACE_AREA * STEFAN_BOLTZMANN_CONSTANT * ((bodytemperature - COSMIC_RADIATION_TEMPERATURE)**4) + // Temperature loss in Watts (kgm^2/s^3) var/temperature_loss = heat_loss/HUMAN_HEAT_CAPACITY - bodytemperature -= temperature_loss + // Since body temperature is in Joules (kgm^2/s^2), we multiply temperature loss by DT (in seconds) to convert from Watts to Joules before subtracting. + bodytemperature -= temperature_loss * seconds_per_tick else var/loc_temp = T0C if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) @@ -437,9 +439,9 @@ baseline += clothing.body_temperature_change return baseline -/mob/living/carbon/human/proc/stabilize_body_temperature() +/mob/living/carbon/human/proc/stabilize_body_temperature(seconds_per_tick) if (species.passive_temp_gain) // We produce heat naturally. - species.handle_temperature_regulation(src) + species.handle_temperature_regulation(src, seconds_per_tick) if (species.body_temperature == null) return //this species doesn't have metabolic thermoregulation @@ -453,19 +455,16 @@ if(bodytemperature < species.cold_level_1) //260.15 is 310.15 - 50, the temperature where you start to feel effects. if(nutrition >= 2) //If we are very, very cold we'll use up quite a bit of nutriment to heat us up. - adjustNutritionLoss(2) - var/recovery_amt = max((body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR), BODYTEMP_AUTORECOVERY_MINIMUM) - bodytemperature += recovery_amt + adjustNutritionLoss(seconds_per_tick) + bodytemperature += max((body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR * seconds_per_tick), BODYTEMP_AUTORECOVERY_MINIMUM * seconds_per_tick) else if(species.cold_level_1 <= bodytemperature && bodytemperature <= species.heat_level_1) - var/recovery_amt = body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR - bodytemperature += recovery_amt + bodytemperature += body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR * seconds_per_tick else if(bodytemperature > species.heat_level_1) //360.15 is 310.15 + 50, the temperature where you start to feel effects. if(hydration >= 2) - adjustHydrationLoss(2) + adjustHydrationLoss(seconds_per_tick) if((species.flags & CAN_SWEAT) && fire_stacks == 0) fire_stacks = -1 - var/recovery_amt = min((body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR), -BODYTEMP_AUTORECOVERY_MINIMUM) //We're dealing with negative numbers - bodytemperature += recovery_amt + bodytemperature += min((body_temperature_difference * seconds_per_tick / BODYTEMP_AUTORECOVERY_DIVISOR), -BODYTEMP_AUTORECOVERY_MINIMUM * seconds_per_tick) //We're dealing with negative numbers /** * Returns a bitflag for the body parts currently heat-protected. Called and used by get_heat_protection() @@ -1134,6 +1133,7 @@ if(!has_drunk_status) add_status_to_hud(DRUNK_STRING, SPAN_GOOD("You are drunk. Your words are slurred, and your movements are uncoordinated.")) else if(has_drunk_status) + client.screen -= status_overlays[DRUNK_STRING] qdel(status_overlays[DRUNK_STRING]) status_overlays -= DRUNK_STRING @@ -1147,6 +1147,7 @@ if(!has_bleeding_status) add_status_to_hud(BLEEDING_STRING, SPAN_HIGHDANGER("Blood gushes from one of your bodyparts, inspect yourself and seal the wound.")) else if(has_bleeding_status) + client.screen -= status_overlays[BLEEDING_STRING] qdel(status_overlays[BLEEDING_STRING]) status_overlays -= BLEEDING_STRING @@ -1155,6 +1156,7 @@ if(!has_posing_status) add_status_to_hud(POSING_STRING, SPAN_NOTICE("You are posing. Your current pose is \"[pose]\"")) else if(has_posing_status) + client.screen -= status_overlays[POSING_STRING] qdel(status_overlays[POSING_STRING]) status_overlays -= POSING_STRING diff --git a/code/modules/mob/living/carbon/human/species/outsider/undead.dm b/code/modules/mob/living/carbon/human/species/outsider/undead.dm index 9896f9ae2e99..f61d776d29b0 100644 --- a/code/modules/mob/living/carbon/human/species/outsider/undead.dm +++ b/code/modules/mob/living/carbon/human/species/outsider/undead.dm @@ -257,7 +257,7 @@ tail = "tajtail" tail_animation = 'icons/mob/species/tajaran/tail.dmi' - slowdown = -1 + slowdown = -0.4 brute_mod = 1.2 fall_mod = 0.5 @@ -383,7 +383,7 @@ stamina = 80 sprint_speed_factor = 1.2 - slowdown = -2 + slowdown = -0.6 standing_jump_range = 5 natural_climbing = TRUE diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 6e4a583d00dd..7c3d6f250a51 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -238,7 +238,7 @@ var/heat_level_2 = 400 /// Heat damage level 3 above this point var/heat_level_3 = 1000 - /// Species will gain this much temperature every second + /// Species will gain this much temperature (in degrees kelvin per second) var/passive_temp_gain = 0 /// Dangerously high pressure var/hazard_high_pressure = HAZARD_HIGH_PRESSURE @@ -468,6 +468,9 @@ /// The default lighting alpha of this species. Override to set innate NVGs. var/default_lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE + /// Controls whether this species spawns with a Morale Component. + var/has_morale = TRUE + /datum/species/proc/get_eyes(var/mob/living/carbon/human/H) return @@ -547,6 +550,7 @@ /datum/species/proc/create_organs(var/mob/living/carbon/human/H) //Handles creation of mob organs. for(var/obj/item/organ/organ in H.contents) if((organ in H.organs) || (organ in H.internal_organs)) + H.drop_from_inventory(organ, null, FALSE, TRUE) qdel(organ) if(H.organs) H.organs.Cut() @@ -597,6 +601,9 @@ if(natural_armor) H.AddComponent(natural_armor_type, natural_armor) + if(has_morale) + H.LoadComponent(MORALE_COMPONENT) + /datum/species/proc/tap(var/mob/living/carbon/human/H,var/mob/living/target) if(H.on_fire) target.fire_stacks += 1 @@ -1002,7 +1009,9 @@ /datum/species/proc/handle_stance_damage(var/mob/living/carbon/human/H, var/damage_only = FALSE) var/static/support_limbs = list( BP_L_LEG = BP_R_LEG, - BP_L_FOOT = BP_R_FOOT + BP_L_FOOT = BP_R_FOOT, + BP_R_LEG = BP_L_LEG, + BP_R_FOOT = BP_L_FOOT ) var/has_opposite_limb = FALSE @@ -1084,9 +1093,11 @@ * This proc handles the species temperature regulation. By default, it just adds `passive_temp_gain` to the human's bodytemperature. * Can be overridden for more complex calculations. */ -/datum/species/proc/handle_temperature_regulation(mob/living/carbon/human/human) - human.bodytemperature += passive_temp_gain +/datum/species/proc/handle_temperature_regulation(mob/living/carbon/human/human, seconds_per_tick) + human.bodytemperature += passive_temp_gain * seconds_per_tick + +/** * Gets a modifier for a skill category based on the character age or other species things. * Must return a list with all three skill categories to a modifier (example: list(SKILL_CATEGORY_EVERYDAY = 1.5) ) */ diff --git a/code/modules/mob/living/carbon/human/species/station/golem.dm b/code/modules/mob/living/carbon/human/species/station/golem.dm index d936037921c5..fb4733ac76c3 100644 --- a/code/modules/mob/living/carbon/human/species/station/golem.dm +++ b/code/modules/mob/living/carbon/human/species/station/golem.dm @@ -320,7 +320,7 @@ GLOBAL_LIST_INIT(golem_types, list( bodytype = "Human" - slowdown = -2 + slowdown = -0.6 brute_mod = 1.5 burn_mod = 3 @@ -345,7 +345,7 @@ GLOBAL_LIST_INIT(golem_types, list( icobase = 'icons/mob/human_races/golem/r_cardboard.dmi' deform = 'icons/mob/human_races/golem/r_cardboard.dmi' - slowdown = -1 + slowdown = -0.3 brute_mod = 1.5 burn_mod = 3 @@ -656,7 +656,7 @@ GLOBAL_LIST_INIT(golem_types, list( brute_mod = 1.2 burn_mod = 1 - slowdown = -2 + slowdown = -0.8 meat_type = /obj/item/ore/glass @@ -711,7 +711,7 @@ GLOBAL_LIST_INIT(golem_types, list( brute_mod = 1.2 burn_mod = 1.3 - slowdown = -1 + slowdown = -0.3 meat_type = /obj/item/stack/material/plastic diff --git a/code/modules/mob/living/carbon/human/species/station/ipc/ipc.dm b/code/modules/mob/living/carbon/human/species/station/ipc/ipc.dm index e2f716de5d33..bdcac6840f0e 100644 --- a/code/modules/mob/living/carbon/human/species/station/ipc/ipc.dm +++ b/code/modules/mob/living/carbon/human/species/station/ipc/ipc.dm @@ -72,7 +72,7 @@ heat_level_3 = 2400 body_temperature = null - passive_temp_gain = 10 + passive_temp_gain = 5 // Degrees kelvin per second inherent_verbs = list( /mob/living/carbon/human/proc/change_monitor, @@ -171,11 +171,11 @@ var/machine_ui_theme = "hackerman" -/datum/species/machine/handle_temperature_regulation(mob/living/carbon/human/human) +/datum/species/machine/handle_temperature_regulation(mob/living/carbon/human/human, seconds_per_tick) // No cooling unit = you're cooking. Broken cooling unit effects are handled by the organ itself. // Here we just want to check if it's been removed. // 500K is about 226 degrees. Spicy! - var/base_heat_gain = passive_temp_gain + var/base_heat_gain = passive_temp_gain * seconds_per_tick var/obj/item/organ/internal/machine/cooling_unit/cooling = human.internal_organs_by_name[BP_COOLING_UNIT] if(!cooling || (cooling?.status & ORGAN_DEAD)) base_heat_gain *= 4 //uh oh diff --git a/code/modules/mob/living/carbon/human/species/station/ipc/ipc_subspecies.dm b/code/modules/mob/living/carbon/human/species/station/ipc/ipc_subspecies.dm index e9e2d37969ae..13a0ae79e941 100644 --- a/code/modules/mob/living/carbon/human/species/station/ipc/ipc_subspecies.dm +++ b/code/modules/mob/living/carbon/human/species/station/ipc/ipc_subspecies.dm @@ -584,7 +584,7 @@ eyes = "zenghu_eyes" brute_mod = 1.5 - slowdown = -0.8 + slowdown = -0.6 sprint_speed_factor = 0.6 sprint_cost_factor = 2 move_charge_factor = 2 diff --git a/code/modules/mob/living/carbon/human/species/station/monkey.dm b/code/modules/mob/living/carbon/human/species/station/monkey.dm index 50de0045f96e..9261ad5c158a 100644 --- a/code/modules/mob/living/carbon/human/species/station/monkey.dm +++ b/code/modules/mob/living/carbon/human/species/station/monkey.dm @@ -200,5 +200,5 @@ brute_mod = 0.8 burn_mod = 2 fall_mod = 0 - slowdown = -1 + slowdown = -0.3 diff --git a/code/modules/mob/living/carbon/human/species/station/tajara/tajara.dm b/code/modules/mob/living/carbon/human/species/station/tajara/tajara.dm index 6afb02165498..5b58a8692a28 100644 --- a/code/modules/mob/living/carbon/human/species/station/tajara/tajara.dm +++ b/code/modules/mob/living/carbon/human/species/station/tajara/tajara.dm @@ -25,7 +25,7 @@ /singleton/maneuver/leap/tajara ) darksight = 8 - slowdown = -1 + slowdown = -0.4 brute_mod = 1.2 fall_mod = 0.5 @@ -135,5 +135,5 @@ . = ..() if(H.shoes) return - var/obj/item/clothing/shoes/sandals/S = new /obj/item/clothing/shoes/sandals(H) + var/obj/item/clothing/shoes/tajara/footwraps/S = new /obj/item/clothing/shoes/tajara/footwraps(H) H.equip_to_slot_or_del(S,slot_shoes) diff --git a/code/modules/mob/living/carbon/human/species/station/tajara/tajaran_subspecies.dm b/code/modules/mob/living/carbon/human/species/station/tajara/tajaran_subspecies.dm index bb809c85a88a..deed857b2774 100644 --- a/code/modules/mob/living/carbon/human/species/station/tajara/tajaran_subspecies.dm +++ b/code/modules/mob/living/carbon/human/species/station/tajara/tajaran_subspecies.dm @@ -3,17 +3,18 @@ name_plural = "Zhan-Khazan Tajara" blurb = "The Zhan-Khazan are a race of Tajara known for their dark fur and large bulky figures. \ They were at one point a race of cave-and-mountain dwelling Tajara that traditionally were \ - entrusted with physical work like mining, farming, ranching, and logging. Zhan-Khazan make \ - up a significant amount of Tajara employed in resource gathering, construction, civil jobs \ - such as law enforcement and even culinary work such as butchering. They experience a lot of racism \ - from their fellow Tajara who cite their lackluster test scores, even among Tajara, and their higher \ - crime rates." + entrusted with physical work like mining, farming, ranching, and logging. Zhan-Khazan today make \ + up a significant amount of Tajara employed in blue-collar work like resource gathering, \ + construction, and even culinary work such as butchering. Despite being no less intelligent \ + than other Tajara, the pressure from the caste system to enter unskilled labor rarely afforded Zhan \ + an easy path to education. Zhan-Khazan are in a transformative state in modern Tajaran society, \ + but still deal with the many barriers from centuries of the caste system." species_height = HEIGHT_CLASS_TALL secondary_langs = list(LANGUAGE_SIIK_TAJR, LANGUAGE_DELVAHII) - slowdown = -0.8 //As opposed to -1 for Base tajara - sprint_speed_factor = 0.55 // As opposed to 0.65 + slowdown = -0.2 + sprint_speed_factor = 0.55 standing_jump_range = 2 stamina = 100 // As opposed to 90 brute_mod = 1.1 // Less Brute Damage @@ -53,12 +54,14 @@ blurb = "The M'sai are a race of Tajara with slender lithe bodies and \ lightly covered fur which blends in with the snowy environments of Adhomai. \ They aren't as well-insulated against Adhomai's cold as their brethren. \ - However, this gives them the benefit of being more agile. Hitorically, they often \ - worked as hunters, later becoming warriors and soldiers as civilization developed." + However, this gives them the benefit of being more agile. Historically, they often \ + worked as hunters, later becoming ranchers, warriors and soldiers as civilization developed. \ + When these roles were shrunken down however, the M'sai commonly found themselves taking \ + similar work to the Zhan-Khazan. As a result, the two races share much in common with their culture." species_height = HEIGHT_CLASS_AVERAGE - slowdown = -1.2 //As opposed to -1 for Base tajara - sprint_speed_factor = 0.75 // As opposed to 0.65 + slowdown = -0.6 + sprint_speed_factor = 0.75 standing_jump_range = 3 stamina = 80 // As opposed to 90 brute_mod = 1.3 // More Brute Damage diff --git a/code/modules/mob/living/carbon/human/species/station/unathi/unathi.dm b/code/modules/mob/living/carbon/human/species/station/unathi/unathi.dm index 3070b2abf2a2..ab98f183eff8 100644 --- a/code/modules/mob/living/carbon/human/species/station/unathi/unathi.dm +++ b/code/modules/mob/living/carbon/human/species/station/unathi/unathi.dm @@ -46,8 +46,8 @@ stamina = 120 // Unathi have the shortest but fastest sprint of all stamina_recovery = 5 - sprint_cost_factor = 1.45 - sprint_speed_factor = 3.2 + sprint_cost_factor = 1.75 + sprint_speed_factor = 1.6 exhaust_threshold = 65 bp_base_systolic = 80 // Default 120 bp_base_disatolic = 50 // Default 80 diff --git a/code/modules/mob/living/carbon/human/species/station/vaurca/vaurca_subspecies.dm b/code/modules/mob/living/carbon/human/species/station/vaurca/vaurca_subspecies.dm index 078ac65c2e7d..4d303fab5ac9 100644 --- a/code/modules/mob/living/carbon/human/species/station/vaurca/vaurca_subspecies.dm +++ b/code/modules/mob/living/carbon/human/species/station/vaurca/vaurca_subspecies.dm @@ -73,7 +73,7 @@ icobase = 'icons/mob/human_races/vaurca/r_vaurcabb.dmi' eyes = "vaurca_attendant_eyes" - slowdown = -0.8 + slowdown = -0.6 brute_mod = 0.9 oxy_mod = 1 radiation_mod = 0.5 diff --git a/code/modules/mob/living/carbon/human/stripping.dm b/code/modules/mob/living/carbon/human/stripping.dm index 85db055520d3..1f54b000d63d 100644 --- a/code/modules/mob/living/carbon/human/stripping.dm +++ b/code/modules/mob/living/carbon/human/stripping.dm @@ -31,7 +31,7 @@ visible_message(SPAN_WARNING("\The [user] is taking a look at \the [src]'s air tank.")) if(do_after(user, HUMAN_STRIP_DELAY, src, do_flags = DO_EQUIP)) var/obj/item/tank/T = internal - to_chat(user, SPAN_NOTICE("\The [T] has [T.air_contents.return_pressure()] kPA left.")) + to_chat(user, SPAN_NOTICE("\The [T] has [XGM_PRESSURE(T.air_contents)] kPA left.")) to_chat(user, SPAN_NOTICE("The [T] is set to release [T.distribute_pressure] kPA.")) return TRUE if("pockets") diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 4f0eb036d2da..4263d8a4bbf3 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -104,26 +104,29 @@ There are several things that need to be remembered: var/list/overlays_raw[TOTAL_LAYERS] // Our set of "raw" overlays that can be modified, but cannot be directly applied to the mob without preprocessing. var/previous_damage_appearance // store what the body last looked like, so we only have to update it if something changed -#define UPDATE_ICON_IGNORE_DIRECTION_UPDATE -1 - // Updates overlays from overlays_raw. /mob/living/carbon/human/update_icon(var/forceDirUpdate = FALSE) if (QDELETED(src)) return // No point. + var/update_lying = (lying_prev != lying) || forceDirUpdate || size_multiplier != 1 + var/draw_specific_icon = (!lying || species.prone_icon) + + if(update_lying && draw_specific_icon) + update_inv_l_hand(FALSE) + update_inv_r_hand(FALSE) + update_hud() //TODO: remove the need for this - ClearOverlays() if(cloaked) icon = 'icons/mob/human.dmi' icon_state = "body_cloaked" - AddOverlays(list(overlays_raw[L_HAND_LAYER], overlays_raw[R_HAND_LAYER])) - - else if (icon_update) + SetOverlays(list(overlays_raw[L_HAND_LAYER], overlays_raw[R_HAND_LAYER])) + else + var/list/ovr = list() if (icon != stand_icon) icon = stand_icon - var/list/ovr = list() // We manually add each element instead of just using Copy() so that lists are appended instead of inserted. for (var/item in overlays_raw) if (item) @@ -137,18 +140,20 @@ There are several things that need to be remembered: var/icon/aura_overlay = icon(A.icon, icon_state = A.icon_state) ovr += aura_overlay - AddOverlays(ovr) - - if (((lying_prev != lying) || forceDirUpdate || size_multiplier != 1) && forceDirUpdate != UPDATE_ICON_IGNORE_DIRECTION_UPDATE) - if(lying && !species.prone_icon) //Only rotate them if we're not drawing a specific icon for being prone. - var/matrix/M = matrix() + SetOverlays(ovr) + if(update_lying) //Only rotate them if we're not drawing a specific icon for being prone. + var/matrix/M = matrix() + M.Scale(size_multiplier) + if(draw_specific_icon) + M.Translate(0, 16*(size_multiplier-1)) + animate(src, transform = M, time = ANIM_LYING_TIME) + else switch(src.dir) if(SOUTH,EAST) M.Turn(90) else M.Turn(-90) - M.Scale(size_multiplier) M.Translate(1,-6) animate(src, transform = M, time = (forceDirUpdate ? 0 : ANIM_LYING_TIME)) @@ -157,15 +162,6 @@ There are several things that need to be remembered: if(istype(src.r_hand, /obj/item/gun) && lying) HeldObjectDirTransform(slot_r_hand, src.dir) - else - update_inv_l_hand(FALSE) - update_inv_r_hand(FALSE) - update_icon(UPDATE_ICON_IGNORE_DIRECTION_UPDATE) - var/matrix/M = matrix() - M.Scale(size_multiplier) - M.Translate(0, 16*(size_multiplier-1)) - animate(src, transform = M, time = ANIM_LYING_TIME) - UpdateOverlays() lying_prev = lying @@ -196,9 +192,7 @@ There are several things that need to be remembered: animate(item_image, transform = item_transform) overlays_raw[layer] = item_image - update_icon(UPDATE_ICON_IGNORE_DIRECTION_UPDATE) - -#undef UPDATE_ICON_IGNORE_DIRECTION_UPDATE + update_icon() //DAMAGE OVERLAYS //constructs damage icon for each organ from mask * damage field and saves it in our overlays_raw list (as a list of icons). @@ -277,9 +271,11 @@ There are several things that need to be remembered: if(update_icons) update_icon() -//Overlays for the worn overlay so you can overlay while you overlay -//eg: ammo counters, primed grenade flashing, etc. -//"icon_file" is used automatically for inhands etc. to make sure it gets the correct inhand file +/** + * Overlays for the worn overlay so you can overlay while you overlay + * eg: ammo counters, primed grenade flashing, etc. + * "icon_file" is used automatically for inhands etc. to make sure it gets the correct inhand file + */ /obj/item/proc/worn_overlays(icon_file) . = list() var/mutable_appearance/M = null @@ -326,7 +322,7 @@ There are several things that need to be remembered: return WORN_GLOVES return "" -//BASE MOB SPRITE +/// BASE MOB SPRITE /mob/living/carbon/human/proc/update_body(var/update_icons=1, var/force_base_icon = FALSE) if (QDELETED(src)) return @@ -442,8 +438,10 @@ There are several things that need to be remembered: if(update_icons) update_icon() -// This proc generates & returns an icon representing a human's hair, using a cached icon from SSicon_cache if possible. -// If `hair_is_visible` is FALSE, only facial hair will be drawn. +/** + * This proc generates & returns an icon representing a human's hair, using a cached icon from SSicon_cache if possible. + * If `hair_is_visible` is FALSE, only facial hair will be drawn. + */ /mob/living/carbon/human/proc/generate_hair_icon(hair_is_visible = TRUE) var/cache_key = "[f_style ? "[f_style][r_facial][g_facial][b_facial]" : "nofacial"]_[(h_style && hair_is_visible) ? "[h_style][r_hair][g_hair][b_hair]" : "nohair"]_[(g_style && g_style != "None" && hair_is_visible) ? "[g_style][r_grad][g_grad][b_grad]" : "nograd"]" @@ -487,7 +485,7 @@ There are several things that need to be remembered: return face_standing -//HAIR OVERLAY +/// HAIR OVERLAY /mob/living/carbon/human/proc/update_hair(var/update_icons=1) if (QDELETED(src)) return @@ -566,7 +564,7 @@ There are several things that need to be remembered: update_icon() /* --------------------------------------- */ -//For legacy support. +/// For legacy support. /mob/living/carbon/human/regenerate_icons() ..() @@ -1245,7 +1243,7 @@ There are several things that need to be remembered: overlays_raw[L_HAND_LAYER] = null if(update_icons) - update_icon(forceDirUpdate = TRUE) + update_icon(TRUE) /mob/living/carbon/human/update_inv_r_hand(update_icons = TRUE) if (QDELETED(src)) @@ -1284,7 +1282,7 @@ There are several things that need to be remembered: overlays_raw[R_HAND_LAYER] = null if(update_icons) - update_icon(forceDirUpdate = TRUE) + update_icon(TRUE) /mob/living/carbon/human/update_inv_wrists(var/update_icons=1) if (QDELETED(src)) @@ -1389,7 +1387,7 @@ There are several things that need to be remembered: if(species.tail && !(mutations & HUSK) && !(mutations & SKELETON) && !(wear_suit && wear_suit.flags_inv & HIDETAIL)) var/icon/tail_s = get_tail_icon() overlays_raw[tail_layer] = image(tail_s, icon_state = "[tail_style]_s") - animate_tail_reset() + animate_tail_reset(FALSE) update_tail_accessory(FALSE) if(update_icons) @@ -1414,7 +1412,7 @@ There are several things that need to be remembered: return tail_icon -/mob/living/carbon/human/proc/set_tail_state(var/mob_state) +/mob/living/carbon/human/proc/set_tail_state(var/mob_state, var/update = TRUE) if(!tail_style) return @@ -1428,8 +1426,7 @@ There are several things that need to be remembered: if(tail_overlay && species.tail_animation) if(tail_overlay.icon_state != mob_state) tail_overlay.icon_state = mob_state - update_tail_accessory() - update_icon() + update_tail_accessory(update) return tail_overlay return null @@ -1461,11 +1458,11 @@ There are several things that need to be remembered: /mob/living/carbon/human/proc/animate_tail_fast() set_tail_state("[tail_style]_loop") -/mob/living/carbon/human/proc/animate_tail_reset() +/mob/living/carbon/human/proc/animate_tail_reset(var/update = TRUE) if(stat != DEAD && !lying) - set_tail_state("[tail_style]_idle") + set_tail_state("[tail_style]_idle", update) else - set_tail_state("[tail_style]_static") + set_tail_state("[tail_style]_static", update) /mob/living/carbon/human/proc/animate_tail_stop(var/update_icons=1) set_tail_state("[tail_style]_static") diff --git a/code/modules/mob/living/carbon/slime/life.dm b/code/modules/mob/living/carbon/slime/life.dm index 2e24a25ddcce..f1f6ec1fbe70 100644 --- a/code/modules/mob/living/carbon/slime/life.dm +++ b/code/modules/mob/living/carbon/slime/life.dm @@ -314,14 +314,14 @@ set_intent(I_HURT) UnarmedAttack(target) Atkcool = TRUE - addtimer(CALLBACK(src, PROC_REF(disable_attack_cooldown)), 4.5 SECONDS) + addtimer(CALLBACK(src, PROC_REF(disable_attack_cooldown)), 4.5 SECONDS, TIMER_DELETE_ME) AIproc = FALSE return if(target.client && !target.lying && prob(60 + powerlevel * 4)) // Try to take down the target first if(!Atkcool) Atkcool = TRUE - addtimer(CALLBACK(src, PROC_REF(disable_attack_cooldown)), 4.5 SECONDS) + addtimer(CALLBACK(src, PROC_REF(disable_attack_cooldown)), 4.5 SECONDS, TIMER_DELETE_ME) set_intent(I_DISARM) UnarmedAttack(target) diff --git a/code/modules/mob/living/carbon/slime/powers.dm b/code/modules/mob/living/carbon/slime/powers.dm index 819498df54c5..1599118626fc 100644 --- a/code/modules/mob/living/carbon/slime/powers.dm +++ b/code/modules/mob/living/carbon/slime/powers.dm @@ -130,7 +130,7 @@ name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])" real_name = name set_content(TRUE) - addtimer(CALLBACK(src, PROC_REF(set_content), FALSE), 1200) // You get two minutes of safety + addtimer(CALLBACK(src, PROC_REF(set_content), FALSE), 1200, TIMER_DELETE_ME) // You get two minutes of safety else to_chat(src, SPAN_NOTICE("I am not ready to evolve yet...")) else diff --git a/code/modules/mob/living/carbon/slime/slime.dm b/code/modules/mob/living/carbon/slime/slime.dm index 4e0067d9a484..d55f8b16b2ec 100644 --- a/code/modules/mob/living/carbon/slime/slime.dm +++ b/code/modules/mob/living/carbon/slime/slime.dm @@ -94,6 +94,7 @@ for(var/mob/friend in friends) friends -= friend friends.Cut() + speech_buffer.Cut() QDEL_NULL(ingested) return ..() @@ -214,7 +215,7 @@ if(is_adult || prob(5)) INVOKE_ASYNC(src, PROC_REF(UnarmedAttack), AM) Atkcool = TRUE - addtimer(CALLBACK(src, PROC_REF(reset_atkcooldown)), 45) + addtimer(CALLBACK(src, PROC_REF(reset_atkcooldown)), 45, TIMER_DELETE_ME) if(ismob(AM)) var/mob/tmob = AM diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index d0f69bde4c1f..8deed2926d03 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -13,7 +13,7 @@ var/datum/gas_mixture/environment = loc.return_air() //Handle temperature/pressure differences between body and environment if(environment) - handle_environment(environment) + handle_environment(environment, seconds_per_tick) blinded = 0 // Placing this here just show how out of place it is. @@ -213,7 +213,7 @@ if(!.) // If we're under or inside shelter, use the z-level rain (for ambience) . = SSweather.weather_by_z["[my_turf.z]"] -/mob/living/proc/handle_environment(var/datum/gas_mixture/environment) +/mob/living/proc/handle_environment(var/datum/gas_mixture/environment, seconds_per_tick) SHOULD_CALL_PARENT(TRUE) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 343acb1d9941..8918aacb97b7 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -19,11 +19,16 @@ if(.) visible_message("\The [src] points to \the [pointing_at].") -/mob/living/drop_from_inventory(var/obj/item/item, var/atom/target) - . = ..(item, target) - if(item && item.GetID()) +/mob/living/drop_from_inventory(var/obj/item/item, var/atom/target, update_icons = TRUE, force = FALSE) + . = ..() + if(item?.GetID()) BITSET(hud_updateflag, ID_HUD) //If we drop our ID, update ID HUD +/mob/living/carbon/drop_from_inventory(obj/item/W, atom/target, update_icons = TRUE, force = FALSE) + if(!force && (W in internal_organs)) + return + return ..() + /*one proc, four uses swapping: if it's 1, the mobs are trying to switch, if 0, non-passive is pushing passive default behaviour is: @@ -818,11 +823,6 @@ default behaviour is: layer = UNDERDOOR underdoor = 1 -/mob/living/carbon/drop_from_inventory(var/obj/item/W, var/atom/target = null) - if(W in internal_organs) - return - ..() - /mob/living/touch_map_edge() //check for nuke disks diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 776e14216415..5658b3ed41dc 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -320,7 +320,7 @@ var/list/channel_to_radio_key = new if(!speaking || !(speaking.flags & PRESSUREPROOF)) //make sure the air can transmit speech - speaker's side var/datum/gas_mixture/environment = T.return_air() - var/pressure = (environment)? environment.return_pressure() : 0 + var/pressure = SAFE_XGM_PRESSURE(environment) if(pressure < SOUND_MINIMUM_PRESSURE) message_range = 1 diff --git a/code/modules/mob/living/silicon/robot/analyzer.dm b/code/modules/mob/living/silicon/robot/analyzer.dm index db9afbb3ef53..786ca5bee22c 100644 --- a/code/modules/mob/living/silicon/robot/analyzer.dm +++ b/code/modules/mob/living/silicon/robot/analyzer.dm @@ -3,9 +3,11 @@ // /obj/item/robotanalyzer name = "cyborg analyzer" - icon = 'icons/obj/item/robotanalyzer.dmi' + icon = 'icons/obj/item/scanner.dmi' icon_state = "robotanalyzer" - item_state = "analyzer" + // Reuses the basic health analyzer inhands. + item_state = "healthanalyzer" + contained_sprite = TRUE desc = "A hand-held scanner able to diagnose robotic injuries." obj_flags = OBJ_FLAG_CONDUCTABLE slot_flags = SLOT_BELT @@ -135,9 +137,6 @@ /obj/item/robotanalyzer/augment name = "retractable cyborg analyzer" desc = "An scanner implanted directly into the hand, popping through the finger. This scanner can diagnose robotic injuries." - icon = 'icons/obj/item/robotanalyzer.dmi' - icon_state = "robotanalyzer" - item_state = "analyzer" slot_flags = null w_class = WEIGHT_CLASS_HUGE diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index cab0ba3a5955..fa9d7f283071 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -537,7 +537,6 @@ set_light(integrated_light_power) else set_light(0) - setup_eye_cache() //update eyes /mob/living/silicon/robot/proc/show_access() if(!module) @@ -558,7 +557,7 @@ if(jetpack) . += "Internal Atmosphere Info: [jetpack.name]" - . += "Tank Pressure: [jetpack.air_contents.return_pressure()]" + . += "Tank Pressure: [XGM_PRESSURE(jetpack.air_contents)]" . += "Lights: [lights_on ? "ON" : "OFF"]" if(module) for(var/datum/matter_synth/ms in module.synths) diff --git a/code/modules/mob/living/silicon/robot/robot_helpers.dm b/code/modules/mob/living/silicon/robot/robot_helpers.dm index 3a78542eefe9..55b970565eb9 100644 --- a/code/modules/mob/living/silicon/robot/robot_helpers.dm +++ b/code/modules/mob/living/silicon/robot/robot_helpers.dm @@ -32,8 +32,8 @@ if(!module_sprites?[icontype]?[ROBOT_EYES]) return var/eye_plane = src.plane - if(lights_on && layer == MOB_LAYER) // in case you're hiding. so eyes don't go through tables. - eye_plane = MOB_EMISSIVE_LAYER //make them glow in the dark if the lamp is on + if(layer == MOB_LAYER) // In case you're hiding. So eyes don't go through tables. + eye_plane = MOB_EMISSIVE_LAYER var/eyeprefix = module_sprites[icontype][ROBOT_EYES] if(speed == -2) // For combat drones with the mobility module. cached_eye_overlays = list( diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index 74fb65fca4e1..7f3b4da951d5 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -372,7 +372,6 @@ GLOBAL_LIST_INIT(robot_modules, list( modules += new /obj/item/screwdriver/robotic(src) modules += new /obj/item/wrench/robotic(src) modules += new /obj/item/weldingtool/experimental(src) - modules += new /obj/item/pipe_painter(src) modules += new /obj/item/gripper/no_use/loader(src) modules += new /obj/item/gripper(src) modules += new /obj/item/t_scanner(src) // to check underfloor wiring @@ -443,7 +442,6 @@ GLOBAL_LIST_INIT(robot_modules, list( modules += new /obj/item/gripper(src) modules += new /obj/item/gripper/no_use/loader(src) modules += new /obj/item/lightreplacer(src) - modules += new /obj/item/pipe_painter(src) modules += new /obj/item/paint_sprayer(src) modules += new /obj/item/taperoll/engineering(src) // To enable 'borgs to telegraph danger visually. modules += new /obj/item/inflatable_dispenser(src) // To enable 'borgs to protect Crew from danger in direct hazards. @@ -984,7 +982,6 @@ GLOBAL_LIST_INIT(robot_modules, list( modules += new /obj/item/lightreplacer(src) modules += new /obj/item/soap/drone(src) modules += new /obj/item/extinguisher(src) - modules += new /obj/item/pipe_painter(src) modules += new /obj/item/paint_sprayer(src) modules += new /obj/item/t_scanner(src) modules += new /obj/item/gripper/multi_purpose(src) diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index b04ff0d44d61..4b7b0b600a8e 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -3,13 +3,14 @@ gender = NEUTER voice_name = "Synthesized Voice" accent = ACCENT_TTS - var/list/speech_synthesizer_langs = list() //which languages can be vocalized by the speech synthesizer + /// Which languages can be vocalized by the speech synthesizer + var/list/speech_synthesizer_langs = list() var/speak_statement = "states" var/speak_exclamation = "declares" var/speak_query = "queries" // Description - var/pose //Yes, now AIs can pose too. + var/pose // Bad Guy Stuff var/syndicate = FALSE @@ -18,8 +19,10 @@ var/datum/ai_laws/laws var/law_channel = DEFAULT_LAW_CHANNEL var/list/additional_law_channels = list("State" = "") - var/list/stating_laws = list() // Channels laws are currently being stated on - var/obj/item/radio/common_radio // Used to determine default channels + /// Channels laws are currently being stated on + var/list/stating_laws = list() + /// Used to determine default channels + var/obj/item/radio/common_radio // Hud Stuff var/list/hud_list[10] @@ -45,7 +48,7 @@ var/obj/item/card/id/id_card var/id_card_type = /obj/item/card/id/synthetic - // ACCENT_ALL_IPC with the added consideration that this selection can be used by the ship AI itself, and should not look bad for the SCC. No dregs, Himeans, Trinarists, etc. + /// ACCENT_ALL_IPC with the added consideration that this selection can be used by the ship AI itself, and should not look bad for the SCC. No dregs, Himeans, Trinarists, etc. var/list/possible_accents = list(ACCENT_CETI, ACCENT_TTS, ACCENT_XANU, ACCENT_COC, ACCENT_ELYRA, ACCENT_ERIDANI, ACCENT_SOL, ACCENT_SILVERSUN_EXPATRIATE, ACCENT_SILVERSUN_ORIGINAL, ACCENT_PHONG, ACCENT_MARTIAN, ACCENT_KONYAN, ACCENT_LUNA, ACCENT_GIBSON_OVAN, ACCENT_GIBSON_UNDIR, ACCENT_VYSOKA, ACCENT_VENUS, ACCENT_VENUSJIN, ACCENT_JUPITER, ACCENT_CALLISTO, ACCENT_EUROPA, ACCENT_EARTH, ACCENT_ASSUNZIONE, ACCENT_VISEGRAD, ACCENT_SANCOLETTE, ACCENT_VALKYRIE, ACCENT_MICTLAN, ACCENT_PERSEPOLIS, ACCENT_MEDINA, ACCENT_NEWSUEZ, ACCENT_AEMAQ, ACCENT_DAMASCUS) @@ -160,34 +163,42 @@ if(bot.connected_ai == ai) return TRUE return FALSE -// This is a pure virtual function, it should be overwritten by all subclasses +/// This is a pure virtual function, it should be overwritten by all subclasses /mob/living/silicon/proc/show_malf_ai() return FALSE -// this function displays the shuttles ETA in the status panel if the shuttle has been called +/// This function displays the shuttles ETA in the status panel if the shuttle has been called /mob/living/silicon/proc/show_emergency_shuttle_eta() if(GLOB.evacuation_controller) var/eta_status = GLOB.evacuation_controller.get_status_panel_eta() if(eta_status) stat(null, eta_status) -// This adds the basic clock, shuttle recall timer, and malf_ai info to all silicon lifeforms +/// This adds the basic clock, shuttle recall timer, and malf_ai info to all silicon lifeforms /mob/living/silicon/get_status_tab_items() . = ..() + + var/area/A = get_area(src) + var/area_name = get_area_display_name(A) + . += "[area_name]" + . += "" + if(A.area_blurb) + . += "[A.area_blurb]" + . += "" + if(!stat) . += "System Integrity: [round((health/maxHealth)*100)]%" else . += "System Integrity: NON-FUNCTIONAL" show_malf_ai() -//can't inject synths +/// can't inject synths /mob/living/silicon/can_inject(mob/user, error_msg) if(error_msg) to_chat(user, SPAN_ALERT("The armored plating is too tough.")) return 0 -//Silicon mob language procs - +// Silicon mob language procs /mob/living/silicon/can_speak(datum/language/speaking) return universal_speak || (speaking in src.speech_synthesizer_langs) //need speech synthesizer support to vocalize a language diff --git a/code/modules/mob/living/simple_animal/friendly/carp.dm b/code/modules/mob/living/simple_animal/friendly/carp.dm index 1bcb14b6cb54..c3555d2079b0 100644 --- a/code/modules/mob/living/simple_animal/friendly/carp.dm +++ b/code/modules/mob/living/simple_animal/friendly/carp.dm @@ -101,12 +101,13 @@ //walk to friend stop_automated_movement = 1 movement_target = friend + RegisterSignal(movement_target, COMSIG_QDELETING, PROC_REF(lostMovementTarget)) GLOB.move_manager.move_to(src, movement_target, near_dist, seek_move_delay) //already following and close enough, stop else if(current_dist <= near_dist) GLOB.move_manager.stop_looping(src) - movement_target = null + lostMovementTarget() stop_automated_movement = 0 if(prob(10)) say("Glub!") diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index e313e0cdb808..0cef2f3c4ece 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -47,14 +47,27 @@ . = ..() src.filters += filter(type="drop_shadow", size = 2, offset = 2, color = rgb(0,208,0,0)) +/mob/living/simple_animal/cat/Destroy() + lost_rattarget() + return ..() + +/mob/living/simple_animal/cat/proc/lost_rattarget() + if(rattarget) + UnregisterSignal(rattarget, COMSIG_QDELETING) + rattarget = null + /mob/living/simple_animal/cat/think() //MICE! ..() if (!stat) for(var/mob/living/simple_animal/rat/snack in oview(src,7)) if(snack.stat != DEAD && prob(65))//The probability allows her to not get stuck target the first rat, reducing exploits + if(rattarget) // fr? + UnregisterSignal(rattarget, COMSIG_QDELETING) rattarget = snack movement_target = snack + RegisterSignal(rattarget, COMSIG_QDELETING, PROC_REF(lost_rattarget)) + RegisterSignal(movement_target, COMSIG_QDELETING, PROC_REF(lostMovementTarget)) if(prob(15)) audible_emote(pick("hisses and spits!","mrowls fiercely!","eyes [snack] hungrily.")) @@ -94,7 +107,7 @@ if(M.stat != DEAD) M.splat() visible_emote(pick("bites \the [M]!","toys with \the [M].","chomps on \the [M]!"),0) - movement_target = null + lostMovementTarget() stop_automated_movement = 0 if (prob(75)) break//usually only kill one rat per proc @@ -229,7 +242,7 @@ //already following and close enough, stop else if (current_dist <= near_dist) GLOB.move_manager.stop_looping(src) - movement_target = null + lostMovementTarget() stop_automated_movement = 0 if (prob(10)) say("Meow!") diff --git a/code/modules/mob/living/simple_animal/friendly/corgi.dm b/code/modules/mob/living/simple_animal/friendly/corgi.dm index 09b0a3b69e7a..a94c4ed4c9c5 100644 --- a/code/modules/mob/living/simple_animal/friendly/corgi.dm +++ b/code/modules/mob/living/simple_animal/friendly/corgi.dm @@ -79,7 +79,7 @@ SPAN_ALERT("[user] baps you on the nose with the rolled up [attacking_item.name]!") ) scan_interval = max_scan_interval - movement_target = null + lostMovementTarget() stop_automated_movement = 0 turns_since_scan = 0 diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm index f590a84da975..552eba706ac1 100644 --- a/code/modules/mob/living/simple_animal/hostile/bear.dm +++ b/code/modules/mob/living/simple_animal/hostile/bear.dm @@ -347,7 +347,7 @@ if(istype(loc,/turf)) var/turf/T = loc var/datum/gas_mixture/environment = T.return_air() - if (environment.return_pressure() <= 80) + if (XGM_PRESSURE(environment) <= 80) bearmode = BEARMODE_SPACE if (bearmode != former) diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm index d21ac777071d..67e18c6dd585 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -86,6 +86,7 @@ speed = -2 venom_type = /singleton/reagent/toxin/greimorian_eggs fed = 1 + lighting_alpha = LIGHTING_PLANE_ALPHA_SOMEWHAT_INVISIBLE var/playable = TRUE sample_data = list("Genetic markers identified as being linked with stem cell differentiaton", "Cellular structures indicative of high offspring production", "Tissue sample contains high neural cell content") @@ -165,6 +166,8 @@ get_light_and_color(parent) add_language(LANGUAGE_GREIMORIAN) add_language(LANGUAGE_GREIMORIAN_HIVEMIND) + remove_language(LANGUAGE_TCB) + default_language = GLOB.all_languages[LANGUAGE_GREIMORIAN] /mob/living/simple_animal/hostile/giant_spider/nurse/servant/Initialize() . = ..() @@ -418,6 +421,10 @@ set desc = "Lay a clutch of eggs to make new spiderlings. This will cost one food point." set category = "Greimorian" + if(fed <= 0) + to_chat(src, SPAN_WARNING("You do not have the nutrients to do this. Try cocooning a corpse!")) + return + var/obj/effect/spider/eggcluster/E = locate() in get_turf(src) if(!E && fed > 0) src.visible_message("\The [src] begins to lay a cluster of eggs.") @@ -433,6 +440,9 @@ set desc = "Lay a greimorian servant, which can be player-controlled. This will cost one food point." set category = "Greimorian" + if(fed <= 0) + to_chat(src, SPAN_WARNING("You do not have the nutrients to do this. Try cocooning a corpse!")) + return var/obj/effect/spider/eggcluster/E = locate() in get_turf(src) if(!E && fed > 0) diff --git a/code/modules/mob/living/simple_animal/hostile/hivebots/hivebot.dm b/code/modules/mob/living/simple_animal/hostile/hivebots/hivebot.dm index 6e93b20cf3d4..55aed40526d6 100644 --- a/code/modules/mob/living/simple_animal/hostile/hivebots/hivebot.dm +++ b/code/modules/mob/living/simple_animal/hostile/hivebots/hivebot.dm @@ -48,21 +48,37 @@ */ var/mob/living/simple_animal/hostile/hivebotbeacon/linked_parent = null -/mob/living/simple_animal/hostile/hivebot/Initialize(mapload,mob/living/simple_animal/hostile/hivebot/hivebotbeacon) +/mob/living/simple_animal/hostile/hivebot/Initialize(mapload,mob/living/simple_animal/hostile/hivebotbeacon/beacon) . = ..() - if(hivebotbeacon) - linked_parent = hivebotbeacon - + do_link(beacon) if(!mapload) spark(get_turf(src), 2, GLOB.alldirs) /mob/living/simple_animal/hostile/hivebot/Destroy() + unlink() + . = ..() + +/mob/living/simple_animal/hostile/hivebot/proc/do_link(mob/living/simple_animal/hostile/hivebotbeacon/beacon) + if(QDELETED(beacon)) + return + if(linked_parent) - linked_parent.linked_bots -= src - linked_parent = null + if(linked_parent == beacon) + return + unlink() - . = ..() + linked_parent = beacon + beacon.do_link(src) + RegisterSignal(linked_parent, COMSIG_QDELETING, PROC_REF(unlink)) + +/mob/living/simple_animal/hostile/hivebot/proc/unlink() + SIGNAL_HANDLER + if(!linked_parent) + return + linked_parent.unlink(src) + UnregisterSignal(linked_parent, COMSIG_QDELETING) + linked_parent = null /mob/living/simple_animal/hostile/hivebot/get_bullet_impact_effect_type(var/def_zone) return BULLET_IMPACT_METAL @@ -97,12 +113,10 @@ var/robot_gib_type = /obj/effect/decal/cleanable/blood/gibs/robot var/atom/turf_gibs = locate(robot_gib_type) in current_turf - if(turf_gibs) // we only want to spawn gibs here if there aren't any already - return - - var/list/gib_types = typesof(robot_gib_type) - var/selected_gib_type = pick(gib_types) - new selected_gib_type(current_turf) + if(!turf_gibs) // we only want to spawn gibs here if there aren't any already + var/list/gib_types = typesof(robot_gib_type) + var/selected_gib_type = pick(gib_types) + new selected_gib_type(current_turf) spark(current_turf, 1, GLOB.alldirs) @@ -155,16 +169,6 @@ mob_swap_flags = ~HEAVY mob_push_flags = 0 -/mob/living/simple_animal/hostile/hivebot/guardian/Initialize(mapload,mob/living/simple_animal/hostile/hivebot/hivebotbeacon) - .=..() - if(hivebotbeacon && linked_parent) - linked_parent.guard_amt++ - -/mob/living/simple_animal/hostile/hivebot/guardian/Destroy() - .=..() - if(linked_parent) - linked_parent.guard_amt-- - /mob/living/simple_animal/hostile/hivebot/guardian/think() . =..() if(stance != HOSTILE_STANCE_IDLE) diff --git a/code/modules/mob/living/simple_animal/hostile/hivebots/hivebot_beacon.dm b/code/modules/mob/living/simple_animal/hostile/hivebots/hivebot_beacon.dm index e78ac398dda4..a6d411fc4a93 100644 --- a/code/modules/mob/living/simple_animal/hostile/hivebots/hivebot_beacon.dm +++ b/code/modules/mob/living/simple_animal/hostile/hivebots/hivebot_beacon.dm @@ -69,7 +69,7 @@ var/maximum_linked_and_alive_hivebots_to_playing_players_scaling_factor = 1 ///A list of `/mob/living/simple_animal/hostile` hivebots that are linked to this beacon - var/list/mob/living/simple_animal/hostile/hivebot/linked_bots = list() + var/list/mob/living/simple_animal/hostile/linked_bots = list() ///Amount of hivebots spawned and alive linked to this beacon, guardian type var/guard_amt = 0 @@ -128,8 +128,10 @@ /mob/living/simple_animal/hostile/hivebotbeacon/Destroy() //Remove the reference from all linked bots to us - for(var/mob/living/simple_animal/hostile/hivebot/latest_child in linked_bots) - latest_child.linked_parent = null + for(var/mob/living/simple_animal/hostile/retaliate/hivebotharvester/hbh in linked_bots) + hbh.unlink() + for(var/mob/living/simple_animal/hostile/hivebot/hb in linked_bots) + hb.unlink() linked_bots.Cut() //Smoke effect, we disappear in a smoke @@ -139,6 +141,48 @@ . = ..() +/mob/living/simple_animal/hostile/hivebotbeacon/proc/do_link(mob/living/simple_animal/hostile/add) + if(QDELETED(add) || (add in linked_bots)) + return + var/mob/living/simple_animal/hostile/hivebot/hb = astype(add) + if(!hb) + var/mob/living/simple_animal/hostile/retaliate/hivebotharvester/hbh = astype(add) + if(hbh) + if(hbh.linked_parent != src) + hbh.do_link(src) + harvester_amt++ + . = TRUE + else + if(hb.linked_parent != src) + hb.do_link(src) + if(istype(add, /mob/living/simple_animal/hostile/hivebot/guardian)) + guard_amt++ + . = TRUE + + if(.) + linked_bots += add + RegisterSignal(add, COMSIG_QDELETING, PROC_REF(unlink)) + + +/mob/living/simple_animal/hostile/hivebotbeacon/proc/unlink(mob/living/simple_animal/hostile/remove) + SIGNAL_HANDLER + if(!remove || !(remove in linked_bots)) + return + UnregisterSignal(remove, COMSIG_QDELETING) + linked_bots -= remove + var/mob/living/simple_animal/hostile/hivebot/hb = astype(remove) + if(hb) + if(hb.linked_parent == src) + hb.unlink() + if(istype(remove, /mob/living/simple_animal/hostile/hivebot/guardian)) + guard_amt-- + else + var/mob/living/simple_animal/hostile/retaliate/hivebotharvester/hbh = astype(remove) + if(hbh) + if(hbh.linked_parent == src) + hbh.unlink() + harvester_amt-- + /mob/living/simple_animal/hostile/hivebotbeacon/proc/generate_warp_destinations() destinations.Cut() diff --git a/code/modules/mob/living/simple_animal/hostile/hivebots/hivebot_harvester.dm b/code/modules/mob/living/simple_animal/hostile/hivebots/hivebot_harvester.dm index 188fc5001d05..03c039255ad6 100644 --- a/code/modules/mob/living/simple_animal/hostile/hivebots/hivebot_harvester.dm +++ b/code/modules/mob/living/simple_animal/hostile/hivebots/hivebot_harvester.dm @@ -45,26 +45,42 @@ psi_pingable = FALSE sample_data = null -/mob/living/simple_animal/hostile/retaliate/hivebotharvester/Initialize(mapload,mob/living/simple_animal/hostile/hivebot/hivebotbeacon) - if(hivebotbeacon) - linked_parent = hivebotbeacon - linked_parent.harvester_amt ++ - .=..() +/mob/living/simple_animal/hostile/retaliate/hivebotharvester/Initialize(mapload,mob/living/simple_animal/hostile/hivebotbeacon/beacon) + do_link(beacon) + . = ..() set_light(3,2,LIGHT_COLOR_RED) if(!mapload) spark(get_turf(src), 3, GLOB.alldirs) +/mob/living/simple_animal/hostile/retaliate/hivebotharvester/proc/do_link(mob/living/simple_animal/hostile/hivebotbeacon/beacon) + if(QDELETED(beacon)) + return + + if(linked_parent) + if(linked_parent == beacon) + return + linked_parent.unlink(src) + + linked_parent = beacon + beacon.do_link(src) + RegisterSignal(linked_parent, COMSIG_QDELETING, PROC_REF(unlink)) + +/mob/living/simple_animal/hostile/retaliate/hivebotharvester/proc/unlink() + SIGNAL_HANDLER + if(!linked_parent) + return + linked_parent.unlink(src) + UnregisterSignal(linked_parent, COMSIG_QDELETING) + linked_parent = null + /mob/living/simple_animal/hostile/retaliate/hivebotharvester/death() ..(null,"teleports away!") - if(linked_parent) - linked_parent.harvester_amt -- spark(get_turf(src), 3, GLOB.alldirs) qdel(src) /mob/living/simple_animal/hostile/retaliate/hivebotharvester/Destroy() + unlink() . = ..() - if(linked_parent) - linked_parent.linked_bots -= src /mob/living/simple_animal/hostile/retaliate/hivebotharvester/Allow_Spacemove(var/check_drift = 0) return 1 diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index f80bfa9ac7e9..48ef25f33f2b 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -55,12 +55,11 @@ ABSTRACT_TYPE(/mob/living/simple_animal/hostile) /mob/living/simple_animal/hostile/Destroy() friends = null - last_found_target = null + unset_last_found_target() targets = null target_type_validator_map = null return ..() - /mob/living/simple_animal/hostile/proc/setup_target_type_validators() target_type_validator_map[/mob/living] = CALLBACK(src, PROC_REF(validator_living)) target_type_validator_map[/obj/machinery/bot] = CALLBACK(src, PROC_REF(validator_bot)) @@ -279,7 +278,7 @@ ABSTRACT_TYPE(/mob/living/simple_animal/hostile) if(target) face_atom(target) if(!ranged && smart_melee) - addtimer(CALLBACK(src, PROC_REF(PostAttack), target), 1.2 SECONDS) + addtimer(CALLBACK(src, PROC_REF(PostAttack), target), 1.2 SECONDS, TIMER_STOPPABLE|TIMER_DELETE_ME) return target /mob/living/simple_animal/hostile/proc/PostAttack(var/atom/target) @@ -390,9 +389,9 @@ ABSTRACT_TYPE(/mob/living/simple_animal/hostile) if(rapid) var/datum/callback/shoot_cb = CALLBACK(src, PROC_REF(shoot_wrapper), target, loc, src) - addtimer(shoot_cb, 1) - addtimer(shoot_cb, 4) - addtimer(shoot_cb, 6) + addtimer(shoot_cb, 1, TIMER_STOPPABLE|TIMER_DELETE_ME) + addtimer(shoot_cb, 4, TIMER_STOPPABLE|TIMER_DELETE_ME) + addtimer(shoot_cb, 6, TIMER_STOPPABLE|TIMER_DELETE_ME) else shoot_wrapper(target, loc, src) diff --git a/code/modules/mob/living/simple_animal/hostile/space_fauna.dm b/code/modules/mob/living/simple_animal/hostile/space_fauna.dm index e05265e87eb9..4abc6db22592 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_fauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_fauna.dm @@ -192,6 +192,12 @@ AddOverlays(eye_overlay) set_light(MINIMUM_USEFUL_LIGHT_RANGE, 2, LIGHT_COLOR_TUNGSTEN) +/mob/living/simple_animal/hostile/carp/shark/reaver/eel/Destroy() + ClearOverlays() + QDEL_NULL(eye_overlay) + set_light(0) + return ..() + /mob/living/simple_animal/hostile/carp/shark/reaver/eel/death() . = ..() ClearOverlays() @@ -223,11 +229,13 @@ change_stance(HOSTILE_STANCE_TIRED) stop_automated_movement = 1 wander = 0 - if(!has_exploded) - icon_state = "bloater_bloating" - icon_living = "bloater_bloating" - has_exploded = TRUE - addtimer(CALLBACK(src, PROC_REF(explode)), 5) + if(has_exploded) + return + + icon_state = "bloater_bloating" + icon_living = "bloater_bloating" + has_exploded = TRUE + addtimer(CALLBACK(src, PROC_REF(explode)), 5, TIMER_STOPPABLE|TIMER_DELETE_ME) /mob/living/simple_animal/hostile/carp/bloater/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit) . = ..() diff --git a/code/modules/mob/living/simple_animal/hostile/spider_queen.dm b/code/modules/mob/living/simple_animal/hostile/spider_queen.dm index ecad360d8477..a7732fdaa5c2 100644 --- a/code/modules/mob/living/simple_animal/hostile/spider_queen.dm +++ b/code/modules/mob/living/simple_animal/hostile/spider_queen.dm @@ -26,6 +26,7 @@ health = 1000 melee_damage_lower = 35 melee_damage_upper = 40 + melee_reach = 2 armor_penetration = 30 resist_mod = 15 // LOL good luck pal heat_damage_per_tick = 20 diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 61227d41fbe3..ab672e022041 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -26,7 +26,7 @@ /// We only try to show a gibbing animation if this exists var/icon_gib = null - appearance_flags = KEEP_TOGETHER + appearance_flags = KEEP_TOGETHER | DEFAULT_APPEARANCE_FLAGS | TILE_BOUND | LONG_GLIDE /// Blood colour for impact visuals var/blood_type = COLOR_HUMAN_BLOOD @@ -118,6 +118,7 @@ //LETTING SIMPLE ANIMALS ATTACK? WHAT COULD GO WRONG. Defaults to zero so Ian can still be cuddly var/melee_damage_lower = 0 var/melee_damage_upper = 0 + var/melee_reach = 1 var/armor_penetration = 0 var/attack_flags = 0 var/attacktext = "attacked" @@ -250,11 +251,15 @@ /mob/living/simple_animal/Destroy() CutOverlays(blood_overlay) - movement_target = null + lostMovementTarget() QDEL_NULL(udder) . = ..() - GC_TEMPORARY_HARDDEL + +/mob/living/simple_animal/proc/lostMovementTarget() + if(movement_target) + UnregisterSignal(movement_target, COMSIG_QDELETING) + movement_target = null /mob/living/simple_animal/Move(NewLoc, direct) // this is a janky way to prevent mobs wandering into chasms, but allows them to be thrown into it by someone else if the mob is dead @@ -753,11 +758,11 @@ /mob/living/simple_animal/cat/proc/handle_movement_target() //if our target is neither inside a turf or inside a human(???), stop if((movement_target) && !(isturf(movement_target.loc) || ishuman(movement_target.loc) )) - movement_target = null + lostMovementTarget() stop_automated_movement = 0 //if we have no target or our current one is out of sight/too far away if( !movement_target || !(movement_target.loc in oview(src, 4)) ) - movement_target = null + lostMovementTarget() stop_automated_movement = 0 if(movement_target) @@ -778,7 +783,7 @@ /mob/living/simple_animal/death(gibbed, deathmessage = "dies!") GLOB.move_manager.stop_looping(src) - movement_target = null + lostMovementTarget() ADD_TRAIT(src, TRAIT_UNDENSE, TRAIT_SOURCE_MOB_DEATH) if (isopenturf(loc)) ADD_FALLING_ATOM(src) @@ -944,7 +949,7 @@ canmove = 0 wander = 0 GLOB.move_manager.stop_looping(src) - movement_target = null + lostMovementTarget() update_icon() /// Wakes the mob up from sleeping @@ -1121,6 +1126,16 @@ visible_message(SPAN_NOTICE("\The [src] fades away!")) qdel(src) +//Taken from /obj/item/proc/attack_can_reach +/mob/living/simple_animal/proc/attack_can_reach(var/atom/us, var/atom/them, var/range) + if(us.Adjacent(them)) + return TRUE // Already adjacent. + else if(range <= 1) + return FALSE + if(AStar(get_turf(us), get_turf(them), /turf/proc/AdjacentTurfsRanged, /turf/proc/Distance, max_nodes=25, max_node_depth=range)) + return TRUE + return FALSE + #undef BLOOD_NONE #undef BLOOD_LIGHT #undef BLOOD_MEDIUM diff --git a/code/modules/mob/living/simple_animal/worm.dm b/code/modules/mob/living/simple_animal/worm.dm index 8848f18b18c0..60e49ee0762e 100644 --- a/code/modules/mob/living/simple_animal/worm.dm +++ b/code/modules/mob/living/simple_animal/worm.dm @@ -69,6 +69,10 @@ /mob/living/simple_animal/space_worm/Destroy() //if a chunk a destroyed, make a new worm out of the split halves if(previous) previous.Detach() + if(next && next.previous == src) + next.previous = null + previous = null + next = null return ..() /mob/living/simple_animal/space_worm/Move() @@ -127,6 +131,11 @@ return /mob/living/simple_animal/space_worm/proc/Detach(die = 0) + if(QDELETED(src)) + previous = null + next = null + return + var/mob/living/simple_animal/space_worm/newHead = new /mob/living/simple_animal/space_worm/head(loc,0) var/mob/living/simple_animal/space_worm/newHeadPrevious = previous diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 0cf82c1188b0..8dafc6e19ea3 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1,10 +1,9 @@ -#define UNBUCKLED 0 -#define PARTIALLY_BUCKLED 1 -#define FULLY_BUCKLED 2 - /mob/Destroy()//This makes sure that mobs with clients/keys are not just deleted from the game. MOB_STOP_THINKING(src) - + // Tell any mobs touching us that they're not pulling us anymore. + stop_pulling() + // Delete and null the grab objects that are touching this mob. + QDEL_LIST(grabbed_by) GLOB.mob_list -= src GLOB.dead_mob_list -= src GLOB.living_mob_list -= src @@ -53,8 +52,6 @@ if(click_handlers) QDEL_LIST(click_handlers) - QDEL_NULL(skills) - return ..() /mob/New() @@ -105,7 +102,9 @@ become_hearing_sensitive() - skills = new skills(src) + // This impacts area/entered(), gravity drifting, and probably plenty more. This will likely + // need to be removed/moved if and when any 'moodlet' system is implemented (ref. TG component). + become_area_sensitive(INNATE_TRAIT) /** * Generate the tag for this mob @@ -320,12 +319,6 @@ return UNBUCKLED return restrained() ? FULLY_BUCKLED : PARTIALLY_BUCKLED -/mob/proc/is_physically_disabled() - return MOB_IS_INCAPACITATED(INCAPACITATION_DISABLED) - -/mob/proc/cannot_stand() - return MOB_IS_INCAPACITATED(INCAPACITATION_KNOCKDOWN) - // Inside this file, you should use MOB_IS_INCAPACITATED for performance reasons /mob/proc/incapacitated(var/incapacitation_flags = INCAPACITATION_DEFAULT) @@ -825,9 +818,6 @@ /mob/proc/is_active() return (0 >= usr.stat) -/mob/proc/is_dead() - return stat == DEAD - /mob/proc/is_mechanical() return FALSE @@ -858,61 +848,60 @@ if(transforming) return 0 return 1 -/// Not sure what to call this. Used to check if humans are wearing an AI-controlled exosuit and hence don't need to fall over yet. -/mob/proc/can_stand_overridden() - return 0 - /// Updates canmove, lying and icons. Could perhaps do with a rename but I can't think of anything to describe it. /mob/proc/update_canmove() - if(in_neck_grab()) - lying = FALSE - for(var/obj/item/grab/G in grabbed_by) - if(G.force_down) - lying = TRUE - break - else if(!resting && cannot_stand() && can_stand_overridden()) - lying = FALSE - lying_is_intentional = FALSE - canmove = TRUE - else - if(istype(buckled_to, /obj/vehicle)) - var/obj/vehicle/V = buckled_to - if(is_physically_disabled()) - lying = TRUE - lying_is_intentional = FALSE - canmove = FALSE - pixel_y = V.mob_offset_y - 5 - else - if(buckled_to.buckle_lying != -1) lying = buckled_to.buckle_lying - lying_is_intentional = FALSE - canmove = TRUE - pixel_y = V.mob_offset_y - else if(buckled_to) - anchored = TRUE - canmove = FALSE - if(isobj(buckled_to)) - if(buckled_to.buckle_lying != -1) - lying = buckled_to.buckle_lying - lying_is_intentional = FALSE - if(buckled_to.buckle_movable) - anchored = FALSE - canmove = TRUE - else if(captured) - anchored = TRUE + var/found_grab = FALSE + for(var/obj/item/grab/G as anything in grabbed_by) + if(G.wielded || G.state >= GRAB_AGGRESSIVE) canmove = FALSE + lying = G.wielded || (G.state >= GRAB_NECK && G.force_down) + found_grab = TRUE + break + var/mob/living/carbon/human/H = astype(src) + if(!found_grab) + if(!resting && MOB_IS_INCAPACITATED(INCAPACITATION_KNOCKDOWN) && H?.can_stand_overridden()) lying = FALSE - else if(m_intent == M_LAY && !incapacitated()) - lying = TRUE - lying_is_intentional = TRUE - canmove = TRUE - else if(sleeping) - lying = resting || is_dead() || (MOB_IS_INCAPACITATED(INCAPACITATION_KNOCKDOWN) && sleeps_horizontal()) // Vaurca, IPCs and Diona sleep standing up, unless they were already lying down lying_is_intentional = FALSE - canmove = !MOB_IS_INCAPACITATED(INCAPACITATION_KNOCKOUT) && !weakened + canmove = TRUE else - lying = resting || is_dead() || MOB_IS_INCAPACITATED(INCAPACITATION_KNOCKDOWN) && !recently_slept - lying_is_intentional = FALSE - canmove = !MOB_IS_INCAPACITATED(INCAPACITATION_KNOCKOUT) && !weakened + if(buckled_to) + if(istype(buckled_to, /obj/vehicle)) + var/obj/vehicle/V = buckled_to + if(MOB_IS_INCAPACITATED(INCAPACITATION_DISABLED)) + lying = TRUE + lying_is_intentional = FALSE + canmove = FALSE + pixel_y = V.mob_offset_y - 5 + else + if(buckled_to.buckle_lying != -1) lying = buckled_to.buckle_lying + lying_is_intentional = FALSE + canmove = TRUE + pixel_y = V.mob_offset_y + else + anchored = TRUE + canmove = FALSE + if(buckled_to.buckle_lying != -1) + lying = buckled_to.buckle_lying + lying_is_intentional = FALSE + if(buckled_to.buckle_movable) + anchored = FALSE + canmove = TRUE + else if(captured) + anchored = TRUE + canmove = FALSE + lying = FALSE + else if(m_intent == M_LAY && !MOB_IS_INCAPACITATED(INCAPACITATION_DEFAULT)) + lying = TRUE + lying_is_intentional = TRUE + canmove = TRUE + else if(sleeping) + lying = resting || (stat == DEAD) || (MOB_IS_INCAPACITATED(INCAPACITATION_KNOCKDOWN) && !(H?.species?.sleeps_upright)) // Vaurca, IPCs and Diona sleep standing up, unless they were already lying down + lying_is_intentional = FALSE + canmove = !MOB_IS_INCAPACITATED(INCAPACITATION_KNOCKOUT) && !weakened + else + lying = resting || (stat == DEAD) || MOB_IS_INCAPACITATED(INCAPACITATION_KNOCKDOWN) && !recently_slept + lying_is_intentional = FALSE + canmove = !MOB_IS_INCAPACITATED(INCAPACITATION_KNOCKOUT) && !weakened if(lying) ADD_TRAIT(src, TRAIT_UNDENSE, TRAIT_SOURCE_LYING_DOWN) @@ -922,30 +911,11 @@ else REMOVE_TRAIT(src, TRAIT_UNDENSE, TRAIT_SOURCE_LYING_DOWN) - for(var/obj/item/grab/G in grabbed_by) - if(G.wielded) - canmove = FALSE - lying = TRUE - break - if(G.state >= GRAB_AGGRESSIVE) - canmove = 0 - break - - //Temporarily moved here from the various life() procs - //I'm fixing stuff incrementally so this will likely find a better home. - //It just makes sense for now. ~Carn - if( update_icon ) //forces a full overlay update - update_icon = 0 - regenerate_icons() - else if( lying != lying_prev ) + if( lying != lying_prev ) update_icon() return canmove - -/mob/proc/sleeps_horizontal() - return TRUE - /mob/proc/facedir(var/ndir, var/force_change = FALSE) if(!canface() || (client && client.moving)) return 0 @@ -1118,7 +1088,7 @@ break if(affected) affected.implants -= implant - for(var/datum/wound/wound in affected.wounds) + for(var/datum/wound/wound as anything in affected.wounds) LAZYREMOVE(wound.embedded_objects, implant) if(!surgical_removal) shock_stage += 20 @@ -1589,7 +1559,3 @@ var/atom/movable/screen/plane_master/lighting/exterior_lighting = hud_used.plane_masters["[EXTERIOR_LIGHTING_PLANE]"] if (exterior_lighting) exterior_lighting.alpha = min(GLOB.minimum_exterior_lighting_alpha, lighting_alpha) - -#undef UNBUCKLED -#undef PARTIALLY_BUCKLED -#undef FULLY_BUCKLED diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index d853413a64fb..d0fba8477677 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -287,5 +287,3 @@ /// A assoc lazylist of to_chat notifications, key = string message, value = world time integer var/list/message_notifications - /// The holder for mob skills. - var/datum/skills/skills = /datum/skills diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index b9f92f70896e..d77c6830c274 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -408,7 +408,7 @@ /obj/item/grab/Destroy() if(!QDELETED(linked_grab)) - qdel(linked_grab) + QDEL_NULL(linked_grab) UnregisterSignal(assailant, COMSIG_MOB_ZONE_SEL_CHANGE) @@ -513,6 +513,12 @@ linked.linked_grab = src linked_grab.set_wielding() +/obj/item/grab/offhand/Destroy() + if(linked_grab) + linked_grab.linked_grab = null + linked_grab.wielded = FALSE + . = ..() + /obj/item/grab/offhand/process() return diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 7fe2d7a587af..49d1221b0992 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -479,23 +479,48 @@ GLOBAL_LIST_INIT(organ_rel_size, list( p=p+n_mod return sanitize(t) -#define TICKS_PER_RECOIL_ANIM 2 -#define PIXELS_PER_STRENGTH_VAL 16 - -/proc/shake_camera(mob/M, duration, strength = 1) - var/current_time = world.time - if(!M || !M.client || (M.shakecamera > current_time)|| M.stat || isEye(M) || isAI(M)) - return - if(((M.client.view != world.view) || (M.client.pixel_x != 0) || (M.client.pixel_y != 0))) //to prevent it while zooming, because zoom does not play well with this code +#define TILES_PER_SECOND 0.7 +/// Shake the camera of the person viewing the mob SO REAL! +/// Takes the mob to shake, the time span to shake for, and the amount of tiles we're allowed to shake by in tiles +/// Duration isn't taken as a strict limit, since we don't trust our coders to not make things feel shitty. So it's more like a soft cap. +/proc/shake_camera(mob/M, duration, strength=1) + if(!M || !M.client || duration < 1) return - M.shakecamera = current_time + max(TICKS_PER_RECOIL_ANIM, duration) - strength = abs(strength)*PIXELS_PER_STRENGTH_VAL - var/steps = min(1, FLOOR(duration/TICKS_PER_RECOIL_ANIM, 1))-1 - animate(M.client, pixel_x = rand(-(strength), strength), pixel_y = rand(-(strength), strength), time = TICKS_PER_RECOIL_ANIM, easing = JUMP_EASING|EASE_IN) - if(steps) - for(var/i = 1 to steps) - animate(pixel_x = 0 + rand(-(strength), strength), pixel_y = 0 + rand(-(strength), strength), time = TICKS_PER_RECOIL_ANIM, easing = JUMP_EASING|EASE_IN) - animate(pixel_x = 0, pixel_y = 0, time = TICKS_PER_RECOIL_ANIM) + var/client/C = M.client + var/oldx = C.pixel_x + var/oldy = C.pixel_y + var/max_x = strength*ICON_SIZE_X + var/max_y = strength*ICON_SIZE_Y + var/min_x = -(strength*ICON_SIZE_X) + var/min_y = -(strength*ICON_SIZE_Y) + + //How much time to allot for each pixel moved + var/time_scalar = (1 / ICON_SIZE_ALL) * TILES_PER_SECOND + var/last_x = oldx + var/last_y = oldy + + var/time_spent = 0 + while(time_spent < duration) + //Get a random pos in our box + var/x_pos = rand(min_x, max_x) + oldx + var/y_pos = rand(min_y, max_y) + oldy + + //We take the smaller of our two distances so things still have the propencity to feel somewhat jerky + var/time = round(max(min(abs(last_x - x_pos), abs(last_y - y_pos)) * time_scalar, 1)) + + if (time_spent == 0) + animate(C, pixel_x=x_pos, pixel_y=y_pos, time=time) + else + animate(pixel_x=x_pos, pixel_y=y_pos, time=time) + + last_x = x_pos + last_y = y_pos + //We go based on time spent, so there is a chance we'll overshoot our duration. Don't care + time_spent += time + + animate(pixel_x=oldx, pixel_y=oldy, time=3) + +#undef TILES_PER_SECOND /proc/findname(msg) for(var/mob/M in GLOB.mob_list) @@ -1227,6 +1252,7 @@ GLOBAL_LIST_INIT(organ_rel_size, list( /mob/proc/set_intent(var/set_intent) a_intent = set_intent + SEND_SIGNAL(src, COMSIG_INTENT_CHANGE, set_intent) /mob/proc/get_accent_icon(var/datum/language/speaking, var/mob/hearer, var/force_accent) SHOULD_CALL_PARENT(TRUE) @@ -1270,6 +1296,8 @@ GLOBAL_LIST_INIT(organ_rel_size, list( M.client.eye = M.client.mob M.client.perspective = MOB_PERSPECTIVE + + /mob/proc/in_neck_grab() for(var/thing in grabbed_by) var/obj/item/grab/G = thing diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index d29835b4a33f..a566eb1b1e32 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -52,6 +52,9 @@ diagonal_action(SOUTHWEST) /client/proc/diagonal_action(direction) + if (!mob) + return + switch(client_dir(direction, 1)) if(NORTHEAST) swap_hand() @@ -67,6 +70,11 @@ to_chat(usr, SPAN_WARNING("This mob type cannot throw items.")) return if(NORTHWEST) + var/cancelled = FALSE + SEND_SIGNAL(mob, COMSIG_INPUT_KEY_DROP, &cancelled) + if (cancelled) + return + if(iscarbon(usr)) var/mob/living/carbon/C = usr if(!C.get_active_hand()) @@ -186,14 +194,13 @@ if(mob.transforming) return //This is sota the goto stop mobs from moving var - var/add_delay = mob.cached_multiplicative_slowdown - if(isliving(mob)) if(SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_PRE_LIVING_MOVE, new_loc, direct) & COMSIG_MOB_CLIENT_BLOCK_PRE_LIVING_MOVE) return FALSE var/mob/living/L = mob if(L.incorporeal_move && isturf(mob.loc))//Move though walls + mob.recalculate_glide_size(old_move_delay, move_delay, direct) Process_Incorpmove(direct, mob) return if(mob.client && ((mob.client.view != world.view) || (mob.client.pixel_x != 0) || (mob.client.pixel_y != 0))) // If mob moves while zoomed in with device, unzoom them. @@ -230,8 +237,9 @@ mob.lastarea = get_area(mob.loc) if(isobj(mob.loc) || ismob(mob.loc)) //Inside an object, tell it we are moving out - var/atom/O = mob.loc + var/atom/movable/O = mob.loc move_delay += (mob.movement_delay() + GLOB.config.walk_speed) * GLOB.config.walk_delay_multiplier + O.recalculate_glide_size(old_move_delay, move_delay, direct) return O.relaymove(mob, direct) if(isturf(mob.loc)) @@ -244,7 +252,6 @@ else mob.inertia_dir = 0 //If not then we can reset inertia and move - if(mob.restrained()) //Why being pulled while cuffed prevents you from moving var/mob/puller = mob.pulledby if(puller) @@ -259,23 +266,16 @@ move_delay = world.time + 1 SECOND // prevent spam return FALSE - //If the move was recent, count using old_move_delay - //We want fractional behavior and all - if(old_move_delay + world.tick_lag > world.time) - //Yes this makes smooth movement stutter if add_delay is too fractional - //Yes this is better then the alternative - move_delay = old_move_delay - else - move_delay = world.time - if(mob.buckled_to) if(istype(mob.buckled_to, /obj/vehicle)) - //manually set move_delay for vehicles so we don't inherit any mob movement penalties - //specific vehicle move delays are set in code\modules\vehicles\vehicle.dm - move_delay = (old_move_delay + world.tick_lag > world.time) ? old_move_delay : world.time //drunk driving if(mob.confused && prob(25)) direct = pick(GLOB.cardinals) + + var/obj/vehicle/vehicle = mob.buckled_to + move_delay += vehicle.move_delay + var/vehicle_glide_size = vehicle.recalculate_glide_size(old_move_delay, move_delay, direct) + mob.set_glide_size(vehicle_glide_size) return mob.buckled_to.relaymove(mob,direct) //TODO: Fuck wheelchairs. @@ -293,6 +293,8 @@ if(mob.confused && prob(25)) direct = pick(GLOB.cardinals) move_delay += max((mob.movement_delay() + GLOB.config.walk_speed) * GLOB.config.walk_delay_multiplier, min_move_delay) + var/wheelchair_glide_size = mob.buckled_to.recalculate_glide_size(old_move_delay, move_delay, direct) + mob.set_glide_size(wheelchair_glide_size) return mob.buckled_to.relaymove(mob,direct) var/tally = mob.movement_delay() + GLOB.config.walk_speed @@ -314,7 +316,6 @@ tally *= GLOB.config.walk_delay_multiplier move_delay += tally - move_delay += add_delay if(mob_is_human && mob.lying) var/mob/living/carbon/human/H = mob @@ -322,21 +323,26 @@ if(crawl_tally >= 120) return FALSE - if(istype(mob.machine, /obj/machinery)) - if(mob.machine.relaymove(mob,direct)) - return //Wheelchair pushing goes here for now. //TODO: Fuck wheelchairs. - if(istype(mob.pulledby, /obj/structure/bed/stool/chair/office/wheelchair) || istype(mob.pulledby, /obj/structure/cart)) + if(istype(mob.pulledby, /obj/structure)) var/obj/structure/S = mob.pulledby move_delay += S.slowdown + var/cart_glide_size = mob.pulledby.recalculate_glide_size(old_move_delay, move_delay, direct) + mob.set_glide_size(cart_glide_size) return mob.pulledby.relaymove(mob, direct) var/old_loc = mob.loc //We are now going to move moving = 1 + var/new_glide_size = mob.recalculate_glide_size(old_move_delay, move_delay, direct) + + if (mob.pulling) + mob.pulling.set_glide_size(new_glide_size) + mob.pulling.relaymove(mob, direct) + if(mob_is_human) for(var/obj/item/grab/G in list(mob.l_hand, mob.r_hand)) switch(G.get_grab_type()) @@ -354,9 +360,11 @@ for (var/obj/item/grab/G in list(mob.l_hand, mob.r_hand)) if (G.state == GRAB_NECK) mob.set_dir(REVERSE_DIR(direct)) + G.affecting.set_glide_size(new_glide_size) G.adjust_position() for (var/obj/item/grab/G in mob.grabbed_by) + G.affecting.set_glide_size(new_glide_size) G.adjust_position() moving = 0 @@ -378,6 +386,21 @@ var/obj/item/organ/external/lfoot = organs_by_name[BP_L_FOOT] . += limb_check(lfoot) +/** + * Updates the glide size of a mob attempting to travel in a specific direction. + * Also returns the new glide size. + */ +/atom/movable/proc/recalculate_glide_size(var/old_move_delay, var/move_delay, var/direction) + var/new_glide_size = glide_size + + if(old_move_delay + world.tick_lag > world.time) + new_glide_size = DELAY_TO_GLIDE_SIZE((move_delay - old_move_delay) * ( (NSCOMPONENT(direction) && EWCOMPONENT(direction)) ? sqrt(2) : 1 ) ) + else + new_glide_size = DELAY_TO_GLIDE_SIZE((move_delay - world.time) * ( (NSCOMPONENT(direction) && EWCOMPONENT(direction)) ? sqrt(2) : 1 ) ) + + set_glide_size(new_glide_size) // set it now in case of pulled objects + return new_glide_size + // Checks status of limb, returns an amount to /mob/living/carbon/human/proc/limb_check(var/obj/item/organ/external/limb) if(!limb) // Limb is null, thus missing. diff --git a/code/modules/mob/skills/skills.dm b/code/modules/mob/skills/skills.dm deleted file mode 100644 index 6535ed995c9f..000000000000 --- a/code/modules/mob/skills/skills.dm +++ /dev/null @@ -1,129 +0,0 @@ -/datum/skills - /// The mob that owns this skill datum. - var/mob/owner - /// The skills that this skill datum holds. Assoc list of skill type to level. - var/list/skills = list() - /// The TGUI module for changing skills. - var/tgui_module - -/datum/skills/New(mob/M) - if(!istype(M)) - crash_with("Invalid mob [M] supplied to skill datum!") - owner = M - ..() - -/** - * Returns the proficiency with a certain skill. - */ -/datum/skills/proc/get_skill_level(skill_type) - if(skill_type in skills) - return skills[skill_type] - return SKILL_LEVEL_UNFAMILIAR - -/** - * Sets skills starting from a preferences datum. - */ -/datum/skills/proc/set_skills_from_pref(datum/preferences/pref) - for(var/S in pref.skills) - var/singleton/skill/skill = GET_SINGLETON(S) - var/skill_level = pref.skills[skill.type] - skills[skill.type] = skill_level - -/** - * Returns the mob's proficiency with a certain skill. - */ -/mob/proc/get_skill_level(skill_type) - return skills.get_skill_level(skill_type) - -/** - * Takes a skill type and the level of skill needed. - * Returns TRUE if the mob's skill level exceeds or equals the skill level needed. - * Returns FALSE otherwise. - */ -/mob/proc/skill_check(skill_type, skill_level_needed) - return get_skill_level(skill_type) >= skill_level_needed - -/** - * Gets the skill difference in a given skill between two mobs. - */ -/mob/proc/get_skill_difference(mob/opponent, skill_type) - return get_skill_level(skill_type) - opponent.get_skill_level(skill_type) - -/** - * Returns a multiplier based on the mob's skill. Takes a skill type and a minimum skill floor at least. - * Bonus and malus are the modifiers added or removed for each skill level of difference from the required skill floor. - */ -/mob/proc/get_skill_multiplier(skill_type, skill_floor = SKILL_LEVEL_TRAINED, bonus = 0.2, malus = 0.2) - var/modifier = 1 - var/skill_level = get_skill_level(skill_type) - if(skill_level > skill_floor) - modifier -= bonus * max(0, skill_level - skill_floor) - else - modifier += malus * max(1, skill_floor - skill_level) - return modifier - -/** - * Returns the highest skill that a mob has in a list. - */ -/mob/proc/get_highest_skill_from_list(list/skills) - if(!length(skills)) - crash_with("Invalid list fed to get_highest_skill_from_list.") - - var/highest_skill - var/highest_skill_level = SKILL_LEVEL_UNFAMILIAR - for(var/skill in skills) - var/skill_level = get_skill_level(skill) - if(skill_level > highest_skill_level) - highest_skill = skill - return highest_skill - -/** - * A do_after modified by skill proficiency. - * - * delay = The base delay in seconds the do_after should take if skill level is equal to `skill_floor`. - * target = The do_after target. - * skill_type = The skill used for this do_after. Can be a list or a path. - * skill_floor = The base skill level at which the delay is unaffected. - * bonus/malus = The bonus added or removed for each step of skill difference, see get_skill_multiplier. - * do_flags = The do_flags fed to the do_after. - */ -/mob/proc/do_after_skill(base_delay, atom/target, skill_type, skill_floor = SKILL_LEVEL_TRAINED, bonus = 0.2, malus = 0.2, do_flags) - var/skill_mult - if(islist(skill_type)) - for(var/skill in skill_type) - skill_mult = min(skill_mult, get_skill_multiplier(skill, skill_floor, bonus, malus)) - else - skill_mult = get_skill_multiplier(skill_type, skill_floor, bonus, malus) - return do_after(src, base_delay * skill_mult, target, do_flags) - -/** - * Throws a DC challenge against the difficulty class. For explanation on how criticals work, see code\__DEFINES\skills.dm. - * A roll is a success if it matches or beats the DC. - * A natural 1 lowers the result by 1. Example: if you would roll a success with a natural 1, then that is downgraded to a normal failure. - * A natural 20 works the same way, it raises the result by 1. - * Remember that you should not check `if(!result)` for a failure. You should do `if(result <= ROLL_RESULT_FAILURE)` instead, so as to also check for a crit fail. - * - * difficulty_class = The DC to beat. - * skill_type = The skill used for this check. - */ -/mob/proc/skill_challenge(difficulty_class, skill_type) - var/roll = rand(1, 20) - var/skill_check = roll + get_skill_level(skill_type) - var/outcome = 0 - if(skill_check >= difficulty_class + 10) - outcome = ROLL_RESULT_CRITICAL_SUCCESS - else if(skill_check >= difficulty_class) - outcome = ROLL_RESULT_SUCCESS - else if(skill_check <= difficulty_class - 10) - outcome = ROLL_RESULT_CRITICAL_FAILURE - else - outcome = ROLL_RESULT_FAILURE - - if(roll == 1) - outcome-- - else if(roll == 20) - outcome++ - - outcome = clamp(outcome, ROLL_RESULT_CRITICAL_FAILURE, ROLL_RESULT_CRITICAL_SUCCESS) - balloon_alert(src, "[roll_result_text(outcome)]") - return outcome diff --git a/code/modules/modular_computers/computers/modular_computer/interaction.dm b/code/modules/modular_computers/computers/modular_computer/interaction.dm index 8e77e9088773..012f9613caec 100644 --- a/code/modules/modular_computers/computers/modular_computer/interaction.dm +++ b/code/modules/modular_computers/computers/modular_computer/interaction.dm @@ -139,20 +139,31 @@ verbs -= /obj/item/modular_computer/proc/eject_personal_ai update_uis() -/obj/item/modular_computer/AltClick(var/mob/user) - if(use_check_and_message(user, 32)) +/obj/item/modular_computer/AltClick(mob/user) + if(use_check_and_message(user, USE_FORCE_SRC_IN_USER)) return if(!card_slot) to_chat(user, SPAN_WARNING("\The [src] does not have an ID card slot.")) return - if(card_slot.stored_card) - eject_id() - else if(card_slot.stored_item) - eject_item() - else - to_chat(user, SPAN_WARNING("\The [src] does not have a card or item stored in the card slot.")) + if(!card_slot.stored_card) + to_chat(user, SPAN_WARNING("\The [src] does not have a card stored in the card slot.")) + return + eject_id() + +/obj/item/modular_computer/CtrlClick(mob/user) + if(use_check_and_message(user, USE_FORCE_SRC_IN_USER)) + return + + if(!card_slot) + to_chat(user, SPAN_WARNING("\The [src] does not have an ID card slot.")) + return + + if(!card_slot.stored_item) + to_chat(user, SPAN_WARNING("\The [src] does not have an item stored in the card slot.")) + return + eject_item() /obj/item/modular_computer/attack(mob/living/target_mob, mob/living/user, target_zone) var/sound_scan = FALSE diff --git a/code/modules/modular_computers/computers/subtypes/dev_console.dm b/code/modules/modular_computers/computers/subtypes/dev_console.dm index 209d0353b0a6..77f891a7cb82 100644 --- a/code/modules/modular_computers/computers/subtypes/dev_console.dm +++ b/code/modules/modular_computers/computers/subtypes/dev_console.dm @@ -1,7 +1,7 @@ /obj/item/modular_computer/console name = "console" desc = "A stationary computer." - icon = 'icons/obj/machinery/modular_console.dmi' + icon = 'icons/obj/modular_computers/modular_console.dmi' icon_state = "computer" icon_state_unpowered = "computer" icon_state_screensaver = "standby" diff --git a/code/modules/modular_computers/computers/subtypes/dev_handheld.dm b/code/modules/modular_computers/computers/subtypes/dev_handheld.dm index 165e392d316f..5cc6b6dafbf8 100644 --- a/code/modules/modular_computers/computers/subtypes/dev_handheld.dm +++ b/code/modules/modular_computers/computers/subtypes/dev_handheld.dm @@ -2,7 +2,7 @@ name = "tablet computer" lexical_name = "tablet" desc = "A portable device for your needs on the go." - icon = 'icons/obj/modular_tablet.dmi' + icon = 'icons/obj/modular_computers/modular_tablet.dmi' icon_state = "tablet" icon_state_unpowered = "tablet" icon_state_menu = "menu" @@ -24,7 +24,6 @@ /obj/item/modular_computer/handheld/Destroy() . = ..() - GC_TEMPORARY_HARDDEL /obj/item/modular_computer/handheld/proc/set_icon() icon_state_unpowered = icon_state diff --git a/code/modules/modular_computers/computers/subtypes/dev_laptop.dm b/code/modules/modular_computers/computers/subtypes/dev_laptop.dm index c4959ac527a9..c250bb00139f 100644 --- a/code/modules/modular_computers/computers/subtypes/dev_laptop.dm +++ b/code/modules/modular_computers/computers/subtypes/dev_laptop.dm @@ -6,7 +6,7 @@ hardware_flag = PROGRAM_LAPTOP can_reset = TRUE icon_state_unpowered = "laptop-open" - icon = 'icons/obj/modular_laptop.dmi' + icon = 'icons/obj/modular_computers/modular_laptop.dmi' icon_state = "laptop-open" icon_state_broken = "laptop-broken" randpixel = 6 diff --git a/code/modules/modular_computers/computers/subtypes/dev_pda.dm b/code/modules/modular_computers/computers/subtypes/dev_pda.dm index 8d4a2d092396..533248fe0180 100644 --- a/code/modules/modular_computers/computers/subtypes/dev_pda.dm +++ b/code/modules/modular_computers/computers/subtypes/dev_pda.dm @@ -2,7 +2,7 @@ name = "\improper PDA" lexical_name = "tablet" desc = "A personal data assistant. The latest in portable microcomputer solutions from Thinktronic Systems LTD." - icon = 'icons/obj/pda.dmi' + icon = 'icons/obj/modular_computers/pda.dmi' icon_state = "pda" item_state = "electronic" contained_sprite = TRUE @@ -18,13 +18,13 @@ icon_state_broken = icon_state /obj/item/modular_computer/handheld/pda/old - icon = 'icons/obj/pda_old.dmi' + icon = 'icons/obj/modular_computers/pda_old.dmi' /obj/item/modular_computer/handheld/pda/rugged - icon = 'icons/obj/pda_rugged.dmi' + icon = 'icons/obj/modular_computers/pda_rugged.dmi' /obj/item/modular_computer/handheld/pda/slate - icon = 'icons/obj/pda_slate.dmi' + icon = 'icons/obj/modular_computers/pda_slate.dmi' /obj/item/modular_computer/handheld/pda/smart - icon = 'icons/obj/pda_smart.dmi' + icon = 'icons/obj/modular_computers/pda_smart.dmi' diff --git a/code/modules/modular_computers/computers/subtypes/dev_silicon.dm b/code/modules/modular_computers/computers/subtypes/dev_silicon.dm index 4614797c653c..31bc55dd425b 100644 --- a/code/modules/modular_computers/computers/subtypes/dev_silicon.dm +++ b/code/modules/modular_computers/computers/subtypes/dev_silicon.dm @@ -3,7 +3,7 @@ desc = "A synthetic computer." hardware_flag = PROGRAM_SILICON icon_state_unpowered = "laptop-open" - icon = 'icons/obj/modular_laptop.dmi' + icon = 'icons/obj/modular_computers/modular_laptop.dmi' icon_state = "laptop-open" icon_state_broken = "laptop-broken" base_idle_power_usage = 5 @@ -29,7 +29,6 @@ /obj/item/modular_computer/silicon/Destroy() computer_host = null . = ..() - GC_TEMPORARY_HARDDEL /obj/item/modular_computer/silicon/computer_use_power(power_usage) // If we have host like AI, borg or pAI we handle their power @@ -61,7 +60,7 @@ hard_drive.store_file(new /datum/computer_file/program/atmos_control(src)) hard_drive.store_file(new /datum/computer_file/program/rcon_console(src)) hard_drive.store_file(new /datum/computer_file/program/law_manager(src, computer_host)) - hard_drive.remove_file(hard_drive.find_file_by_name("clientmanager")) + hard_drive.remove_file(hard_drive.find_file_by_name("clientmanager"), TRUE) addtimer(CALLBACK(src, PROC_REF(register_chat)), 1 SECOND) /obj/item/modular_computer/silicon/proc/register_chat() @@ -73,4 +72,4 @@ hard_drive.store_file(new /datum/computer_file/program/filemanager(src)) hard_drive.store_file(new /datum/computer_file/program/ntnetdownload(src)) hard_drive.store_file(new /datum/computer_file/program/alarm_monitor/all(src)) - hard_drive.remove_file(hard_drive.find_file_by_name("clientmanager")) + hard_drive.remove_file(hard_drive.find_file_by_name("clientmanager"), TRUE) diff --git a/code/modules/modular_computers/computers/subtypes/dev_telescreen.dm b/code/modules/modular_computers/computers/subtypes/dev_telescreen.dm index 21e74cdd4d78..a94673eca0fb 100644 --- a/code/modules/modular_computers/computers/subtypes/dev_telescreen.dm +++ b/code/modules/modular_computers/computers/subtypes/dev_telescreen.dm @@ -1,7 +1,7 @@ /obj/item/modular_computer/telescreen name = "telescreen" desc = "A stationary wall-mounted touchscreen" - icon = 'icons/obj/modular_telescreen.dmi' + icon = 'icons/obj/modular_computers/modular_telescreen.dmi' icon_state = "telescreen" icon_state_unpowered = "telescreen" icon_state_menu = "menu" diff --git a/code/modules/modular_computers/computers/subtypes/dev_wristbound.dm b/code/modules/modular_computers/computers/subtypes/dev_wristbound.dm index 46dfae05060c..820c4b470237 100644 --- a/code/modules/modular_computers/computers/subtypes/dev_wristbound.dm +++ b/code/modules/modular_computers/computers/subtypes/dev_wristbound.dm @@ -3,7 +3,7 @@ lexical_name = "wristbound" desc = "A portable wristbound device for your needs on the go. Quite comfortable." desc_extended = "A NanoTrasen design, this wristbound computer allows the user to quickly and safely access critical info, without taking their hands out of the equation." - icon = 'icons/obj/modular_wristbound.dmi' + icon = 'icons/obj/modular_computers/modular_wristbound.dmi' icon_state = "wristbound" icon_state_unpowered = "wristbound" icon_state_menu = "menu" diff --git a/code/modules/modular_computers/computers/subtypes/preset_laptop.dm b/code/modules/modular_computers/computers/subtypes/preset_laptop.dm index 7ad8f619c7ca..44992286d79f 100644 --- a/code/modules/modular_computers/computers/subtypes/preset_laptop.dm +++ b/code/modules/modular_computers/computers/subtypes/preset_laptop.dm @@ -5,7 +5,6 @@ /obj/item/modular_computer/laptop/preset/Destroy() . = ..() - GC_TEMPORARY_HARDDEL /obj/item/modular_computer/laptop/preset/install_default_hardware() ..() diff --git a/code/modules/modular_computers/computers/subtypes/preset_telescreen.dm b/code/modules/modular_computers/computers/subtypes/preset_telescreen.dm index b38049f27e6b..9366a204b6a6 100644 --- a/code/modules/modular_computers/computers/subtypes/preset_telescreen.dm +++ b/code/modules/modular_computers/computers/subtypes/preset_telescreen.dm @@ -1,6 +1,5 @@ /obj/item/modular_computer/telescreen/preset/Destroy() . = ..() - GC_TEMPORARY_HARDDEL /obj/item/modular_computer/telescreen/preset/install_default_hardware() ..() diff --git a/code/modules/modular_computers/file_system/computer_file.dm b/code/modules/modular_computers/file_system/computer_file.dm index 4684bb3ad095..527ce2161bdc 100644 --- a/code/modules/modular_computers/file_system/computer_file.dm +++ b/code/modules/modular_computers/file_system/computer_file.dm @@ -28,7 +28,7 @@ GLOBAL_VAR_INIT(file_uid, 0) if(!hard_drive) return ..() - hard_drive.remove_file(src) + hard_drive.remove_file(src, TRUE) // hard_drive.hard_drive is the computer that has drive installed. If we are Destroy()ing program that's currently running kill it. if(hard_drive.parent_computer?.active_program == src) hard_drive.parent_computer.kill_program(TRUE) diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm index 7cf422963c42..08787f46ac7c 100644 --- a/code/modules/modular_computers/file_system/program.dm +++ b/code/modules/modular_computers/file_system/program.dm @@ -110,7 +110,6 @@ ABSTRACT_TYPE(/datum/computer_file/program) computer = null . = ..() - GC_TEMPORARY_HARDDEL /datum/computer_file/program/ui_host() if(computer) diff --git a/code/modules/modular_computers/file_system/programs/_program.dm b/code/modules/modular_computers/file_system/programs/_program.dm index 9caaeee3e4d7..72030a2d2d12 100644 --- a/code/modules/modular_computers/file_system/programs/_program.dm +++ b/code/modules/modular_computers/file_system/programs/_program.dm @@ -18,6 +18,10 @@ ..() src.program = program +/datum/nano_module/program/Destroy() + program = null + return ..() + /datum/topic_manager/program var/datum/program @@ -25,6 +29,10 @@ ..() src.program = program +/datum/topic_manager/program/Destroy() + program = null + return ..() + // Calls forwarded to PROGRAM itself should begin with "PRG_" // Calls forwarded to COMPUTER running the program should begin with "PC_" /datum/topic_manager/program/Topic(href, href_list) diff --git a/code/modules/modular_computers/file_system/programs/civilian/cargo_control.dm b/code/modules/modular_computers/file_system/programs/civilian/cargo_control.dm index 74f69f033b93..46e1fceb0ff0 100644 --- a/code/modules/modular_computers/file_system/programs/civilian/cargo_control.dm +++ b/code/modules/modular_computers/file_system/programs/civilian/cargo_control.dm @@ -224,14 +224,28 @@ computer.visible_message(SPAN_NOTICE("\The [computer] prints out paper.")) if("bounty_print") if(computer && computer.nano_printer) - var/text = "

SCC Cargo Bounties


" + var/text = "" + text += "
" + text += "

SCC Bounty requisition manifest

" + text += "
" + text += "
Manifest of requisition requests for the operations department.
Manifest version: [worlddate2text()] [worldtime2text()]" + text += "

" + text += "" for(var/datum/bounty/B in SScargo.bounties_list) if(B.claimed) continue - text += "

[B.name]

" - text += "[B.description]" - text += "
  • Reward: [B.reward_string()]
  • " - text += "
  • Completed: [B.completion_string()]
" + text += "
[B.name]
[B.description]

Requisitioned: [B.completion_string()]
Payment: [B.reward_string()]
" + text += "

" + text += "" + text += "" + text += "
Powered by Orion Express logistics software.
Faster than light.
" + text += "
" + text += "
This document has been automatically generated based off of current inventory statistics. Under no circumstances should the requisition count or the resulting payment be adjusted by personnel. Payment is automatically credited to the operations department and not towards any individual. Requisitions above the requested count receive no additional payment above the listed values. This manifest is a public read-only version, and can be shared. It does not need to be returned." + text += "
" + text += "
" + text += "" + text += "Generated by OE.SCC.ReqApp 2.4
Manifest form version 5.87, Hash:
456E6A6F79696E6720796F7572207061706572776F726B3F" + text += "
" if(!computer.nano_printer.print_text(text,"paper - Bounties")) to_chat(usr, SPAN_WARNING("Hardware error: Printer was unable to print the file. It may be out of paper.")) return diff --git a/code/modules/modular_computers/file_system/programs/generic/manifest.dm b/code/modules/modular_computers/file_system/programs/generic/manifest.dm index 41d7333213ca..4e818697a388 100644 --- a/code/modules/modular_computers/file_system/programs/generic/manifest.dm +++ b/code/modules/modular_computers/file_system/programs/generic/manifest.dm @@ -18,6 +18,6 @@ /datum/computer_file/program/manifest/ui_static_data(mob/user) var/list/data = list() data["manifest"] = SSrecords.get_manifest_list() - data["allow_follow"] = isobserver(usr) - data["show_ooc_roles"] = isabstractmob(usr) + data["allow_follow"] = isobserver(user) + data["show_ooc_roles"] = isabstractmob(user) && !isEye(user) return data diff --git a/code/modules/modular_computers/file_system/programs/generic/records.dm b/code/modules/modular_computers/file_system/programs/generic/records.dm index 6c9a1b402e8c..a56a0ce12d3c 100644 --- a/code/modules/modular_computers/file_system/programs/generic/records.dm +++ b/code/modules/modular_computers/file_system/programs/generic/records.dm @@ -22,7 +22,7 @@ var/datum/record/virus/active_virus var/listener/record/rconsole/listener var/authenticated = FALSE - var/default_screen = "general" + var/default_screen = "General" var/record_prefix = "" var/typechoices = list( "physical_status" = list("Active", "*Deceased*", "*SSD*", "*Missing*", "Physically Unfit", "Disabled"), @@ -53,7 +53,7 @@ records_type = RECORD_MEDICAL | RECORD_VIRUS edit_type = RECORD_MEDICAL - default_screen = "medical" + default_screen = "Medical" program_icon_state = "medical_record" program_key_icon_state = "teal_key" color = LIGHT_COLOR_CYAN @@ -70,7 +70,7 @@ records_type = RECORD_SECURITY edit_type = RECORD_SECURITY - default_screen = "security" + default_screen = "Security" program_icon_state = "security_record" program_key_icon_state = "yellow_key" color = LIGHT_COLOR_YELLOW @@ -88,6 +88,7 @@ records_type = RECORD_GENERAL | RECORD_SECURITY edit_type = RECORD_GENERAL + default_screen = "General" program_icon_state = "employment_record" program_key_icon_state = "lightblue_key" color = LIGHT_COLOR_BLUE @@ -267,12 +268,6 @@ if("medical") if(!(edit_type & RECORD_MEDICAL)) return FALSE - if("diseases") - if(!(edit_type & RECORD_MEDICAL)) - return FALSE - if("allergies") - if(!(edit_type & RECORD_MEDICAL)) - return FALSE if("blood_type") if(!(edit_type & RECORD_MEDICAL) || (edit_type & RECORD_SECURITY)) return FALSE diff --git a/code/modules/modular_computers/file_system/programs/pai/radio.dm b/code/modules/modular_computers/file_system/programs/pai/radio.dm index 6fe225190194..06fa59fa6787 100644 --- a/code/modules/modular_computers/file_system/programs/pai/radio.dm +++ b/code/modules/modular_computers/file_system/programs/pai/radio.dm @@ -54,5 +54,5 @@ if(action == "radio_range") //fuck nanoUI and fuck vueui two-way bullshit, and fuck topic hooking host.radio.canhear_range = params["radio_range"] else - host.radio.Topic(action, params) + host.radio.ui_act(action, params, ui, state) . = TRUE diff --git a/code/modules/modular_computers/hardware/hard_drive.dm b/code/modules/modular_computers/hardware/hard_drive.dm index 999edff66047..eef9f9d78a21 100644 --- a/code/modules/modular_computers/hardware/hard_drive.dm +++ b/code/modules/modular_computers/hardware/hard_drive.dm @@ -100,12 +100,10 @@ /** * Use this proc to remove files to the drive. Returns 1 on success and 0 on failure. Contains necessary sanity checks. */ -/obj/item/computer_hardware/hard_drive/proc/remove_file(var/datum/computer_file/F) - if(!F || !istype(F)) - return FALSE - if(!stored_files || read_only) +/obj/item/computer_hardware/hard_drive/proc/remove_file(var/datum/computer_file/F, force = FALSE) + if(!F || !istype(F) || !stored_files) return FALSE - if(!check_functionality()) + if(!force && (read_only || !check_functionality())) return FALSE if(F in stored_files) stored_files -= F diff --git a/code/modules/modular_computers/hardware/hardware.dm b/code/modules/modular_computers/hardware/hardware.dm index 2c2dbb4cc8aa..3686dc633a5e 100644 --- a/code/modules/modular_computers/hardware/hardware.dm +++ b/code/modules/modular_computers/hardware/hardware.dm @@ -1,7 +1,7 @@ /obj/item/computer_hardware name = "Hardware" desc = "Unknown Hardware." - icon = 'icons/obj/modular_components.dmi' + icon = 'icons/obj/modular_computers/modular_components.dmi' var/obj/item/modular_computer/parent_computer /// If the hardware uses extra power, change this. var/power_usage = 0 diff --git a/code/modules/modular_computers/hardware/portable_hard_drive.dm b/code/modules/modular_computers/hardware/portable_hard_drive.dm index fcd2912d9fa2..409060ed0780 100644 --- a/code/modules/modular_computers/hardware/portable_hard_drive.dm +++ b/code/modules/modular_computers/hardware/portable_hard_drive.dm @@ -26,7 +26,9 @@ max_capacity = 256 origin_tech = list(TECH_DATA = 4) -/obj/item/computer_hardware/hard_drive/portable/New() - ..() +/obj/item/computer_hardware/hard_drive/portable/Initialize(mapload) + . = ..() + for(var/datum/computer_file/F in stored_files) + remove_file(F, TRUE) stored_files = list() recalculate_size() diff --git a/code/modules/modular_computers/hardware/portable_hard_drive_presets.dm b/code/modules/modular_computers/hardware/portable_hard_drive_presets.dm index ada04cc625f2..38f7d1c91eda 100644 --- a/code/modules/modular_computers/hardware/portable_hard_drive_presets.dm +++ b/code/modules/modular_computers/hardware/portable_hard_drive_presets.dm @@ -2,10 +2,6 @@ . = ..() add_programs() -/obj/item/computer_hardware/hard_drive/portable/super/preset/all/Destroy() - . = ..() - GC_TEMPORARY_HARDDEL - /obj/item/computer_hardware/hard_drive/portable/super/preset/all/proc/add_programs() for(var/F in typesof(/datum/computer_file/program)) var/datum/computer_file/program/prog = new F("Compless") diff --git a/code/modules/modular_computers/items/paper_scanner.dm b/code/modules/modular_computers/items/paper_scanner.dm index 4046d9dec310..d9e64a519ff3 100644 --- a/code/modules/modular_computers/items/paper_scanner.dm +++ b/code/modules/modular_computers/items/paper_scanner.dm @@ -1,7 +1,7 @@ /obj/item/paper_scanner name = "paper scanner" desc = "A simple device that can be used to scan paper or paper bundles in order to digitize them." - icon = 'icons/obj/devices/paperscanner.dmi' + icon = 'icons/obj/item/scanner.dmi' icon_state = "paperscanner" item_state = "paperscanner" contained_sprite = TRUE diff --git a/code/modules/multiz/movement.dm b/code/modules/multiz/movement.dm index 881a28ba832f..8756860cffc7 100644 --- a/code/modules/multiz/movement.dm +++ b/code/modules/multiz/movement.dm @@ -230,7 +230,7 @@ return 1 /mob/living/silicon/robot/can_ztravel(var/direction) - if(incapacitated() || is_dead()) + if(incapacitated() || (stat == DEAD)) return FALSE if(Allow_Spacemove()) //Checks for active jetpack diff --git a/code/modules/multiz/pipes.dm b/code/modules/multiz/pipes.dm index 863a7132037a..3a3f371eb185 100644 --- a/code/modules/multiz/pipes.dm +++ b/code/modules/multiz/pipes.dm @@ -74,7 +74,7 @@ if(!loc) return FALSE var/datum/gas_mixture/environment = loc.return_air() - var/pressure_difference = pressure - environment.return_pressure() + var/pressure_difference = pressure - XGM_PRESSURE(environment) if(pressure_difference > maximum_pressure) burst() diff --git a/code/modules/multiz/zmimic/mimic_movable.dm b/code/modules/multiz/zmimic/mimic_movable.dm index 7b52e762cb47..f33cbbea644b 100644 --- a/code/modules/multiz/zmimic/mimic_movable.dm +++ b/code/modules/multiz/zmimic/mimic_movable.dm @@ -10,7 +10,14 @@ bound_overlay.set_dir(ndir) /atom/movable/update_above() - if (!bound_overlay || !isturf(loc)) + if (!bound_overlay) + return + + if (QDELETED(bound_overlay)) + bound_overlay = null + return + + if (!isturf(loc)) return var/turf/T = loc @@ -82,7 +89,7 @@ plane = OPEN_SPACE_PLANE_END var/atom/movable/associated_atom var/depth - var/queued = 0 + var/queued = FALSE var/destruction_timer var/mimiced_type var/original_z @@ -100,6 +107,8 @@ associated_atom.bound_overlay = null associated_atom = null + queued = FALSE + if (destruction_timer) deltimer(destruction_timer) diff --git a/code/modules/nano/modules/follow_menu.dm b/code/modules/nano/modules/follow_menu.dm index 87b033df6f11..657895e3718e 100644 --- a/code/modules/nano/modules/follow_menu.dm +++ b/code/modules/nano/modules/follow_menu.dm @@ -1,3 +1,5 @@ +GLOBAL_DATUM_INIT(follow_menu, /datum/tgui_module/follow_menu, new) + /datum/tgui_module/follow_menu/ui_interact(var/mob/user, var/datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) @@ -14,9 +16,15 @@ return if(action == "follow_target") - ghost.ManualFollow(locate(params["follow_target"]) in GLOB.mob_list) + if(!ghost.ManualFollow(locate(params["follow_target"]) in GLOB.mob_list)) + to_chat(ghost, SPAN_WARNING("Failed to follow selected target. Refreshing mob list...")) + return TRUE + + if(action == "refresh") + ui.send_full_update() + return TRUE -/datum/tgui_module/follow_menu/ui_data(mob/user) +/datum/tgui_module/follow_menu/ui_static_data(mob/user) var/list/data = list() // Don't worry about this is_mod check being for storytellers as well - all it does is highlight antags in red. var/is_mod = check_rights(R_MOD|R_ADMIN, 0, user) || isstoryteller(user) diff --git a/code/modules/nano/modules/nano_module.dm b/code/modules/nano/modules/nano_module.dm index 00f7bb7d5907..9cf703ec89cd 100644 --- a/code/modules/nano/modules/nano_module.dm +++ b/code/modules/nano/modules/nano_module.dm @@ -9,6 +9,11 @@ src.host = host src.topic_manager = topic_manager +/datum/nano_module/Destroy() + host = null + topic_manager = null + return ..() + /datum/nano_module/ui_host() return host ? host.ui_host() : src diff --git a/code/modules/nano/modules/narrate_panel.dm b/code/modules/nano/modules/narrate_panel.dm index 6e7ffdd64a42..03bc127bc021 100644 --- a/code/modules/nano/modules/narrate_panel.dm +++ b/code/modules/nano/modules/narrate_panel.dm @@ -77,6 +77,10 @@ switch(narrate_filter) if ("Skrell-like Psi-sensitives") for(var/mob/filteree in filtered_list) + // Keep observers in the list, which includes ghosts, aghosts, and storytellers. + if (isghost(filteree)) + continue + // This will check for anyone who is capable of receiving and interpreting telepathic messages. // It will include Skrell who don't have a mindshield or the Low Psi-sensitivity trait. // It will also include characters who have Psi-receivers, the High Psi-sensitivity trait, or are under the effects of Psycho-nootropic drugs. @@ -85,12 +89,20 @@ continue if ("Human-like Psi-sensitives") for(var/mob/filteree in filtered_list) + // Keep observers in the list, which includes ghosts, aghosts, and storytellers. + if (isghost(filteree)) + continue + // This will check for anyone who has a Zona Bovina capable of hearing psionics at all. if (IS_TELEPATHY_BLOCKED(filteree, 0)) mobs_to_message.Remove(filteree) continue if ("Silicons") for(var/mob/filteree in filtered_list) + // Keep observers in the list, which includes ghosts, aghosts, and storytellers. + if (isghost(filteree)) + continue + // List will include Borgs, Robots, Shipbounds, pAIs, and IPCs. if(issilicon(filteree) || isipc(filteree) || ispAI(filteree)) continue @@ -99,11 +111,14 @@ mobs_to_message.Remove(filteree) if ("Silicons + Implants") for(var/mob/filteree in filtered_list) + // Keep observers in the list, which includes ghosts, aghosts, and storytellers. + if (isghost(filteree)) + continue + // List will include Borgs, Robots, Shipbounds, pAIs, and IPCs. if(issilicon(filteree) || isipc(filteree) || ispAI(filteree)) continue - if (!ishuman(filteree)) // The mob in question can't have a brain at all, filter it early. mobs_to_message.Remove(filteree) @@ -119,6 +134,10 @@ mobs_to_message.Remove(filteree) if ("Hivenet") for(var/mob/filteree in filtered_list) + // Keep observers in the list, which includes ghosts, aghosts, and storytellers. + if (isghost(filteree)) + continue + // Filter anyone who doesn't have the Vaurca language at all. if (!(GLOB.all_languages[LANGUAGE_VAURCA] in filteree.languages)) mobs_to_message.Remove(filteree) diff --git a/code/modules/nano/nanoexternal.dm b/code/modules/nano/nanoexternal.dm index dc15f0dcd54d..23987d4af759 100644 --- a/code/modules/nano/nanoexternal.dm +++ b/code/modules/nano/nanoexternal.dm @@ -37,4 +37,4 @@ return // Used by the Nano UI Manager (/datum/SSnanoui) to track UIs opened by this mob -/mob/var/list/open_uis = list() +/mob/var/list/open_nanouis = list() diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm index 9baa217ba530..c441af104f2c 100644 --- a/code/modules/nano/nanoui.dm +++ b/code/modules/nano/nanoui.dm @@ -519,7 +519,7 @@ nanoui is used to open and update nano browser uis * @return nothing */ /datum/nanoui/process(update = 0) - if (!src_object || !user) + if (QDELETED(src_object) || QDELETED(user)) close() return diff --git a/code/modules/organs/internal/_internal.dm b/code/modules/organs/internal/_internal.dm index 2ef8e5edc48a..6ad50469cc37 100644 --- a/code/modules/organs/internal/_internal.dm +++ b/code/modules/organs/internal/_internal.dm @@ -27,14 +27,15 @@ min_broken_damage = 10 /obj/item/organ/internal/Destroy() - if(owner) + if(owner && owner.internal_organs) owner.internal_organs.Remove(src) owner.internal_organs_by_name[organ_tag] = null owner.internal_organs_by_name -= organ_tag while(null in owner.internal_organs) owner.internal_organs -= null - var/obj/item/organ/external/E = owner.organs_by_name[parent_organ] - if(istype(E)) E.internal_organs -= src + if(parent_organ in owner.organs_by_name) + var/obj/item/organ/external/E = astype(owner.organs_by_name[parent_organ]) + E?.internal_organs -= src return ..() /// Sets the internal organ as belonging to the targeted external organ, and matches the target's species/robotness. Also updates all organ lists belonging to the owner. diff --git a/code/modules/organs/internal/heart.dm b/code/modules/organs/internal/heart.dm index 5cfb60622d84..e2a364f99805 100644 --- a/code/modules/organs/internal/heart.dm +++ b/code/modules/organs/internal/heart.dm @@ -247,7 +247,7 @@ var/list/do_spray = list() for(var/obj/item/organ/external/temp in owner.bad_external_organs) if((temp.status & ORGAN_BLEEDING) && !BP_IS_ROBOTIC(temp)) - for(var/datum/wound/W in temp.wounds) + for(var/datum/wound/W as anything in temp.wounds) if(W.bleeding()) open_wound = TRUE if(temp.applied_pressure) diff --git a/code/modules/organs/internal/species/machine/cooling_unit.dm b/code/modules/organs/internal/species/machine/cooling_unit.dm index 25c33f969cca..b73088fbe5c5 100644 --- a/code/modules/organs/internal/species/machine/cooling_unit.dm +++ b/code/modules/organs/internal/species/machine/cooling_unit.dm @@ -22,8 +22,11 @@ /// The power consumed when we are cooling down. var/base_power_consumption = 8 - /// The passive temperature change. Basically, cooling units counteract an IPC's passive temperature gain. But the IPC's temperature goes to get itself fucked if the cooling unit dies. - /// Remember, can be negative or positive. Depends on what we're trying to stabilize towards. + /** + * The passive temperature change in "Degrees Kelvin Per Second". This is reduced by a variety of conditions. + * Basically, cooling units counteract an IPC's passive temperature gain. But the IPC's temperature goes to get itself fucked if the cooling unit dies. + * Remember, can be negative or positive. Depends on what we're trying to stabilize towards. + */ var/passive_temp_change = 2 /// The temperature that this cooling unit tries to regulate towards. var/thermostat = T20C @@ -41,6 +44,8 @@ var/safety_burnt = FALSE /// If the thermostat is locked and thus cannot be changed. Used for spooky effects, like the high integrity damage in the positronic brain. var/locked_thermostat = FALSE + /// The amount of degrees kelvin (per second) of heat the cooling unit will generate if it is blocked by a space suit. + var/spacesuited_heat_per_second = 5 /obj/item/organ/internal/machine/cooling_unit/Initialize() . = ..() @@ -138,16 +143,14 @@ if(prob(owner.bodytemperature * 0.1)) take_internal_damage(owner.bodytemperature * 0.01) - var/temperature_change = passive_temp_change + var/temperature_change = passive_temp_change * seconds_per_tick if(owner.wear_suit) if(!spaceproof && istype(owner.wear_suit, /obj/item/clothing/suit/space)) //cooling is going to SUCK if you have heat-regulating clothes - if(owner.bodytemperature < species.heat_level_3) - owner.bodytemperature = min(owner.bodytemperature + 5, owner.species.heat_level_2) - temperature_change *= 0.5 + temperature_change *= 0.5 // Check if there is somehow no air, or if we are in an ambient without enough air to properly cool us. - if((!ambient || (ambient && owner.calculate_affecting_pressure(ambient.return_pressure()) < owner.species.warning_low_pressure))) + if((!ambient || (ambient && owner.calculate_affecting_pressure(XGM_PRESSURE(ambient)) < owner.species.warning_low_pressure))) if(!spaceproof) temperature_change *= 0 else diff --git a/code/modules/organs/internal/species/machine/posibrain.dm b/code/modules/organs/internal/species/machine/posibrain.dm index 4b150ab9b663..640b25ba67fe 100644 --- a/code/modules/organs/internal/species/machine/posibrain.dm +++ b/code/modules/organs/internal/species/machine/posibrain.dm @@ -365,14 +365,14 @@ else owner.robot_pain.icon_state = null -/obj/item/organ/internal/machine/posibrain/low_integrity_damage(integrity) +/obj/item/organ/internal/machine/posibrain/low_integrity_damage(integrity, seconds_per_tick) var/damage_probability = get_integrity_damage_probability(integrity) - if(prob(damage_probability)) + if(SPT_PROB(damage_probability, seconds_per_tick)) to_chat(owner, SPAN_MACHINE_WARNING("Neural pathway error located at block 0x[generate_hex()].")) take_internal_damage(2) . = ..() -/obj/item/organ/internal/machine/posibrain/medium_integrity_damage(integrity) +/obj/item/organ/internal/machine/posibrain/medium_integrity_damage(integrity, seconds_per_tick) var/damage_probability = get_integrity_damage_probability(integrity) var/list/static/medium_integrity_damage_messages = list( "Your neural subroutines' alarms are all going off at once.", @@ -381,14 +381,14 @@ "Your software warns you of dangerously low neural coherence.", "Your self-preservation subroutines threaten to kick in. [SPAN_DANGER("WARNING. WARNING.")]" ) - if(prob(damage_probability)) + if(SPT_PROB(damage_probability, seconds_per_tick)) to_chat(owner, SPAN_MACHINE_WARNING(pick(medium_integrity_damage_messages))) take_internal_damage(2) . = ..() -/obj/item/organ/internal/machine/posibrain/high_integrity_damage(integrity) +/obj/item/organ/internal/machine/posibrain/high_integrity_damage(integrity, seconds_per_tick) var/damage_probability = get_integrity_damage_probability(integrity) - if(prob(damage_probability)) + if(SPT_PROB(damage_probability, seconds_per_tick)) var/damage_roll = rand(1, 50) switch(damage_roll) if(1 to 10) diff --git a/code/modules/organs/internal/species/machine/power_core.dm b/code/modules/organs/internal/species/machine/power_core.dm index 2857f3570ee7..7c2bedd8f55f 100644 --- a/code/modules/organs/internal/species/machine/power_core.dm +++ b/code/modules/organs/internal/species/machine/power_core.dm @@ -24,6 +24,10 @@ replace_cell(new cell(src)) . = ..() +/obj/item/organ/internal/machine/power_core/Destroy() + QDEL_NULL(cell) + return ..() + /** * Returns current charge in %. */ diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 47e5894c0c90..e483b1cc2da8 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -248,9 +248,8 @@ cached_markings = null mob_icon = null - for(var/datum/wound/wound in wounds) - qdel(wound) - + if(wounds) + QDEL_NULL_LIST(wounds) QDEL_LIST(children) QDEL_LIST(internal_organs) QDEL_LIST(implants) @@ -605,7 +604,7 @@ return //Heal damage on the individual wounds - for(var/datum/wound/W in wounds) + for(var/datum/wound/W as anything in wounds) if(brute == 0 && burn == 0) break @@ -695,7 +694,7 @@ This function completely restores a damaged organ to perfect condition. if((type == INJURY_TYPE_CUT || type == INJURY_TYPE_BRUISE) && damage >= 5) //we need to make sure that the wound we are going to worsen is compatible with the type of damage... var/list/compatible_wounds = list() - for (var/datum/wound/W in wounds) + for (var/datum/wound/W as anything in wounds) if (W.can_worsen(type, damage)) compatible_wounds += W @@ -730,14 +729,17 @@ This function completely restores a damaged organ to perfect condition. for(var/datum/wound/other in wounds) if(other.can_merge(W)) other.merge_wound(W) - W = null // to signify that the wound was added + W = other break - LAZYADD(wounds, W) - if(bandage_level) - owner.visible_message(SPAN_WARNING("The bandages on [owner.name]'s [name] gets [is_burn_type_damage ? "burnt" : "ripped"] off!"), SPAN_WARNING("The bandages on your [name] gets [is_burn_type_damage ? "burnt" : "ripped"] off!")) - bandage_level = BANDAGE_LEVEL_NONE - owner.update_bandages() + if(!QDELETED(W)) + if(!LAZYISIN(wounds, W)) + LAZYADD(wounds, W) + + if(bandage_level) + owner.visible_message(SPAN_WARNING("The bandages on [owner.name]'s [name] gets [is_burn_type_damage ? "burnt" : "ripped"] off!"), SPAN_WARNING("The bandages on your [name] gets [is_burn_type_damage ? "burnt" : "ripped"] off!")) + bandage_level = BANDAGE_LEVEL_NONE + owner.update_bandages() return W /**************************************************** @@ -888,24 +890,21 @@ Note that amputating the affected organ does in fact remove the infection from t var/antibiotics = 0 if(CE_ANTIBIOTIC in owner.chem_effects) antibiotics = owner.chem_effects[CE_ANTIBIOTIC] - for(var/datum/wound/W in wounds) + var/increased_own_germs = FALSE + for(var/datum/wound/W as anything in wounds) //Open wounds can become infected if (owner.germ_level > W.germ_level && W.infection_check()) W.germ_level++ - - if(antibiotics < 5) - for(var/datum/wound/W in wounds) - //Infected wounds raise the organ's germ level - if (W.germ_level > germ_level && W.infection_check()) + if(!increased_own_germs && antibiotics < 5 && W.germ_level > germ_level) germ_level++ - break //limit increase to a maximum of one per second + increased_own_germs = TRUE // limit increase to 1/tick /obj/item/organ/external/proc/get_infect_target(var/list/infect_candidates = list()) var/obj/item/organ/temp_target shuffle(infect_candidates) //Slightly randomizes since if all germ levels are zero, it'll always be the first pick of the list //figure out which organs we can spread germs to - for (var/obj/item/organ/I in infect_candidates) + for (var/obj/item/organ/I as anything in infect_candidates) if(I.germ_level < min(germ_level, INFECTION_LEVEL_TWO)) //Only choose organs that have less germs than us AND are below level two //The below will always be the organ with the highest germ level. It picks a temp_target first then cycles through to find which, if any, has more germs. if(!temp_target || I.germ_level > temp_target.germ_level) @@ -977,11 +976,12 @@ Note that amputating the affected organ does in fact remove the infection from t //Updating wounds. Handles wound natural I had some free spachealing, internal bleedings and infections /obj/item/organ/external/proc/update_wounds() + if(status & (ORGAN_ROBOT|ORGAN_ADV_ROBOT|ORGAN_PLANT)) + return //Robotic limbs don't heal or get worse. Diona limbs heal using their own mechanic - if((status & ORGAN_ROBOT) || (status & ORGAN_ADV_ROBOT) || (status & ORGAN_PLANT)) //Robotic limbs don't heal or get worse. Diona limbs heal using their own mechanic - return var/updatehud - for(var/datum/wound/W in wounds) + var/num_total_wounds = LAZYLEN(wounds) + for(var/datum/wound/W as anything in wounds) // wounds can disappear after 10 minutes at the earliest if(W.damage <= 0 && W.created + (10 MINUTES) <= world.time) qdel(W) @@ -995,22 +995,20 @@ Note that amputating the affected organ does in fact remove the infection from t var/heal_amt = 0 // if damage >= 50 AFTER treatment then it's probably too severe to heal within the timeframe of a round. - if (W.can_autoheal() && W.wound_damage() && brute_ratio < 50 && burn_ratio < 50) + if (updatehud && brute_ratio < 50 && burn_ratio < 50 && W.can_autoheal()) heal_amt += 0.5 //we only update wounds once in [wound_update_accuracy] ticks so have to emulate realtime - heal_amt = heal_amt * wound_update_accuracy + heal_amt *= wound_update_accuracy //configurable regen speed woo, no-regen hardcore or instaheal hugbox, choose your destiny - heal_amt = heal_amt * GLOB.config.organ_regeneration_multiplier + heal_amt *= GLOB.config.organ_regeneration_multiplier // amount of healing is spread over all the wounds - heal_amt = heal_amt / (LAZYLEN(wounds) + 1) + heal_amt /= ((number_wounds / num_total_wounds) + 1) // making it look prettier on scanners - heal_amt = round(heal_amt,0.1) - var/dam_type = DAMAGE_BRUTE - if (W.damage_type == INJURY_TYPE_BURN) - dam_type = DAMAGE_BURN + heal_amt = round(heal_amt, 0.1) + var/dam_type = W.damage_type == INJURY_TYPE_BURN ? DAMAGE_BURN : DAMAGE_BRUTE - if(owner.can_autoheal(dam_type) && (heal_amt > 0)) + if((heal_amt > 0) && owner.can_autoheal(dam_type)) W.heal_damage(heal_amt) // Salving also helps against infection @@ -1037,12 +1035,11 @@ Note that amputating the affected organ does in fact remove the infection from t status &= ~ORGAN_BLEEDING var/clamped = 0 - var/mob/living/carbon/human/H - if(istype(owner,/mob/living/carbon/human)) - H = owner + var/mob/living/carbon/human/H = astype(owner) + var/can_bleed = !BP_IS_ROBOTIC(src) && (H && !(H.species.flags & NO_BLOOD)) //update damage counts - for(var/datum/wound/W in wounds) + for(var/datum/wound/W as anything in wounds) if(W.damage <= 0) qdel(W) @@ -1055,7 +1052,7 @@ Note that amputating the affected organ does in fact remove the infection from t if(W.damage_type == INJURY_TYPE_CUT) cut_dam += W.damage - if(!(status & ORGAN_ROBOT) && W.bleeding() && (H && !(H.species.flags & NO_BLOOD))) + if(can_bleed && W.bleeding()) W.handle_bleeding(H, src) clamped |= W.clamped @@ -1063,18 +1060,18 @@ Note that amputating the affected organ does in fact remove the infection from t number_wounds += W.amount //things tend to bleed if they are CUT OPEN - if (open && !clamped && (H && !(H.species.flags & NO_BLOOD) && !(status & ORGAN_ROBOT))) + if (open && !clamped && can_bleed) status |= ORGAN_BLEEDING - if (istype(tendon)) + if (tendon) tendon.update_damage(cut_dam - min_broken_damage) update_damage_ratios() /obj/item/organ/external/proc/update_damage_ratios() var/limb_loss_threshold = max_damage * 2 - brute_ratio = Percent(brute_dam, limb_loss_threshold) - burn_ratio = Percent(burn_dam, limb_loss_threshold) + brute_ratio = AS_PCT(brute_dam, limb_loss_threshold) + burn_ratio = AS_PCT(burn_dam, limb_loss_threshold) // new damage icon system // returns just the brute/burn damage code @@ -1231,21 +1228,21 @@ Note that amputating the affected organ does in fact remove the infection from t // checks if all wounds on the organ are bandaged /obj/item/organ/external/proc/is_bandaged() - for(var/datum/wound/W in wounds) + for(var/datum/wound/W as anything in wounds) if(!W.bandaged) return 0 return 1 // checks if all wounds on the organ are salved /obj/item/organ/external/proc/is_salved() - for(var/datum/wound/W in wounds) + for(var/datum/wound/W as anything in wounds) if(!W.salved) return 0 return 1 // checks if all wounds on the organ are disinfected /obj/item/organ/external/proc/is_disinfected() - for(var/datum/wound/W in wounds) + for(var/datum/wound/W as anything in wounds) if(!W.disinfected) return 0 return 1 @@ -1253,21 +1250,21 @@ Note that amputating the affected organ does in fact remove the infection from t /obj/item/organ/external/proc/bandage() var/rval = 0 status &= ~ORGAN_BLEEDING - for(var/datum/wound/W in wounds) + for(var/datum/wound/W as anything in wounds) rval |= !W.bandaged W.bandage() return rval /obj/item/organ/external/proc/salve() var/rval = 0 - for(var/datum/wound/W in wounds) + for(var/datum/wound/W as anything in wounds) rval |= !W.salved W.salve() return rval /obj/item/organ/external/proc/disinfect() var/rval = 0 - for(var/datum/wound/W in wounds) + for(var/datum/wound/W as anything in wounds) rval |= !W.disinfected W.disinfect() W.germ_level = 0 @@ -1276,7 +1273,7 @@ Note that amputating the affected organ does in fact remove the infection from t /obj/item/organ/external/proc/clamp_organ() var/rval = 0 src.status &= ~ORGAN_BLEEDING - for(var/datum/wound/W in wounds) + for(var/datum/wound/W as anything in wounds) rval |= !W.clamped W.clamped = 1 return rval @@ -1396,7 +1393,7 @@ Note that amputating the affected organ does in fact remove the infection from t return max(brute_dam + burn_dam - perma_injury, perma_injury) //could use max_damage? /obj/item/organ/external/proc/has_infected_wound() - for(var/datum/wound/W in wounds) + for(var/datum/wound/W as anything in wounds) if(W.germ_level > INFECTION_LEVEL_ONE) return 1 return 0 @@ -1428,6 +1425,8 @@ Note that amputating the affected organ does in fact remove the infection from t else return FALSE +#define EMBED_BASE_DAMAGE 5 + /obj/item/organ/external/proc/embed(obj/item/W, silent = FALSE, supplied_message, datum/wound/supplied_wound) if(!owner || loc != owner) return @@ -1442,11 +1441,15 @@ Note that amputating the affected organ does in fact remove the infection from t owner.visible_message(SPAN_DANGER("\The [W] sticks in [owner]'s wound!"), SPAN_DANGER("\The [W] sticks in your wound!")) - if(supplied_wound) - for(var/datum/wound/wound in wounds) - if ((wound.damage_type == INJURY_TYPE_CUT || wound.damage_type == INJURY_TYPE_PIERCE) && wound.damage >= W.w_class * 5) + //Did we not get a supplied wound? Start by finding an existing wound that fits. + if(!supplied_wound) + for(var/datum/wound/wound as anything in wounds) + if ((wound.damage_type == INJURY_TYPE_CUT || wound.damage_type == INJURY_TYPE_PIERCE) && wound.damage >= W.w_class * EMBED_BASE_DAMAGE) supplied_wound = wound break + //Nothing still? Make a new wound for this object to embed in. + if(!supplied_wound) + supplied_wound = createwound(INJURY_TYPE_PIERCE, W.w_class * EMBED_BASE_DAMAGE) if(!supplied_wound || (W in supplied_wound.embedded_objects)) // Just in case. return @@ -1461,6 +1464,8 @@ Note that amputating the affected organ does in fact remove the infection from t H.drop_from_inventory(W,owner) W.forceMove(owner) +#undef EMBED_BASE_DAMAGE + /obj/item/organ/external/removed(var/mob/living/user, var/ignore_children = 0) if(!owner) @@ -1570,7 +1575,7 @@ Note that amputating the affected organ does in fact remove the infection from t wound_descriptors["an open incision"] = 1 else if (open) wound_descriptors["an incision"] = 1 - for(var/datum/wound/W in wounds) + for(var/datum/wound/W as anything in wounds) var/this_wound_desc = W.desc if(W.damage_type == DAMAGE_BURN && W.salved) this_wound_desc = "salved [this_wound_desc]" diff --git a/code/modules/organs/subtypes/augment/augments/psi_receiver.dm b/code/modules/organs/subtypes/augment/augments/psi_receiver.dm index ca1be8afd747..0d1972e21fbc 100644 --- a/code/modules/organs/subtypes/augment/augments/psi_receiver.dm +++ b/code/modules/organs/subtypes/augment/augments/psi_receiver.dm @@ -1,11 +1,12 @@ /obj/item/organ/internal/augment/bioaug/psi name = "psionic receiver" desc = "A cybernetic implant that allows for the carrier of a receiver to be sensitive enough to accept and interpret psionic signals " \ - + "Essentially an implanted and carefully encased cultured zona bovinae, these receivers are regularly found within dionae and vaurca who otherwise lack this specialized portion of the brain entirely." \ - + "It is also used by other sophonts who regularly interact with skrell to the point of necessitating it." \ + + "Essentially an implanted and carefully encased cultured zona bovinae, these receivers are regularly found within dionae and vaurca who otherwise lack this specialized portion of the brain entirely. " \ + + "It is also used by other sophonts who regularly interact with skrell to the point of necessitating it. " \ + "Some psionically weak skrell will also implant themselves with a receiver in the same way a hearing aid is utilized." organ_tag = BP_AUG_PSI parent_organ = BP_HEAD + icon_state = "mind_blanker" species_restricted = list( SPECIES_HUMAN_OFFWORLD, SPECIES_HUMAN, diff --git a/code/modules/organs/subtypes/standard.dm b/code/modules/organs/subtypes/standard.dm index 242123f7532c..8802cd657382 100644 --- a/code/modules/organs/subtypes/standard.dm +++ b/code/modules/organs/subtypes/standard.dm @@ -194,12 +194,11 @@ /obj/item/organ/external/hand/is_malfunctioning() . = ..() - if(!.) - if(owner.is_mechanical()) - var/actuator_type = limb_name == BP_L_HAND ? BP_ACTUATORS_LEFT : BP_ACTUATORS_RIGHT - var/obj/item/organ/internal/machine/actuators/actuator = owner.internal_organs_by_name[actuator_type] - if(!actuator || (actuator.status & ORGAN_DEAD)) - return TRUE + if(!. && owner?.is_mechanical()) + var/actuator_type = limb_name == BP_L_HAND ? BP_ACTUATORS_LEFT : BP_ACTUATORS_RIGHT + var/obj/item/organ/internal/machine/actuators/actuator = owner.internal_organs_by_name[actuator_type] + if(!actuator || (actuator.status & ORGAN_DEAD)) + return TRUE /obj/item/organ/external/hand/take_damage(brute, burn, damage_flags, used_weapon, list/forbidden_limbs, silent) . = ..() diff --git a/code/modules/organs/subtypes/vaurca.dm b/code/modules/organs/subtypes/vaurca.dm index b4a5b2f24ad8..e3f381242306 100644 --- a/code/modules/organs/subtypes/vaurca.dm +++ b/code/modules/organs/subtypes/vaurca.dm @@ -375,7 +375,7 @@ if ((istype(attacking_item, /obj/item/analyzer)) && get_dist(user, src) <= 1) user.visible_message(SPAN_WARNING("[user] has used [attacking_item] on [icon2html(icon, viewers(get_turf(user)))] [src].")) - var/pressure = air_contents.return_pressure() + var/pressure = XGM_PRESSURE(air_contents) manipulated_by = user.real_name //This person is aware of the contents of the tank. var/total_moles = air_contents.total_moles @@ -409,7 +409,7 @@ // this is the data which will be sent to the ui var/data[0] - data["tankPressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0) + data["tankPressure"] = round(SAFE_XGM_PRESSURE(air_contents)) data["releasePressure"] = round(distribute_pressure ? distribute_pressure : 0) data["defaultReleasePressure"] = round(TANK_DEFAULT_RELEASE_PRESSURE) data["maxReleasePressure"] = round(TANK_MAX_RELEASE_PRESSURE) @@ -513,7 +513,7 @@ if(!air_contents) return null - var/tank_pressure = air_contents.return_pressure() + var/tank_pressure = XGM_PRESSURE(air_contents) if((tank_pressure < distribute_pressure) && prob(5)) to_chat(owner, SPAN_WARNING("There is a buzzing in your [parent_organ].")) @@ -534,7 +534,7 @@ if(!air_contents) return 0 - var/pressure = air_contents.return_pressure() + var/pressure = XGM_PRESSURE(air_contents) if(pressure > TANK_FRAGMENT_PRESSURE) if(!istype(src.loc,/obj/item/transfer_valve)) message_admins("Explosive tank rupture! last key to touch the tank was [src.fingerprintslast].") @@ -545,7 +545,7 @@ air_contents.react() air_contents.react() - pressure = air_contents.return_pressure() + pressure = XGM_PRESSURE(air_contents) var/range = (pressure-TANK_FRAGMENT_PRESSURE)/TANK_FRAGMENT_SCALE explosion( diff --git a/code/modules/organs/wounds/wound.dm b/code/modules/organs/wounds/wound.dm index 879d05e4e74d..7ac788c95b3c 100644 --- a/code/modules/organs/wounds/wound.dm +++ b/code/modules/organs/wounds/wound.dm @@ -104,16 +104,14 @@ if(LAZYLEN(embedded_objects)) return FALSE - return (wound_damage() <= autoheal_cutoff) ? TRUE : is_treated() + return ((src.damage / src.amount) <= autoheal_cutoff) ? TRUE : is_treated() /// Checks whether the wound has been appropriately treated /datum/wound/proc/is_treated() - if(!LAZYLEN(embedded_objects)) - switch(damage_type) - if(INJURY_TYPE_BRUISE, INJURY_TYPE_CUT, INJURY_TYPE_PIERCE) - return bandaged - if(INJURY_TYPE_BURN) - return salved + if(LAZYLEN(embedded_objects)) + return FALSE + + return damage_type == INJURY_TYPE_BURN ? salved : bandaged /// Checks whether other other can be merged into src. /datum/wound/proc/can_merge(datum/wound/other) @@ -144,7 +142,7 @@ /datum/wound/proc/infection_check() if (damage < 10) //small cuts, tiny bruises, and moderate burns shouldn't be infectable. return FALSE - if (is_treated() && damage < 25) //anything less than a flesh wound (or equivalent) isn't infectable if treated properly + if (damage < 25 && is_treated()) //anything less than a flesh wound (or equivalent) isn't infectable if treated properly return FALSE if (disinfected) germ_level = 0 //reset this, just in case @@ -186,7 +184,7 @@ amount -= healed_damage src.damage -= healed_damage - while(src.wound_damage() < damage_list[current_stage] && current_stage < length(src.desc_list)) + while((src.damage / src.amount) < damage_list[current_stage] && current_stage < length(src.desc_list)) current_stage++ desc = desc_list[current_stage] src.min_damage = damage_list[current_stage] @@ -226,14 +224,14 @@ return TRUE /datum/wound/proc/bleeding() - for(var/obj/item/thing in embedded_objects) + for(var/obj/item/thing as anything in embedded_objects) if(thing.w_class > WEIGHT_CLASS_SMALL) return FALSE if (bandaged||clamped) return FALSE - return ((bleed_timer > 0 || wound_damage() > bleed_threshold) && current_stage <= max_bleeding_stage) + return ((bleed_timer > 0 || (src.damage / src.amount) > bleed_threshold) && current_stage <= max_bleeding_stage) /// Called in organ_external.dm update_damages, this will update the limb's status to bleeding, and lowers the bleed_timer if applicable /datum/wound/proc/handle_bleeding(var/mob/victim, var/obj/item/organ/external/limb) diff --git a/code/modules/overmap/exoplanets/decor/turfs/water.dm b/code/modules/overmap/exoplanets/decor/turfs/water.dm index b4bc5a5f9a20..e2cff88ff212 100644 --- a/code/modules/overmap/exoplanets/decor/turfs/water.dm +++ b/code/modules/overmap/exoplanets/decor/turfs/water.dm @@ -165,7 +165,7 @@ var/obj/item/organ/external/E = A if(BP_IS_ROBOTIC(E)) continue - for(var/datum/wound/W in E.wounds) + for(var/datum/wound/W as anything in E.wounds) if(W.germ_level < INFECTION_LEVEL_ONE) W.germ_level = INFECTION_LEVEL_ONE W.germ_level += rand(10, 50) diff --git a/code/modules/overmap/exoplanets/exoplanet.dm b/code/modules/overmap/exoplanets/exoplanet.dm index 5adcd1b527cb..4c43b1a824db 100644 --- a/code/modules/overmap/exoplanets/exoplanet.dm +++ b/code/modules/overmap/exoplanets/exoplanet.dm @@ -328,8 +328,8 @@ /obj/effect/overmap/visitable/sector/exoplanet/proc/adapt_seed(var/datum/seed/S) SET_SEED_TRAIT_BOUNDED(S, TRAIT_IDEAL_HEAT, atmosphere.temperature + rand(-5,5), 800, 70, null) SET_SEED_TRAIT_BOUNDED(S, TRAIT_HEAT_TOLERANCE, GET_SEED_TRAIT(S, TRAIT_HEAT_TOLERANCE) + rand(-5,5), 800, 70, null) - SET_SEED_TRAIT_BOUNDED(S, TRAIT_LOWKPA_TOLERANCE, atmosphere.return_pressure() + rand(-5,-50), 80, 0, null) - SET_SEED_TRAIT_BOUNDED(S, TRAIT_HIGHKPA_TOLERANCE, atmosphere.return_pressure() + rand(5,50), 500, 110, null) + SET_SEED_TRAIT_BOUNDED(S, TRAIT_LOWKPA_TOLERANCE, XGM_PRESSURE(atmosphere) + rand(-5,-50), 80, 0, null) + SET_SEED_TRAIT_BOUNDED(S, TRAIT_HIGHKPA_TOLERANCE, XGM_PRESSURE(atmosphere) + rand(5,50), 500, 110, null) SET_SEED_TRAIT(S, TRAIT_SPREAD, 0) if(S.exude_gasses) S.exude_gasses -= badgas @@ -508,7 +508,7 @@ gases += gas_data.name[g] extra_data += "Atmosphere composition: [english_list(gases)]" var/inaccuracy = rand(8,12)/10 - extra_data += "Atmosphere pressure: [atmosphere.return_pressure()*inaccuracy] kPa, temperature: [atmosphere.temperature*inaccuracy] K" + extra_data += "Atmosphere pressure: [XGM_PRESSURE(atmosphere)*inaccuracy] kPa, temperature: [atmosphere.temperature*inaccuracy] K" if(seeds.len) extra_data += "
Unrecognized xenoflora detected." diff --git a/code/modules/overmap/exoplanets/exoplanet_skybox.dm b/code/modules/overmap/exoplanets/exoplanet_skybox.dm index 67e9d35fe1e9..0e1318e429dd 100644 --- a/code/modules/overmap/exoplanets/exoplanet_skybox.dm +++ b/code/modules/overmap/exoplanets/exoplanet_skybox.dm @@ -21,7 +21,7 @@ water.SetTransform(rotation = rand(0, 360)) skybox_image.overlays += water - if (atmosphere && atmosphere.return_pressure() > SOUND_MINIMUM_PRESSURE) + if (SAFE_XGM_PRESSURE(atmosphere) > SOUND_MINIMUM_PRESSURE) var/atmo_color = get_atmosphere_color() if (!atmo_color) diff --git a/code/modules/overmap/ship_weaponry/_targeting_console.dm b/code/modules/overmap/ship_weaponry/_targeting_console.dm index 9d17f37e7d81..428c9964beb1 100644 --- a/code/modules/overmap/ship_weaponry/_targeting_console.dm +++ b/code/modules/overmap/ship_weaponry/_targeting_console.dm @@ -16,7 +16,7 @@ /obj/machinery/computer/ship/targeting/terminal name = "targeting systems terminal" desc = "A targeting systems terminal using Zavodskoi software." - icon = 'icons/obj/machinery/modular_terminal.dmi' + icon = 'icons/obj/modular_computers/modular_terminal.dmi' icon_screen = "hostile" icon_keyboard = "red_key" icon_keyboard_emis = "red_key_mask" diff --git a/code/modules/overmap/ships/computers/engine_control.dm b/code/modules/overmap/ships/computers/engine_control.dm index 4961ecbf1db8..ee74eded8c1e 100644 --- a/code/modules/overmap/ships/computers/engine_control.dm +++ b/code/modules/overmap/ships/computers/engine_control.dm @@ -19,7 +19,7 @@ /obj/machinery/computer/ship/engines/terminal name = "engine control terminal" - icon = 'icons/obj/machinery/modular_terminal.dmi' + icon = 'icons/obj/modular_computers/modular_terminal.dmi' icon_screen = "engines" icon_keyboard = "tech_key" icon_keyboard_emis = "tech_key_mask" diff --git a/code/modules/overmap/ships/computers/helm.dm b/code/modules/overmap/ships/computers/helm.dm index bef793e91416..c048c8b95fb2 100644 --- a/code/modules/overmap/ships/computers/helm.dm +++ b/code/modules/overmap/ships/computers/helm.dm @@ -27,7 +27,7 @@ /obj/machinery/computer/ship/helm/terminal name = "helm control terminal" - icon = 'icons/obj/machinery/modular_terminal.dmi' + icon = 'icons/obj/modular_computers/modular_terminal.dmi' icon_screen = "helm" icon_keyboard = "security_key" icon_keyboard_emis = "security_key_mask" @@ -329,7 +329,7 @@ /obj/machinery/computer/ship/navigation/terminal name = "navigation terminal" - icon = 'icons/obj/machinery/modular_terminal.dmi' + icon = 'icons/obj/modular_computers/modular_terminal.dmi' icon_screen = "nav" icon_keyboard = "generic_key" icon_keyboard_emis = "generic_key_mask" diff --git a/code/modules/overmap/ships/computers/sensors.dm b/code/modules/overmap/ships/computers/sensors.dm index 306dc0dd73c7..d2c9801bbc10 100644 --- a/code/modules/overmap/ships/computers/sensors.dm +++ b/code/modules/overmap/ships/computers/sensors.dm @@ -38,7 +38,7 @@ /obj/machinery/computer/ship/sensors/terminal name = "sensors terminal" - icon = 'icons/obj/machinery/modular_terminal.dmi' + icon = 'icons/obj/modular_computers/modular_terminal.dmi' icon_screen = "teleport" icon_keyboard = "teleport_key" icon_keyboard_emis = "teleport_key_mask" @@ -462,7 +462,7 @@ var/turf/T=get_turf(src) if(istype(T)) var/datum/gas_mixture/environment = T.return_air() - if(environment && environment.return_pressure() > MINIMUM_PRESSURE_DIFFERENCE_TO_SUSPEND) + if(SAFE_XGM_PRESSURE(environment) > MINIMUM_PRESSURE_DIFFERENCE_TO_SUSPEND) return 0 return 1 diff --git a/code/modules/overmap/ships/computers/ship.dm b/code/modules/overmap/ships/computers/ship.dm index 7dd904f37d7f..c14847be733f 100644 --- a/code/modules/overmap/ships/computers/ship.dm +++ b/code/modules/overmap/ships/computers/ship.dm @@ -65,6 +65,13 @@ somewhere on that shuttle. Subtypes of these can be then used to perform ship ov return ..() /obj/machinery/computer/ship/attack_hand(mob/user) + // Snowflake case for checking player characters for a Pilot Spacecraft Skill. + // Only player characters will have the component. Which will both always be present on them, and will only enable its own return logic if it exists. + // NPCs, Ghostroles, and Offship Antags that don't generate skills are unaffected by this check by intentional design so that we don't have to account for them. + if (user.GetComponent(PILOT_SPACECRAFT_SKILL_COMPONENT)?.skill_level == SKILL_LEVEL_UNFAMILIAR) + to_chat(user, SPAN_WARNING("There's just so many buttons... You have no idea where to even begin.")) + return + if(use_check_and_message(user)) return if(!emagged && !allowed(user)) diff --git a/code/modules/overmap/ships/computers/shuttle.dm b/code/modules/overmap/ships/computers/shuttle.dm index d8133db34b1e..bcbb71263607 100644 --- a/code/modules/overmap/ships/computers/shuttle.dm +++ b/code/modules/overmap/ships/computers/shuttle.dm @@ -65,7 +65,7 @@ /obj/machinery/computer/shuttle_control/explore/terminal name = "shuttle control terminal" - icon = 'icons/obj/machinery/modular_terminal.dmi' + icon = 'icons/obj/modular_computers/modular_terminal.dmi' icon_screen = "helm" icon_keyboard = "tech_key" icon_keyboard_emis = "tech_key_mask" diff --git a/code/modules/overmap/ships/engines/gas_thruster.dm b/code/modules/overmap/ships/engines/gas_thruster.dm index 4d10e1eed52b..1ec2c4e43dd8 100644 --- a/code/modules/overmap/ships/engines/gas_thruster.dm +++ b/code/modules/overmap/ships/engines/gas_thruster.dm @@ -170,7 +170,7 @@ .+= "Propellant total mass: [round(air_contents.get_mass(),0.01)] kg." .+= "Propellant used per burn: [round(air_contents.get_mass() * volume_per_burn * thrust_limit / air_contents.volume,0.01)] kg." - .+= "Propellant pressure: [round(air_contents.return_pressure()/1000,0.1)] MPa." + .+= "Propellant pressure: [round(XGM_PRESSURE(air_contents)/1000,0.1)] MPa." . = jointext(.,"
") /obj/machinery/atmospherics/unary/engine/power_change() @@ -241,10 +241,12 @@ T = get_step(T, exhaust_dir) if(T) T.assume_air(removed) - new/obj/effect/engine_exhaust(T, dir, air_contents.check_combustibility() && air_contents.temperature >= PHORON_MINIMUM_BURN_TEMPERATURE) + var/is_cmb = 0 + CHECK_COMBUSTIBLE(is_cmb, air_contents) + new/obj/effect/engine_exhaust(T, dir, is_cmb && air_contents.temperature >= PHORON_MINIMUM_BURN_TEMPERATURE) /obj/machinery/atmospherics/unary/engine/proc/calculate_thrust(datum/gas_mixture/propellant, used_part = 1) - return round(sqrt(propellant.get_mass() * used_part * sqrt(air_contents.return_pressure()/200)),0.1) + return round(sqrt(propellant.get_mass() * used_part * sqrt(XGM_PRESSURE(air_contents)/200)),0.1) //Exhaust effect /obj/effect/engine_exhaust diff --git a/code/modules/overmap/ships/ship.dm b/code/modules/overmap/ships/ship.dm index d7f47ac56049..dd7ab6b8373c 100644 --- a/code/modules/overmap/ships/ship.dm +++ b/code/modules/overmap/ships/ship.dm @@ -188,49 +188,50 @@ /obj/effect/overmap/visitable/ship/proc/get_brake_path() if(!get_acceleration()) return INFINITY - if(is_still()) - return 0 - if(!burn_delay) - return 0 - if(!get_speed()) + + if(is_still() || !burn_delay || !get_speed()) return 0 - var/num_burns = get_speed()/get_acceleration() + 2 //some padding in case acceleration drops form fuel usage - var/burns_per_grid = 1/ (burn_delay * get_speed()) - return round(num_burns/burns_per_grid) + var/num_burns = get_speed() / get_acceleration() + 2 // some padding in case acceleration drops form fuel usage + var/burns_per_grid = 1 / (burn_delay * get_speed()) + return round(num_burns / burns_per_grid) /obj/effect/overmap/visitable/ship/proc/decelerate() - if(can_burn()) - // Pythagorean theorem gives us the magnitude of the ship's velocity, which is always an absolute value. - // This is also the mathematical definition for Vector.size - var/magnitude_velocity = ((speed[1] ** 2) + (speed[2] **2)) ** (1/2) + if((!speed[1] && !speed[2]) || !can_burn()) + return - // Get the magnitude of our desired change in velocity - var/alpha = min(get_burn_acceleration(), magnitude_velocity) + // Pythagorean theorem gives us the magnitude of the ship's velocity, which is always an absolute value. + // This is also the mathematical definition for Vector.size + var/magnitude_velocity = ((speed[1] ** 2) + (speed[2] **2)) ** (1/2) - // First we "Normalize" the current velocity to get the direction without a distance - // Then we take the exact negative of this direction to get its true opposite - // And finally multiply by the magnitude of our desired delta_v to get the true delta_v - var/delta_x = -(speed[1] / magnitude_velocity) * alpha - var/delta_y = -(speed[2] / magnitude_velocity) * alpha + // Get the magnitude of our desired change in velocity + var/alpha = min(get_burn_acceleration(), magnitude_velocity) - adjust_speed(delta_x, delta_y) - last_burn = world.time + // First we "Normalize" the current velocity to get the direction without a distance + // Then we take the exact negative of this direction to get its true opposite + // And finally multiply by the magnitude of our desired delta_v to get the true delta_v + var/delta_x = -(speed[1] / magnitude_velocity) * alpha + var/delta_y = -(speed[2] / magnitude_velocity) * alpha + + adjust_speed(delta_x, delta_y) + last_burn = world.time /obj/effect/overmap/visitable/ship/proc/accelerate(direction, accel_limit) - if(can_burn()) - last_burn = world.time + if(!can_burn()) + return + + last_burn = world.time - // Get our "Alpha" value as the ship's desired acceleration (change in Velocity) - var/acceleration = min(get_burn_acceleration(), accel_limit) + // Get our "Alpha" value as the ship's desired acceleration (change in Velocity) + var/acceleration = min(get_burn_acceleration(), accel_limit) - // Convert from cardinal directions to an angle (in degrees) - // !This is absolutely terrible and should at some point be swapped to Radians - // !But for now it's "Okay" until overmap ships are updated to work on time differentials properly. - var/theta = dir2degree(direction) + // Convert from cardinal directions to an angle (in degrees) + // !This is absolutely terrible and should at some point be swapped to Radians + // !But for now it's "Okay" until overmap ships are updated to work on time differentials properly. + var/theta = dir2degree(direction) - // This comes from the actual definition of a Vector2d, , where theta is an Angle, and A is a constant multiplier that traditionally represents distance. - // In this case A is our DeltaVelocity, or Acceleration. - adjust_speed(acceleration * cos(theta), acceleration * sin(theta)) + // This comes from the actual definition of a Vector2d, , where theta is an Angle, and A is a constant multiplier that traditionally represents distance. + // In this case A is our DeltaVelocity, or Acceleration. + adjust_speed(acceleration * cos(theta), acceleration * sin(theta)) /obj/effect/overmap/visitable/ship/process() ..() diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm index 4c9abcc0f36b..f386cd11de39 100644 --- a/code/modules/paperwork/filingcabinet.dm +++ b/code/modules/paperwork/filingcabinet.dm @@ -167,9 +167,6 @@ Mental Status: [R.mental_status]
Medical Data

Blood Type: [R.medical.blood_type]
DNA: [R.medical.blood_dna]

-Disabilities: [R.medical.disabilities]

-Allergies: [R.medical.allergies]
-Current Diseases: [R.medical.diseases] (per disease info placed in log/comment section)

Important Notes:
[replacetext(R.medical.notes, "\n", "
")]

Comments/Log

diff --git a/code/modules/paperwork/folders.dm b/code/modules/paperwork/folders.dm index a4f4f1d56149..bfabe4a99599 100644 --- a/code/modules/paperwork/folders.dm +++ b/code/modules/paperwork/folders.dm @@ -76,15 +76,13 @@ if(href_list["remove"]) var/obj/item/P = locate(href_list["remove"]) if(P && (P.loc == src) && istype(P)) - P.forceMove(usr.loc) - usr.put_in_hands(P) - handle_post_remove() + handle_remove(P, astype(usr, /mob)) else if(href_list["write"]) var/obj/item/paper/paper = locate(href_list["write"]) if(!istype(paper) || paper.loc != src) return var/obj/item/pen = usr.get_inactive_hand() - if(!pen || !pen.tool_behaviour == TOOL_PEN) + if(!pen || pen.tool_behaviour != TOOL_PEN) pen = usr.get_active_hand() if(pen?.tool_behaviour == TOOL_PEN) paper.attackby(pen, usr) @@ -127,6 +125,10 @@ return TRUE return FALSE +/obj/item/folder/proc/handle_remove(obj/item/P, mob/user) + user?.put_in_hands(P) + handle_post_remove() + /obj/item/folder/proc/handle_post_remove() return @@ -149,6 +151,13 @@ return TRUE return FALSE +/obj/item/folder/embedded/handle_remove(obj/item/paper/P, mob/user) + . = ..() + if(istype(P, /obj/item/paper/notepad)) + P.ripped = TRUE + playsound(src.loc, 'sound/items/poster_ripped.ogg', 25, 1) + P.update_icon() + /obj/item/folder/embedded/handle_post_remove() if(!length(contents)) qdel(src) diff --git a/code/modules/paperwork/handlabeler.dm b/code/modules/paperwork/handlabeler.dm index f9d6c5ccab43..e1d8d49744e2 100644 --- a/code/modules/paperwork/handlabeler.dm +++ b/code/modules/paperwork/handlabeler.dm @@ -31,6 +31,7 @@ icon = 'icons/obj/bureaucracy.dmi' icon_state = "labeler0" item_state = "labeler0" + contained_sprite = TRUE w_class = WEIGHT_CLASS_SMALL var/label = null var/labels_left = 30 diff --git a/code/modules/paperwork/journal.dm b/code/modules/paperwork/journal.dm index 8e8f7d4600a9..8d78112a90df 100644 --- a/code/modules/paperwork/journal.dm +++ b/code/modules/paperwork/journal.dm @@ -165,7 +165,7 @@ . = ..() var/obj/item/folder/embedded/E = generate_index("Notes") for(var/i = 1 to 5) - new /obj/item/paper(E) + new /obj/item/paper/notepad(E) update_icon() /obj/item/journal/notepad/scc @@ -181,7 +181,7 @@ . = ..() var/obj/item/folder/embedded/E = generate_index("Notes") for(var/i = 1 to 5) - new /obj/item/paper(E) + new /obj/item/paper/notepad(E) update_icon() /obj/item/journal/notepad/filled/security diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 51906ee20265..444f3075db21 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -42,6 +42,8 @@ var/rigged = 0 var/last_honk = 0 + /// Is the paper ripped from a book? + var/ripped = FALSE /// The name of the paper before it was folded into a plane. var/old_name @@ -49,6 +51,8 @@ var/can_fold = TRUE /// Is it made of paper and/or burnable material? var/paper_like = TRUE + // Is the paper crumpled up? + var/crumpled = FALSE var/const/deffont = "Verdana" var/const/signfont = "Times New Roman" @@ -117,10 +121,15 @@ /obj/item/paper/update_icon() if(!can_change_icon_state) return - else if (info && length(trim(info))) + if (crumpled) + icon_state = "scrap" + return + if (info && length(trim(info))) icon_state = "[base_state]_words" else icon_state = "[base_state]" + if(ripped) + icon_state = "[icon_state]_r" /** * Updates the amount of free space in the paper @@ -175,18 +184,22 @@ /obj/item/paper/attack_self(mob/living/user as mob) if(user.a_intent == I_HURT && paper_like) - if(icon_state == "scrap") + if(crumpled) user.show_message(SPAN_WARNING("\The [src] is already crumpled.")) return //crumple dat paper info = stars(info,85) user.visible_message("\The [user] crumples \the [src] into a ball!", "You crumple \the [src] into a ball.") playsound(src, 'sound/items/bureaucracy/papercrumple.ogg', 50, 1) - icon_state = "scrap" + if(istype(src, /obj/item/paper/stickynotes)) + icon_state = "stickynote_scrap" + else + icon_state = "scrap" throw_range = 4 //you can now make epic paper ball hoops into the disposals (kinda dumb that you could only throw crumpled paper 1 tile) -wezzy + crumpled = TRUE return - if (user.a_intent == I_GRAB && icon_state != "scrap" && can_fold) + if (user.a_intent == I_GRAB && !crumpled && can_fold) if (icon_state == "paper_plane") user.show_message(SPAN_ALERT("The paper is already folded into a plane.")) return @@ -200,7 +213,7 @@ ClearOverlays() //Removes stamp icons return - if (user.a_intent == I_DISARM && icon_state != "scrap" && can_fold) + if (user.a_intent == I_DISARM && !crumpled && can_fold) if (icon_state == "paper_swan") user.show_message(SPAN_ALERT("The paper is already folded into a swan.")) return @@ -366,6 +379,8 @@ t = replacetext(t, "\[logo_golden\]", "") t = replacetext(t, "\[logo_pvpolice\]", "") t = replacetext(t, "\[logo_pvpolice_small\]", "") + t = replacetext(t, "\[logo_outereyes\]", "") + t = replacetext(t, "\[logo_outereyes_small\]", "") t = replacetext(t, "\[barcode\]", "") if(istypewriter) @@ -415,6 +430,8 @@ playsound(src.loc, 'sound/items/bureaucracy/paperburn.ogg', 50, 1) if(icon_state == "scrap") flick("scrap_onfire", src) + else if(icon_state == "stickynote_scrap") + flick("stickynote_scrap_onfire", src) else flick("paper_onfire", src) @@ -576,6 +593,8 @@ if(istype(i, /obj/item/pen/typewriter)) playsound(src, ('sound/machines/typewriter.ogg'), 40) else + if(istype(src, /obj/item/paper/stickynotes)) + usr.visible_message(SPAN_NOTICE("\The [usr] jots a note down on \the [src].")) playsound(src, pick('sound/items/bureaucracy/pen1.ogg','sound/items/bureaucracy/pen2.ogg'), 20) update_icon() @@ -603,12 +622,12 @@ /obj/item/paper/attackby(obj/item/attacking_item, mob/user) ..() - if(istype(attacking_item, /obj/item/tape_roll) && !istype(src, /obj/item/paper/business_card)) + if(istype(attacking_item, /obj/item/tape_roll) && (!istype(src, /obj/item/paper/business_card) || !istype(src, /obj/item/paper/stickynotes))) var/obj/item/tape_roll/tape = attacking_item tape.stick(src, user) return - if(istype(attacking_item, /obj/item/paper) || istype(attacking_item, /obj/item/photo)) + if((istype(attacking_item, /obj/item/paper) && !istype(src, /obj/item/paper/stickynotes/pad)) || istype(attacking_item, /obj/item/photo)) if (istype(attacking_item, /obj/item/paper/carbon)) var/obj/item/paper/carbon/C = attacking_item if (!C.iscopy && !C.copied) @@ -649,7 +668,10 @@ src.forceMove(get_turf(h_user)) if(h_user.client) h_user.client.screen -= src h_user.put_in_hands(B) - to_chat(user, SPAN_NOTICE("You clip the [attacking_item.name] to [(src.name == "paper") ? "the paper" : src.name].")) + var/obj/item/paper/stickynotes/sticky = astype(attacking_item) + if(istype(attacking_item, /obj/item/paper)) + to_chat(user, SPAN_NOTICE("You [sticky ? "stick" : "clip"] \the [attacking_item] to \the [src].")) + src.forceMove(B) B.pages.Add(src) @@ -658,7 +680,7 @@ B.update_icon() else if(attacking_item.tool_behaviour == TOOL_PEN) - if(icon_state == "scrap") + if(crumpled) to_chat(user, SPAN_WARNING("The [src] is too crumpled to write on.")) return @@ -722,6 +744,7 @@ /obj/item/paper/crumpled name = "paper scrap" icon_state = "scrap" + crumpled = TRUE /obj/item/paper/crumpled/update_icon() return @@ -779,6 +802,18 @@ . = ..() scan_target = WEAKREF(set_scan_target) +/obj/item/paper/notepad + name = "notepad paper" + desc = "A piece of paper from a notepad." + icon_state = "notepad" + slot_flags = NONE + color = "#DBDBAE" + +/obj/item/paper/notepad/receipt + name = "receipt paper" + desc = "A receipt." + color = null + /*############################################# PERSISTENT #############################################*/ @@ -799,6 +834,133 @@ var/obj/structure/noticeboard/notice_board = object notice_board.add_papers_from_turf() +/* +* Sticky notes +* +* Small pieces of paper that can be applied to walls and objects like stickers, or like taped paper. +*/ + +/obj/item/paper/stickynotes + name = "sticky note" + desc = "A small paper with adhesive on the back. Useful to keep track of things, or annoy your coworkers." + icon = 'icons/obj/bureaucracy.dmi' + icon_state = "stickynote" + item_state = "stickynote" + w_class = WEIGHT_CLASS_TINY + color = COLOR_PALE_YELLOW + free_space = MAX_MESSAGE_LEN //Smaller piece of paper means less space to write. + slot_flags = 0 + item_flags = ITEM_FLAG_NO_BLUDGEON + +/obj/item/paper/stickynotes/update_icon() + if(icon_state == "stickynote_scrap") + return + if(crumpled) + icon_state = "stickynote_scrap" + return + + icon_state = info ? "stickynote_words" : "stickynote" + +/obj/item/paper/stickynotes/persistence_get_content() + var/list/content = ..() + content["color"] = color + content["pixel_x"] = pixel_x + content["pixel_y"] = pixel_y + return content + +/obj/item/paper/stickynotes/persistence_apply_content(content, x, y, z) + src.name = content["title"] + src.info = content["text"] + src.color = content["color"] + src.pixel_x = content["pixel_x"] + src.pixel_y = content["pixel_y"] + src.x = x + src.y = y + src.z = z + +/obj/item/paper/stickynotes/pickup() + SSpersistence.deregister_track(src) + ..() + +/obj/item/paper/stickynotes/afterattack(var/A, mob/user, var/prox, var/params) + if(!in_range(user, A) || istype(A, /obj/machinery) || istype(A, /obj/item/paper) || crumpled) + return + + var/turf/target_turf = get_turf(A) + var/turf/source_turf = get_turf(user) + + var/dir_offset = 0 + if(target_turf != source_turf) + dir_offset = get_dir(source_turf, target_turf) + + if(!params || !prox) + return + + SSpersistence.register_track(src, ckey(user.key)) + user.drop_from_inventory(src,source_turf) + if(params) //Parallels taped paper placement method, and avoids seeing stickynotes through walls + var/list/mouse_control = mouse_safe_xy(params) + if(mouse_control["icon-x"]) + pixel_x = mouse_control["icon-x"] - 16 + if(dir_offset & EAST) + pixel_x += 32 + else if(dir_offset & WEST) + pixel_x -= 32 + if(mouse_control["icon-y"]) + pixel_y = mouse_control["icon-y"] - 16 + if(dir_offset & NORTH) + pixel_y += 32 + else if(dir_offset & SOUTH) + pixel_y -= 32 + +/obj/item/paper/stickynotes/pad + name = "sticky note pad" + desc = "A pad of densely packed sticky notes." + icon_state = "stickypad_full" + item_state = "stickynote" + w_class = WEIGHT_CLASS_SMALL + var/papers = 25 + var/paper_type = /obj/item/paper/stickynotes + +/obj/item/paper/stickynotes/pad/update_icon() + if(papers <= 15) + icon_state = "stickypad_empty" + else if(papers <= 25) + icon_state = "stickypad_used" + else + icon_state = "stickypad_full" + if(info) + icon_state = "[icon_state]_words" + +/obj/item/paper/stickynotes/pad/feedback_hints(mob/user, distance, is_adjacent) + . += ..() + . += "It has [papers] sticky note\s left." + +/obj/item/paper/stickynotes/pad/mechanics_hints() + . += ..() + . += "You can click it on grab intent to pick it up." + +/obj/item/paper/stickynotes/pad/attack_hand(mob/user) + if(user.a_intent == I_GRAB) + return ..() + + var/obj/item/paper/stickynotes/paper = new paper_type(get_turf(src)) + paper.set_content("sticky note", info) + paper.color = color + info = null + user.put_in_hands(paper) + to_chat(user, SPAN_NOTICE("You pull \the [paper] off \the [src].")) + papers-- + if(papers <= 0) + qdel(src) + return + + update_icon() + +/obj/item/paper/stickynotes/pad/random/Initialize() + . = ..() + color = pick(COLOR_YELLOW_GRAY , COLOR_GREEN_GRAY, COLOR_BLUE_GRAY , COLOR_ORANGE, COLOR_PALE_PINK) + /*############################################# FLUFF PAPERS SUBTYPE diff --git a/code/modules/paperwork/paper_bundle.dm b/code/modules/paperwork/paper_bundle.dm index 7da6ab09eaf0..968a11e0942c 100644 --- a/code/modules/paperwork/paper_bundle.dm +++ b/code/modules/paperwork/paper_bundle.dm @@ -36,6 +36,8 @@ /obj/item/paper_bundle/attackby(obj/item/attacking_item, mob/user) ..() + if (istype(attacking_item, /obj/item/paper/stickynotes/pad)) + return if (istype(attacking_item, /obj/item/paper/carbon)) var/obj/item/paper/carbon/C = attacking_item @@ -77,10 +79,9 @@ return /obj/item/paper_bundle/proc/insert_sheet_at(mob/user, var/index, obj/item/sheet) - if(istype(sheet, /obj/item/paper)) - to_chat(user, SPAN_NOTICE("You add [(sheet.name == "paper") ? "the paper" : sheet.name] to [(src.name == "paper bundle") ? "the paper bundle" : src.name].")) - else if(istype(sheet, /obj/item/photo)) - to_chat(user, SPAN_NOTICE("You add [(sheet.name == "photo") ? "the photo" : sheet.name] to [(src.name == "paper bundle") ? "the paper bundle" : src.name].")) + if(!is_type_in_list(sheet, list(/obj/item/paper, /obj/item/photo))) + return + to_chat(user, SPAN_NOTICE("You stick \the [sheet] to \the [src].")) user.drop_from_inventory(sheet,src) diff --git a/code/modules/paperwork/papershredder.dm b/code/modules/paperwork/papershredder.dm index ea0c37d1fd65..b0f1641d0266 100644 --- a/code/modules/paperwork/papershredder.dm +++ b/code/modules/paperwork/papershredder.dm @@ -45,7 +45,7 @@ return if (paper_result > 0) paperamount += paper_result - if(attacking_item.icon_state == "scrap") + if(astype(attacking_item, /obj/item/paper)?.crumpled) flick("papershredder_s_on", src) else if(attacking_item.icon_state == "paper_words") flick("papershredder_w_on", src) diff --git a/code/modules/paperwork/typewriter.dm b/code/modules/paperwork/typewriter.dm index 0c0e60e99a11..496e6b0eeb93 100644 --- a/code/modules/paperwork/typewriter.dm +++ b/code/modules/paperwork/typewriter.dm @@ -94,6 +94,9 @@ if(attacking_item.icon_state == "scrap") to_chat(user, SPAN_ALERT("\The [attacking_item] is too crumpled to feed correctly!")) return + if(istype(attacking_item, /obj/item/paper/stickynotes)) + to_chat(user, SPAN_ALERT("\The [attacking_item] is too small to feed correctly!")) + return else user.drop_item(attacking_item) user.unEquip(attacking_item) diff --git a/code/modules/power/antimatter/control.dm b/code/modules/power/antimatter/control.dm index d3dca02cf2e7..a0e68791ab1e 100644 --- a/code/modules/power/antimatter/control.dm +++ b/code/modules/power/antimatter/control.dm @@ -75,7 +75,7 @@ check_core_stability() - add_avail(stored_power) + ADD_TO_POWERNET(src, stored_power) power_cycle++ if(power_cycle >= power_cycle_delay) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index ba7b2b7863d0..5452f01f9994 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -39,11 +39,23 @@ #define CHARGING_ON 1 #define CHARGING_FULL 2 -//channel settings -#define CHANNEL_OFF 0 -#define CHANNEL_OFF_AUTO 1 -#define CHANNEL_ON 2 -#define CHANNEL_ON_AUTO 3 +// APC channel status: +/// The APCs power channel is off. +#define CHANNEL_OFF 0 +/// The APCs power channel is on. +#define CHANNEL_ON BITFLAG(0) +/// The APCs power channel is being controlled automatically. +#define CHANNEL_AUTO BITFLAG(1) +/// The APCs power channel is automatically on. +#define CHANNEL_AUTO_ON (CHANNEL_ON | CHANNEL_AUTO) + +// APC autoset enums: +/// The APC turns automated and manual power channels off. +#define AUTOSET_FORCE_OFF 0 +/// The APC turns automated power channels off. +#define AUTOSET_OFF 2 +/// The APC turns automated power channels on. +#define AUTOSET_ON 1 //channel types #define CHANNEL_EQUIPMENT 0 @@ -60,6 +72,28 @@ #define AUTOFLAG_ENVIRON_ON 1 #define AUTOFLAG_ENVIRON_LIGHTS_ON 2 #define AUTOFLAG_ALL_ON 3 +/** + * Returns the new status value for an APC channel. + * + * Arguments: + * - val: The current status of the power channel. + * - [APC_CHANNEL_OFF]: The APCs channel has been manually set to off. This channel will not automatically change. + * - [APC_CHANNEL_AUTO_OFF]: The APCs channel is running on automatic and is currently off. Can be automatically set to [APC_CHANNEL_AUTO_ON]. + * - [APC_CHANNEL_ON]: The APCs channel has been manually set to on. This will be automatically changed only if the APC runs completely out of power or is disabled. + * - [APC_CHANNEL_AUTO_ON]: The APCs channel is running on automatic and is currently on. Can be automatically set to [APC_CHANNEL_AUTO_OFF]. + * - on: An enum dictating how to change the channel's status. + * - [AUTOSET_FORCE_OFF]: The APC forces the channel to turn off. This includes manually set channels. + * - [AUTOSET_ON]: The APC allows automatic channels to turn back on. + * - [AUTOSET_OFF]: The APC turns automatic channels off. + */ + +#define autoset(val, on) (((val & CHANNEL_AUTO) || on == AUTOSET_FORCE_OFF) ? ((val & ~CHANNEL_ON) | on == AUTOSET_ON) : val) + +#define APC_DELTA_POWER (((src.lastused_charging * 2) - src.lastused_total) * CELLRATE) +#define APC_GOAL(dp) (dp < 0) ? (cell.charge) : (cell.maxcharge - cell.charge) +#define APC_UPDATE_TIME(dp, goal) (world.time + (dp ? ((goal / abs(dp)) * (world.time - src.last_time)) : 0)) +#define APC_CHARGE_MODE(dp) (dp < 0 ? CHARGE_MODE_DISCHARGE : dp > 0 ? CHARGE_MODE_CHARGE : CHARGE_MODE_STABLE) + // the Area Power Controller (APC), formerly Power Distribution Unit (PDU) // one per area, needs wire conection to power network through a terminal @@ -93,9 +127,9 @@ ABSTRACT_TYPE(/obj/machinery/power/apc) var/shorted = FALSE /// Determines if the light level is set to dimmed or not var/night_mode = FALSE - var/lighting = CHANNEL_ON_AUTO - var/equipment = CHANNEL_ON_AUTO - var/environ = CHANNEL_ON_AUTO + var/lighting = CHANNEL_AUTO_ON + var/equipment = CHANNEL_AUTO_ON + var/environ = CHANNEL_AUTO_ON var/infected = FALSE var/operating = TRUE var/charging = CHARGING_OFF @@ -188,7 +222,7 @@ ABSTRACT_TYPE(/obj/machinery/power/apc) area.power_light = 0 area.power_equip = 0 area.power_environ = 0 - area.power_change() + SEND_SIGNAL(area, COMSIG_AREA_POWER_CHANGE) QDEL_NULL(wires) QDEL_NULL(terminal) if(cell) @@ -442,21 +476,21 @@ ABSTRACT_TYPE(/obj/machinery/power/apc) if (equipment == CHANNEL_OFF) update_overlay |= APC_UPOVERLAY_EQUIPMENT0 - else if(equipment == CHANNEL_OFF_AUTO) + else if(equipment == CHANNEL_AUTO) update_overlay |= APC_UPOVERLAY_EQUIPMENT1 else if(equipment == CHANNEL_ON) update_overlay |= APC_UPOVERLAY_EQUIPMENT2 if(lighting == CHANNEL_OFF) update_overlay |= APC_UPOVERLAY_LIGHTING0 - else if(lighting == CHANNEL_OFF_AUTO) + else if(lighting == CHANNEL_AUTO) update_overlay |= APC_UPOVERLAY_LIGHTING1 else if(lighting == CHANNEL_ON) update_overlay |= APC_UPOVERLAY_LIGHTING2 if(environ == CHANNEL_OFF) update_overlay |= APC_UPOVERLAY_ENVIRON0 - else if(environ == CHANNEL_OFF_AUTO) + else if(environ == CHANNEL_AUTO) update_overlay |= APC_UPOVERLAY_ENVIRON1 else if(environ == CHANNEL_ON) update_overlay |= APC_UPOVERLAY_ENVIRON2 @@ -943,17 +977,25 @@ ABSTRACT_TYPE(/obj/machinery/power/apc) ui.open() /obj/machinery/power/apc/proc/update() + var/old_lt = area.power_light + var/old_eq = area.power_equip + var/old_ev = area.power_environ + + var/any_power = old_lt || old_eq || old_ev + if(operating && !shorted && !failure_timer) - area.power_light = (lighting > 1) - area.power_equip = (equipment > 1) - area.power_environ = (environ > 1) + area.power_light = lighting & CHANNEL_ON + area.power_equip = equipment & CHANNEL_ON + area.power_environ = environ & CHANNEL_ON - else + else if(any_power) area.power_light = FALSE area.power_equip = FALSE area.power_environ = FALSE playsound(src.loc, 'sound/machines/terminal/terminal_off.ogg', 50, FALSE) - area.power_change() + + if(old_lt != area.power_light || old_eq != area.power_equip || old_ev != area.power_environ) + SEND_SIGNAL(area, COMSIG_AREA_POWER_CHANGE) /obj/machinery/power/apc/proc/isWireCut(var/wireIndex) return wires.is_cut(wireIndex) @@ -1087,11 +1129,12 @@ ABSTRACT_TYPE(/obj/machinery/power/apc) var/val = text2num(params["set"]) switch(params["chan"]) if("Equipment") - equipment = setsubsystem(val) + equipment = val if("Lighting") - lighting = setsubsystem(val) + lighting = val if("Environment") - environ = setsubsystem(val) + environ = val + autoflag = AUTOFLAG_OFF intent_message(BUTTON_FLICK, 5) playsound(src, 'sound/machines/terminal/terminal_select.ogg', 18, TRUE) update_icon() @@ -1137,39 +1180,25 @@ ABSTRACT_TYPE(/obj/machinery/power/apc) visible_message(SPAN_DANGER("The [name] suddenly lets out a blast of smoke and some sparks!"), \ SPAN_DANGER("You hear sizzling electronics.")) - -/obj/machinery/power/apc/surplus() - return terminal?.surplus() - /obj/machinery/power/apc/proc/last_surplus() return terminal?.powernet?.last_surplus() -//Returns 1 if the APC should attempt to charge -/obj/machinery/power/apc/proc/attempt_charging() - return (chargemode && charging == CHARGING_ON && operating) - -/obj/machinery/power/apc/draw_power(var/amount) - return terminal?.powernet?.draw_power(amount) - -/obj/machinery/power/apc/avail() - return terminal?.avail() - /obj/machinery/power/apc/process(seconds_per_tick) if(stat & (BROKEN|MAINT)) return if(!area.requires_power) return - if(failure_timer) - update() - queue_icon_update() + if(failure_timer > 0) failure_timer-- - force_update = TRUE + if(!(update_state & UPDATE_BLUESCREEN)) + update() + SSicon_update.add_to_queue(src) return - lastused_light = area.usage(AREA_USAGE_LIGHT) - lastused_equip = area.usage(AREA_USAGE_EQUIP) - lastused_environ = area.usage(AREA_USAGE_ENVIRON) - area.clear_usage() + lastused_light = LIGHT_USAGE(area) + lastused_equip = EQUIP_USAGE(area) + lastused_environ = ENVIRON_USAGE(area) + CLEAR_USAGE(area) lastused_total = lastused_light + lastused_equip + lastused_environ @@ -1179,9 +1208,9 @@ ABSTRACT_TYPE(/obj/machinery/power/apc) var/last_en = environ var/last_ch = charging - var/excess = surplus() + var/excess = POWER_SURPLUS(src.terminal) - if(!avail()) + if(POWER_AVAIL(src.terminal) <= 0) main_status = 0 else if(excess < 0) main_status = 1 @@ -1189,27 +1218,33 @@ ABSTRACT_TYPE(/obj/machinery/power/apc) main_status = 2 if(cell && !shorted) - update_time() + var/delta_power = APC_DELTA_POWER + var/goal = APC_GOAL(delta_power) + time = APC_UPDATE_TIME(delta_power, goal) + last_time = world.time + charge_mode = APC_CHARGE_MODE(delta_power) // draw power from cell as before to power the area cellused = min(cell.charge, (CELLRATE * lastused_total)) // clamp deduction to a max, amount left in cell cell.use(cellused) var/draw = 0 if(excess > lastused_total) // if power excess recharge the cell // by the same amount just used - draw = draw_power(cellused/CELLRATE) // draw the power needed to charge this cell + draw = TERMINAL_POWER_DRAW(cellused/CELLRATE) // draw the power needed to charge this cell + TERMINAL_DRAW_POWER(draw) cell.give(draw * CELLRATE) else // no excess, and not enough per-apc if((cell.charge/CELLRATE + excess) >= lastused_total) // can we draw enough from cell+grid to cover last usage? - draw = draw_power(excess) + draw = TERMINAL_POWER_DRAW(excess) + TERMINAL_DRAW_POWER(draw) cell.charge = min(cell.maxcharge, cell.charge + CELLRATE * draw) //recharge with what we can charging = CHARGING_OFF else // not enough power available to run the last tick! charging = CHARGING_OFF chargecount = 0 // This turns everything off in the case that there is still a charge left on the battery, just not enough to run the room. - equipment = autoset(equipment, CHANNEL_OFF) - lighting = autoset(lighting, CHANNEL_OFF) - environ = autoset(environ, CHANNEL_OFF) + equipment = autoset(equipment, AUTOSET_FORCE_OFF) + lighting = autoset(lighting, AUTOSET_FORCE_OFF) + environ = autoset(environ, AUTOSET_FORCE_OFF) autoflag = AUTOFLAG_OFF // Set channels depending on how much charge we have left @@ -1217,12 +1252,13 @@ ABSTRACT_TYPE(/obj/machinery/power/apc) // now trickle-charge the cell lastused_charging = 0 // Clear the variable for new use. - if(attempt_charging()) + if((chargemode && charging == CHARGING_ON && operating)) if(excess > 0) // check to make sure we have enough to charge // Max charge is capped to % per second constant var/ch = min(excess*CELLRATE, cell.maxcharge*chargelevel) - ch = draw_power(ch/CELLRATE) // Removes the power we're taking from the grid + ch = TERMINAL_POWER_DRAW(ch/CELLRATE) // Removes the power we're taking from the grid + TERMINAL_DRAW_POWER(ch) cell.give(ch*CELLRATE) // actually recharge the cell lastused_charging = ch + draw lastused_total += ch + draw // Sensors need this to stop reporting APC charging as "Other" load @@ -1254,19 +1290,19 @@ ABSTRACT_TYPE(/obj/machinery/power/apc) else // no cell, switch everything off charging = CHARGING_OFF chargecount = 0 - equipment = autoset(equipment, CHANNEL_OFF) - lighting = autoset(lighting, CHANNEL_OFF) - environ = autoset(environ, CHANNEL_OFF) + equipment = autoset(equipment, AUTOSET_FORCE_OFF) + lighting = autoset(lighting, AUTOSET_FORCE_OFF) + environ = autoset(environ, AUTOSET_FORCE_OFF) GLOB.power_alarm.triggerAlarm(loc, src) autoflag = AUTOFLAG_OFF // update icon & area power if anything changed if(last_lt != lighting || last_eq != equipment || last_en != environ || force_update) force_update = FALSE - queue_icon_update() + SSicon_update.add_to_queue(src) update() else if (last_ch != charging) - queue_icon_update() + SSicon_update.add_to_queue(src) /obj/machinery/power/apc/proc/update_channels() // Allow the APC to operate as normal if the cell can charge @@ -1275,51 +1311,38 @@ ABSTRACT_TYPE(/obj/machinery/power/apc) else if(longtermpower > -10) longtermpower -= 2 - if((cell.percent() > 30) || longtermpower > 0) // Put most likely at the top so we don't check it last, effeciency 101 - if(autoflag != AUTOFLAG_ALL_ON) - equipment = autoset(equipment, CHANNEL_OFF_AUTO) - lighting = autoset(lighting, CHANNEL_OFF_AUTO) - environ = autoset(environ, CHANNEL_OFF_AUTO) - autoflag = AUTOFLAG_ALL_ON - GLOB.power_alarm.clearAlarm(loc, src) - else if((cell.percent() <= 30) && (cell.percent() > 15) && longtermpower < 0) // <30%, turn off equipment - if(autoflag != AUTOFLAG_ENVIRON_LIGHTS_ON) - equipment = autoset(equipment, CHANNEL_ON) - lighting = autoset(lighting, CHANNEL_OFF_AUTO) - environ = autoset(environ, CHANNEL_OFF_AUTO) - GLOB.power_alarm.triggerAlarm(loc, src) - autoflag = AUTOFLAG_ENVIRON_LIGHTS_ON - else if(cell.percent() <= 15) // <15%, turn off lighting & equipment - if((autoflag > AUTOFLAG_ENVIRON_ON && longtermpower < 0) || (autoflag > AUTOFLAG_ENVIRON_ON && longtermpower >= 0)) - equipment = autoset(equipment, CHANNEL_ON) - lighting = autoset(lighting, CHANNEL_ON) - environ = autoset(environ, CHANNEL_OFF_AUTO) - GLOB.power_alarm.triggerAlarm(loc, src) - autoflag = AUTOFLAG_ENVIRON_ON - else // zero charge, turn all off - if(autoflag != AUTOFLAG_OFF) - equipment = autoset(equipment, CHANNEL_OFF) - lighting = autoset(lighting, CHANNEL_OFF) - environ = autoset(environ, CHANNEL_OFF) - GLOB.power_alarm.triggerAlarm(loc, src) - autoflag = AUTOFLAG_OFF - -/obj/machinery/power/apc/proc/autoset(var/val, var/on) - if(on == CHANNEL_EQUIPMENT) - if(val == CHANNEL_ON) - return CHANNEL_OFF - else if(val == CHANNEL_ON_AUTO) - return CHANNEL_OFF_AUTO + var/cell_charge = cell.maxcharge && ((cell.charge / cell.maxcharge) * 100.0) - else if(on == CHANNEL_LIGHTING) - if(val == CHANNEL_OFF_AUTO) - return CHANNEL_ON_AUTO - - else if(on == CHANNEL_ENVIRONMENT) - if(val == CHANNEL_ON_AUTO) - return CHANNEL_OFF_AUTO - - return val + if((cell_charge > 30 || longtermpower > 0)) + if(autoflag == AUTOFLAG_ALL_ON) + return + equipment = autoset(equipment, AUTOSET_ON) + lighting = autoset(lighting, AUTOSET_ON) + environ = autoset(environ, AUTOSET_ON) + autoflag = AUTOFLAG_ALL_ON + GLOB.power_alarm.clearAlarm(loc, src) + else if(cell_charge > 15) // <30%, turn off equipment + if(autoflag == AUTOFLAG_ENVIRON_LIGHTS_ON) + return + equipment = autoset(equipment, AUTOSET_OFF) + lighting = autoset(lighting, AUTOSET_ON) + environ = autoset(environ, AUTOSET_ON) + GLOB.power_alarm.triggerAlarm(loc, src) + autoflag = AUTOFLAG_ENVIRON_LIGHTS_ON + else if(cell_charge <= 15) // <15%, turn off lighting & equipment + if(autoflag == AUTOFLAG_ENVIRON_ON) + return + equipment = autoset(equipment, AUTOSET_OFF) + lighting = autoset(lighting, AUTOSET_OFF) + environ = autoset(environ, AUTOSET_ON) + GLOB.power_alarm.triggerAlarm(loc, src) + autoflag = AUTOFLAG_ENVIRON_ON + else // zero charge, turn all off + equipment = autoset(equipment, AUTOSET_FORCE_OFF) + lighting = autoset(lighting, AUTOSET_FORCE_OFF) + environ = autoset(environ, AUTOSET_FORCE_OFF) + GLOB.power_alarm.triggerAlarm(loc, src) + autoflag = AUTOFLAG_OFF // damage and destruction acts /obj/machinery/power/apc/emp_act(severity) @@ -1328,9 +1351,9 @@ ABSTRACT_TYPE(/obj/machinery/power/apc) if(cell) cell.emp_act(severity) - lighting = CHANNEL_OFF - equipment = CHANNEL_OFF - environ = CHANNEL_OFF + lighting = 0 + equipment = 0 + environ = 0 update() update_icon() @@ -1339,7 +1362,7 @@ ABSTRACT_TYPE(/obj/machinery/power/apc) /obj/machinery/power/apc/proc/post_emp_act() update_channels() update() - queue_icon_update() + SSicon_update.add_to_queue(src) /obj/machinery/power/apc/ex_act(severity) switch(severity) @@ -1381,7 +1404,7 @@ ABSTRACT_TYPE(/obj/machinery/power/apc) stat |= BROKEN operating = 0 failure_timer = 0 - queue_icon_update() + SSicon_update.add_to_queue(src) update() // overload the lights in this APC area @@ -1425,14 +1448,6 @@ ABSTRACT_TYPE(/obj/machinery/power/apc) night_mode = !night_mode intent_message(BUTTON_FLICK, 5) -/obj/machinery/power/apc/proc/setsubsystem(val) - if(cell && cell.charge > 0) - return (val == CHANNEL_OFF_AUTO) ? CHANNEL_OFF : val - else if(val == CHANNEL_ON_AUTO) - return CHANNEL_OFF_AUTO - else - return CHANNEL_OFF - // Malfunction: Transfers APC under AI's control /obj/machinery/power/apc/proc/ai_hack(var/mob/living/silicon/ai/A = null) if(!A || !A.hacked_apcs || hacker || aidisabled || A.stat == DEAD) @@ -1443,21 +1458,6 @@ ABSTRACT_TYPE(/obj/machinery/power/apc) update_icon() return TRUE -/obj/machinery/power/apc/proc/update_time() - - var/delta_power = (lastused_charging * 2) - lastused_total - delta_power *= CELLRATE - - var/goal = (delta_power < 0) ? (cell.charge) : (cell.maxcharge - cell.charge) - time = world.time + (delta_power ? ((goal / abs(delta_power)) * (world.time - last_time)) : 0) - // If it is negative - we are discharging - if(delta_power < 0) - charge_mode = CHARGE_MODE_DISCHARGE - else if(delta_power > 0) - charge_mode = CHARGE_MODE_CHARGE - else - charge_mode = CHARGE_MODE_STABLE - last_time = world.time /obj/machinery/power/apc/proc/manage_emergency(var/new_security_level) for(var/obj/machinery/M in area) @@ -1618,9 +1618,9 @@ ABSTRACT_TYPE(/obj/machinery/power/apc) // Construction site APC, starts turned off /obj/machinery/power/apc/high/inactive cell_type = /obj/item/cell/high - lighting = CHANNEL_OFF - equipment = CHANNEL_OFF - environ = CHANNEL_OFF + lighting = 0 + equipment = 0 + environ = 0 locked = FALSE coverlocked = FALSE start_charge = 100 @@ -1733,9 +1733,9 @@ ABSTRACT_TYPE(/obj/machinery/power/apc) #undef CHARGING_ON #undef CHARGING_FULL #undef CHANNEL_OFF -#undef CHANNEL_OFF_AUTO +#undef CHANNEL_AUTO #undef CHANNEL_ON -#undef CHANNEL_ON_AUTO +#undef CHANNEL_AUTO_ON #undef CHANNEL_EQUIPMENT #undef CHANNEL_LIGHTING #undef CHANNEL_ENVIRONMENT @@ -1746,3 +1746,8 @@ ABSTRACT_TYPE(/obj/machinery/power/apc) #undef AUTOFLAG_ENVIRON_ON #undef AUTOFLAG_ENVIRON_LIGHTS_ON #undef AUTOFLAG_ALL_ON +#undef autoset +#undef APC_DELTA_POWER +#undef APC_GOAL +#undef APC_UPDATE_TIME +#undef APC_CHARGE_MODE diff --git a/code/modules/power/batteryrack.dm b/code/modules/power/batteryrack.dm index d63586199263..c085146a182f 100644 --- a/code/modules/power/batteryrack.dm +++ b/code/modules/power/batteryrack.dm @@ -156,7 +156,8 @@ if(terminal) if(input_attempt) var/target_load = min((capacity-charge)/SMESRATE, input_level) // charge at set rate, limited to spare capacity - var/actual_load = draw_power(target_load) // add the load to the terminal side network + var/actual_load = POWER_DRAW(src, target_load) // add the load to the terminal side network + DRAW_POWER(src, actual_load) charge += actual_load * SMESRATE // increase the charge if (actual_load >= target_load) // did the powernet have enough power available for us? @@ -167,7 +168,7 @@ if(output_attempt) // if outputting output_used = min( charge/SMESRATE, output_level) //limit output to that stored charge -= output_used*SMESRATE // reduce the storage (may be recovered in /restore() if excessive) - add_avail(output_used) // add output to powernet (smes side) + ADD_TO_POWERNET(src, output_used) // add output to powernet (smes side) if(charge < 0.0001) outputting(0) // stop output if charge falls to zero diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 4fec198b13a2..7f05b9278b5c 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -62,10 +62,9 @@ By design, d1 is the smallest direction and d2 is the highest if(drain_check) return TRUE - var/datum/powernet/PN = powernet - if(!PN) return FALSE + . = POWERNET_POWER_DRAW(powernet, amount) - return PN.draw_power(amount) + DRAW_FROM_POWERNET(powernet, .) /obj/structure/cable/yellow color = COLOR_YELLOW @@ -563,7 +562,7 @@ By design, d1 is the smallest direction and d2 is the highest to_chat(user, SPAN_NOTICE("You don't have enough coils for this!")) return user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) - for(var/datum/wound/W in affecting.wounds) + for(var/datum/wound/W as anything in affecting.wounds) if(W.bandaged) continue if(W.current_stage <= W.max_bleeding_stage) diff --git a/code/modules/power/collector.dm b/code/modules/power/collector.dm index 88f4d4680f6d..d8fd7eae13bd 100644 --- a/code/modules/power/collector.dm +++ b/code/modules/power/collector.dm @@ -226,7 +226,7 @@ GLOBAL_LIST_INIT_TYPED(rad_collectors, /obj/machinery/power/rad_collector, list( if(loaded_tank && active) var/power_produced = 0 power_produced = min(100*loaded_tank.air_contents.gas[GAS_PHORON]*pulse_strength*pulse_coeff,max_power) - add_avail(power_produced) + ADD_TO_POWERNET(src, power_produced) last_power_new = power_produced return return diff --git a/code/modules/power/crystal_agitator.dm b/code/modules/power/crystal_agitator.dm index d66bbf0d513a..41f111ecea62 100644 --- a/code/modules/power/crystal_agitator.dm +++ b/code/modules/power/crystal_agitator.dm @@ -73,7 +73,8 @@ toggle_active() return - var/actual_load = draw_power(active_power_usage) + var/actual_load = POWER_DRAW(src, active_power_usage) + DRAW_POWER(src, active_power_usage) if(actual_load < active_power_usage) toggle_active() return diff --git a/code/modules/power/fractal_reactor.dm b/code/modules/power/fractal_reactor.dm index 566aded8fda5..e9857c837fef 100644 --- a/code/modules/power/fractal_reactor.dm +++ b/code/modules/power/fractal_reactor.dm @@ -26,4 +26,4 @@ powernet_connection_failed = 1 spawn(150) // Error! Check again in 15 seconds. powernet_connection_failed = 0 - add_avail(power_generation_rate) + ADD_TO_POWERNET(src, power_generation_rate) diff --git a/code/modules/power/fusion/consoles/_consoles.dm b/code/modules/power/fusion/consoles/_consoles.dm index 6119a80b2d27..e0108dcffbd5 100644 --- a/code/modules/power/fusion/consoles/_consoles.dm +++ b/code/modules/power/fusion/consoles/_consoles.dm @@ -43,6 +43,11 @@ . = data /obj/machinery/computer/fusion/ui_interact(mob/user, datum/tgui/ui) + var/cancelled = FALSE + SEND_SIGNAL(user, COMSIG_USE_REACTOR_COMPUTER, &cancelled) + if (cancelled) + return + ui = SStgui.try_update_ui(user, src, ui) if (!ui) ui = new(user, src, ui_template, name) diff --git a/code/modules/power/fusion/consoles/core_control.dm b/code/modules/power/fusion/consoles/core_control.dm index 04670bcc2020..23e373ff94e2 100644 --- a/code/modules/power/fusion/consoles/core_control.dm +++ b/code/modules/power/fusion/consoles/core_control.dm @@ -4,7 +4,7 @@ /obj/machinery/computer/fusion/core_control/terminal name = "\improper INDRA fusion core control" - icon = 'icons/obj/machinery/modular_terminal.dmi' + icon = 'icons/obj/modular_computers/modular_terminal.dmi' icon_screen = "solar_screen" icon_keyboard = "id_key" icon_keyboard_emis = "id_key_mask" @@ -53,7 +53,7 @@ for(var/i = 1 to LAZYLEN(fusion_cores)) var/list/core = list() var/obj/machinery/power/fusion_core/C = fusion_cores[i] - var/power_available = C.avail() + var/power_available = POWER_AVAIL(C) var/power_usage = C.active_power_usage var/power_generated = C.owned_field?.output_avg diff --git a/code/modules/power/fusion/consoles/gyrotron_control.dm b/code/modules/power/fusion/consoles/gyrotron_control.dm index 9bcd1b61c85b..b4d27d896de6 100644 --- a/code/modules/power/fusion/consoles/gyrotron_control.dm +++ b/code/modules/power/fusion/consoles/gyrotron_control.dm @@ -9,7 +9,7 @@ /obj/machinery/computer/fusion/gyrotron/terminal name = "gyrotron control terminal" - icon = 'icons/obj/machinery/modular_terminal.dmi' + icon = 'icons/obj/modular_computers/modular_terminal.dmi' icon_screen = "rust_screen" icon_keyboard = "generic_key" icon_keyboard_emis = "generic_key_mask" diff --git a/code/modules/power/fusion/consoles/injector_control.dm b/code/modules/power/fusion/consoles/injector_control.dm index 1b0f8f0326fd..66c8c50c7a03 100644 --- a/code/modules/power/fusion/consoles/injector_control.dm +++ b/code/modules/power/fusion/consoles/injector_control.dm @@ -9,7 +9,7 @@ /obj/machinery/computer/fusion/fuel_control/terminal name = "fuel injection control terminal" - icon = 'icons/obj/machinery/modular_terminal.dmi' + icon = 'icons/obj/modular_computers/modular_terminal.dmi' icon_screen = "power_screen" icon_keyboard = "med_key" icon_keyboard_emis = "med_key_mask" diff --git a/code/modules/power/fusion/core/_core.dm b/code/modules/power/fusion/core/_core.dm index 353a461bcfcd..0c00aebab7f0 100644 --- a/code/modules/power/fusion/core/_core.dm +++ b/code/modules/power/fusion/core/_core.dm @@ -141,6 +141,6 @@ connect_to_network() if(stat & BROKEN) return FALSE - if(idle_power_usage > avail()) + if(idle_power_usage > POWER_AVAIL(src)) return FALSE . = TRUE diff --git a/code/modules/power/fusion/core/core_field.dm b/code/modules/power/fusion/core/core_field.dm index 9a58ba1426d0..af6e65c86724 100644 --- a/code/modules/power/fusion/core/core_field.dm +++ b/code/modules/power/fusion/core/core_field.dm @@ -221,7 +221,7 @@ output_archive_2 = output_archive_1 output_archive_1 = power_output output_avg = ((output_archive_1 + output_archive_2 + output_archive_3 + output_archive_4 + output_archive_5 ) / 5) - owned_core.add_avail(power_output) + ADD_TO_POWERNET(owned_core, power_output) // Roundstart update if(field_strength < 20) diff --git a/code/modules/power/fusion/gyrotron/gyrotron.dm b/code/modules/power/fusion/gyrotron/gyrotron.dm index a2db1fb1cdde..50dc191872dd 100644 --- a/code/modules/power/fusion/gyrotron/gyrotron.dm +++ b/code/modules/power/fusion/gyrotron/gyrotron.dm @@ -34,7 +34,7 @@ return E /obj/machinery/power/emitter/gyrotron/update_icon() - if (active && powernet && avail(active_power_usage)) + if (active && powernet && POWER_AVAIL(src)) icon_state = "emitter-on" else icon_state = "emitter-off" diff --git a/code/modules/power/generator.dm b/code/modules/power/generator.dm index 198085538a23..0bcf1381cb99 100644 --- a/code/modules/power/generator.dm +++ b/code/modules/power/generator.dm @@ -1,6 +1,6 @@ /obj/machinery/power/generator - name = "thermoelectric generator" - desc = "It's a high efficiency thermoelectric generator." + name = "\improper Stirling engine" + desc = "It's a high efficiency Stirling engine. This model produces electricity from the temperature and differential between two gas loops." icon_state = "teg-unassembled" density = TRUE anchored = FALSE @@ -44,11 +44,13 @@ circ2 = null return ..() -//generators connect in dir and reverse_dir(dir) directions -//mnemonic to determine circulator/generator directions: the cirulators orbit clockwise around the generator -//so a circulator to the NORTH of the generator connects first to the EAST, then to the WEST -//and a circulator to the WEST of the generator connects first to the NORTH, then to the SOUTH -//note that the circulator's outlet dir is it's always facing dir, and it's inlet is always the reverse +/** + * Circulators connect in dir and reverse_dir(dir) directions + * A mnemonic to determine circulator/generator directions: the cirulators orbit clockwise around the generator. + * So a circulator to the NORTH of the generator connects first to the EAST, then to the WEST, + * and a circulator to the WEST of the generator connects first to the NORTH, then to the SOUTH. + * Note that the circulator's outlet dir is it's always facing dir, and it's inlet is always the reverse + */ /obj/machinery/power/generator/proc/reconnect() if(circ1) circ1.temperature_overlay = null @@ -78,11 +80,11 @@ /obj/machinery/power/generator/update_icon() icon_state = anchored ? "teg-assembled" : "teg-unassembled" ClearOverlays() - if (circ1) + if(circ1) circ1.temperature_overlay = null - if (circ2) + if(circ2) circ2.temperature_overlay = null - if (stat & (NOPOWER|BROKEN)) + if(stat & (NOPOWER|BROKEN)) return TRUE else if (lastgenlev != 0) @@ -91,10 +93,14 @@ var/extreme = (lastgenlev > 9) ? "ex" : "" if (circ1.last_temperature < circ2.last_temperature) circ1.temperature_overlay = "circ-[extreme]cold" + circ1.is_hot_loop = FALSE circ2.temperature_overlay = "circ-[extreme]hot" + circ2.is_hot_loop = TRUE else circ1.temperature_overlay = "circ-[extreme]hot" + circ1.is_hot_loop = TRUE circ2.temperature_overlay = "circ-[extreme]cold" + circ2.is_hot_loop = FALSE return TRUE /obj/machinery/power/generator/process() @@ -102,8 +108,6 @@ stored_energy = 0 return - updateDialog() - var/datum/gas_mixture/air1 = circ1.return_transfer_air() var/datum/gas_mixture/air2 = circ2.return_transfer_air() @@ -163,7 +167,7 @@ if(genlev != lastgenlev) lastgenlev = genlev update_icon() - add_avail(effective_gen) + ADD_TO_POWERNET(src, effective_gen) /obj/machinery/power/generator/attack_ai(mob/user) if(!ai_can_interact(user)) @@ -174,6 +178,7 @@ if(attacking_item.tool_behaviour == TOOL_WRENCH) attacking_item.play_tool_sound(get_turf(src), 75) anchored = !anchored + balloon_alert(user, "[anchored ? "secure" : "unsecure"]") user.visible_message("[user.name] [anchored ? "secures" : "unsecures"] the bolts holding [src.name] to the floor.", \ "You [anchored ? "secure" : "unsecure"] the bolts holding [src] to the floor.", \ "You hear a ratchet") @@ -193,56 +198,50 @@ reconnect() ui_interact(user) -/obj/machinery/power/generator/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - // this is the data which will be sent to the ui - var/vertical = 0 - if (dir == NORTH || dir == SOUTH) - vertical = 1 +/obj/machinery/power/generator/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + // Interface ID should match your tgui route registration/name. + ui = new(user, src, "StirlingEngine", "Stirling Engine") + ui.open() - var/data[0] - data["totalOutput"] = effective_gen/1000 - data["maxTotalOutput"] = max_power/1000 - data["thermalOutput"] = last_thermal_gen/1000 - data["circConnected"] = 0 +/obj/machinery/power/generator/ui_data(mob/user) + var/list/data = list() + + var/vertical = FALSE + if(dir == NORTH || dir == SOUTH) + vertical = TRUE + + data["totalOutput"] = effective_gen / 1000 + data["maxTotalOutput"] = max_power / 1000 + data["thermalOutput"] = last_thermal_gen / 1000 + data["circConnected"] = FALSE if(circ1) - //The one on the left (or top) + // The one on the left (or top) data["primaryDir"] = vertical ? "top" : "left" data["primaryOutput"] = last_circ1_gen/1000 data["primaryFlowCapacity"] = circ1.volume_capacity_used*100 - data["primaryInletPressure"] = circ1.air1.return_pressure() + data["primaryInletPressure"] = XGM_PRESSURE(circ1.air1) data["primaryInletTemperature"] = circ1.air1.temperature - data["primaryOutletPressure"] = circ1.air2.return_pressure() + data["primaryOutletPressure"] = XGM_PRESSURE(circ1.air2) data["primaryOutletTemperature"] = circ1.air2.temperature + data["primaryIsHot"] = circ1.is_hot_loop if(circ2) - //Now for the one on the right (or bottom) + // The one on the right (or bottom) data["secondaryDir"] = vertical ? "bottom" : "right" data["secondaryOutput"] = last_circ2_gen/1000 data["secondaryFlowCapacity"] = circ2.volume_capacity_used*100 - data["secondaryInletPressure"] = circ2.air1.return_pressure() + data["secondaryInletPressure"] = XGM_PRESSURE(circ2.air1) data["secondaryInletTemperature"] = circ2.air1.temperature - data["secondaryOutletPressure"] = circ2.air2.return_pressure() + data["secondaryOutletPressure"] = XGM_PRESSURE(circ2.air2) data["secondaryOutletTemperature"] = circ2.air2.temperature + data["secondaryIsHot"] = circ2.is_hot_loop - if(circ1 && circ2) - data["circConnected"] = 1 - else - data["circConnected"] = 0 - + data["circConnected"] = (circ1 && circ2) ? TRUE : FALSE - // update the ui if it exists, returns null if no ui is passed/found - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "generator.tmpl", "Thermoelectric Generator", 450, 500) - // when the ui is first opened this is the data it will use - ui.set_initial_data(data) - // open the new ui window - ui.open() - // auto update every Master Controller tick - ui.set_auto_update(1) + return data /obj/machinery/power/generator/power_change() ..() diff --git a/code/modules/power/portgen.dm b/code/modules/power/portgen.dm index 1409b0c10d7e..9a325b244873 100644 --- a/code/modules/power/portgen.dm +++ b/code/modules/power/portgen.dm @@ -53,8 +53,7 @@ /obj/machinery/power/portgen/process() if(active && HasFuel() && !IsBroken() && anchored) set_light(2, 1, l_color = portgen_lightcolour) - if(powernet) - add_avail(power_gen * power_output) + ADD_TO_POWERNET(src, power_gen * power_output) UseFuel() else set_light(0) @@ -215,7 +214,7 @@ if(!loc) return var/datum/gas_mixture/environment = loc.return_air() if (environment) - var/ratio = min(environment.return_pressure()/ONE_ATMOSPHERE, 1) + var/ratio = min(XGM_PRESSURE(environment)/ONE_ATMOSPHERE, 1) var/ambient = environment.temperature - T20C lower_limit += ambient*ratio upper_limit += ambient*ratio @@ -247,7 +246,7 @@ if(T) var/datum/gas_mixture/environment = T.return_air() if (environment) - var/ratio = min(environment.return_pressure()/ONE_ATMOSPHERE, 1) + var/ratio = min(XGM_PRESSURE(environment)/ONE_ATMOSPHERE, 1) var/ambient = environment.temperature - T20C cooling_temperature += ambient*ratio diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index e9fe60817230..20973556675f 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -24,39 +24,6 @@ /////////////////////////////// // General procedures ////////////////////////////// - -// common helper procs for all power machines -/obj/machinery/power/drain_power(var/drain_check, var/surge, var/amount = 0) - if(drain_check) - return 1 - - if(powernet && powernet.avail) - powernet.trigger_warning() - return powernet.draw_power(amount) - -/obj/machinery/power/proc/add_avail(var/amount) - if(powernet) - powernet.newavail += amount - return 1 - return 0 - -/obj/machinery/power/proc/draw_power(var/amount) - if(powernet) - return powernet.draw_power(amount) - return 0 - -/obj/machinery/power/proc/surplus() - if(powernet) - return powernet.avail-powernet.load - else - return 0 - -/obj/machinery/power/proc/avail() - if(powernet) - return powernet.avail - else - return 0 - // Proc: power_wattage_readable() // Parameters: 1 (amount - Power in Watts to be converted to W, kW or MW) // Description: Helper proc that converts reading in Watts to kW or MW (returns string version of amount parameter) @@ -370,7 +337,8 @@ source_area.use_power_oneoff(drained_energy/CELLRATE) else if (istype(power_source,/datum/powernet)) var/drained_power = drained_energy/CELLRATE - drained_power = PN.draw_power(drained_power) + drained_power = POWERNET_POWER_DRAW(PN, drained_power) + DRAW_FROM_POWERNET(PN, drained_power) else if (istype(power_source, /obj/item/cell)) cell.use(drained_energy) return drained_energy diff --git a/code/modules/power/powernet.dm b/code/modules/power/powernet.dm index 8562b578bb8f..b60d14aafda4 100644 --- a/code/modules/power/powernet.dm +++ b/code/modules/power/powernet.dm @@ -39,11 +39,6 @@ /datum/powernet/proc/last_surplus() return max(avail - load, 0) -/datum/powernet/proc/draw_power(var/amount) - var/draw = between(0, amount, avail - load) - load += draw - return draw - /datum/powernet/proc/is_empty() return !cables.len && !nodes.len diff --git a/code/modules/power/radial_floodlight.dm b/code/modules/power/radial_floodlight.dm index 2f833807614c..553b55990f2b 100644 --- a/code/modules/power/radial_floodlight.dm +++ b/code/modules/power/radial_floodlight.dm @@ -28,7 +28,8 @@ update_icon() /obj/machinery/power/radial_floodlight/process() - var/actual_load = draw_power(active_power_usage) + var/actual_load = POWER_DRAW(src, active_power_usage) + DRAW_POWER(src, active_power_usage) if(!on || !anchored || (stat & BROKEN) || !powernet || actual_load < active_power_usage) STOP_PROCESSING_MACHINE(src, MACHINERY_PROCESS_SELF) update_use_power(POWER_USE_OFF) @@ -56,7 +57,7 @@ if(!powernet) to_chat(user, SPAN_WARNING("\The [src] isn't connected to a power network.")) return - if(avail() < active_power_usage) + if(POWER_AVAIL(src) < active_power_usage) to_chat(user, SPAN_WARNING("\The [src]'s power network doesn't have enough power.")) return toggle_active() diff --git a/code/modules/power/rtg.dm b/code/modules/power/rtg.dm index 5a7ec10e6586..885e1ddc2d39 100644 --- a/code/modules/power/rtg.dm +++ b/code/modules/power/rtg.dm @@ -38,7 +38,7 @@ /obj/machinery/power/rtg/process() ..() - add_avail(power_gen) + ADD_TO_POWERNET(src, power_gen) if(panel_open && irradiate) for (var/mob/living/L in range(2, src)) L.apply_damage(10, DAMAGE_RADIATION, damage_flags = DAMAGE_FLAG_DISPERSED) // Weak but noticeable. diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index a77f91fbac0c..457bbc0b9b21 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -92,16 +92,19 @@ /obj/machinery/power/emitter/update_icon() ClearOverlays() - if(active && powernet && avail(active_power_usage)) + if(active && powernet && POWER_AVAIL(src)) AddOverlays(emissive_appearance(icon, "[icon_state]_lights")) AddOverlays("[icon_state]_lights") /obj/machinery/power/emitter/attack_hand(mob/user) add_fingerprint(user) - var/max_engineering_skill = max(user.get_skill_level(/singleton/skill/reactor_systems), user.get_skill_level(/singleton/skill/electrical_engineering)) + var/max_engineering_skill = \ + max(astype(user.GetComponent(REACTOR_SYSTEMS_SKILL_COMPONENT), SKILL_COMPONENT)?.skill_level, \ + astype(user.GetComponent(ELECTRICAL_ENGINEERING_SKILL_COMPONENT), SKILL_COMPONENT)?.skill_level) + if(max_engineering_skill <= SKILL_LEVEL_TRAINED) to_chat(user, SPAN_WARNING("You try to find the switch on \the [src]... How do you even turn this thing on?")) - if(!user.do_after_skill(3 SECONDS, src, list(/singleton/skill/reactor_systems, /singleton/skill/electrical_engineering))) + if(!do_after(user, 3 SECONDS + 1.5 SECONDS * (SKILL_LEVEL_TRAINED - max_engineering_skill))) return to_chat(user, SPAN_NOTICE("You finally find the switch!")) activate(user) @@ -155,7 +158,8 @@ update_icon() return if(((last_shot + fire_delay) <= world.time) && active) - var/actual_load = draw_power(active_power_usage) + var/actual_load = POWER_DRAW(src, active_power_usage) + DRAW_POWER(src, actual_load) if(actual_load >= active_power_usage) //does the laser have enough power to shoot? if(!powered) powered = TRUE diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index 1f66c696353c..73a5b3e5d26d 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -175,13 +175,6 @@ return TRUE return FALSE -/obj/machinery/power/smes/add_avail(var/amount) - if(..(amount)) - powernet.smes_newavail += amount - return 1 - return 0 - - /obj/machinery/power/smes/disconnect_terminal() if(terminal) terminal.master = null @@ -236,7 +229,8 @@ var/inputted_power = target_load * (percentage/100) inputted_power = between(0, inputted_power, target_load) if(terminal && terminal.powernet) - inputted_power = terminal.powernet.draw_power(inputted_power) + inputted_power = TERMINAL_POWER_DRAW(inputted_power) + TERMINAL_DRAW_POWER(inputted_power) charge += inputted_power * SMESRATE input_taken = inputted_power if(percentage == 100) @@ -295,7 +289,7 @@ if(output_attempt && (!output_pulsed && !output_cut) && powernet && charge) output_used = min( charge/SMESRATE, output_level) //limit output to that stored charge -= output_used*SMESRATE // reduce the storage (may be recovered in /restore() if excessive) - add_avail(output_used) // add output to powernet (smes side) + SMES_ADD_TO_POWERNET(src, output_used) // add output to powernet (smes side) outputting = 2 else if(!powernet || !charge) outputting = 1 @@ -358,12 +352,6 @@ return 0 return 1 - -/obj/machinery/power/smes/draw_power(var/amount) - if(terminal && terminal.powernet) - return terminal.powernet.draw_power(amount) - return FALSE - /obj/machinery/power/smes/attack_ai(mob/user) if(!ai_can_interact(user)) return diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm index a363338655e7..fd60f32e8cd4 100644 --- a/code/modules/power/solar.dm +++ b/code/modules/power/solar.dm @@ -125,7 +125,7 @@ if(obscured) //get no light from the sun, so don't generate power return var/sgen = SOLARGENRATE * sunfrac - add_avail(sgen) + ADD_TO_POWERNET(src, sgen) control.gen += sgen else //if we're no longer on the same powernet, remove from control computer unset_control() @@ -269,7 +269,7 @@ /obj/machinery/power/solar_control name = "solar panel control" desc = "A controller for solar panel arrays." - icon = 'icons/obj/machinery/modular_console.dmi' + icon = 'icons/obj/modular_computers/modular_console.dmi' icon_state = "computer" light_color = LIGHT_COLOR_YELLOW anchored = 1 diff --git a/code/modules/power/tesla/coil.dm b/code/modules/power/tesla/coil.dm index 3435101be1e3..f57084d6c0d9 100644 --- a/code/modules/power/tesla/coil.dm +++ b/code/modules/power/tesla/coil.dm @@ -53,7 +53,7 @@ //don't lose arc power when it's not connected to anything //please place tesla coils all around the station to maximize effectiveness var/power_produced = powernet ? power / power_loss : power - add_avail(power_produced*input_power_multiplier) + ADD_TO_POWERNET(src, power_produced*input_power_multiplier) flick("coilhit", src) playsound(src.loc, 'sound/magic/LightningShock.ogg', 100, 1, extrarange = 5) tesla_zap(src, 5, power_produced) diff --git a/code/modules/power/turbine.dm b/code/modules/power/turbine.dm index 3a42c56118cb..aab86f1e1773 100644 --- a/code/modules/power/turbine.dm +++ b/code/modules/power/turbine.dm @@ -200,7 +200,7 @@ rpm = max(0, rpm - (rpm*rpm)/(COMPFRICTION*efficiency)) if(!(stat & NOPOWER)) - draw_power(2800) + DRAW_POWER(src, 2800) if(rpm < 1000) rpmtarget = 1000 else @@ -272,7 +272,7 @@ else lastgen = ((compressor.rpm / TURBPOWER) ** TURBCURVESHAPE) * TURBPOWER * productivity * POWER_CURVE_MOD - add_avail(lastgen) + ADD_TO_POWERNET(src, lastgen) var/newrpm = (compressor.gas_contained.temperature * compressor.gas_contained.total_moles) / 4 diff --git a/code/modules/projectiles/ammunition/ammo_pile.dm b/code/modules/projectiles/ammunition/ammo_pile.dm index 0a17eec9a396..48fec4c02e64 100644 --- a/code/modules/projectiles/ammunition/ammo_pile.dm +++ b/code/modules/projectiles/ammunition/ammo_pile.dm @@ -9,7 +9,7 @@ var/max_ammo = 5 /obj/item/ammo_pile/Destroy() - ammo.Cut() + QDEL_LIST(ammo) ammo_overlays.Cut() . = ..() diff --git a/code/modules/projectiles/ammunition/boxes.dm b/code/modules/projectiles/ammunition/boxes.dm index 4e39d28c44f4..cded65a7f2dc 100644 --- a/code/modules/projectiles/ammunition/boxes.dm +++ b/code/modules/projectiles/ammunition/boxes.dm @@ -545,6 +545,15 @@ If nothing is chosen, reload sounds revert to the default, which is metal_slide_ ammo_type = /obj/item/ammo_casing/vintage caliber = "vintage" +/obj/item/ammo_magazine/boltaction/adhomai + name = "ammo clip (6.8mm)" + icon_state = "762" + ammo_type = /obj/item/ammo_casing/a68 + caliber = "6.8mm" + +/obj/item/ammo_magazine/boltaction/adhomai/blank + ammo_type = /obj/item/ammo_casing/a68/blank + /obj/item/ammo_magazine/d762 name = "magazine (7.62mm)" icon_state = "SVD" @@ -558,6 +567,25 @@ If nothing is chosen, reload sounds revert to the default, which is metal_slide_ /obj/item/ammo_magazine/d762/empty initial_ammo = 0 +/obj/item/ammo_magazine/a68 + name = "magazine (6.8mm)" + icon_state = "a68" + mag_type = MAGAZINE + caliber = "6.8mm" + matter = list(DEFAULT_WALL_MATERIAL = 1800) + ammo_type = /obj/item/ammo_casing/a68/ + max_ammo = 25 + multiple_sprites = 1 + insert_sound = SFX_RELOAD_RIFLE_SLIDE + +/obj/item/ammo_magazine/a68/empty + initial_ammo = 0 + +/obj/item/ammo_magazine/a68/hotaki + icon_state = "SVD" + ammo_type = /obj/item/ammo_casing/a68/ap + max_ammo = 10 + // Shotguns and special // /obj/item/ammo_magazine/flechette name = "flechette rounds" diff --git a/code/modules/projectiles/ammunition/bullets.dm b/code/modules/projectiles/ammunition/bullets.dm index 53f350ae7748..6058f16b269b 100644 --- a/code/modules/projectiles/ammunition/bullets.dm +++ b/code/modules/projectiles/ammunition/bullets.dm @@ -263,6 +263,27 @@ . = ..() expend() +/obj/item/ammo_casing/a68 + desc = "A Z33 Tamparii bullet casing." + caliber = "6.8mm" + projectile_type = /obj/projectile/bullet/rifle/a68 + icon_state = "rifle-casing" + spent_icon = "rifle-casing-spent" + max_stack = 5 + +/obj/item/ammo_casing/a68/spent/Initialize() + . = ..() + expend() + +/obj/item/ammo_casing/a68/ap + desc = "A Z33r Tamparii bullet casing." + projectile_type = /obj/projectile/bullet/rifle/a68/ap + max_stack = 5 + +/obj/item/ammo_casing/a68/blank + desc = "A Z33t Tamparii blank casing." + projectile_type = /obj/projectile/bullet/blank + /obj/item/ammo_casing/a762/blank desc = "A 7.62mm blank casing." projectile_type = /obj/projectile/bullet/blank diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index ebf48afa3811..c82395f61cea 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -292,6 +292,11 @@ return /obj/item/gun/proc/toggle_firing_mode(var/mob/user, var/list/message_mobs) + var/cancelled = FALSE + SEND_SIGNAL(user, COMSIG_GUN_TOGGLE_FIRING_MODE, src, &cancelled) + if (cancelled) + return + var/datum/firemode/new_mode = switch_firemodes(user) if(new_mode) playsound(user, safetyoff_sound, 25) @@ -431,7 +436,7 @@ return TRUE -/obj/item/gun/proc/Fire(atom/target, mob/living/user, clickparams, pointblank=0, reflex=0, accuracy_decrease=0, is_offhand=0) +/obj/item/gun/proc/Fire(atom/target, mob/living/user, clickparams, pointblank = 0, reflex = 0, var/accuracy_decrease = 0, is_offhand = 0) if(!fire_checks(target,user,clickparams,pointblank,reflex)) return FALSE @@ -441,6 +446,10 @@ var/decreased_accuracy = SG.w_class - SG.offhand_accuracy addtimer(CALLBACK(SG, PROC_REF(Fire), target, user, clickparams, pointblank, reflex, decreased_accuracy, TRUE), 1) + /// The amount of extra degrees of firing arc the gun will have from the effects of a signal raised on the user. + var/dispersion_increase = 0 + SEND_SIGNAL(user, COMSIG_BEFORE_GUN_FIRE, &accuracy_decrease, &dispersion_increase) + //actually attempt to shoot var/turf/targloc = get_turf(target) //cache this in case target gets deleted during shooting, e.g. if it was a securitron that got destroyed. for(var/i in 1 to burst) @@ -450,7 +459,7 @@ break var/acc = burst_accuracy[min(i, burst_accuracy.len)] - accuracy_decrease - var/disp = dispersion[min(i, dispersion.len)] + var/disp = dispersion[min(i, dispersion.len)] + dispersion_increase process_accuracy(projectile, user, target, acc, disp) if(pointblank) diff --git a/code/modules/projectiles/guns/launcher/pneumatic.dm b/code/modules/projectiles/guns/launcher/pneumatic.dm index 29a26dda8f0f..4967a4f30cba 100644 --- a/code/modules/projectiles/guns/launcher/pneumatic.dm +++ b/code/modules/projectiles/guns/launcher/pneumatic.dm @@ -30,7 +30,7 @@ return . += "The valve is dialed to [pressure_setting]%." if(tank) - . += "The tank dial reads [tank.air_contents.return_pressure()] kPa." + . += "The tank dial reads [XGM_PRESSURE(tank.air_contents)] kPa." else . += "Nothing is attached to the tank valve!" @@ -101,9 +101,9 @@ if(T) var/datum/gas_mixture/environment = T.return_air() if(environment) - environment_pressure = environment.return_pressure() + environment_pressure = XGM_PRESSURE(environment) - fire_pressure = (tank.air_contents.return_pressure() - environment_pressure)*pressure_setting/100 + fire_pressure = (XGM_PRESSURE(tank.air_contents) - environment_pressure)*pressure_setting/100 if(fire_pressure < 10) to_chat(user, "There isn't enough gas in the tank to fire [src].") return null diff --git a/code/modules/projectiles/guns/launcher/rocket.dm b/code/modules/projectiles/guns/launcher/rocket.dm index 1743699d964a..fd2a31ced2aa 100644 --- a/code/modules/projectiles/guns/launcher/rocket.dm +++ b/code/modules/projectiles/guns/launcher/rocket.dm @@ -19,6 +19,10 @@ var/max_rockets = 1 var/list/rockets = new/list() +/obj/item/gun/launcher/rocket/Destroy() + QDEL_LIST(rockets) + return ..() + /obj/item/gun/launcher/rocket/feedback_hints(mob/user, distance, is_adjacent) . += ..() if(is_adjacent) diff --git a/code/modules/projectiles/guns/projectile/automatic.dm b/code/modules/projectiles/guns/projectile/automatic.dm index 8de28415e6fb..c6bc54f437ac 100644 --- a/code/modules/projectiles/guns/projectile/automatic.dm +++ b/code/modules/projectiles/guns/projectile/automatic.dm @@ -545,13 +545,15 @@ automatic rifle. Laser weapons are usually used by high-ranking soldiers or special operatives. Regardless of advances in the small arms field, artillery is the Republican army’s \ main weapon and pride." - load_method = SINGLE_CASING|SPEEDLOADER - - ammo_type = /obj/item/ammo_casing/a762 - allowed_magazines = null - magazine_type = null + load_method = MAGAZINE|SPEEDLOADER + caliber = "6.8mm" + ammo_type = /obj/item/ammo_casing/a68 + allowed_magazines = list(/obj/item/ammo_magazine/a68, /obj/item/ammo_magazine/boltaction/adhomai) + magazine_type = /obj/item/ammo_magazine/a68 max_shells = 25 + worn_x_dimension = 48 //Uses 48x32 gun sprite + origin_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 2) fire_sound = 'sound/weapons/gunshot/gunshot_rifle.ogg' @@ -561,6 +563,17 @@ knife_x_offset = 23 knife_y_offset = 14 +/obj/item/gun/projectile/automatic/rifle/adhomian/update_icon() + item_state = (ammo_magazine)? "tsarrayut" : "tsarrayut_nomag" + ..() //Placed here so in-hand sprite reflects no magazine properly. + icon_state = (ammo_magazine)? "tsarrayut" : "tsarrayut_nomag" + +/obj/item/gun/projectile/automatic/rifle/adhomian/attackby(obj/item/attacking_item, mob/user) + if(istype(attacking_item, /obj/item/ammo_magazine/boltaction) && !ammo_magazine) + to_chat(user, SPAN_WARNING("\The [src] cannot be reloaded without a magazine!")) + return + ..() + /obj/item/gun/projectile/automatic/rifle/dpra name = "adhomian assault rifle" desc = "The Mrrazhak Model-1 is the newest Al'mariist automatic rifle. The Mrrazhak is notorious for its simple and reliable design; it can be fabricated and assembled without the \ @@ -568,33 +581,32 @@ icon = 'icons/obj/guns/mrrazhak.dmi' icon_state = "mrrazhak" item_state = "mrrazhak" - - can_bayonet = TRUE - knife_x_offset = 22 - knife_y_offset = 13 + contained_sprite = TRUE origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2) + + load_method = MAGAZINE|SPEEDLOADER + caliber = "6.8mm" + ammo_type = /obj/item/ammo_casing/a68 + allowed_magazines = list(/obj/item/ammo_magazine/a68) + magazine_type = /obj/item/ammo_magazine/a68 + max_shells = 25 + + worn_x_dimension = 48 //Uses 48x32 gun sprite + + origin_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 2) fire_sound = 'sound/weapons/gunshot/gunshot_rifle.ogg' is_wieldable = TRUE - magazine_type = /obj/item/ammo_magazine/c762/dpra - allowed_magazines = list(/obj/item/ammo_magazine/c762/dpra) + can_bayonet = TRUE + knife_x_offset = 23 + knife_y_offset = 14 /obj/item/gun/projectile/automatic/rifle/dpra/update_icon() - if(ammo_magazine) - icon_state = "mrrazhak" - item_state = "mrrazhak" - else - icon_state = "mrrazhak_nomag" - item_state = "mrrazhak_nomag" - ..() - -/obj/item/gun/projectile/automatic/rifle/dpra/gold - name = "gold plated adhomian assault rifle" - desc = "The Mrrazhak Model-1 is the newest Al'mariist automatic rifle. The Mrrazhak is notorious for its simple and reliable design; it can be fabricated and assembled without the \ - need of a specialized industry or a highly trained workforce. This one is golden plated." - icon = 'icons/obj/guns/golden_mrrazhak.dmi' + item_state = (ammo_magazine)? "mrrazhak" : "mrrazhak_nomag" + ..() //Placed here so in-hand sprite reflects no magazine properly. + icon_state = (ammo_magazine)? "mrrazhak" : "mrrazhak_nomag" /obj/item/gun/projectile/automatic/tommygun name = "submachine gun" diff --git a/code/modules/projectiles/guns/projectile/rifle.dm b/code/modules/projectiles/guns/projectile/rifle.dm index 6844cb5cd9fd..15103c5d1f9f 100644 --- a/code/modules/projectiles/guns/projectile/rifle.dm +++ b/code/modules/projectiles/guns/projectile/rifle.dm @@ -6,9 +6,9 @@ item_state = "moistnugget" origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2) fire_sound = 'sound/weapons/gunshot/gunshot_rifle.ogg' - caliber = "a762" - ammo_type = /obj/item/ammo_casing/a762 - magazine_type = /obj/item/ammo_magazine/boltaction + caliber = "6.8mm" + ammo_type = /obj/item/ammo_casing/a68 + magazine_type = /obj/item/ammo_magazine/boltaction/adhomai max_shells = 5 rack_sound = 'sound/weapons/riflebolt.ogg' @@ -37,7 +37,7 @@ /obj/item/gun/projectile/shotgun/pump/rifle/blank desc = "A replica of a traditional Adhomian bolt action rifle. It has the seal of the Grand Romanovich Casino on its stock." - ammo_type = /obj/item/ammo_casing/a762/blank + ammo_type = /obj/item/ammo_casing/a68/blank /obj/item/gun/projectile/shotgun/pump/rifle/scope name = "sniper bolt action rifle" diff --git a/code/modules/projectiles/guns/projectile/sniper.dm b/code/modules/projectiles/guns/projectile/sniper.dm index afabaf4af1b1..6dc0db9206c2 100644 --- a/code/modules/projectiles/guns/projectile/sniper.dm +++ b/code/modules/projectiles/guns/projectile/sniper.dm @@ -189,14 +189,16 @@ force = 15 slot_flags = SLOT_BACK origin_tech = list(TECH_COMBAT = 8, TECH_MATERIAL = 3, TECH_MAGNET = 2, TECH_ILLEGAL = 5) - caliber = "a762" + caliber = "6.8mm" recoil = 2 fire_sound = 'sound/weapons/gunshot/gunshot_svd.ogg' load_method = MAGAZINE max_shells = 10 - magazine_type = /obj/item/ammo_magazine/d762 - allowed_magazines = list(/obj/item/ammo_magazine/d762) + worn_x_dimension = 48 //Uses 48x32 gun sprite + + magazine_type = /obj/item/ammo_magazine/a68/hotaki + allowed_magazines = list(/obj/item/ammo_magazine/a68/hotaki) accuracy = -4 scoped_accuracy = 3 @@ -208,11 +210,9 @@ fire_delay = ROF_SUPERHEAVY /obj/item/gun/projectile/dragunov/update_icon() - ..() - if(ammo_magazine) - icon_state = "dragunov" - else - icon_state = "dragunov-empty" + item_state = (ammo_magazine)? "dragunov" : "dragunov_nomag" + ..() //Placed here so in-hand sprite reflects no magazine properly. + icon_state = (ammo_magazine)? "dragunov" : "dragunov_nomag" /obj/item/gun/projectile/dragunov/special_check(mob/user) if(!wielded) diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index 34d927607cbf..178201d5d937 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -302,6 +302,18 @@ armor_penetration = 30 penetrating = FALSE +/obj/projectile/bullet/rifle/a68 + name = "R33 Tamparii bullet" + damage = 40 + armor_penetration = 17 + penetrating = FALSE + +/obj/projectile/bullet/rifle/a68/ap + name = "R33s Tamparii bullet" + damage = 30 + armor_penetration = 30 + penetrating = TRUE + /obj/projectile/bullet/rifle/a145 damage = 80 stun = 3 diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm index d7cabd9f73d6..39949b7bba61 100644 --- a/code/modules/projectiles/projectile/energy.dm +++ b/code/modules/projectiles/projectile/energy.dm @@ -149,7 +149,7 @@ pass_flags = PASSTABLE | PASSGRILLE | PASSRAILING range = 10 embed = 0 - speed = 2 + speed = 1 light_range = 4 light_color = "#b5ff5b" diff --git a/code/modules/psionics/abilities/read_mind.dm b/code/modules/psionics/abilities/read_mind.dm index 203764951e4c..0db11f9d0142 100644 --- a/code/modules/psionics/abilities/read_mind.dm +++ b/code/modules/psionics/abilities/read_mind.dm @@ -23,10 +23,7 @@ read_mind(hit_atom, user) /obj/item/spell/read_mind/proc/read_mind(atom/hit_atom, mob/user) - if(!isliving(hit_atom)) - return - - if(!isliving(user)) + if(!isliving(hit_atom) || !isliving(user)) return var/mob/living/target = hit_atom @@ -48,36 +45,79 @@ user.visible_message(SPAN_WARNING("[user] lays a palm on [hit_atom]'s forehead...")) var/question if(!safe_mode) - question = sanitize(input(user, "Ask your question.", "Read Mind") as null|text) + question = tgui_input_text(user, "Ask your question.", "Read Mind", timeout = 1 MINUTE) if((!safe_mode && !question) || user.incapacitated()) return TRUE - var/started_mindread = world.time - if(target.has_psi_aug()) - to_chat(user, SPAN_NOTICE("Your psyche links with [target]'s psi-receiver, seeking [safe_mode ? "their surface thoughts." : "an answer from their mind's surface: [question]"]")) - to_chat(target, SPAN_NOTICE("[user]'s psyche links with your psi-receiver. [safe_mode ? "What are you thinking about, currently?" : "You cannot avoid the following question, and must answer truthfully: [question]"]")) - else - to_chat(user, SPAN_NOTICE("You dip your mentality into the surface layer of \the [target]'s mind, seeking an answer: [question]")) - to_chat(target, SPAN_NOTICE("Your mind is compelled to answer. [safe_mode ? "What are you thinking about, currently?" : "You cannot avoid the following question, and must answer truthfully: [question]"]")) - var/answer = sanitize(input(target, "[question]\n[safe_mode ? "You must answer with what you are currently thinking about." : "You must answer truthfully."]\nYou have 25 seconds to type a response.", "Read Mind") as null|text) - if(!answer || world.time > started_mindread + 25 SECONDS || user.stat != CONSCIOUS) + to_chat(user, SPAN_NOTICE(\ + target_sensitivity >= PSI_RANK_SENSITIVE \ + ? "Your consciousness mingles with [target]'s thoughts, imploring them to share an answer: [question]"\ + : "You dip your mentality into the surface layer of \the [target]'s mind, seeking an answer: [question]")) + to_chat(target, SPAN_NOTICE("Your mind is compelled to answer." \ + + safe_mode \ + /* If the target wins the psi-sensitivity check, they're prompted to say whatever they want.*/\ + ? "What are you thinking about, currently?" \ + /* And if the caster wins, the target is forced to answer a specific question.*/\ + : "You cannot avoid the following question, and must answer truthfully: " \ + + "[question]")) + + // Attempt to get an answer from the target. + var/answer = tgui_input_text(\ + target,\ + "[question]\n"\ + + safe_mode \ + ? "You must answer with what you are currently thinking about.\n" \ + : "You must answer truthfully.\n"\ + + "You have one minute to type a response.", \ + "Read Mind", \ + timeout = 1 MINUTE) + + // Exit early if the target failed to answer. + if(!answer || user.stat != CONSCIOUS) to_chat(user, SPAN_NOTICE("You receive nothing useful from \the [target].")) to_chat(target, SPAN_NOTICE("Your mind blanks out momentarily.")) + return + + if (target_sensitivity < 0) + // Negative sensitivity (of target) case. Underdeveloped Zona Bovinae return a scrambled message. + var/scrambled_message = stars(answer, (abs(target_sensitivity) * 25)) + to_chat(user, SPAN_NOTICE("You tease a half-formed thought from [target]'s mind: [scrambled_message]")) + to_chat(target, SPAN_NOTICE("Your answer to [user] arrives vaguely as: [scrambled_message]")) + else if(safe_mode) + to_chat(user, SPAN_NOTICE("You skim the first thoughts in [target]'s mind: [answer]")) + to_chat(target, SPAN_NOTICE("you answer [user] with: [answer]")) else - if (target_sensitivity < 0) - // Negative sensitivity (of target) case. Underdeveloped Zona Bovinae return a scrambled message. - var/scrambled_message = stars(answer, (abs(target_sensitivity) * 25)) - to_chat(user, SPAN_NOTICE("You tease a half-formed thought from [target]'s mind: [scrambled_message]")) - else if(safe_mode) - to_chat(user, SPAN_NOTICE("You skim the first thoughts in [target]'s mind: [answer]")) - else - to_chat(user, SPAN_NOTICE("You pry the answer to your question from [target]'s mind: [answer]")) - msg_admin_attack("[key_name(user)] read mind of [key_name(target)] [safe_mode ? "skimming their surface thoughts" : "forcing them to answer truthfully with question \"[question]\""] and [answer?"got answer \"[answer]\".":"got no answer."]") - if(safe_mode) - target.confused += 15 - target.adjustBrainLoss(10) - to_chat(target, SPAN_WARNING("You feel somewhat nauseated, and a headache's come up too...")) - else - target.adjustBrainLoss(20) - target.confused += 20 - to_chat(target, SPAN_DANGER("Your head feels like it's going to explode, and you feel nauseated...")) + to_chat(user, SPAN_NOTICE("You pry the answer to your question from [target]'s mind: [answer]")) + to_chat(target, SPAN_NOTICE("You are compelled to answer [user] with: [answer]")) + + msg_admin_attack("[key_name(user)] read mind of [key_name(target)] " \ + + safe_mode \ + ? "skimming their surface thoughts " \ + : "forcing them to answer truthfully with question: \"[question]\" " \ + + "and " \ + + answer \ + ? "got answer: \"[answer]\"." \ + : "got no answer.") + + // We take the logistic curve of the psi_sensitivity in order to create a double asymptote that confines the effects without requiring truncating to 0, or setting a maximum. + // Maximums occur at +/- infinity. While normal values roughly around 0.5x occur very close to +/- 1. + // "More sensitivity" reduces negative effects of the power. + // "Less sensitivity" increases said negative effects. + // See this graph for a visual explanation of what this is doing: https://www.desmos.com/calculator/dl8zapsnsn + var/psi_sensitivity_ratio = (20 - (ftanh(0.5 * target_sensitivity) * 20)) * (safe_mode ? 0.5 : 1) + + // Minimum of confusion time 0 seconds, maximum of 40 seconds. 20 seconds for an unaugmented human. + target.confused += psi_sensitivity_ratio SECONDS + + // Minimum brain damage of 0, maximum of 20%. 10% for a unaugmented human. + target.adjustBrainLoss(psi_sensitivity_ratio) + + to_chat(target, \ + target_sensitivity >= PSI_RANK_SENSITIVE \ + /* Case for high-sensitivity.*/\ + ? SPAN_NOTICE("Your mind reels as it resists a blast of psychic pressure.")\ + : target_sensitivity >= 0 \ + /* Case for standard-human psi-sensitivity.*/\ + ? SPAN_DANGER("Your head feels like it's going to explode, and you feel nauseated...")\ + /* Case for low-sensitivity.*/\ + : SPAN_DANGER("You black out briefly, awakening to a world that inexplicably smells like burnt toast.")) diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents.dm index ba40bc225e99..c3c7eb3cf9e8 100644 --- a/code/modules/reagents/Chemistry-Reagents.dm +++ b/code/modules/reagents/Chemistry-Reagents.dm @@ -61,6 +61,8 @@ var/accelerant_quality = 0 ///Should this reagent burn a different color? var/fire_color = null + ///Should this reagent spawn napalm from a flamethrower? + var/obj/effect/decal/cleanable/napalm/flamethrower_effect = null /// Called when the reagent is created. /singleton/reagent/proc/initialize_data(var/newdata, var/datum/reagents/holder) diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm index b97e994c7425..a10632dc967c 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm @@ -104,6 +104,7 @@ M.inject_blood(REAGENT_VOLUME(holder, type), holder) remove_self(REAGENT_VOLUME(holder, type), holder) +#define WATER_MOLS_PER_MIL 0.0556 // How many mols of water exist per mL #define WATER_LATENT_HEAT 19000 // How much heat is removed when applied to a hot turf, in J/unit (19000 makes 120 u of water roughly equivalent to 4L) /singleton/reagent/water name = "Water" @@ -147,11 +148,24 @@ T.assume_air(lowertemp) qdel(hotspot) - if (environment && environment.temperature > min_temperature) // Abstracted as steam or something + var/obj/effect/decal/cleanable/napalm/napalm = (locate(/obj/effect/decal/cleanable/napalm) in T) + if(napalm?.on_fire) + //Punish players for attempting to put out napalm fires with water by adding more napalm. Simulate spreading it more. + napalm.add_napalm(amount / 4) + environment.adjust_gas(GAS_WATERVAPOR, WATER_MOLS_PER_MIL * amount) + napalm.audible_message( + SPAN_DANGER("The water sputters violently as it lands on \the [napalm.name]!"), + SPAN_DANGER("The fire goes down a bit on \the [napalm.name], but immediately returns!") + ) + return + + if (environment && environment.temperature > min_temperature) // Abstracted as steam or something -- NOT ANYMORE! REAL STEAM! var/removed_heat = between(0, amount * WATER_LATENT_HEAT, -environment.get_thermal_energy_change(min_temperature)) environment.add_thermal_energy(-removed_heat) if (prob(5)) - T.visible_message(SPAN_WARNING("The water sizzles as it lands on \the [T]!")) + T.audible_message(SPAN_WARNING("The water sizzles as it lands on \the [T]!")) + + environment.adjust_gas(GAS_WATERVAPOR, WATER_MOLS_PER_MIL * amount) else if(amount >= 10) T.wet_floor(WET_TYPE_WATER,amount) @@ -199,7 +213,7 @@ if(!S.client && S.target) S.target = null ++S.discipline - +#undef WATER_MOLS_PER_MIL /singleton/reagent/fuel name = "Welding Fuel" diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Drugs.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Drugs.dm index d0108be28788..921f4a0c6c3e 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Drugs.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Drugs.dm @@ -312,7 +312,7 @@ M.hallucination = max(M.hallucination, drug_strength) if(prob(15)) - to_chat(SPAN_GOOD(pick("The floor is melting...", "Everything is so much brighter! Wow!", "Everything is shifting around you."))) + to_chat(M, SPAN_GOOD(pick("The floor is melting...", "Everything is so much brighter! Wow!", "Everything is shifting around you."))) /singleton/reagent/drugs/night_juice diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm index ffc50d528756..c269b4f3be65 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm @@ -328,7 +328,7 @@ /singleton/reagent/mortaphenyl name = "Mortaphenyl" - description = "Mortaphenyl is an advanced, powerful analgesic medication which is highly effective at treating mild-severe pain as a result of severe, physical injury. Mortaphenyl is not effective when inhaled." + description = "Mortaphenyl is a weak, synthetic, analgesic opioid which is highly effective at treating mild-severe pain as a result of severe, physical injury. Mortaphenyl is not effective when inhaled." reagent_state = LIQUID color = "#CB68FC" overdose = 15 @@ -443,7 +443,7 @@ /singleton/reagent/tramarine name = "Tramarine" - description = "Tramarine is a synthetic form of morphine developed by NanoTrasen early in its history, that can be used in its place for most medical purposes. It is known to be more dangerous however with alcohol, other opiods, or an overdose." + description = "Tramarine is a synthetic form of morphine developed by NanoTrasen early in its history, that can be used in its place for most medical purposes. It is known to be more dangerous however with alcohol, other opioids, or an overdose." reagent_state = LIQUID color = "#c4a05d" overdose = 15 diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm index 393fde24cc24..7dca107a8c75 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm @@ -642,6 +642,32 @@ to_chat(M, SPAN_WARNING("You seem back to your normal self.")) +/singleton/reagent/fuel/napalm + name = "napalm" + description = "A flammable gel used in warfare." + reagent_state = LIQUID + color = "#D35908" + touch_met = 50 + taste_description = "fiery death" + taste_mult = 20 + accelerant_quality = 20 + flamethrower_effect = /obj/effect/decal/cleanable/napalm + +/singleton/reagent/fuel/napalm/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder) + new /obj/effect/decal/cleanable/napalm(T, amount/3) + for(var/mob/living/L in T) + L.adjust_fire_stacks(amount / 10) + remove_self(amount, holder) + return + +/singleton/reagent/fuel/napalm/touch_mob(var/mob/living/L, var/amount, var/datum/reagents/holder) + . = ..() + if(istype(L)) + L.adjust_fire_stacks(amount / 10) // Splashing people with welding fuel to make them easy to ignite! + new /obj/effect/decal/cleanable/napalm(get_turf(L), amount/3) + L.adjustFireLoss(amount / 10) + remove_self(amount, holder) + /singleton/reagent/fuel/zoragel name = "Inert Gel" description = "A particularly adhesive but otherwise inert and harmless gel." @@ -650,28 +676,29 @@ touch_met = 50 taste_description = "plhegm" -/singleton/reagent/fuel/napalm - name = "Zo'rane Fire" - description = "A highly flammable and cohesive gel once used commonly in the tunnels of Sedantis. Napalm sticks to kids." +/singleton/reagent/fuel/zorane_fire + name = "Zo'rane fire" + description = "A highly flammable and cohesive gel once used commonly in the tunnels of Sedantis." reagent_state = LIQUID - color = "#D35908" + color = "#FA00AF" touch_met = 50 taste_description = "fiery death" taste_mult = 20 - accelerant_quality = 20 + accelerant_quality = 40 + flamethrower_effect = /obj/effect/decal/cleanable/napalm/zorane_fire -/singleton/reagent/fuel/napalm/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder) - new /obj/effect/decal/cleanable/liquid_fuel/napalm(T, amount/3) +/singleton/reagent/fuel/zorane_fire/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder) + new /obj/effect/decal/cleanable/napalm/zorane_fire(T, amount/3) for(var/mob/living/L in T) L.adjust_fire_stacks(amount / 10) remove_self(amount, holder) return -/singleton/reagent/fuel/napalm/touch_mob(var/mob/living/L, var/amount, var/datum/reagents/holder) +/singleton/reagent/fuel/zorane_fire/touch_mob(var/mob/living/L, var/amount, var/datum/reagents/holder) . = ..() if(istype(L)) L.adjust_fire_stacks(amount / 10) // Splashing people with welding fuel to make them easy to ignite! - new /obj/effect/decal/cleanable/liquid_fuel/napalm(get_turf(L), amount/3) + new /obj/effect/decal/cleanable/napalm/zorane_fire(get_turf(L), amount/3) L.adjustFireLoss(amount / 10) remove_self(amount, holder) diff --git a/code/modules/reagents/Chemistry-Recipes.dm b/code/modules/reagents/Chemistry-Recipes.dm index bae511a6bb46..e1ec60ad8c44 100644 --- a/code/modules/reagents/Chemistry-Recipes.dm +++ b/code/modules/reagents/Chemistry-Recipes.dm @@ -168,7 +168,7 @@ name = "Perconol" id = "perconol" result = /singleton/reagent/perconol - required_reagents = list(/singleton/reagent/mortaphenyl = 1, /singleton/reagent/sugar = 1, /singleton/reagent/water = 1) + required_reagents = list(/singleton/reagent/mortaphenyl = 1, /singleton/reagent/sugar = 1, /singleton/reagent/hydrazine = 1) result_amount = 3 /datum/chemical_reaction/oxycomorphine @@ -1017,16 +1017,9 @@ name = "Napalm" id = "napalm" result = null - required_reagents = list(/singleton/reagent/aluminum = 1, /singleton/reagent/toxin/phoron = 1, /singleton/reagent/acid = 1 ) + required_reagents = list(/singleton/reagent/aluminum = 1, /singleton/reagent/fuel = 1, /singleton/reagent/acid = 1 ) result_amount = 1 - -/datum/chemical_reaction/napalm/on_reaction(var/datum/reagents/holder, var/created_volume) - var/turf/location = get_turf(holder.my_atom.loc) - for(var/turf/simulated/floor/target_tile in range(0,location)) - target_tile.assume_gas(GAS_PHORON, created_volume, 400+T0C) - spawn (0) target_tile.hotspot_expose(700, 400) - holder.del_reagent(/singleton/reagent/fuel/napalm) - return + log_is_important = TRUE /datum/chemical_reaction/zoragel name = "Inert Gel" @@ -1038,10 +1031,10 @@ /datum/chemical_reaction/zorafire name = "Zo'rane Fire" id = "greekfire" - result = /singleton/reagent/fuel/napalm + result = /singleton/reagent/fuel/zorane_fire required_reagents = list(/singleton/reagent/nitroglycerin = 2, /singleton/reagent/pyrosilicate = 2, /singleton/reagent/toxin/phoron = 3, /singleton/reagent/fuel/zoragel = 3) result_amount = 1 - log_is_important = 1 + log_is_important = TRUE /datum/chemical_reaction/chemsmoke name = "Chemsmoke" @@ -1894,6 +1887,20 @@ new /obj/item/reagent_containers/food/snacks/sliceable/cheesewheel(location) return +/datum/chemical_reaction/adhomian_cheesewheel + name = "Adhomian Cheese" + id = "adhomian cheese" + result = null + required_reagents = list(/singleton/reagent/drink/milk/adhomai/fermented = 40) + catalysts = list(/singleton/reagent/enzyme = 5) + result_amount = 1 + +/datum/chemical_reaction/adhomian_cheesewheel/on_reaction(var/datum/reagents/holder, var/created_volume) + var/location = get_turf(holder.my_atom) + for(var/i = 1, i <= created_volume, i++) + new /obj/item/reagent_containers/food/snacks/sliceable/adhomian_cheese(location) + return + /datum/chemical_reaction/nakarka name = "Nakarka Cheese" id = "nakarka" diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 1d4e02d35630..144a0296bdca 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -248,6 +248,7 @@ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) //puts a limit on how fast people can eat/drink things self_feed_message(user) reagents.trans_to_mob(user, min(10,amount_per_transfer_from_this), CHEM_INGEST) //A sane limiter. So you don't go drinking 300u all at once. + SEND_SIGNAL(src, COMSIG_CONTAINER_DRANK, user) feed_sound(user) return TRUE else @@ -350,8 +351,8 @@ var/trans = reagents.trans_to(target, amount_per_transfer_from_this) to_chat(user, SPAN_NOTICE("You transfer [trans] units of the solution to [target].")) - on_pour() + on_pour(target) return 1 -/obj/item/reagent_containers/proc/on_pour() +/obj/item/reagent_containers/proc/on_pour(var/atom/target) playsound(src, SFX_POUR, 25, 1) diff --git a/code/modules/reagents/reagent_containers/food/cans.dm b/code/modules/reagents/reagent_containers/food/cans.dm index d100b29a55f6..18aeb200c120 100644 --- a/code/modules/reagents/reagent_containers/food/cans.dm +++ b/code/modules/reagents/reagent_containers/food/cans.dm @@ -474,6 +474,16 @@ reagents_to_add = list(/singleton/reagent/drink/milk/adhomai/fermented = 30) +/obj/item/reagent_containers/food/drinks/cans/earthen_juice + name = "earthen-root juice" + desc = "A can of earthen-root juice, imported from Adhomai." + icon_state = "earthen_can" + item_state = "earthen_can" + center_of_mass = list("x"=16, "y"=10) + desc_extended = "The Earthen-Root, or Binajr-nab'at, is a herbaceous plant native to the region of the Northern Harr'masir, and is popular in the New Kingdom of Adhomai due to it's resilience in harsh environments. Common uses for the Earth-Root, besides being used in dishes, include distillation to brew alcoholic beverages, extraction of the blue pigment for the fabrication of dyes, and the production of sugar." + + reagents_to_add = list(/singleton/reagent/drink/earthenrootjuice = 30) + /obj/item/reagent_containers/food/drinks/cans/beetle_milk name = "\improper Hakhma Milk" desc = "A can of Hakhma beetle milk, sourced from Scarab and Drifter communities." diff --git a/code/modules/reagents/reagent_containers/food/drinks.dm b/code/modules/reagents/reagent_containers/food/drinks.dm index 2504f2c9a5ad..48bdfbafbc2c 100644 --- a/code/modules/reagents/reagent_containers/food/drinks.dm +++ b/code/modules/reagents/reagent_containers/food/drinks.dm @@ -368,6 +368,9 @@ If you add a drink with an empty icon sprite, ensure it is in the same folder, e var/twisted = FALSE var/obj/item/shaker_top/top var/obj/item/reagent_containers/food/drinks/shaker_cup/cap + var/drink_quality = null + var/drink_moodlet_value = null + var/moodlet_value_per_bartending_rank = 5 /obj/item/reagent_containers/food/drinks/shaker/mechanics_hints(mob/user, distance, is_adjacent) . += ..() @@ -429,6 +432,16 @@ If you add a drink with an empty icon sprite, ensure it is in the same folder, e if(last_shake <= world.time - 10) //Spam limiter. last_shake = world.time playsound(src.loc, SFX_SHAKER_SHAKING, 50, 1) + + /** + ------------ Bartender Skill Handling ------------ + */ + var/datum/component/skill/bartending/bar_skill = user.GetComponent(BARTENDING_SKILL_COMPONENT) + if (bar_skill) + drink_moodlet_value = moodlet_value_per_bartending_rank * bar_skill.skill_level + if (isnull(drink_quality)) + drink_quality = rand(1, 20) + 3 * bar_skill.skill_level + src.add_fingerprint(user) return @@ -464,7 +477,28 @@ If you add a drink with an empty icon sprite, ensure it is in the same folder, e return TRUE return ..() -/obj/item/reagent_containers/food/drinks/shaker/on_pour() +/obj/item/reagent_containers/food/drinks/shaker/on_pour(var/atom/target) + if (!isnull(drink_quality)) + switch (drink_quality) + if (0 to 5) + target.name = "inferior " + target.name + if (5 to 10) + target.name = "cheap " + target.name + if (10 to 15) + target.name = "finely-mixed " + target.name + if (15 to 20) + target.name = "superior quality " + target.name + if (20 to INFINITY) + target.name = "masterful " + target.name + + if (!isnull(drink_moodlet_value)) + target.LoadComponent(/datum/component/drink_moodlet_provider, drink_moodlet_value, FALSE) + + // Bartender has finished pouring a drink, prepare the shaker to make the next one. + if (!reagents.total_volume) + drink_quality = null + drink_moodlet_value = null + if(!top) playsound(src, 'sound/effects/pour_big.ogg', 50, 1) return diff --git a/code/modules/reagents/reagent_containers/food/lunch.dm b/code/modules/reagents/reagent_containers/food/lunch.dm index 566e1d5f9b9f..e2dec63f238a 100644 --- a/code/modules/reagents/reagent_containers/food/lunch.dm +++ b/code/modules/reagents/reagent_containers/food/lunch.dm @@ -10,7 +10,7 @@ GLOBAL_LIST_INIT(lunchables_lunches_, list( /obj/item/reagent_containers/food/snacks/tastybread, /obj/item/reagent_containers/food/snacks/liquidfood, /obj/item/reagent_containers/food/snacks/jellysandwich/cherry, - /obj/item/reagent_containers/food/snacks/salad/tossedsalad, + /obj/item/reagent_containers/food/snacks/salad/applesalad, /obj/item/reagent_containers/food/snacks/funnelcake, /obj/item/reagent_containers/food/snacks/hotdog, /obj/item/reagent_containers/food/snacks/tajaran_bread, @@ -32,7 +32,13 @@ GLOBAL_LIST_INIT(lunchables_lunches_, list( /obj/item/reagent_containers/food/snacks/stokkebab, /obj/item/reagent_containers/food/snacks/batwings, /obj/item/reagent_containers/food/snacks/salad/earthenroot, - /obj/item/reagent_containers/food/snacks/pepperoniroll + /obj/item/reagent_containers/food/snacks/pepperoniroll, + /obj/item/reagent_containers/food/snacks/hardbread, + /obj/item/reagent_containers/food/snacks/nomadskewer, + /obj/item/reagent_containers/food/snacks/earthenroot_mash, + /obj/item/reagent_containers/food/snacks/earthenroot_fries, + /obj/item/reagent_containers/food/snacks/explorer_ration, + /obj/item/reagent_containers/food/snacks/clam_pasta )) GLOBAL_LIST_INIT(lunchables_snacks_, list( @@ -81,7 +87,10 @@ GLOBAL_LIST_INIT(lunchables_snacks_, list( /obj/item/reagent_containers/food/snacks/honeybun, /obj/item/reagent_containers/food/snacks/stuffed_meatball, /obj/item/reagent_containers/food/snacks/grilled_peppers, - /obj/item/reagent_containers/food/snacks/salmiak + /obj/item/reagent_containers/food/snacks/salmiak, + /obj/item/reagent_containers/food/snacks/chip/miniavah/full, + /obj/item/reagent_containers/food/snacks/zkahnkowaslice/filled, + /obj/item/reagent_containers/food/snacks/dirt_roast )) GLOBAL_LIST_INIT(lunchables_drinks_, list( @@ -118,7 +127,8 @@ GLOBAL_LIST_INIT(lunchables_drinks_, list( /obj/item/reagent_containers/food/drinks/cans/zorasoda/lemonlime, /obj/item/reagent_containers/food/drinks/cans/zorasoda/xuizi, /obj/item/reagent_containers/food/drinks/cans/zorasoda/dyn, - /obj/item/reagent_containers/food/drinks/cans/zorasoda/buzz + /obj/item/reagent_containers/food/drinks/cans/zorasoda/buzz, + /obj/item/reagent_containers/food/drinks/cans/earthen_juice )) GLOBAL_LIST_INIT(lunchables_vaurca_, list( diff --git a/code/modules/reagents/reagent_containers/food/snacks/breads.dm b/code/modules/reagents/reagent_containers/food/snacks/breads.dm index e5470665f91f..bec7c8446946 100644 --- a/code/modules/reagents/reagent_containers/food/snacks/breads.dm +++ b/code/modules/reagents/reagent_containers/food/snacks/breads.dm @@ -629,7 +629,7 @@ /obj/item/reagent_containers/food/snacks/cucumber_sandwich name = "cucumber sandwich" - desc = "Slices of cucumber between two buttered pieces of white bread witht he crust cut off. A light and delightful little finger food to have alongside your tea." + desc = "Slices of cucumber between two buttered pieces of white bread with the crust cut off. A light and delightful little finger food to have alongside your tea." icon = 'icons/obj/item/reagent_containers/food/bread.dmi' icon_state = "cucumbersandwich" filling_color = "#97df68" diff --git a/code/modules/reagents/reagent_containers/food/snacks/cultural/human.dm b/code/modules/reagents/reagent_containers/food/snacks/cultural/human.dm index 2dedd99bf60a..919dd0823c0c 100644 --- a/code/modules/reagents/reagent_containers/food/snacks/cultural/human.dm +++ b/code/modules/reagents/reagent_containers/food/snacks/cultural/human.dm @@ -343,6 +343,75 @@ bitesize = 10 filling_color = "#be7017" +/obj/item/reagent_containers/food/snacks/chipplate/churros + name = "churros" + gender = PLURAL + desc = "Sweet, deep fried batter coated in powdered sugar. While this beloved dish originated in Europe, it became popular in cultures all around Earth long before Humanity took to the stars, and as such - today it can be found in many different cultures all across the spur. Despite this, it is sometimes attributed to Mictlani cuisine for whatever reason." + icon = 'icons/obj/item/reagent_containers/food/cultural/human.dmi' + icon_state = "churros" + unitname = "churro" + filling_color = "#a77339" + trash = /obj/item/trash/chipbasket + vendingobject = /obj/item/reagent_containers/food/snacks/churro + bitesize = 3 + reagents_to_add = list(/singleton/reagent/nutriment = 6) + reagent_data = list(/singleton/reagent/nutriment = list("fried pastry dough" = 5, "cinnamon sugar" = 4)) + +/obj/item/reagent_containers/food/snacks/chipplate/churros/update_icon() + switch(reagents.total_volume) + if(1 to 3) + icon_state = "churros_half" + if(4 to INFINITY) + icon_state = "churros" + +/obj/item/reagent_containers/food/snacks/chipplate/churros/attack_hand(mob/user) + SHOULD_CALL_PARENT(FALSE) + var/obj/item/reagent_containers/food/snacks/returningitem = new vendingobject(loc) + returningitem.reagents.clear_reagents() + reagents.trans_to(returningitem, bitesize) + user.put_in_hands(returningitem) + if (reagents && reagents.total_volume) + to_chat(user, "You take \a [unitname] from the plate.") + else + to_chat(user, "You take the last [unitname] from the plate.") + var/obj/waste = new trash(loc) + if (loc == user) + user.put_in_hands(waste) + qdel(src) + +/obj/item/reagent_containers/food/snacks/churro + name = "churro" + desc = "A classic sweet fried batter stick found anywhere from carnival booths to higher end restaurants." + icon = 'icons/obj/item/reagent_containers/food/cultural/human.dmi' + icon_state = "churro" + filling_color = "#a77339" + center_of_mass = list("x"=15, "y"=9) + bitesize = 1 + +/obj/item/reagent_containers/food/snacks/churro/on_reagent_change() + if(reagents.has_reagent(/singleton/reagent/condiment/syrup_chocolate)) + if(bitecount>=1) + icon_state = "churro_bitten" + else + name = "chocolate dipped churro" + desc = "The sweets just keep getting sweeter!" + icon_state = "churro_chocolate" + + else if(reagents.has_reagent(/singleton/reagent/condiment/syrup_caramel)) + if(bitecount>=1) + icon_state = "churro_bitten" + else + name = "caramel dipped churro" + desc = "A classic snack with a classic dip." + icon_state = "churro_caramel" + else if(bitecount>=1) + icon_state = "churro_bitten" + + +/obj/item/reagent_containers/food/snacks/churro/filled + reagents_to_add = list(/singleton/reagent/nutriment = 3) + reagent_data = list(/singleton/reagent/nutriment = list("fried pastry dough" = 5, "cinnamon sugar" = 4)) + // Konyang /obj/item/reagent_containers/food/snacks/mossbowl @@ -848,17 +917,34 @@ ABSTRACT_TYPE(/obj/item/reagent_containers/food/snacks/bowl) //Silversun -/obj/item/reagent_containers/food/snacks/clams_casino +/obj/item/reagent_containers/food/snacks/bowl/clams_casino name = "silversun clams casino" desc = "A true silversun classic, clams on the halfshell with breadcrumbs, bacon, and bell peppers. Somehow landing right in the middle ring between average joe finger food and upper class fanciness." icon = 'icons/obj/item/reagent_containers/food/cultural/human.dmi' icon_state = "clamscasino" + gender = PLURAL + unitname = "clam casino" + vendingobject = /obj/item/reagent_containers/food/snacks/clam_casino trash = /obj/item/trash/plate bitesize = 2 filling_color = "#a5683f" reagents_to_add = list(/singleton/reagent/nutriment/protein/seafood/mollusc = 6, /singleton/reagent/nutriment/protein = 2, /singleton/reagent/nutriment = 2) reagent_data = list(/singleton/reagent/nutriment/protein/seafood/mollusc = list("buttery clams" = 15), /singleton/reagent/nutriment/protein = list ("bacon" = 15), /singleton/reagent/nutriment = list("breadcrumbs" = 10, "bell peppers" = 10)) +/obj/item/reagent_containers/food/snacks/bowl/clams_casino/update_icon() + switch(reagents.total_volume) + if(1 to 3) + icon_state = "clamscasino_half" + if(4 to INFINITY) + icon_state = "clamscasino" + +/obj/item/reagent_containers/food/snacks/clam_casino + name = "clam casino" + desc = "Buttery, crunchy, fancy without being hoity toity, nothing says nouveau riche like clams casino" + icon = 'icons/obj/item/reagent_containers/food/cultural/human.dmi' + icon_state = "clam_casino" + filling_color = "#c98151" + /obj/item/reagent_containers/food/snacks/sliceable/lady_lulaine name = "lady lulaine" desc = "This rich and creamy berry-coated dessert was invented in a small coastal town on Silversun. It's very tricky to get it stable enough to not collapse under it's own weight. What are you waiting for? Slice it up!" @@ -1120,3 +1206,71 @@ ABSTRACT_TYPE(/obj/item/reagent_containers/food/snacks/bowl) icon = 'icons/obj/item/reagent_containers/food/cultural/human.dmi' icon_state = "belina" filling_color = "#c98151" + +//Venus + +/obj/item/reagent_containers/food/snacks/elata + name = "elata" + desc = "An overwhelmingly sweet and photogenic Cytherean dessert with a berry flavored shell, a thick, creamy interior and a dulce de leche core. Too sweet for some, absolute decedance for those who can handle it." + icon = 'icons/obj/item/reagent_containers/food/cultural/human.dmi' + icon_state = "elata" + filling_color = "#d872be" + bitesize = 2 + reagents_to_add = list(/singleton/reagent/nutriment/ = 3, /singleton/reagent/nutriment/glucose = 2, /singleton/reagent/drink/milk/cream = 3, /singleton/reagent/drink/ice = 1) + reagent_data = list(/singleton/reagent/nutriment = list("dulche de leche" = 5, "sweet cream" = 4, "wafer" = 3, "pink attitude" = 3)) + +/obj/item/reagent_containers/food/snacks/elata/update_icon() + var/expected_initial_reagent_volume + for(var/k in src.reagents_to_add) + expected_initial_reagent_volume += reagents_to_add[k] + var/percent_elata = round((reagents.total_volume / expected_initial_reagent_volume) * 100) + switch(percent_elata) + if(0 to 90) + icon_state = "elata_half" + if(91 to INFINITY) + icon_state = "elata" + +/obj/item/reagent_containers/food/snacks/filet_cabaret + name = "filet cabaret" + desc = "A fancy Cytherian dish of braised, slow cooked, buttery prime tenderloin soaked in red wine and herbs. Just like the true 5-star dish it is, it is fancy, it is delicious, and it is so abhorrently tiny there's no way you'll feel like you ate anything. If you have to ask how much it costs, you can't afford it." + icon = 'icons/obj/item/reagent_containers/food/cultural/human.dmi' + icon_state = "filet_cabaret" + bitesize = 2 + filling_color = "#61391e" + reagents_to_add = list(/singleton/reagent/nutriment/protein = 1, /singleton/reagent/nutriment = 1, /singleton/reagent/alcohol/wine/assunzione = 1) + reagent_data = list(/singleton/reagent/nutriment = list("fanciness" =5), /singleton/reagent/nutriment/protein = list("juicy meat" = 5, "herbs" = 5)) + +/obj/item/reagent_containers/food/snacks/embassy_strips + name = "embassy strips" + desc = "A fairly fancy Cytherian dish with clear inspiration in Asian and Konyanger cuisine, it offers strips of fish in vinigrette sauce, soy jelly cubes with dyn coating, ginger and mayonnaise." + icon = 'icons/obj/item/reagent_containers/food/cultural/human.dmi' + icon_state = "embassy" + bitesize = 2 + filling_color = "#f0eaca" + reagents_to_add = list(/singleton/reagent/nutriment/protein/seafood = 5, /singleton/reagent/nutriment = 2) + reagent_data = list(/singleton/reagent/nutriment/protein/seafood = list("lemony seasoned fish" = 5), /singleton/reagent/nutriment = list("soy jelly" = 5, "mayonnaise" = 5, "mint" = 4)) + +/obj/item/reagent_containers/food/snacks/embassy_strips/update_icon() + var/expected_initial_reagent_volume + for(var/k in src.reagents_to_add) + expected_initial_reagent_volume += reagents_to_add[k] + var/percent_embassy = round((reagents.total_volume / expected_initial_reagent_volume) * 100) + switch(percent_embassy) + if(0 to 50) + icon_state = "embassy_half" + if(51 to INFINITY) + icon_state = "embassy" + +/obj/item/reagent_containers/food/snacks/blitz_shake //Yes, it's a food, not a drink. + name = "blitz shake" + desc = "Specifically created to look good on social media and blind innocent passerbys, this trendy Cytherian milkshake has an entire candystore toppled on top of it. Whipped cream, sprinkles, marshmallows, candy... Hell, there's an entire freaking donut on this thing! Calling this a drink would be very generous, calling it diabetic shock might be a bit more accurate." + icon = 'icons/obj/item/reagent_containers/food/cultural/human.dmi' + icon_state = "blitz" + item_state = "blitz" + bitesize = 2 + trash = /obj/item/reagent_containers/food/drinks/drinkingglass + filling_color = "#ff00ea" + is_liquid = TRUE + contained_sprite = TRUE + reagents_to_add = list(/singleton/reagent/drink/shake_strawberry = 3, /singleton/reagent/nutriment/sprinkles = 3, /singleton/reagent/nutriment/glucose = 3, /singleton/reagent/nutriment = 3) + reagent_data = list(/singleton/reagent/nutriment/sprinkles = list("unicorns" = 5), /singleton/reagent/nutriment/glucose = list("rainbows" = 5), /singleton/reagent/nutriment = list("your doctor crying" = 5)) diff --git a/code/modules/reagents/reagent_containers/food/snacks/cultural/tajara.dm b/code/modules/reagents/reagent_containers/food/snacks/cultural/tajara.dm index 27574938fd78..e7a3a105a77b 100644 --- a/code/modules/reagents/reagent_containers/food/snacks/cultural/tajara.dm +++ b/code/modules/reagents/reagent_containers/food/snacks/cultural/tajara.dm @@ -193,7 +193,7 @@ /obj/item/reagent_containers/food/snacks/soup/zharkir name = "zharkir" item_state = "zharkir" - desc = "A thick, hot, creamy dish, not unlike a chowder (and known as 'adhomian chowder' in some cultures). It is made with sarmikhir, earthenroot and various adhomian herbs, balancing sweet and savory, and served in a traditional dish - a tall bowl with grooves on the side just big enough for tajaran hands to hold it up to their mouths and warm themselves on a cold Adhomian evening." + desc = "A thick, hot, creamy dish, not unlike a chowder (and known as 'adhomian chowder' in some cultures). It is made with sarmikhir, earthenroot and various Adhomian herbs, balancing sweet and savory, and served in a traditional dish - a tall bowl with grooves on the side just big enough for tajaran hands to hold it up to their mouths and warm themselves on a cold Adhomian evening." icon = 'icons/obj/item/reagent_containers/food/cultural/tajara.dmi' icon_state = "zharkir" is_liquid = TRUE @@ -320,6 +320,10 @@ bitten_state = "avah_half" bitesize = 3 +/obj/item/reagent_containers/food/snacks/chip/miniavah/full + reagents_to_add = list(/singleton/reagent/nutriment = 3, /singleton/reagent/nutriment/protein = 3) + reagent_data = list(/singleton/reagent/nutriment = list("baked dough" = 3), /singleton/reagent/nutriment/protein = list("savoury meat" = 3)) + /obj/item/reagent_containers/food/snacks/chip/miniavah/cheese name = "cheese mini-avah" desc = "A miniature avah filled with meat. This one has cheese on it." @@ -785,3 +789,72 @@ reagent_data = list(/singleton/reagent/nutriment = list("sour cream" = 2), /singleton/reagent/nutriment/protein = list("roasted sausage" = 2)) bitesize = 1 filling_color = "#94372A" + +/obj/item/reagent_containers/food/snacks/sliceable/adhomian_cheese + name = "adhomian cheese" + desc = "Cheese made from fermented fatshouter milk. Adhomai, much like Earth, developed many different ways to make and flavor cheese, long before either culture made contact with the other. It's interesting that these things happened unrelated to each other, but then again, someone's unattended glass of milk was bound to go bad and curdle sooner or later." + icon = 'icons/obj/item/reagent_containers/food/cultural/tajara.dmi' + icon_state = "cheese" + slice_path = /obj/item/reagent_containers/food/snacks/adhomian_cheese_wedge + slices_num = 8 + filling_color = "#fdfdfd" + center_of_mass = list("x"=16, "y"=10) + bitesize = 2 + reagents_to_add = list(/singleton/reagent/nutriment/protein/cheese = 15, /singleton/reagent/drink/milk/adhomai/fermented = 5) + +/obj/item/reagent_containers/food/snacks/adhomian_cheese_wedge + name = "adhomian cheese wedge" + desc = "A wedge of soft Adhomian cheese. It smells like fermented fatshouter milk that's gone bad... in a very delicious way!" + icon = 'icons/obj/item/reagent_containers/food/cultural/tajara.dmi' + icon_state = "cheese_wedge" + ingredient_name = "cheese" + filling_color = "#fdfdfd" + bitesize = 2 + center_of_mass = list("x"=16, "y"=10) + +/obj/item/reagent_containers/food/snacks/adhomian_cheese_wedge/filled/reagents_to_add = list( + /singleton/reagent/nutriment/protein/cheese = 3, + /singleton/reagent/drink/milk/adhomai/fermented = 1 + ) + +/obj/item/reagent_containers/food/snacks/sliceable/cheesebake + name = "adhomian cheesebake" + desc = "A hearty dish fit for a celebration. Creamy Adhomian cheese with dirtberries mixed in, topped with a layer of earthenroot slices, all sitting on a crispy Adhomian bread base and baked to perfection. Can be served whole or sliced into smaller portions." + icon = 'icons/obj/item/reagent_containers/food/cultural/tajara.dmi' + icon_state = "cheesebake" + slice_path = /obj/item/reagent_containers/food/snacks/cheesebake_slice + slices_num = 2 + filling_color = "#d0e6ff" + bitesize = 2 + reagents_to_add = list(/singleton/reagent/nutriment = 6, /singleton/reagent/drink/milk/adhomai/fermented = 3, /singleton/reagent/nutriment/protein/cheese = 3) + reagent_data = list(/singleton/reagent/nutriment/protein/cheese = list("soft baked cheese" = 4), /singleton/reagent/nutriment = list("sweet potato" = 4, "nutty dirtberries" = 3, "crunch" = 2)) + +/obj/item/reagent_containers/food/snacks/sliceable/cheesebake/update_icon() + var/expected_initial_reagent_volume + for(var/k in src.reagents_to_add) + expected_initial_reagent_volume += reagents_to_add[k] + var/percent_cheesebake = round((reagents.total_volume / expected_initial_reagent_volume) * 100) + switch(percent_cheesebake) + if(0 to 50) + icon_state = "cheesebake_half" + if(51 to INFINITY) + icon_state = "cheesebake" + +/obj/item/reagent_containers/food/snacks/cheesebake_slice + name = "adhomian cheesebake slice" + desc = "A slice of Adhomian cheesebake. Baked Earthenroot slices on top, dirtberry-studded cheese below it and an adhomian bread base." + icon = 'icons/obj/item/reagent_containers/food/cultural/tajara.dmi' + icon_state = "cheesebake_slice" + filling_color = "#d0e6ff" + +/obj/item/reagent_containers/food/snacks/cheesebake_slice/filled/reagents_to_add = list(/singleton/reagent/nutriment = 3, /singleton/reagent/drink/milk/adhomai/fermented = 1.5, /singleton/reagent/nutriment/protein/cheese = 1.5) + +/obj/item/reagent_containers/food/snacks/cheese_twig + name = "cheese twig" + desc = "Twisted dough with a chewy cheese center. Despite being a salty snack beloved by many, cheese twigs are often associated with dairy farmers, and the stereotype of an Adhomian farmer typically has them gnawing idly on a cheese twig. As a result, 'cheesetwig' has become a slang name for farmers in Adhomian society." + icon = 'icons/obj/item/reagent_containers/food/cultural/tajara.dmi' + icon_state = "cheesetwig" + filling_color = "#865a26" + reagents_to_add = list(/singleton/reagent/nutriment = 3, /singleton/reagent/drink/milk/adhomai/fermented = 1, /singleton/reagent/nutriment/protein/cheese = 1) + reagent_data = list(/singleton/reagent/nutriment = list("pretzel" = 3), /singleton/reagent/nutriment/protein/cheese = list("chewy cheese" = 3)) + bitesize = 2 diff --git a/code/modules/reagents/reagent_containers/food/snacks/eggs.dm b/code/modules/reagents/reagent_containers/food/snacks/eggs.dm index adbdcff57256..0d0935d1eba7 100644 --- a/code/modules/reagents/reagent_containers/food/snacks/eggs.dm +++ b/code/modules/reagents/reagent_containers/food/snacks/eggs.dm @@ -176,16 +176,30 @@ filling_color = "#FC5647" /obj/item/reagent_containers/food/snacks/omelette + name = "omelette" + desc = "An eggy omelette, neatly folded and entirely fromageless." + icon = 'icons/obj/item/reagent_containers/food/egg.dmi' + icon_state = "omelette_plain" + filling_color = "#ffce47" + reagents_to_add = list(/singleton/reagent/nutriment/protein/egg = 6) + bitesize = 1 + +/obj/item/reagent_containers/food/snacks/omelette/veggie + name = "veggie omelette" + desc = "An omelette full of herbs, green onions, and other stuff that's probably good for you. Start your day off right!" + icon_state = "omelette_veggie" + reagents_to_add = list(/singleton/reagent/nutriment/protein/egg = 3, /singleton/reagent/nutriment = 3) + reagent_data = list(/singleton/reagent/nutriment = list("veggies" = 3)) + +/obj/item/reagent_containers/food/snacks/omelette/fromage name = "omelette du fromage" desc = "That's all you can say!" - icon = 'icons/obj/item/reagent_containers/food/egg.dmi' icon_state = "omelette" trash = /obj/item/trash/plate filling_color = "#FFF9A8" center_of_mass = list("x"=16, "y"=13) - bitesize = 1 - reagents_to_add = list(/singleton/reagent/nutriment/protein/egg = 8) + reagent_data = list(/singleton/reagent/nutriment/protein/egg = list("cheesy egg" = 3)) /obj/item/reagent_containers/food/snacks/poachedegg name = "poached egg" diff --git a/code/modules/reagents/reagent_containers/food/snacks/fryer.dm b/code/modules/reagents/reagent_containers/food/snacks/fryer.dm index e6edc0086794..9efddc8fd226 100644 --- a/code/modules/reagents/reagent_containers/food/snacks/fryer.dm +++ b/code/modules/reagents/reagent_containers/food/snacks/fryer.dm @@ -141,7 +141,6 @@ icon_state = "onionrings" trash = /obj/item/trash/plate filling_color = "#eddd00" - center_of_mass = "x=16;y=11" reagents_to_add = list(/singleton/reagent/nutriment = 5) reagent_data = list(/singleton/reagent/nutriment = list("fried onions" = 5)) bitesize = 2 @@ -457,3 +456,15 @@ trash = /obj/item/trash/bowl_small reagents_to_add = list(/singleton/reagent/nutriment = 1) reagent_data = list(/singleton/reagent/nutriment = list("crunch" = 5)) + +/obj/item/reagent_containers/food/snacks/poutine + name = "poutine" + desc = "Fries swimming in thick gravy and melty cheese. Oh, Canada! You really know what it's all aboot." + icon = 'icons/obj/item/reagent_containers/food/fryer.dmi' + icon_state = "poutine" + trash = /obj/item/trash/plate + filling_color = "#9c5e24" + center_of_mass = list("x"=16, "y"=11) + reagents_to_add = list(/singleton/reagent/nutriment = 3, /singleton/reagent/nutriment/protein/cheese = 3, /singleton/reagent/condiment/gravy = 3) + reagent_data = list(/singleton/reagent/nutriment = list("fresh fries" = 3)) + bitesize = 2 diff --git a/code/modules/reagents/reagent_containers/food/snacks/ingredients.dm b/code/modules/reagents/reagent_containers/food/snacks/ingredients.dm index b88fed995433..0a63e234fb87 100644 --- a/code/modules/reagents/reagent_containers/food/snacks/ingredients.dm +++ b/code/modules/reagents/reagent_containers/food/snacks/ingredients.dm @@ -46,7 +46,7 @@ /obj/item/reagent_containers/food/snacks/nakarka_wedge name = "nakarka cheese wedge" - desc = "Zzztop calling it Nakarka cheezzze. You sound ridicoulouzzz. Nakarka meanzzz cheezzze. You are literally calling it cheezzze cheezzze." + desc = "Zzztop calling it Nakarka cheezzze. You zzzound ridicoulouzzz. Nakarka meanzzz cheezzze. You are literally calling it cheezzze cheezzze." icon = 'icons/obj/item/reagent_containers/food/ingredients.dmi' icon_state = "nakarka_wedge" ingredient_name = "nakarka" diff --git a/code/modules/reagents/reagent_containers/food/snacks/mix.dm b/code/modules/reagents/reagent_containers/food/snacks/mix.dm index 42cab2cee979..e15baf3cab2c 100644 --- a/code/modules/reagents/reagent_containers/food/snacks/mix.dm +++ b/code/modules/reagents/reagent_containers/food/snacks/mix.dm @@ -36,8 +36,8 @@ reagent_data = list(/singleton/reagent/nutriment = list("apples" = 3,"salad" = 5)) bitesize = 3 -/obj/item/reagent_containers/food/snacks/salad/tossedsalad - name = "tossed salad" +/obj/item/reagent_containers/food/snacks/salad/applesalad + name = "apple salad" desc = "A proper salad, basic and simple, with little bits of carrot, tomato and apple intermingled. Vegan!" icon = 'icons/obj/item/reagent_containers/food/mix.dmi' icon_state = "herbsalad" diff --git a/code/modules/reagents/reagent_containers/food/snacks/pizza.dm b/code/modules/reagents/reagent_containers/food/snacks/pizza.dm index 3e0fd7597b17..e713052353d5 100644 --- a/code/modules/reagents/reagent_containers/food/snacks/pizza.dm +++ b/code/modules/reagents/reagent_containers/food/snacks/pizza.dm @@ -194,6 +194,28 @@ reagent_data = list(/singleton/reagent/nutriment = list("flatbread" = 5)) filling_color = "#BD8939" +/obj/item/reagent_containers/food/snacks/sliceable/pizza/chocolate_pizza + name = "chocolate pizza" + desc = "Chocolate, nougat, candy... Absolutely zero cheese... This isn't even pizza, it's just a very flat chocolate pie that looks like a birthday party exploded over it. This will make your inner 8 year old very very happy, and your inner 40 year old very very nauseous." + icon = 'icons/obj/item/reagent_containers/food/pizza.dmi' + icon_state = "chocolate_pizza" + slice_path = /obj/item/reagent_containers/food/snacks/chocolate_pizza_slice + slices_num = 6 + center_of_mass = list("x"=16, "y"=11) + filling_color = "#5f2e12" + reagents_to_add = list(/singleton/reagent/nutriment = 30, /singleton/reagent/sugar = 12) + reagent_data = list(/singleton/reagent/nutriment = list("sugarpocalypse" = 10)) + bitesize = 2 + +/obj/item/reagent_containers/food/snacks/chocolate_pizza_slice + name = "chocolate pizza slice" + desc = "About 9 different sugary things that are horribly bad for you and at least 3 infractions of culinary law spread colorfully on some pizza dough. This candy-coated slice of what can only charitably be referred to as pizza is sure to give you seconds of joy and days of elevated blood pressure!" + icon = 'icons/obj/item/reagent_containers/food/pizza.dmi' + icon_state = "chocolate_pizza_slice" + filling_color = "#5f2e12" + bitesize = 2 + center_of_mass = list("x"=18, "y"=13) + //Deep Dish ABSTRACT_TYPE(/obj/item/reagent_containers/food/snacks/sliceable/pizza/deepdish/) diff --git a/code/modules/reagents/reagent_containers/food/snacks/processed.dm b/code/modules/reagents/reagent_containers/food/snacks/processed.dm index 100d33727635..455239483ca5 100644 --- a/code/modules/reagents/reagent_containers/food/snacks/processed.dm +++ b/code/modules/reagents/reagent_containers/food/snacks/processed.dm @@ -302,6 +302,27 @@ unpopped = max(0, unpopped-1) ..() +/obj/item/reagent_containers/food/snacks/popcorn/caramel + name = "caramel popcorn" + desc = "Salty and sweet, gets stuck in your teeth while also ruining them! Yum!" + icon_state = "popcorn_caramel" + bitesize = 0.4 + reagent_data = list(/singleton/reagent/nutriment = list("caramel" = 3, "popcorn" = 3)) + +/obj/item/reagent_containers/food/snacks/popcorn/cheese + name = "cheese popcorn" + desc = "For the absolutely cheesiest movies." + icon_state = "popcorn_cheese" + bitesize = 0.4 + reagent_data = list(/singleton/reagent/nutriment = list("cheese" = 3, "popcorn" = 3)) + +/obj/item/reagent_containers/food/snacks/popcorn/chocolate + name = "chocolate popcorn" + desc = "Cocoacorn, if you will." + icon_state = "popcorn_chocolate" + bitesize = 0.4 + reagent_data = list(/singleton/reagent/nutriment = list("chocolate" = 3, "popcorn" = 3)) + /obj/item/reagent_containers/food/snacks/sosjerky name = "Scaredy's Private Reserve beef jerky" icon = 'icons/obj/item/reagent_containers/food/processed.dmi' @@ -1039,6 +1060,7 @@ icon_state = "toptart_strawberry_box" icon_type = "toptart" storage_type = "box" + w_class = WEIGHT_CLASS_SMALL starts_with = list(/obj/item/reagent_containers/food/snacks/toptart_strawberry_raw = 4) can_hold = list( /obj/item/reagent_containers/food/snacks/toptart_strawberry_raw, @@ -1058,6 +1080,7 @@ icon_state = "toptart_chocolate_box" icon_type = "toptart" storage_type = "box" + w_class = WEIGHT_CLASS_SMALL starts_with = list(/obj/item/reagent_containers/food/snacks/toptart_chocolate_peanutbutter_raw = 4) can_hold = list( /obj/item/reagent_containers/food/snacks/toptart_strawberry_raw, @@ -1077,6 +1100,7 @@ icon_state = "toptart_blueberry_box" icon_type = "toptart" storage_type = "box" + w_class = WEIGHT_CLASS_SMALL starts_with = list(/obj/item/reagent_containers/food/snacks/toptart_blueberry_raw = 4) can_hold = list( /obj/item/reagent_containers/food/snacks/toptart_strawberry_raw, diff --git a/code/modules/reagents/reagent_containers/glass/bottle.dm b/code/modules/reagents/reagent_containers/glass/bottle.dm index f01914ea5765..dbc431c4d609 100644 --- a/code/modules/reagents/reagent_containers/glass/bottle.dm +++ b/code/modules/reagents/reagent_containers/glass/bottle.dm @@ -162,6 +162,12 @@ icon_state = "bottle-4" reagents_to_add = list(/singleton/reagent/adrenaline = 60) +/obj/item/reagent_containers/glass/bottle/dexalin + name = "dexalin bottle" + desc = "A small bottle. Contains Dexalin that is used in the treatment of oxygen deprivation. It is somewhat effective, and is twice as powerful and lasts twice as long when inhaled." + icon_state = "bottle-4" + reagents_to_add = list(/singleton/reagent/dexalin = 60) + /obj/item/reagent_containers/glass/bottle/dexalin_plus name = "dexalin plus bottle" desc = "A small bottle. Contains Dexalin Plus that is used in the treatment of oxygen deprivation. It is highly effective, and is twice as powerful and lasts twice as long when inhaled." @@ -186,6 +192,12 @@ icon_state = "bottle-4" reagents_to_add = list(/singleton/reagent/thetamycin = 60) +/obj/item/reagent_containers/glass/bottle/tricordrazine + name = "tricordrazine bottle" + desc = "A small bottle. Contains bicaridine - treats all wounds slowly." + icon_state = "bottle-3" + reagents_to_add = list(/singleton/reagent/tricordrazine = 60) + /obj/item/reagent_containers/glass/bottle/bicaridine name = "bicaridine bottle" desc = "A small bottle. Contains bicaridine - treats damaged tissues." diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index b00028130e5d..c06e09d74272 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -402,7 +402,7 @@ data["mode"] = mode data["uses_air"] = uses_air data["panel_open"] = panel_open - data["pressure"] = CLAMP01(air_contents.return_pressure() / (SEND_PRESSURE)) + data["pressure"] = CLAMP01(XGM_PRESSURE(air_contents) / (SEND_PRESSURE)) return data /obj/machinery/disposal/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) @@ -507,13 +507,13 @@ update() // Validate whether we're pressurized or not. - if(mode == MODE_PRESSURIZING && air_contents.return_pressure() >= SEND_PRESSURE) + if(mode == MODE_PRESSURIZING && XGM_PRESSURE(air_contents) >= SEND_PRESSURE) mode = MODE_READY update() return // If you turn this into a bare 'else' statement it just tries to pressurize infinitely and I don't know why. - else if(mode == MODE_PRESSURIZING && air_contents.return_pressure() < SEND_PRESSURE) + else if(mode == MODE_PRESSURIZING && XGM_PRESSURE(air_contents) < SEND_PRESSURE) src.pressurize() update() return @@ -541,7 +541,7 @@ if (power_draw > 0) use_power_oneoff(power_draw) // If we've reached the target pressure, we're ready to flush - if(air_contents.return_pressure() >= SEND_PRESSURE) + if(XGM_PRESSURE(air_contents) >= SEND_PRESSURE) mode = MODE_READY /** diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm index 6248f1b0dd0a..5c4873f96d0f 100755 --- a/code/modules/recycling/sortingmachinery.dm +++ b/code/modules/recycling/sortingmachinery.dm @@ -252,6 +252,8 @@ desc = "Used to set the destination of properly wrapped packages." icon = 'icons/obj/item/dest_tagger.dmi' icon_state = "dest_tagger" + item_state = "dest_tagger" + contained_sprite = TRUE var/currTag = 0 matter = list(DEFAULT_WALL_MATERIAL = 250, MATERIAL_GLASS = 140) w_class = WEIGHT_CLASS_SMALL diff --git a/code/modules/research/xenoarchaeology/tools/tools_anoscanner.dm b/code/modules/research/xenoarchaeology/tools/tools_anoscanner.dm index 8108ece7bbc7..de6d9dd428ae 100644 --- a/code/modules/research/xenoarchaeology/tools/tools_anoscanner.dm +++ b/code/modules/research/xenoarchaeology/tools/tools_anoscanner.dm @@ -2,9 +2,10 @@ /obj/item/ano_scanner name = "Alden-Saraspova counter" desc = "Aids in triangulation of exotic particles." - icon = 'icons/obj/xenoarchaeology.dmi' + icon = 'icons/obj/item/scanner.dmi' icon_state = "xenoarch_scanner" item_state = "xenoarch_scanner" + contained_sprite = TRUE w_class = WEIGHT_CLASS_SMALL slot_flags = SLOT_BELT var/nearest_artifact_id = "unknown" diff --git a/code/modules/research/xenoarchaeology/tools/tools_depthscanner.dm b/code/modules/research/xenoarchaeology/tools/tools_depthscanner.dm index 547b52f7e2e5..9579bcddf090 100644 --- a/code/modules/research/xenoarchaeology/tools/tools_depthscanner.dm +++ b/code/modules/research/xenoarchaeology/tools/tools_depthscanner.dm @@ -6,9 +6,10 @@ /obj/item/depth_scanner name = "depth analysis scanner" desc = "Used to check spatial depth and density of rock outcroppings." - icon = 'icons/obj/xenoarchaeology.dmi' + icon = 'icons/obj/item/scanner.dmi' icon_state = "depth_scanner" item_state = "depth_scanner" + contained_sprite = TRUE w_class = WEIGHT_CLASS_SMALL slot_flags = SLOT_BELT var/list/positive_locations = list() diff --git a/code/modules/shieldgen/shield_capacitor.dm b/code/modules/shieldgen/shield_capacitor.dm index 29292452a1fa..0fd4a0c647d0 100644 --- a/code/modules/shieldgen/shield_capacitor.dm +++ b/code/modules/shieldgen/shield_capacitor.dm @@ -123,7 +123,8 @@ if (PN) var/power_draw = between(0, max_charge - stored_charge, charge_rate) //what we are trying to draw - power_draw = PN.draw_power(power_draw) //what we actually get + power_draw = POWERNET_POWER_DRAW(PN, power_draw) //what we actually get + DRAW_FROM_POWERNET(PN, power_draw) stored_charge += power_draw time_since_fail++ diff --git a/code/modules/shieldgen/shieldwallgen.dm b/code/modules/shieldgen/shieldwallgen.dm index 4525642e1284..54b6944a9a4f 100644 --- a/code/modules/shieldgen/shieldwallgen.dm +++ b/code/modules/shieldgen/shieldwallgen.dm @@ -85,7 +85,8 @@ return FALSE var/shieldload = between(500, max_stored_power - storedpower, (power_draw*seconds_per_tick)) //what we try to draw - shieldload = PN.draw_power(shieldload) //what we actually get + shieldload = POWERNET_POWER_DRAW(PN, shieldload) //what we actually get + DRAW_FROM_POWERNET(PN, shieldload) storedpower += shieldload //If we're still in the red, then there must not be enough available power to cover our load. diff --git a/code/modules/shuttles/escape_pods.dm b/code/modules/shuttles/escape_pods.dm index c1684f1276f1..d5c8e315787c 100644 --- a/code/modules/shuttles/escape_pods.dm +++ b/code/modules/shuttles/escape_pods.dm @@ -21,11 +21,12 @@ GLOBAL_LIST_EMPTY(escape_pods_by_name) if(own_target) var/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/own_target_master = own_target.master if(own_target_master) - own_target_master.pod = src + own_target_master.set_pod(src) /datum/shuttle/autodock/ferry/escape_pod/Destroy() GLOB.escape_pods -= src GLOB.escape_pods_by_name -= name + arming_controller = null . = ..() /datum/shuttle/autodock/ferry/escape_pod/can_launch() @@ -50,6 +51,21 @@ GLOBAL_LIST_EMPTY(escape_pods_by_name) name = "escape pod controller" var/datum/shuttle/autodock/ferry/escape_pod/pod +/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/Destroy() + pod = null + . = ..() + +/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/proc/set_pod(datum/shuttle/autodock/ferry/escape_pod/new_pod) + if(istype(new_pod)) + pod = new_pod + RegisterSignal(pod, COMSIG_QDELETING, PROC_REF(clear_pod)) + +/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/proc/clear_pod() + SIGNAL_HANDLER + if(pod) + UnregisterSignal(pod, COMSIG_QDELETING) + pod = null + /obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) diff --git a/code/modules/shuttles/shuttle_console.dm b/code/modules/shuttles/shuttle_console.dm index 2966904f98f0..2bdcdcba00d5 100644 --- a/code/modules/shuttles/shuttle_console.dm +++ b/code/modules/shuttles/shuttle_console.dm @@ -89,6 +89,13 @@ return ..() /obj/machinery/computer/shuttle_control/attack_hand(mob/user) + // Snowflake case for checking player characters for a Pilot Spacecraft Skill. + // Only player characters will have the component. Which will both always be present on them, and will only enable its own return logic if it exists. + // NPCs, Ghostroles, and Offship Antags that don't generate skills are unaffected by this check by intentional design so that we don't have to account for them. + if (user.GetComponent(PILOT_SPACECRAFT_SKILL_COMPONENT)?.skill_level == SKILL_LEVEL_UNFAMILIAR) + to_chat(user, SPAN_WARNING("There's just so many buttons... You have no idea where to even begin.")) + return + if(use_check_and_message(user)) return if(!emagged && !allowed(user)) @@ -170,6 +177,7 @@ "can_force" = shuttle.can_force(), "can_rename_ship" = can_rename_ship, "ship_name" = shuttle.name, + "current_location" = shuttle.get_location_name(), ) /obj/machinery/computer/shuttle_control/ui_act(action, params) diff --git a/code/modules/spell_system/spells/spell_list/others/generic/mend.dm b/code/modules/spell_system/spells/spell_list/others/generic/mend.dm index 33ecdbcf38cd..d5ce416e0457 100644 --- a/code/modules/spell_system/spells/spell_list/others/generic/mend.dm +++ b/code/modules/spell_system/spells/spell_list/others/generic/mend.dm @@ -47,7 +47,7 @@ user.visible_message(SPAN_NOTICE("\The [user] rests a hand on \the [target]'s [E.name].")) to_chat(target, SPAN_NOTICE("A healing warmth suffuses you.")) - for(var/datum/wound/W in E.wounds) + for(var/datum/wound/W as anything in E.wounds) if(W.bleeding()) to_chat(user, SPAN_NOTICE("You knit together severed veins and broken flesh, stemming the bleeding.")) W.bleed_timer = 0 diff --git a/code/modules/supermatter/supermatter.dm b/code/modules/supermatter/supermatter.dm index 9d663ef2ee7a..45a3b71e3ec1 100644 --- a/code/modules/supermatter/supermatter.dm +++ b/code/modules/supermatter/supermatter.dm @@ -385,7 +385,7 @@ if(loc && !istype(loc, /turf/space)) env = src.loc.return_air() data["ambient_temp"] = round(env?.temperature) - data["ambient_pressure"] = round(env?.return_pressure()) + data["ambient_pressure"] = round(SAFE_XGM_PRESSURE(env)) data["detonating"] = grav_pulling return data diff --git a/code/modules/surgery/bones.dm b/code/modules/surgery/bones.dm index 8596f20ea93b..3b13a0a5a5d4 100644 --- a/code/modules/surgery/bones.dm +++ b/code/modules/surgery/bones.dm @@ -14,6 +14,7 @@ min_duration = 30 max_duration = 40 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/glue_bone/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -50,6 +51,7 @@ min_duration = 30 max_duration = 50 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/set_bone/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -90,6 +92,7 @@ min_duration = 40 max_duration = 50 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/mend_skull/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -127,6 +130,7 @@ min_duration = 30 max_duration = 40 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/finish_bone/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) diff --git a/code/modules/surgery/encased.dm b/code/modules/surgery/encased.dm index a0f872e099b8..73c69353a703 100644 --- a/code/modules/surgery/encased.dm +++ b/code/modules/surgery/encased.dm @@ -7,6 +7,7 @@ priority = 2 can_infect = TRUE blood_level = 1 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/open_encased/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -73,6 +74,7 @@ min_duration = 20 max_duration = 30 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/open_encased/retract/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -127,6 +129,7 @@ min_duration = 20 max_duration = 30 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/open_encased/close/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -185,6 +188,7 @@ min_duration = 20 max_duration = 30 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/open_encased/mend/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) diff --git a/code/modules/surgery/face.dm b/code/modules/surgery/face.dm index ad7815de60bb..754c1ffc82e9 100644 --- a/code/modules/surgery/face.dm +++ b/code/modules/surgery/face.dm @@ -12,6 +12,7 @@ min_duration = 70 max_duration = 90 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/generic/cut_face/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) return ..() && target_zone == BP_MOUTH && target.op_stage.face == FACE_NORMAL @@ -42,6 +43,7 @@ min_duration = 70 max_duration = 90 + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/robotics/face/synthskin/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) return ..() && target.op_stage.face == FACE_NORMAL && target.get_species() == SPECIES_IPC_SHELL diff --git a/code/modules/surgery/facial_surgery.dm b/code/modules/surgery/facial_surgery.dm index 6bb7f408ae18..430ea28999fd 100644 --- a/code/modules/surgery/facial_surgery.dm +++ b/code/modules/surgery/facial_surgery.dm @@ -8,6 +8,7 @@ name = "Retract Facial Incisions" priority = 2 can_infect = FALSE + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/face/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -25,6 +26,7 @@ min_duration = 70 max_duration = 90 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/generic/prepare_face/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) return ..() && target_zone == BP_MOUTH && target.op_stage.face == FACE_CUT_OPEN @@ -57,6 +59,7 @@ min_duration = 30 max_duration = 70 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/generic/alter_face/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) return ..() && target_zone == BP_MOUTH && target.op_stage.face == FACE_RETRACTED @@ -104,6 +107,7 @@ min_duration = 50 max_duration = 80 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/face/cauterize/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) return ..() && target.op_stage.face > FACE_NORMAL @@ -147,6 +151,7 @@ min_duration = 70 max_duration = 90 + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/robotics/face/synthskinopen/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) return ..() && target.op_stage.face == FACE_NORMAL && target.get_species() == SPECIES_IPC_SHELL @@ -175,6 +180,7 @@ min_duration = 70 max_duration = 90 + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/robotics/face/prepare_face/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) return ..() && target_zone == BP_MOUTH && target.op_stage.face == FACE_CUT_OPEN @@ -204,6 +210,7 @@ min_duration = 30 max_duration = 70 + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/robotics/face/alter_synthface/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) return ..() && target_zone == BP_MOUTH && target.op_stage.face == FACE_RETRACTED @@ -249,6 +256,7 @@ min_duration = 50 max_duration = 80 + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/robotics/face/seal_face/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) return ..() && target.op_stage.face > FACE_NORMAL diff --git a/code/modules/surgery/generic.dm b/code/modules/surgery/generic.dm index 47bad2751776..c8f5a985670a 100644 --- a/code/modules/surgery/generic.dm +++ b/code/modules/surgery/generic.dm @@ -30,6 +30,8 @@ priority = 2 min_duration = 50 max_duration = 70 + // Basic procedure any novice can do + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR) /singleton/surgery_step/generic/cut_with_laser/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -73,6 +75,8 @@ priority = 2 min_duration = 60 max_duration = 80 + // Automated tool that requires no skill + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_UNFAMILIAR) /singleton/surgery_step/generic/incision_manager/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -117,6 +121,8 @@ min_duration = 60 max_duration = 80 + // Basic surgery any novice surgeon can do + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR) /singleton/surgery_step/generic/cut_open/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -161,6 +167,8 @@ min_duration = 80 max_duration = 100 + // Basic surgery any novice surgeon can do + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR) /singleton/surgery_step/generic/cut_open_vaurca/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -205,6 +213,8 @@ min_duration = 20 max_duration = 30 + // Basic surgery any novice surgeon can do + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR) /singleton/surgery_step/generic/clamp_bleeders/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -244,6 +254,8 @@ min_duration = 20 max_duration = 30 + // Basic surgery any novice surgeon can do + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR) /singleton/surgery_step/generic/retract_skin/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -307,6 +319,8 @@ min_duration = 40 max_duration = 70 + // Basic surgery any novice surgeon can do + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR) /singleton/surgery_step/generic/cauterize/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) diff --git a/code/modules/surgery/implant.dm b/code/modules/surgery/implant.dm index b39aea2bf51e..a22c0d01d5e1 100644 --- a/code/modules/surgery/implant.dm +++ b/code/modules/surgery/implant.dm @@ -6,6 +6,7 @@ /singleton/surgery_step/cavity priority = 1 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/cavity/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -49,6 +50,7 @@ min_duration = 50 max_duration = 70 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/cavity/make_space/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -81,6 +83,7 @@ min_duration = 50 max_duration = 70 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/cavity/close_space/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -108,6 +111,7 @@ min_duration = 60 max_duration = 80 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/cavity/place_item/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -159,6 +163,7 @@ min_duration = 60 max_duration = 80 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/cavity/implant_removal/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) diff --git a/code/modules/surgery/limb_reattach.dm b/code/modules/surgery/limb_reattach.dm index 686b6ae98256..152f25032eee 100644 --- a/code/modules/surgery/limb_reattach.dm +++ b/code/modules/surgery/limb_reattach.dm @@ -6,6 +6,7 @@ /singleton/surgery_step/limb priority = 3 // Must be higher than /singleton/surgery_step/internal can_infect = FALSE + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/limb/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -27,6 +28,7 @@ min_duration = 40 max_duration = 60 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/limb/attach/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/E = tool @@ -60,6 +62,7 @@ min_duration = 80 max_duration = 100 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/limb/connect/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -98,6 +101,7 @@ min_duration = 60 max_duration = 80 + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/limb/mechanize/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm index 5ba79b6ad787..0fc05226843f 100644 --- a/code/modules/surgery/organs_internal.dm +++ b/code/modules/surgery/organs_internal.dm @@ -3,6 +3,7 @@ priority = 2 can_infect = TRUE blood_level = 1 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/internal/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -28,6 +29,7 @@ min_duration = 50 max_duration = 70 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/internal/fix_organ/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -116,6 +118,7 @@ min_duration = 50 max_duration = 70 + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/internal/fix_organ_robotic/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -187,6 +190,7 @@ min_duration = 70 max_duration = 90 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/internal/detach_organ/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -253,6 +257,7 @@ min_duration = 40 max_duration = 60 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/internal/remove_organ/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -312,6 +317,7 @@ min_duration = 40 max_duration = 60 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/internal/replace_organ/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -417,6 +423,7 @@ min_duration = 80 max_duration = 100 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/internal/attach_organ/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -471,6 +478,7 @@ min_duration = 80 max_duration = 100 + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/internal/prepare/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) diff --git a/code/modules/surgery/other.dm b/code/modules/surgery/other.dm index 15e3cb29eb8a..768c582b8a09 100644 --- a/code/modules/surgery/other.dm +++ b/code/modules/surgery/other.dm @@ -16,6 +16,7 @@ min_duration = 40 max_duration = 60 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR) /singleton/surgery_step/fix_vein/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -65,6 +66,7 @@ min_duration = 80 max_duration = 130 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_PROFESSIONAL) /singleton/surgery_step/internal/fix_dead_tissue/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -130,6 +132,7 @@ min_duration = 80 max_duration = 90 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_PROFESSIONAL) /singleton/surgery_step/treat_necrosis/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -196,6 +199,7 @@ min_duration = 50 max_duration = 70 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/fix_tendon/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -237,6 +241,7 @@ min_duration = 100 max_duration = 160 + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR) /singleton/surgery_step/hardsuit/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -274,6 +279,7 @@ min_duration = 90 max_duration = 140 + skill_requirements = alist(SURGERY_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR) /singleton/surgery_step/amputate/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) diff --git a/code/modules/surgery/robotics.dm b/code/modules/surgery/robotics.dm index 2d83360d4bae..23a772295b5a 100644 --- a/code/modules/surgery/robotics.dm +++ b/code/modules/surgery/robotics.dm @@ -5,6 +5,7 @@ /singleton/surgery_step/robotics can_infect = FALSE + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/robotics/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -34,6 +35,8 @@ max_duration = 70 requires_surgery_compatibility = FALSE + // Basic surgery any novice roboticist can do + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR) /singleton/surgery_step/robotics/unscrew_hatch/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -76,6 +79,8 @@ max_duration = 70 requires_surgery_compatibility = FALSE + // Basic surgery any novice roboticist can do + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR) /singleton/surgery_step/robotics/screw_hatch/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -116,6 +121,8 @@ min_duration = 20 max_duration = 30 + // Basic surgery any novice roboticist can do + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/robotics/open_hatch/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -153,6 +160,8 @@ min_duration = 50 max_duration = 80 + // Basic surgery any novice roboticist can do + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/robotics/close_hatch/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -193,6 +202,8 @@ min_duration = 30 max_duration = 40 + // Basic surgery any novice roboticist can do + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR) /singleton/surgery_step/robotics/repair_brute/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -237,6 +248,8 @@ min_duration = 30 max_duration = 40 + // Basic surgery any novice roboticist can do + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR) /singleton/surgery_step/robotics/repair_burn/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -280,6 +293,7 @@ min_duration = 70 max_duration = 90 + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/robotics/detach_organ_robotic/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -332,6 +346,7 @@ max_duration = 100 requires_surgery_compatibility = FALSE + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/robotics/attach_organ_robotic/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -381,6 +396,7 @@ min_duration = 40 max_duration = 60 + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/robotics/install_mmi/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -456,6 +472,7 @@ min_duration = 50 max_duration = 70 + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/internal/fix_internal_wiring/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -505,6 +522,7 @@ min_duration = 100 max_duration = 200 + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/internal/fix_internal_electronics/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -545,6 +563,7 @@ min_duration = 75 max_duration = 120 + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/internal/fix_internal_plating/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -596,6 +615,7 @@ min_duration = 100 max_duration = 150 + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/internal/replace_internal_plating/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -641,6 +661,7 @@ max_duration = 200 var/fast_repair = FALSE + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/internal/replace_external_plating/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -681,12 +702,14 @@ min_duration = 100 max_duration = 150 + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_FAMILIAR) /singleton/surgery_step/internal/replace_external_plating/g2 name = "Replace G2 External Armour Plating" min_duration = 90 max_duration = 100 fast_repair = TRUE + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/internal/degunk/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) @@ -731,6 +754,7 @@ min_duration = 15 max_duration = 25 + skill_requirements = alist(ROBOTICS_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/robotics/repair_endoskeleton/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!..()) diff --git a/code/modules/surgery/slimes.dm b/code/modules/surgery/slimes.dm index 3f448b9d81bb..7fb196301e08 100644 --- a/code/modules/surgery/slimes.dm +++ b/code/modules/surgery/slimes.dm @@ -19,6 +19,7 @@ min_duration = 10 max_duration = 35 + skill_requirements = alist(XENOBIOLOGY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/slime/cut_flesh/can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) return ..() && istype(target) && target.core_removal_stage == ORGAN_CLOSED @@ -47,6 +48,7 @@ min_duration = 20 max_duration = 45 + skill_requirements = alist(XENOBIOLOGY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/slime/cut_innards/can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) return ..() && istype(target) && target.core_removal_stage == ORGAN_OPEN_INCISION @@ -74,6 +76,7 @@ min_duration = 35 max_duration = 55 + skill_requirements = alist(XENOBIOLOGY_SKILL_COMPONENT = SKILL_LEVEL_TRAINED) /singleton/surgery_step/slime/saw_core/can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) return ..() && (istype(target) && target.core_removal_stage == ORGAN_OPEN_RETRACTED && target.cores > 0) //This is being passed a human as target, unsure why. diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm index 715e21963012..db2135954dd2 100644 --- a/code/modules/surgery/surgery.dm +++ b/code/modules/surgery/surgery.dm @@ -21,6 +21,9 @@ var/requires_surgery_compatibility = TRUE + /// The associative list of skills and their paired requirement levels to be able to perform a given surgery. + var/alist/skill_requirements + /// Returns how well tool is suited for this step. /singleton/surgery_step/proc/tool_quality(obj/item/tool) for(var/T in allowed_tools) @@ -53,6 +56,13 @@ /singleton/surgery_step/proc/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(!ishuman(target)) return FALSE + + var/obj/item/organ/external/affected = target.get_organ(target_zone) + var/canceled = FALSE + SEND_SIGNAL(target, COMSIG_BEGIN_SURGERY, &canceled, affected, user, src) + if(canceled) + return FALSE + return TRUE /// Does stuff to begin the step, usually just printing messages. Moved germs transfering and bloodying here too @@ -121,6 +131,14 @@ if(user.client) // In case of future autodocs. S = tgui_input_list(user, "Which surgery would you like to perform?", "Surgery", possible_surgeries) + // Check via skill components if the user knows how to perform the surgery. + for (var/skill_comp, required_level in S.skill_requirements) + var/skill_level = GET_SKILL_LEVEL(user, skill_comp) + // Null condition handles NPCs and Antags that won't have the skill setup. + if (!isnull(skill_level) && skill_level < required_level) + to_chat(user, SPAN_WARNING("You lack the skills needed to perform this surgical procedure.")) + return FALSE + // We didn't find a surgery, or decided not to perform one. if(!istype(S)) if(tool.item_flags & ITEM_FLAG_SURGERY) //Is this supposed to be used for surgery? diff --git a/code/modules/synthesized_instruments/real_instruments/Guitar/guitar.dm b/code/modules/synthesized_instruments/real_instruments/Guitar/guitar.dm index b876835cdd04..1e54ed7f67af 100644 --- a/code/modules/synthesized_instruments/real_instruments/Guitar/guitar.dm +++ b/code/modules/synthesized_instruments/real_instruments/Guitar/guitar.dm @@ -4,6 +4,7 @@ icon = 'icons/obj/musician.dmi' icon_state = "guitar" item_state = "guitar" + contained_sprite = TRUE slot_flags = SLOT_BACK sound_player = /datum/sound_player/synthesizer path = /datum/instrument/guitar/clean_crisis @@ -15,6 +16,21 @@ icon = 'icons/obj/musician.dmi' icon_state = "eguitar" item_state = "eguitar" + contained_sprite = TRUE slot_flags = SLOT_BACK sound_player = /datum/sound_player/synthesizer path = /datum/instrument/guitar + +/obj/item/synthesized_instrument/guitar/prrama + name = "p'rrama" + desc = "A traditional Adhomian string instrument, played with the hands and tail." + icon = 'icons/obj/tajara_items.dmi' + icon_state = "prrama" + item_state = "prrama" + contained_sprite = TRUE + +/obj/item/synthesized_instrument/guitar/prrama/interact(mob/user) + if(!istajara(user)) + balloon_alert(user, "not a tajara!") + return + . = ..() diff --git a/code/modules/synthesized_instruments/song_editor.dm b/code/modules/synthesized_instruments/song_editor.dm index b0e897ae34e0..ee2f4ddc4b42 100644 --- a/code/modules/synthesized_instruments/song_editor.dm +++ b/code/modules/synthesized_instruments/song_editor.dm @@ -11,6 +11,9 @@ src.host = host src.song = song +/datum/nano_module/song_editor/Destroy() + song = null + return ..() /datum/nano_module/song_editor/proc/pages() return Ceil(src.song.lines.len / GLOB.musical_config.song_editor_lines_per_page) diff --git a/code/modules/telesci/gps.dm b/code/modules/telesci/gps.dm index cc3ea9817aff..af31dd9a624f 100644 --- a/code/modules/telesci/gps.dm +++ b/code/modules/telesci/gps.dm @@ -6,6 +6,7 @@ GLOBAL_LIST_EMPTY(gps_list) icon = 'icons/obj/item/gps.dmi' icon_state = "gps-com" item_state = "radio" + contained_sprite = TRUE w_class = WEIGHT_CLASS_SMALL slot_flags = SLOT_BELT origin_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2) diff --git a/code/modules/tgui/external.dm b/code/modules/tgui/external.dm index 48235d976f53..bcd97a912451 100644 --- a/code/modules/tgui/external.dm +++ b/code/modules/tgui/external.dm @@ -70,7 +70,7 @@ * change static data. */ /datum/proc/update_static_data_for_all_viewers() - for (var/datum/tgui/window as anything in SStgui.open_uis_by_src[text_ref(src)]) + for (var/datum/tgui/window as anything in open_uis) window.send_full_update() /** diff --git a/code/modules/tgui/tgui.dm b/code/modules/tgui/tgui.dm index d1dbc3026884..62b40969958e 100644 --- a/code/modules/tgui/tgui.dm +++ b/code/modules/tgui/tgui.dm @@ -40,6 +40,9 @@ /// Are byond mouse events beyond the window passed in to the ui var/mouse_hooked = FALSE + /// Any partial packets that we have received from TGUI, waiting to be sent + var/partial_packets + /** * public * @@ -326,6 +329,31 @@ // Pass act type messages to ui_act if(type && copytext(type, 1, 5) == "act/") var/act_type = copytext(type, 5) + + var/id = href_list["packetId"] + if(!isnull(id)) + id = text2num(id) + + var/total = text2num(href_list["totalPackets"]) + + if(total > MAX_MESSAGE_CHUNKS) + return + + if(id == 1) + partial_packets = new /list(total) + + partial_packets[id] = href_list["packet"] + + if(id != total) + return + + var/assembled_payload = "" + for(var/packet in partial_packets) + assembled_payload += packet + + payload = json_decode(assembled_payload) + partial_packets = null + log_tgui(user, "Action: [act_type] [href_list["payload"]]", window = window, src_object = src_object) diff --git a/code/modules/tgui_input/list.dm b/code/modules/tgui_input/list.dm index 405a815a4149..1192bb55b85e 100644 --- a/code/modules/tgui_input/list.dm +++ b/code/modules/tgui_input/list.dm @@ -81,7 +81,8 @@ /datum/tgui_list_input/Destroy(force, ...) SStgui.close_uis(src) - QDEL_NULL(items) + items?.Cut() + items_map?.Cut() return ..() /** diff --git a/code/modules/tgui_panel/telemetry.dm b/code/modules/tgui_panel/telemetry.dm new file mode 100644 index 000000000000..d3e8e281eb67 --- /dev/null +++ b/code/modules/tgui_panel/telemetry.dm @@ -0,0 +1,69 @@ +/*! + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +/** + * Maximum number of connection records allowed to analyze. + * Should match the value set in the browser. + */ +#define TGUI_TELEMETRY_MAX_CONNECTIONS 5 + +/** + * Maximum time allocated for sending a telemetry packet. + */ +#define TGUI_TELEMETRY_RESPONSE_WINDOW (30 SECONDS) + +/// Time of telemetry request +/datum/tgui_panel/var/telemetry_requested_at +/// Time of telemetry analysis completion +/datum/tgui_panel/var/telemetry_analyzed_at +/// List of previous client connections +/datum/tgui_panel/var/list/telemetry_connections + +/** + * private + * + * Requests some telemetry from the client. + */ +/datum/tgui_panel/proc/request_telemetry() + telemetry_requested_at = world.time + telemetry_analyzed_at = null + window.send_message("telemetry/request", list( + "limits" = list( + "connections" = TGUI_TELEMETRY_MAX_CONNECTIONS, + ), + )) + +/** + * private + * + * Analyzes a telemetry packet. + * + * Does nothing except kick people who try to send a billion requests. + */ +/datum/tgui_panel/proc/analyze_telemetry(payload) + if(world.time > telemetry_requested_at + TGUI_TELEMETRY_RESPONSE_WINDOW) + message_admins("[key_name(client)] sent telemetry outside of the allocated time window.") + return + if(telemetry_analyzed_at) + message_admins("[key_name(client)] sent telemetry more than once.") + return + telemetry_analyzed_at = world.time + if(!payload) + return + telemetry_connections = payload["connections"] + var/len = length(telemetry_connections) + if(len == 0) + return + if(len > TGUI_TELEMETRY_MAX_CONNECTIONS) + message_admins("[key_name(client)] was kicked for sending a huge telemetry payload") + qdel(client) + return + + var/ckey = client?.ckey + if (!ckey) + return + +#undef TGUI_TELEMETRY_MAX_CONNECTIONS +#undef TGUI_TELEMETRY_RESPONSE_WINDOW diff --git a/code/modules/tgui_panel/tgui_panel.dm b/code/modules/tgui_panel/tgui_panel.dm index 3404e3c2ccf0..05ebeb692dd8 100644 --- a/code/modules/tgui_panel/tgui_panel.dm +++ b/code/modules/tgui_panel/tgui_panel.dm @@ -51,7 +51,9 @@ window.send_asset(get_asset_datum(/datum/asset/simple/namespaced/tgfont)) window.send_asset(get_asset_datum(/datum/asset/spritesheet/chat)) // Other setup + request_telemetry() addtimer(CALLBACK(src, PROC_REF(on_initialize_timed_out)), 5 SECONDS) + window.send_message("testTelemetryCommand") /** * private diff --git a/code/modules/vehicles/train.dm b/code/modules/vehicles/train.dm index de83edb84131..9f47d0dfce50 100644 --- a/code/modules/vehicles/train.dm +++ b/code/modules/vehicles/train.dm @@ -50,6 +50,26 @@ unattach() return 0 +/// Trains need to recursively recalculate their glide size for all their towed objects. +/obj/vehicle/train/recalculate_glide_size(old_move_delay, move_delay, direction) + var/new_glide_size = glide_size + + if(old_move_delay + world.tick_lag > world.time) + new_glide_size = DELAY_TO_GLIDE_SIZE((move_delay - old_move_delay) * ( (NSCOMPONENT(direction) && EWCOMPONENT(direction)) ? sqrt(2) : 1 ) ) + else + new_glide_size = DELAY_TO_GLIDE_SIZE((move_delay - world.time) * ( (NSCOMPONENT(direction) && EWCOMPONENT(direction)) ? sqrt(2) : 1 ) ) + + recurse_glide_size(new_glide_size) // set it now in case of pulled objects + return new_glide_size + +/// Sets the glide size of the entire train. +/obj/vehicle/train/proc/recurse_glide_size(var/glide_size) + set_glide_size(glide_size) + if (!tow) + return + + tow.recurse_glide_size(glide_size) + /obj/vehicle/train/Collide(atom/Obstacle) . = ..() if(!istype(Obstacle, /atom/movable)) diff --git a/code/modules/vehicles/vehicle.dm b/code/modules/vehicles/vehicle.dm index a9726b238b70..596d0b17b91d 100644 --- a/code/modules/vehicles/vehicle.dm +++ b/code/modules/vehicles/vehicle.dm @@ -202,15 +202,13 @@ if(powered && cell?.charge < charge_use && !organic) return FALSE on = TRUE - set_light_range_power_color(initial(light_range)) - set_light_on(on) + set_light(initial(light_range)) update_icon() return TRUE /obj/vehicle/proc/turn_off() on = FALSE - set_light_range_power_color(0) - set_light_on(on) + set_light(0) update_icon() /obj/vehicle/emag_act(var/remaining_charges, mob/user as mob) diff --git a/code/modules/ventcrawl/ventcrawl.dm b/code/modules/ventcrawl/ventcrawl.dm index 0d28a84ab2e2..5b5a05db3406 100644 --- a/code/modules/ventcrawl/ventcrawl.dm +++ b/code/modules/ventcrawl/ventcrawl.dm @@ -174,7 +174,7 @@ GLOBAL_LIST_INIT(can_enter_vent_with, list( if(BODYTEMP_HEAT_DAMAGE_LIMIT to INFINITY) to_chat(src, SPAN_DANGER("You feel a searing heat coming from the vent!")) - switch(vent_found.air_contents.return_pressure()) + switch(XGM_PRESSURE(vent_found.air_contents)) if(0 to HAZARD_LOW_PRESSURE) to_chat(src, SPAN_DANGER("You feel a rushing draw pulling you into the vent!")) if(HAZARD_LOW_PRESSURE to WARNING_LOW_PRESSURE) diff --git a/code/modules/weather/weather_effects.dm b/code/modules/weather/weather_effects.dm index f1b934fde2f9..0f86d9934aee 100644 --- a/code/modules/weather/weather_effects.dm +++ b/code/modules/weather/weather_effects.dm @@ -1,7 +1,7 @@ /obj/abstract/weather_system/proc/get_movement_delay(var/datum/gas_mixture/env, var/travel_dir) // It's quiet. Too quiet. - if(!wind_direction || !base_wind_delay || !travel_dir || !env || env.return_pressure() < MIN_WIND_PRESSURE) + if(!wind_direction || !base_wind_delay || !travel_dir || !env || XGM_PRESSURE(env) < MIN_WIND_PRESSURE) return 0 // May the wind be always at your back! diff --git a/code/modules/weather/weather_wind.dm b/code/modules/weather/weather_wind.dm index e4624673dc07..0353a4d79996 100644 --- a/code/modules/weather/weather_wind.dm +++ b/code/modules/weather/weather_wind.dm @@ -30,7 +30,7 @@ var/turf/T = get_turf(M) if(istype(T)) var/datum/gas_mixture/environment = T.return_air() - if(environment && environment.return_pressure() >= MIN_WIND_PRESSURE) // Arbitrary low pressure bound. + if(SAFE_XGM_PRESSURE(environment) >= MIN_WIND_PRESSURE) // Arbitrary low pressure bound. var/absolute_strength = abs(wind_strength) if(absolute_strength <= 0.5 || !wind_direction) to_chat(M, SPAN_NOTICE("The wind is calm.")) diff --git a/code/modules/xgm/xgm_gas_mixture.dm b/code/modules/xgm/xgm_gas_mixture.dm index 2c31d9af1ec5..ce3b6763288e 100644 --- a/code/modules/xgm/xgm_gas_mixture.dm +++ b/code/modules/xgm/xgm_gas_mixture.dm @@ -216,14 +216,6 @@ else total_moles += gas[g] - -///Returns the pressure of the gas mix. Only accurate if there have been no gas modifications since update_values() has been called. -/datum/gas_mixture/proc/return_pressure() - if(volume) - return total_moles * R_IDEAL_GAS_EQUATION * temperature / volume - return 0 - - ///Removes moles from the gas mixture and returns a gas_mixture containing the removed air. /datum/gas_mixture/proc/remove(amount) amount = min(amount, total_moles * group_multiplier) //Can not take more air than the gas mixture has! @@ -332,7 +324,7 @@ return 0 marked[g] = 1 - if(abs(return_pressure() - sample.return_pressure()) > MINIMUM_PRESSURE_DIFFERENCE_TO_SUSPEND) + if(abs(XGM_PRESSURE(src) - XGM_PRESSURE(sample)) > MINIMUM_PRESSURE_DIFFERENCE_TO_SUSPEND) return 0 for(var/g in sample.gas) @@ -350,11 +342,6 @@ return 1 - -/datum/gas_mixture/proc/react() - zburn(null, force_burn=0, no_check=0) //could probably just call zburn() here with no args but I like being explicit. - - //Rechecks the gas_mixture and adjusts the graphic list if needed. //Two lists can be passed by reference if you need know specifically which graphics were added and removed. /datum/gas_mixture/proc/check_tile_graphic(list/graphic_add = null, list/graphic_remove = null) @@ -381,8 +368,10 @@ else if (heat_overlay in graphic) LAZYADD(graphic_remove, heat_overlay) + var/pressure = XGM_PRESSURE(src) + var/cold_overlay = get_tile_overlay(GAS_COLD) - if(temperature <= FOGGING_TEMPERATURE && (return_pressure() >= (ONE_ATMOSPHERE / 4))) + if(temperature <= FOGGING_TEMPERATURE && (pressure >= (ONE_ATMOSPHERE / 4))) if(!(cold_overlay in graphic)) LAZYADD(graphic_add, cold_overlay) else if (cold_overlay in graphic) @@ -396,7 +385,7 @@ graphic -= graphic_remove . = 1 if(length(graphic)) - var/pressure_mod = clamp(return_pressure() / ONE_ATMOSPHERE, 0, 2) + var/pressure_mod = clamp(pressure / ONE_ATMOSPHERE, 0, 2) for(var/obj/gas_overlay/O in graphic) if(istype(O, /obj/gas_overlay/heat)) //Heat based var/new_alpha = clamp(max(125, 255 * ((temperature - CARBON_LIFEFORM_FIRE_RESISTANCE) / CARBON_LIFEFORM_FIRE_RESISTANCE * 4)), 125, 255) diff --git a/code/unit_tests/zas_tests.dm b/code/unit_tests/zas_tests.dm index 0834a2879d90..b2b730a1e02a 100644 --- a/code/unit_tests/zas_tests.dm +++ b/code/unit_tests/zas_tests.dm @@ -74,7 +74,7 @@ GLOBAL_LIST_EMPTY(turfs_to_map_type) var/t_msg = "Turf: [T] | Location: [T.x] // [T.y] // [T.z]" var/datum/gas_mixture/GM = T.return_air() - var/pressure = GM.return_pressure() + var/pressure = XGM_PRESSURE(GM) var/temp = GM.temperature diff --git a/config/example/game_options.txt b/config/example/game_options.txt index 2624af33c519..30ee357014c2 100644 --- a/config/example/game_options.txt +++ b/config/example/game_options.txt @@ -36,7 +36,7 @@ REVIVAL_BRAIN_LIFE -1 ## This will globally modify the movement speed of all mobs. ## Note that it can do so unproportionally, meaning you'll lose the relationships between the different species. As such, modifying the delay multipliers below should be preferred. -WALK_SPEED 4 +WALK_SPEED 3 ## The following two will globally affect all movement speed, while retaining the proportional relationships between the different mob's movement speeds. ## Ideally, you want to modify these. Any value between 0 and 1 will increase speed by decreasing the movement delay, anything above 1 will slow everyone down by increasing the delay. @@ -45,10 +45,17 @@ RUN_DELAY_MULTIPLIER 1 VEHICLE_DELAY_MULTIPLIER 1 ## The variables below affect the movement of specific mob types. +## These are summed with all other delay modifiers to form the "Base" movement delay. + +# All Mob/living/carbon/human HUMAN_DELAY 0 +# Unused ROBOT_DELAY 1 +# Unused MONKEY_DELAY 1 +# Unused ALIEN_DELAY 1 +# All Simple Mobs ANIMAL_DELAY 1 diff --git a/html/changelogs/AnIssueWithGloves.yml b/html/changelogs/AnIssueWithGloves.yml deleted file mode 100644 index cad30c4b41a2..000000000000 --- a/html/changelogs/AnIssueWithGloves.yml +++ /dev/null @@ -1,9 +0,0 @@ -author: TheGreyWolf - -delete-after: True - -changes: - - rscadd: "Black gloves have been renamed to work gloves, to better indicate that they are unique from other colored gloves." - - rscadd: "Added taj and unathi variants of work gloves to the drobes having them, and taj workboots to the ones having normal workboots." - - rscadd: "Renamed taj and unathi work gloves, leather gloves and workboots to be clear who can wear it." - - rscadd: "Made hangar techs spawn with workboots by default, instead of with sneakers. Safety first." diff --git a/html/changelogs/archive/2026-02.yml b/html/changelogs/archive/2026-02.yml index e19064bb947f..eb5d5c88b553 100644 --- a/html/changelogs/archive/2026-02.yml +++ b/html/changelogs/archive/2026-02.yml @@ -76,3 +76,440 @@ TheGreyWolf: - bugfix: Fixes janitorial carts not showing their contents after spawning. - bugfix: The tug will no longer run over people who are leaning on walls. +2026-02-04: + Batrachophrenoboocosmomachia: + - bugfix: Restores area_sensitive trait for mobs, fixing zero-gravity drifting, + ambience and ship hum, and area blurbs. + - rscdel: Removes area blurb text from status window (band-aid fix prior to discovering + root cause of them not appearing consistently). + Greenjoe: + - rscadd: Adds the Adhomian p'rrama to the game. + - rscadd: Adds Adhomian dogtags and a walking stick (maikahar) to the Tajaran loadout. + - rscadd: Adds the Adhomian hunting coat to the Tajaran coat selection. + - rscadd: The shillelagh is renamed to maikahar. + Hellfirejag: + - rscadd: Off-ship player characters can now be viewed from the crew manifest, so + long as you are either an observer, or are in the lobby. + - bugfix: Fixed player characters with apostrophes in their name showing up weirdly + on the manifest. + MattAtlas, FluffyGhost: + - experiment: Atom gliding is now in, which gives us smoother movement. Remember + that this is affected by your FPS setting. + - experiment: The baseline speed is now twice as fast for everything. Fast species + were nerfed slightly to compensate. + TheGreyWolf: + - rscadd: Black gloves have been renamed to work gloves, to better indicate that + they are unique from other colored gloves. + - rscadd: Added taj and unathi variants of work gloves to the drobes having them, + and taj workboots to the ones having normal workboots. + - rscadd: Renamed taj and unathi work gloves, leather gloves and workboots to be + clear who can wear it. + - rscadd: Made hangar techs spawn with workboots by default, instead of with sneakers. + Safety first. +2026-02-05: + Batrachophrenoboocosmomachia: + - qol: Moves area blurbs entirely from chat window to status tab. + - code_imp: Updates comments in affected files to use dmdocs. + Hellfirejag: + - bugfix: Observers (such as Storytellers) are now always included in Narrates with + a filter. + - bugfix: Fixed admin bombs being dropped at the wrong location. +2026-02-06: + AlaunusLux: + - balance: Greimorian servants can now see in the dark. + - balance: Things pulled by greimorians will always pass through webs. + - qol: Greimorians attempting to lay eggs or a servant now get feedback if it fails. + - experiment: Gives Greimorian Queens a melee attack reach of two tiles. + - bugfix: Greimorian servants can no longer speak Tau Ceti Basic. + - bugfix: Fixes Greimorian Queen icon state being set to resting if the controlling + player ghosts. + - bugfix: Fixed a runtime error that occurred when a vampire tried to suck blood + from a target whose mind was null. + Hellfirejag: + - refactor: Killed the last few ancient Goto statements. + TheGreyWolf: + - rscadd: The antag toolbox now also have insulated gloves fitting taj and unathi. +2026-02-07: + AlaunusLux: + - bugfix: Fixed ghost roles falling off manifest when a player leaves the round. + Hellfirejag: + - bugfix: Fixed some situations where a character in-game could view the ooc-manifest + that includes off-ship roles. + - bugfix: Fixed mobs other than humans not moving smoothly. + - bugfix: Fixed mobs cheating their movement speed on diagonals. + - bugfix: Fixed smooth movement not working on mechs. + - bugfix: Fixed smooth movement not working on wheelchairs/rollerbeds/vehicles in + general. + - bugfix: Fixed mobs moving at lightspeed. + SimpleMaroon: + - bugfix: Fixed accented softcaps missing the accent on the worn and held icons. + TheGreyWolf: + - bugfix: Fixed the name of the fluff maintenance panels around the ship. + - rscadd: The towel now keeps its name and description when unfolded on the floor + and picked up again. + - bugfix: Fixes several light in-hand sprites. + - bugfix: Fixes the directional glow to be a radius instead for the torch, flare + and marshal wand. + - bugfix: Added hammers to the autolathe. + - bugfix: Fixed the consular and RD psi receiver boxes decaying. They get organ + coolers now. + - bugfix: Fixed minor spelling stuff for the psi receiver. + - bugfix: Fixes the psi receiver using the wrong sprite. + - bugfix: Fixes the francisca being incorrect. + UltraBigRat: + - rscadd: Added nanopaste to the uplink. + fyni: + - rscadd: Adds the Outer Eyes small and large flag, only available to mappers, ST + and modmins. + - rscadd: Adds the Outer Eyes paperwork icon, [logo_toe], available for anyone to + use. Don't go marking your paperwork with wierd icons though. +2026-02-08: + Greenjoe: + - rscadd: Adds Tajara versions of several human hairstyles. + Hellfirejag: + - bugfix: Fixed closets opening themselves when pulled. + fyni: + - bugfix: Fixes an upside down sprite on the right large flag, properly capatalizes + flag name. +2026-02-09: + Acetrea: + - balance: Changes the perconol recipe from water to hydrazine. + - balance: Slightly edits the description of mortaphenyl to reflect changes made + to the cargo order menu. + - spellcheck: Corrects 'opiod' to 'opioid'. + Batrachophrenoboocosmomachia: + - bugfix: Removes TC spawn from the Horizon's Secure Technical Storage compartment + (accidental inclusion). + GeneralCamo: + - rscadd: Added passive vents, that passively interact with the air outside of them. + - bugfix: Vent and scrubber items will now use the correct icons. + Helfirejag: + - bugfix: Fixed the credit symbol not being correctly applied when using [cr] on + a paper. + MynameAsJeff: + - bugfix: Fixes several airlock and wiring errors on the SSRM Corvette. + - bugfix: Gives the SSRM Corvette's Chief Petty Officer a proper ID. + - rscadd: Reworks the Sol Frigate's Officer Quarters into a single office and living + space. + - rscadd: Gives the Sol Frigate extra kit for it's armory and 'exosuit. This is + intended to bring the Frigate up to par with the Xanu Frigate and TCAF Corvette + in terms of boarding capability. + TheGreyWolf: + - rscadd: 'Added a new music cartridge with the adhomai lobby music: Adhomai vibes.' + - bugfix: Fixes the misplaced grating outside the commissary. + - rscadd: Added a request console to the commissary. + - rscadd: Added tape to the commissary. + - rscadd: Modified the disposal leading to the commissary to always output packages + in the customer section. + - bugfix: Added the missing request console to the machinist workshop. + - bugfix: Fixed one of the signs on the security elevator moving with the elevator. + - rscadd: Updated the receipt from the commissary register and the quikpay. + - bugfix: Fixed the quikpay not working as intended for multi-item payments. + - rscadd: 'Added the following options as food in the lunchbox: Hard bread, nomad + skewer, mashed earthen-root, earthen-root fries, scout ration and ras''val pasta.' + - rscadd: 'Added the following options as snacks in the lunchbox: A singular mini-avah, + zkahnkowa slice, roasted dirtberries.' + - rscadd: Canned earthen-root juice was added to the commissary drink restock pack + and as an option to the lunchbox. + Wildkins: + - bugfix: Fix tool interactions using the target as the tool rather than the tool. +2026-02-10: + ChangeMe: + - rscadd: Added a changelog editing system that should cause fewer conflicts and + more accurate timestamps. + - rscdel: Killed innocent kittens. + FabianK3: + - rscadd: Updated the bounties paper design. + Hellfirejag: + - bugfix: Added a check to prevent division by 0 in ship math. + Wildkins: + - refactor: Every single datum no longer does REF(src) on /Destroy to see if it + has an open nanoui + - bugfix: Showing held items no longer causes every recording device to runtime. + - refactor: Every obj/item/Destroy no longer updates the held mob's icon three times. + - refactor: Follow menu is now a global UI and should no longer DDOS the server + when 50 people have it open + - refactor: Follow menu no longer auto-updates the list of mobs while open, use + the refresh button. + - bugfix: Fix runtime when a /human without hair or facial hair would be skeletonized + - refactor: Cleaned up human icon update code. Lying / direction changes no longer + cause four update_icon calls. Tailed species turning no longer causes six. + - bugfix: Fix runtime caused by detached / ownerless mechanical hands. + - bugfix: Fix colorspace runtime. + - bugfix: Fix lighting harddel caused by using improper handlers for static lights. + - bugfix: Lifts now grey out the current location, instead of throwing a runtime + when you click it. + - bugfix: Fix runtime when a bloodless/fakedeath mob has their pulse taken. +2026-02-12: + Batrachophrenoboocosmomachia: + - bugfix: Fixes headphones/earbuds from causing early cutoffs in other nearby sounds + in several configurations. + JohnWildkins: + - bugfix: Augments given by culture (i.e. Vaurca language processors) no longer + get applied twice when spawning in. + TheGreyWolf: + - bugfix: Fixed that journals and notepads could not be written in when held in + hand. + - bugfix: Fixed the quik-pay not getting prices correct when clicking an item with + it to input it quickly. + - spellcheck: Standardised how the credit symbol is shown in several places, and + replaces several instances of credits with the symbol. + arrow768: + - server: Removes verbs to get log files from the server, use the WI, TGS or logging + infrastructure. +2026-02-14: + Batrachophrenoboocosmomachia: + - rscdel: Removes 'Assembled Solar Panels' bounty from bounty pool and updates the + 'Solar Assemblies or Trackers' with its old description referencing the phoron + scarcity. + Greenjoe: + - rscadd: Adds bodyguard outfits for Tau Ceti, Sol, Elyra, Nralakk and the Golden + Deep. + - bugfix: Fixes the Elyran navy uniform lacking an item icon. + JohnWildkins: + - refactor: Updates TGUI backend to hopefully reduce instability / failures to load. + - bugfix: Fixes TGchat scrolling issues. + - refactor: Change traitor uplink to use static data to improve server performance. + - refactor: Open UIs are now tracked by their owner datum rather than by the tgui + subsystem, to improve server performance when closing UIs. + TheGreyWolf: + - bugfix: Fixes Kathira's custom item cloak. + - bugfix: Fixed the inverted roll up/down message. + fyni: + - rscadd: Adds a red and pink heart balloon for valentines! Also adds them to the + random balloon pool. <3 <3 +2026-02-15: + JohnWildkins: + - bugfix: Fix lobby screen system failing to switch to the last lobby screen in + a set. +2026-02-17: + FabianK3: + - rscadd: Added the alt title Foreign Service Officer to the consular job. This + alt title can only be selected if the citizenship is set to Sol Alliance. + - code_imp: Added citizenship check to job titles, allowing alt titles to be locked + to specific backgrounds. +2026-02-18: + Batrachophrenoboocosmomachia: + - rscadd: Restores or migrates to contained_sprite already-existing inhands sprites + for MANY items. + - rscadd: Adds new inhand (coder)sprites for many additional items. + - rscadd: Ports inhand sprites for Hydraulic Rescue Tool from /tg/station. + - rscadd: Adds flick animation to gas analyzer. + - bugfix: Fixes minor issues with several inhand sprites (pixel shifting, mismatched + colors, etc). + - code_imp: Moves sprites for 'scanner' type items to all reside in icons/obj/item/scanner.dmi. + - code_imp: Standardizes icon_state naming conventions for several items. + - code_imp: Updates code docs to use DMDocs. + - code_imp: Consolidates scattered modular_computer sprite files to single subfolder. + - qol: Renames 'analyzer' to 'gas analyzer' for consistency with other 'analyzer' + devices. + - bugfix: Allows knives to be stored in cowboy boots. + - refactor: Ports smooth shake_camera proc from /tg/station. + Batrachophrenoboocosmomachia, Tomixcomics: + - rscadd: Adds new Inflatables and Inflatables Box inhand sprites (Tomixcomics spriting). + CatsinHD: + - imageadd: Resprites the Mrrazhak, Tsarayut, and Hotaki rifles. + - rscadd: Adds the Z33 Tamparii bullet. + - rscadd: Adds stickynotes, as well as a stickynotes pad. + - rscadd: Adds notepad paper and receipts. Receipts are printed for cash transactions. + Notepad papers are utilized by the notepad. + ElorgRHG: + - imageadd: Resprited engineering, medical and security webbings (which are now + thinner to not poke out from under suit clothing) and drop pouches. + - imageadd: Added a proper colorable sprite for the colorable drop pouches. + - imageadd: Resprited all jeans, black pants and colorable dress pants. + - rscdel: Removed tan, khaki, red, white pants due to the existance of colorable + dress pants. All maps and outfits where these were used now use black pants + (I did not want to put in the effort). + Hellfirejag: + - rscadd: Reworked mech controls to be Battletech-style. W and S are Forward and + Reverse throttle, while A and D rotate the mech left and right. Mechs have different + forward and reverse speeds based on their chassis. When reversing, your faced + direction doesn't change. + - rscadd: Reworked leg damage for mechs. A mech's movement speeds are reduced by + up to a certain amount based on their percentage of damage taken. Larger legs + can generally take more of a beating before they slow down too much. + - rscadd: Mechs can now strafe left and right with the Q and E keys respectively. + - code_imp: Added a library of Floating Point Hyperbolic functions. I just wanted + Hyperbolic Tangent but figured I might as well add the whole set. + - rscadd: Reworked the Read Mind power to be more interactive with psi-sensitivity. + It also now gives feedback to the victim on what message was sent. + - bugfix: Fixed improper sanitization for Read Mind messages. + - bugfix: Removed a very large variety of hard deletes. + - rscadd: 'Records consoles now show their appropriate records types by default, + EG: Medical showing full medical records, instead of only basic info.' + - rscdel: Medical records no longer displays Allergies, Disabilities and Diseases. + These were vestigial remnants of something removed from the game 10 years ago. +2026-02-19: + CatsinHD: + - bugfix: Stickynotes can now interact with machinery normally, such as disposals. + - bugfix: Crumpled stickynotes can no longer be written on or attached to a surface. + - bugfix: Paper shredders now show the correct(ish) sprite when shredding a crumbled + stickynote. + GeneralCamo: + - rscadd: Changed how napalm works. Instead of directly causing turf fires, napalm + now creates a long-term burning turf fire. + - rscadd: Split Zo'rane fire and napalm. Zo'rane fire is now a much more powerful + version of napalm. + - rscadd: Added a military-grade flamethrower, capable of using napalm. Other fuels + instead give a 150% power bonus. + - balance: Standard (improvised) flamethrowers are no longer capable of using napalm. + They will explode if you try. + - rscadd: Using a wrench on a flamethrower will now prompt you to dismantle either + the igniter, welding tool, or whole thing. + - rscadd: Flamethrowers can now be upgraded in the field. + - balance: Reduced the cost of the standard flamethrower in the uplink from 10 to + 6. + Hellfirejag: + - bugfix: Fixed a hard delete related to human mobs. + JohnWildkins: + - refactor: Fix TGUI chat / stat panel failing to load properly when connecting. + - refactor: Reduce lag by ensuring refreshing char select preview doesn't cause + 50 trillion icon update operations (estimated). + SimpleMaroon: + - qol: Made various adjustments to Vaurca body markings, including standardizing + the mecha eye palette, standardizing the mecha spine palette, removing the forced + green eyes from the mecha mandibles, and separating the hand panels into chassis + and lights. + - imagedel: Removed the 'large' version of the Vaurca mecha eye body markings. + TheGreyWolf: + - bugfix: The adhomian surgeon garb now offers protection equal to a surgical gown + and surgery mask. + - bugfix: The adhomian surgeon garb can now be selected by machinists again. + - bugfix: Assunzioni Sera Stellata di Dalyan Wine can be ordered again. + - bugfix: Sandals now default to being wood colored if not otherwise given color. + - bugfix: Added camera film to the toy shelf storage and briefcases and canes to + the clothing shelf storage. + - bugfix: Fixed that the operations lobby was powered by the wrong grid. + - bugfix: Added some custom items to the merchant blacklist. + - bugfix: Fixed stickynote pad path in the map file. +2026-02-21: + Batrachophrenoboocosmomachia: + - rscadd: Updates vending machine ads. + FabianK3: + - bugfix: Decoupled robot eye sprite from the internal light state. + - qol: Dark mode is now the new default for the UI. The light mode is still available + and can be switched to in the settings found in the chat panel. + - bugfix: Fixed airlocks closing immediataly after the manual override was used + during APC reboots, commonly during eletrical storms. + JohnWildkins: + - bugfix: Fix many instances of objects hard deleting, causing lag spikes. + TheGreyWolf: + - rscadd: A signal was added to bone fixing surgery, for potential future uses where + a bone repair surgery might not work. + - bugfix: Added spotlight light tubes to the autolathe. +2026-02-22: + Hellfirejag: + - bugfix: Fixed the Set Odyssey verb not working. It can now be used anytime after + initialization, but before the round actually starts. + JohnWildkins: + - bugfix: Fixed devs and other non-modmin staff getting errors attempting to submit/reply + to ahelps. + MattAtlas: + - bugfix: Potentially fix a hard delete to do with status icons. + TheGreyWolf: + - rscadd: Native tajaran foot-wear has been renamed to kah'romra. + - rscadd: Changed the default taj shoes from sandals to kah'romra. + Tomixcomics: + - rscadd: Added Cytherian cuisine to the game with 4 specifically cytherian dishes + as well as some popcorn flavors. + - rscadd: Added Adhomian cheese and two new Adhomian cuisine dishes for everyone + who has been asking for more Tajaran foods. + - rscadd: Added an alternate, vegan way to make dough that doesn't require eggs. + - rscadd: Added cheese-less omelettes. + - rscadd: Added a few other miscellaneous dishes such as Poutine, Churros, and chocolate + pizzas. + - rscadd: Trays of clams casino now dispense individual clams that can be eaten + seperately. + - rscadd: Added a new kitchen bounty for some of the new desserts and added the + new tajaran dishes to the adhomian cuisine bounty. + - qol: Changed North Sixty seafood platters to include regular clams instead of + R'sval clams since R'sval clams are Adhomian and I suspect regular clams were + the intention for this dish all along. + - qol: Renamed the old tossed salad to 'apple salad', now that there's a newe, less + fruit-based tossed salad. + - bugfix: Made it so onion rings can be placed freely like every other food instead + of being locked to one spot. + - bugfix: Fixed description typos. +2026-02-23: + Batrachophrenoboocosmomachia: + - refactor: Converts xenobotany's Bioballistic Delivery System interface from NanoUI + to TGUI. + - refactor: Converts xenobotany's Lysis-Isolation Centrifuge interface from NanoUI + to TGUI. + JohnWildkins: + - rscdel: Removed lobby messages when a gamemode fails to be selected. + TheGreyWolf: + - rscadd: 'Added stickynote pads to the following locations: Command offices, bridge, + rep and liaison offices, journalist office, eng, medical and operations lobby, + invest office and lab, galley, vacant office on D3, all three custodial closets, + security meeting room, HR meeting room, machinist workshop, and tool storage.' + - rscadd: Added stickynotes to the loadout. + - qol: Plastic bags can now hold more items and slightly bigger ones. + - qol: Made toptart packages smaller so they fit in plastic bags. +2026-02-27: + AlaunusLux: + - experiment: Adds vampiric and changeling jumpstarters to the uplink and prohibits + voting for those modes. + Batrachophrenoboocosmomachia: + - bugfix: Restores inhand sprites for all radio variants. + - rscadd: Paint sprayers can now be used on unpainted crates and lockers to give + them a custom appearance. + - rscadd: Adds paint sprayers to Hangar Tech lockers. + - qol: Moves pipe painter functionality to paint sprayers; pipe painters now just + flavor objects on some offsites. + - qol: Adds paint sprayers to allowed items list for utility toolbelts. + - imageadd: Codersprites pipe painter with recolorable paint storage component indicating + current color (used by paint sprayer). + - imagedel: Removes old paint sprayer sprite. + - bugfix: Removes old runtime caused by targeting turfs w/ paint sprayers that don't + have flooring singletons assigned. + CatsinHD: + - rscadd: Adds Party Representative as an alt-title for Consulars from the People's + Republic of Adhomai. + - rscadd: Adds the Tsarrayut'an rifle to the cargo order list. + - rscadd: Adds 6.8mm magazine, clip, and AP magazine to the cargo order list. + ElorgRHG: + - imageadd: Tweaked the north facing caligae sprite for Unathi. + - bugfix: Fixes the caligae sock variant going over the claws on the side sprites + for Unathi. + - rscadd: Alt clicking a modular computer to first get the stored card and then + the item has been split to Alt clicking to get the card, and Ctrl clicking to + get the item. + FabianK3: + - rscadd: Updated hangar tech marshalling wands. The marshalling wands now have + color based of intent giving a clearer visual distinction on the action. In + addition, holding two wands in your hands will automatically sync their settings. + - qol: Add the second missing marshalling wand to the tech closets. + - qol: Adjusted hangar tech round start spawn locations. + Hellfirejag: + - bugfix: Fixed organs ticking 50% faster than intended. + - rscadd: Reworked most of IPC heat/cooling code to no longer create uncontrollable + heat spikes. + - bugfix: Fixed IPCs in space suits generating impossible to manage levels of heat + even with a suit cooler. + - bugfix: Fixed suit coolers not even working on IPCs in a space suit in the first + place. + JohnWildkins: + - refactor: Rewrite several heavily-called functions to either inline statements + or otherwise optimize to reduce server load. + - refactor: Improved garbage collection on ammo piles, rocket launchers, and mob + spawners to reduce server lag spikes. + - refactor: Refactored status displays so they don't create 50 overlays a second. + - bugfix: Fix shortwave radios not being able to select channels. + - rscadd: Converted radio/headset interface to TGUI. + TheGreyWolf: + - rscadd: Smartfridges and variants got an UI upgrade. + kermit: + - rscadd: Removes human origin restrictions and whitelists skrell + diona + vaurca + + unathi for custom bioaugs due to their prevalence in lore. Does not unrestrict + Galatean-specific bioaugs. + nauticall: + - rscdel: 'Removes the following offship maps from rotation (1/2): Casino Ship, + Dominian Unathi Privateer, Freebooter Ship, Miners Guild Station, NKA Merchant + Ship, Database Freighter.' + - rscdel: 'Removes the following offship maps too (2/2): SFA Patrol Ship, Tajaran + Smuggler, Unathi Pirate Izharshan Ship, Unathi Pirate Tarwa Ship, COC Surveyor, + Dominian Science Vessel.' + - code_imp: The Freebooter Salvager will now take the place of the old Freebooter + Ship; spawn weight was adjusted to 1 (normal). diff --git a/html/changelogs/archive/2026-03.yml b/html/changelogs/archive/2026-03.yml new file mode 100644 index 000000000000..d040a8a197d8 --- /dev/null +++ b/html/changelogs/archive/2026-03.yml @@ -0,0 +1,83 @@ +2026-03-01: + ASmallCuteCat: + - qol: Adds one light to Medical that solves the huge blob of darkness in the middle + of the GTR + FabianK3: + - bugfix: Fixed handheld sprite for marshalling wands. + GeneralCamo: + - rscadd: Allowed M'sai Tajara to be Executive Officers. + - rscadd: Allowed Zhan-Khazan Tajara to be Operations Managers and Chief Engineers. + - rscadd: Allowed Zhan-Khazan Tajara to be Diplomatic Aides and Bodyguards for the + PRA, and DPRA. + - rscadd: Allowed M'sai Tajara to be Consular Officers for the PRA, DPRA, and NKA. + - rscdel: Disallowed M'sai Tajara to be Diplomatic Aides for the NKA. + - qol: Touched up the Tajara ethnicity descriptions. + Hellfirejag: + - bugfix: Fixed bug with firelocks and doors. + JohnWildkins: + - code_imp: Add check to qdel() to prevent attempts to qdel lists. + - bugfix: Fix bad qdels on tgui list inputs and engicarts. Minor performance increase. + TheGreyWolf: + - rscadd: The commissary cash register can now be filled out with a paper form. +2026-03-02: + Batrachophrenoboocosmomachia: + - bugfix: Cleans up Access Controller TGUI to restore functionality of manually + securing interior/exterior doors, general cleanup and jank reduction. + WickedCybs: + - rscdel: Removed quite a bit of unused custom items. They can return should their + characters resume activity. +2026-03-03: + Batrachophrenoboocosmomachia: + - spellcheck: Renames TEGs to Stirling engines to more accurately reflect their + functionality. + - refactor: Refactor of interface for TEG/Stirling Engines to use TGUI instead of + NanoUI. + GeneralCamo: + - bugfix: Fixed shrapnel not correctly creating new wounds, causing them to disappear. + Greenjoe: + - rscadd: Allows Little Adhomai tajara to select Biesel citizenship. + - rscadd: Little Adhomai tajara are now more used to heat compared to Adhomian tajara. + JohnWildkins: + - refactor: Move smartfridge icon generation to static data and cache results to + improve performance. + - bugfix: Fix chemical bottles not having proper colors in SmartFridge UI. + - bugfix: Fix hivebot hard delete. + Mynameasjeff: + - qol: The Ranger Gunboat has been given a bit of a update. Thank you to @Cormallenfield + on discord for helping with the submap inserts. +2026-03-05: + CatsinHD: + - bugfix: Fixes stickynotes adding papers to the noticeboard despite not being able + to be added to one. + Evandorf: + - rscadd: Standardizes the airlocks in all shuttles by adding manual shutters to + the Spark, Quark, and Canary. This also coincides with changes to SoP - Preflight + Safety Checks. + Hellfirejag: + - balance: Balance pass for 'damaged movement delays' and movement types in general + for mech legs to make them less punishing. Quad mechs now uniquely don't have + a strafe delay. Combat mechs and heavier mechs are in general more resistant + to losing movespeed from damage. + - rscadd: Cult mechs now have a unique mechanic where their movement speed increases + as they take damage. For the Dark Gods! + - bugfix: Fixed mechs not having correct glide sizes for smooth movement when strafing + and reversing. + JohnWildkins: + - rscadd: Added a debug command for devs/admins to list timer sources. + - bugfix: Fixed an issue where Extended wouldn't be selected if no votes for gamemode + were cast. + - code_imp: PRs can now correctly ignore CI runs or just unit tests with [CI Ignore] + and [UT Ignore] respectively. + Timby: + - imageadd: Changes the camera sprites to not be so r4407. Resultantly changes the + ever-popular camera gun's sprite. + - imagedel: Old camera and camera gun sprites are gone. +2026-03-06: + GeneralCamo: + - rscadd: Added bicaridine, dermaline, and tricordrazine to the cargo order interface. + - balance: Dermaline and butazoline are now priced as premium medicines. + - rscadd: The Horizon's medical bay now starts with a single bottle of bicaridine, + kelotane, and dexalin. + - rscadd: Smartfridges now have emissive masks. + fyni: + - rscadd: Adds a sign for the commissary - Quik Stop, by Orion. diff --git a/html/changelogs/hellfirejag - Skills System.yml b/html/changelogs/hellfirejag - Skills System.yml new file mode 100644 index 000000000000..e23b95d1fd3f --- /dev/null +++ b/html/changelogs/hellfirejag - Skills System.yml @@ -0,0 +1,4 @@ +author: Hellfirejag and Matt Atlas +delete-after: True +changes: + - rscadd: "Added a basic initial implementation of a Mechanical Skills System." diff --git a/html/changelogs/hellfirejag-offships-manifest.yml b/html/changelogs/hellfirejag-offships-manifest.yml deleted file mode 100644 index fd13d50fb3b5..000000000000 --- a/html/changelogs/hellfirejag-offships-manifest.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: Hellfirejag -delete-after: True -changes: - - rscadd: "Off-ship player characters can now be viewed from the crew manifest, so long as you are either an observer, or are in the lobby." - - bugfix: "Fixed player characters with apostrophes in their name showing up weirdly on the manifest." diff --git a/html/images/outereyeslogo.png b/html/images/outereyeslogo.png new file mode 100644 index 000000000000..254752c8c712 Binary files /dev/null and b/html/images/outereyeslogo.png differ diff --git a/html/images/outereyeslogo_small.png b/html/images/outereyeslogo_small.png new file mode 100644 index 000000000000..3db34a441194 Binary files /dev/null and b/html/images/outereyeslogo_small.png differ diff --git a/icons/atmos/vent_passive.dmi b/icons/atmos/vent_passive.dmi new file mode 100644 index 000000000000..83acbff75440 Binary files /dev/null and b/icons/atmos/vent_passive.dmi differ diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index 78350a08b645..1fbd4ec1026e 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/icons/mob/human_face/msai_hair.dmi b/icons/mob/human_face/msai_hair.dmi index 00daa7dc638f..1b5f03a45ae2 100644 Binary files a/icons/mob/human_face/msai_hair.dmi and b/icons/mob/human_face/msai_hair.dmi differ diff --git a/icons/mob/human_face/tajara_hair.dmi b/icons/mob/human_face/tajara_hair.dmi index f8009dc1bb72..1d492df0a28e 100644 Binary files a/icons/mob/human_face/tajara_hair.dmi and b/icons/mob/human_face/tajara_hair.dmi differ diff --git a/icons/mob/human_races/markings_vaurca.dmi b/icons/mob/human_races/markings_vaurca.dmi index 7411030a9003..fccc64d1fbaa 100644 Binary files a/icons/mob/human_races/markings_vaurca.dmi and b/icons/mob/human_races/markings_vaurca.dmi differ diff --git a/icons/mob/items/lefthand_toy.dmi b/icons/mob/items/lefthand_toy.dmi index befc93b4f093..7508ec97d1d9 100644 Binary files a/icons/mob/items/lefthand_toy.dmi and b/icons/mob/items/lefthand_toy.dmi differ diff --git a/icons/mob/items/righthand_toy.dmi b/icons/mob/items/righthand_toy.dmi index c27dce9c3081..765a40ae3a3f 100644 Binary files a/icons/mob/items/righthand_toy.dmi and b/icons/mob/items/righthand_toy.dmi differ diff --git a/icons/obj/ammo.dmi b/icons/obj/ammo.dmi index ac7970fbf5f9..340abea2718a 100644 Binary files a/icons/obj/ammo.dmi and b/icons/obj/ammo.dmi differ diff --git a/icons/obj/apc_repair.dmi b/icons/obj/apc_repair.dmi index df295e2551b3..805e51e974b5 100644 Binary files a/icons/obj/apc_repair.dmi and b/icons/obj/apc_repair.dmi differ diff --git a/icons/obj/bureaucracy.dmi b/icons/obj/bureaucracy.dmi index e3233825df66..07ad7cb619ae 100644 Binary files a/icons/obj/bureaucracy.dmi and b/icons/obj/bureaucracy.dmi differ diff --git a/icons/obj/clothing/hats/soft_caps.dmi b/icons/obj/clothing/hats/soft_caps.dmi index 144a6a0d2cbf..5d18ed80f276 100644 Binary files a/icons/obj/clothing/hats/soft_caps.dmi and b/icons/obj/clothing/hats/soft_caps.dmi differ diff --git a/icons/obj/custom_items/aavs_mask.dmi b/icons/obj/custom_items/aavs_mask.dmi deleted file mode 100644 index 98900a1d7581..000000000000 Binary files a/icons/obj/custom_items/aavs_mask.dmi and /dev/null differ diff --git a/icons/obj/custom_items/akara_mask.dmi b/icons/obj/custom_items/akara_mask.dmi deleted file mode 100644 index fd184144b255..000000000000 Binary files a/icons/obj/custom_items/akara_mask.dmi and /dev/null differ diff --git a/icons/obj/custom_items/akila_jacket.dmi b/icons/obj/custom_items/akila_jacket.dmi deleted file mode 100644 index 7e9988a88504..000000000000 Binary files a/icons/obj/custom_items/akila_jacket.dmi and /dev/null differ diff --git a/icons/obj/custom_items/akinyi_symphette.dmi b/icons/obj/custom_items/akinyi_symphette.dmi deleted file mode 100644 index 942d65c00bdd..000000000000 Binary files a/icons/obj/custom_items/akinyi_symphette.dmi and /dev/null differ diff --git a/icons/obj/custom_items/andersen_goggles.dmi b/icons/obj/custom_items/andersen_goggles.dmi deleted file mode 100644 index 737b4196e3bd..000000000000 Binary files a/icons/obj/custom_items/andersen_goggles.dmi and /dev/null differ diff --git a/icons/obj/custom_items/bells_zora_items.dmi b/icons/obj/custom_items/bells_zora_items.dmi deleted file mode 100644 index 804a9fb827a6..000000000000 Binary files a/icons/obj/custom_items/bells_zora_items.dmi and /dev/null differ diff --git a/icons/obj/custom_items/bian_flag.dmi b/icons/obj/custom_items/bian_flag.dmi deleted file mode 100644 index 542c70fc3122..000000000000 Binary files a/icons/obj/custom_items/bian_flag.dmi and /dev/null differ diff --git a/icons/obj/custom_items/dekel_smock.dmi b/icons/obj/custom_items/dekel_smock.dmi deleted file mode 100644 index 3d4068e47e7a..000000000000 Binary files a/icons/obj/custom_items/dekel_smock.dmi and /dev/null differ diff --git a/icons/obj/custom_items/djar_cape.dmi b/icons/obj/custom_items/djar_cape.dmi deleted file mode 100644 index 03611861e49e..000000000000 Binary files a/icons/obj/custom_items/djar_cape.dmi and /dev/null differ diff --git a/icons/obj/custom_items/eden_cloak.dmi b/icons/obj/custom_items/eden_cloak.dmi deleted file mode 100644 index 3f41beeff512..000000000000 Binary files a/icons/obj/custom_items/eden_cloak.dmi and /dev/null differ diff --git a/icons/obj/custom_items/godard_cape.dmi b/icons/obj/custom_items/godard_cape.dmi deleted file mode 100644 index becd8f0399ef..000000000000 Binary files a/icons/obj/custom_items/godard_cape.dmi and /dev/null differ diff --git a/icons/obj/custom_items/hadley_camera.dmi b/icons/obj/custom_items/hadley_camera.dmi deleted file mode 100644 index ec9b4b9c675f..000000000000 Binary files a/icons/obj/custom_items/hadley_camera.dmi and /dev/null differ diff --git a/icons/obj/custom_items/hidemichi_items.dmi b/icons/obj/custom_items/hidemichi_items.dmi deleted file mode 100644 index 924f37aabf56..000000000000 Binary files a/icons/obj/custom_items/hidemichi_items.dmi and /dev/null differ diff --git a/icons/obj/custom_items/ielia_tarot.dmi b/icons/obj/custom_items/ielia_tarot.dmi deleted file mode 100644 index 680554e808bf..000000000000 Binary files a/icons/obj/custom_items/ielia_tarot.dmi and /dev/null differ diff --git a/icons/obj/custom_items/imogen_items.dmi b/icons/obj/custom_items/imogen_items.dmi deleted file mode 100644 index 7f8b9c36abfe..000000000000 Binary files a/icons/obj/custom_items/imogen_items.dmi and /dev/null differ diff --git a/icons/obj/custom_items/ird_face.dmi b/icons/obj/custom_items/ird_face.dmi deleted file mode 100644 index d9146dc88e61..000000000000 Binary files a/icons/obj/custom_items/ird_face.dmi and /dev/null differ diff --git a/icons/obj/custom_items/leo_coat.dmi b/icons/obj/custom_items/leo_coat.dmi deleted file mode 100644 index ef48e99ac0aa..000000000000 Binary files a/icons/obj/custom_items/leo_coat.dmi and /dev/null differ diff --git a/icons/obj/custom_items/leo_scarf.dmi b/icons/obj/custom_items/leo_scarf.dmi deleted file mode 100644 index c0663ff0c8c0..000000000000 Binary files a/icons/obj/custom_items/leo_scarf.dmi and /dev/null differ diff --git a/icons/obj/custom_items/leonid_chokha.dmi b/icons/obj/custom_items/leonid_chokha.dmi deleted file mode 100644 index fb0115d6605a..000000000000 Binary files a/icons/obj/custom_items/leonid_chokha.dmi and /dev/null differ diff --git a/icons/obj/custom_items/naali_blanket.dmi b/icons/obj/custom_items/naali_blanket.dmi deleted file mode 100644 index 5cad0d6ebbe0..000000000000 Binary files a/icons/obj/custom_items/naali_blanket.dmi and /dev/null differ diff --git a/icons/obj/custom_items/nai_items.dmi b/icons/obj/custom_items/nai_items.dmi deleted file mode 100644 index 4aba61417f52..000000000000 Binary files a/icons/obj/custom_items/nai_items.dmi and /dev/null differ diff --git a/icons/obj/custom_items/nasira_burner.dmi b/icons/obj/custom_items/nasira_burner.dmi deleted file mode 100644 index 2059ea091ddf..000000000000 Binary files a/icons/obj/custom_items/nasira_burner.dmi and /dev/null differ diff --git a/icons/obj/custom_items/nikit_zippo.dmi b/icons/obj/custom_items/nikit_zippo.dmi deleted file mode 100644 index 5fd228d13b7b..000000000000 Binary files a/icons/obj/custom_items/nikit_zippo.dmi and /dev/null differ diff --git a/icons/obj/custom_items/osborne_suit.dmi b/icons/obj/custom_items/osborne_suit.dmi deleted file mode 100644 index c633b0d85838..000000000000 Binary files a/icons/obj/custom_items/osborne_suit.dmi and /dev/null differ diff --git a/icons/obj/custom_items/ozuha_cape.dmi b/icons/obj/custom_items/ozuha_cape.dmi deleted file mode 100644 index 8a9b9f7d457b..000000000000 Binary files a/icons/obj/custom_items/ozuha_cape.dmi and /dev/null differ diff --git a/icons/obj/custom_items/provenance_jacket.dmi b/icons/obj/custom_items/provenance_jacket.dmi deleted file mode 100644 index 25896309f577..000000000000 Binary files a/icons/obj/custom_items/provenance_jacket.dmi and /dev/null differ diff --git a/icons/obj/custom_items/qoi_console.dmi b/icons/obj/custom_items/qoi_console.dmi deleted file mode 100644 index c17a553a0d1a..000000000000 Binary files a/icons/obj/custom_items/qoi_console.dmi and /dev/null differ diff --git a/icons/obj/custom_items/ramit_jacket.dmi b/icons/obj/custom_items/ramit_jacket.dmi deleted file mode 100644 index 63302453b8dc..000000000000 Binary files a/icons/obj/custom_items/ramit_jacket.dmi and /dev/null differ diff --git a/icons/obj/custom_items/ravna_items.dmi b/icons/obj/custom_items/ravna_items.dmi deleted file mode 100644 index 70441398d3c5..000000000000 Binary files a/icons/obj/custom_items/ravna_items.dmi and /dev/null differ diff --git a/icons/obj/custom_items/rex_watch.dmi b/icons/obj/custom_items/rex_watch.dmi deleted file mode 100644 index 594714340ab6..000000000000 Binary files a/icons/obj/custom_items/rex_watch.dmi and /dev/null differ diff --git a/icons/obj/custom_items/rifler_holster.dmi b/icons/obj/custom_items/rifler_holster.dmi deleted file mode 100644 index 62253a7a536b..000000000000 Binary files a/icons/obj/custom_items/rifler_holster.dmi and /dev/null differ diff --git a/icons/obj/custom_items/ryn_clothing.dmi b/icons/obj/custom_items/ryn_clothing.dmi deleted file mode 100644 index 300d1d9c7183..000000000000 Binary files a/icons/obj/custom_items/ryn_clothing.dmi and /dev/null differ diff --git a/icons/obj/custom_items/schlosser_hat.dmi b/icons/obj/custom_items/schlosser_hat.dmi deleted file mode 100644 index a313828b97c3..000000000000 Binary files a/icons/obj/custom_items/schlosser_hat.dmi and /dev/null differ diff --git a/icons/obj/custom_items/sentiment_bouquet.dmi b/icons/obj/custom_items/sentiment_bouquet.dmi deleted file mode 100644 index 7eb7423d34e1..000000000000 Binary files a/icons/obj/custom_items/sentiment_bouquet.dmi and /dev/null differ diff --git a/icons/obj/custom_items/talon_coat.dmi b/icons/obj/custom_items/talon_coat.dmi deleted file mode 100644 index 1caad87eb3e9..000000000000 Binary files a/icons/obj/custom_items/talon_coat.dmi and /dev/null differ diff --git a/icons/obj/custom_items/thea_tea.dmi b/icons/obj/custom_items/thea_tea.dmi deleted file mode 100644 index 98488a96a167..000000000000 Binary files a/icons/obj/custom_items/thea_tea.dmi and /dev/null differ diff --git a/icons/obj/custom_items/valetzrhonaja_cloak.dmi b/icons/obj/custom_items/valetzrhonaja_cloak.dmi deleted file mode 100644 index c94a681c1200..000000000000 Binary files a/icons/obj/custom_items/valetzrhonaja_cloak.dmi and /dev/null differ diff --git a/icons/obj/custom_items/vira_coat.dmi b/icons/obj/custom_items/vira_coat.dmi deleted file mode 100644 index cb66e6e344c6..000000000000 Binary files a/icons/obj/custom_items/vira_coat.dmi and /dev/null differ diff --git a/icons/obj/custom_items/zubari_jacket.dmi b/icons/obj/custom_items/zubari_jacket.dmi deleted file mode 100644 index 1333ad6541b8..000000000000 Binary files a/icons/obj/custom_items/zubari_jacket.dmi and /dev/null differ diff --git a/icons/obj/devices/paperscanner.dmi b/icons/obj/devices/paperscanner.dmi deleted file mode 100644 index 1af5e9691343..000000000000 Binary files a/icons/obj/devices/paperscanner.dmi and /dev/null differ diff --git a/icons/obj/geiger_counter.dmi b/icons/obj/geiger_counter.dmi deleted file mode 100644 index 3e67804ccc48..000000000000 Binary files a/icons/obj/geiger_counter.dmi and /dev/null differ diff --git a/icons/obj/guns/cameragun.dmi b/icons/obj/guns/cameragun.dmi index 501421651cca..20db6ef43345 100644 Binary files a/icons/obj/guns/cameragun.dmi and b/icons/obj/guns/cameragun.dmi differ diff --git a/icons/obj/guns/dragunov.dmi b/icons/obj/guns/dragunov.dmi index 5e91fb00c096..3f9e801d81cd 100644 Binary files a/icons/obj/guns/dragunov.dmi and b/icons/obj/guns/dragunov.dmi differ diff --git a/icons/obj/guns/mrrazhak.dmi b/icons/obj/guns/mrrazhak.dmi index a55ff26e2682..7df437bb68cc 100644 Binary files a/icons/obj/guns/mrrazhak.dmi and b/icons/obj/guns/mrrazhak.dmi differ diff --git a/icons/obj/guns/tsarrayut.dmi b/icons/obj/guns/tsarrayut.dmi index 537bd2b8fb7d..9b57ecec0a6d 100644 Binary files a/icons/obj/guns/tsarrayut.dmi and b/icons/obj/guns/tsarrayut.dmi differ diff --git a/icons/obj/hacktool.dmi b/icons/obj/hacktool.dmi index ce2f374a50a4..32a59fb25769 100644 Binary files a/icons/obj/hacktool.dmi and b/icons/obj/hacktool.dmi differ diff --git a/icons/obj/ipc_utilities.dmi b/icons/obj/ipc_utilities.dmi index b98485fe6e66..1fe755520838 100644 Binary files a/icons/obj/ipc_utilities.dmi and b/icons/obj/ipc_utilities.dmi differ diff --git a/icons/obj/item/adv_mining_scanner.dmi b/icons/obj/item/adv_mining_scanner.dmi deleted file mode 100644 index ffbc48ce56d7..000000000000 Binary files a/icons/obj/item/adv_mining_scanner.dmi and /dev/null differ diff --git a/icons/obj/item/advanced_healthanalyzer.dmi b/icons/obj/item/advanced_healthanalyzer.dmi deleted file mode 100644 index 1e5657ae5fa0..000000000000 Binary files a/icons/obj/item/advanced_healthanalyzer.dmi and /dev/null differ diff --git a/icons/obj/item/air_analyzer.dmi b/icons/obj/item/air_analyzer.dmi deleted file mode 100644 index 847c696185b3..000000000000 Binary files a/icons/obj/item/air_analyzer.dmi and /dev/null differ diff --git a/icons/obj/item/autopsy_scanner.dmi b/icons/obj/item/autopsy_scanner.dmi deleted file mode 100644 index 6bda17e0eb71..000000000000 Binary files a/icons/obj/item/autopsy_scanner.dmi and /dev/null differ diff --git a/icons/obj/item/breath_analyzer.dmi b/icons/obj/item/breath_analyzer.dmi deleted file mode 100644 index dbef0c6b023b..000000000000 Binary files a/icons/obj/item/breath_analyzer.dmi and /dev/null differ diff --git a/icons/obj/item/clothing/accessory/holster.dmi b/icons/obj/item/clothing/accessory/holster.dmi index 57060b9efa4d..3303ae169fa4 100644 Binary files a/icons/obj/item/clothing/accessory/holster.dmi and b/icons/obj/item/clothing/accessory/holster.dmi differ diff --git a/icons/obj/item/clothing/accessory/webbing.dmi b/icons/obj/item/clothing/accessory/webbing.dmi index ddaa1fefcbba..26adcb7b84f2 100644 Binary files a/icons/obj/item/clothing/accessory/webbing.dmi and b/icons/obj/item/clothing/accessory/webbing.dmi differ diff --git a/icons/obj/item/clothing/pants/pants.dmi b/icons/obj/item/clothing/pants/pants.dmi index b5051e7b08a6..e7627b9dd3b2 100644 Binary files a/icons/obj/item/clothing/pants/pants.dmi and b/icons/obj/item/clothing/pants/pants.dmi differ diff --git a/icons/obj/item/clothing/pants/shorts.dmi b/icons/obj/item/clothing/pants/shorts.dmi index a6379dd0773a..8957676c613b 100644 Binary files a/icons/obj/item/clothing/pants/shorts.dmi and b/icons/obj/item/clothing/pants/shorts.dmi differ diff --git a/icons/obj/item/clothing/shoes/sandals.dmi b/icons/obj/item/clothing/shoes/sandals.dmi index 70b21e710ff0..dbb155ee3523 100644 Binary files a/icons/obj/item/clothing/shoes/sandals.dmi and b/icons/obj/item/clothing/shoes/sandals.dmi differ diff --git a/icons/obj/item/cratescanner.dmi b/icons/obj/item/cratescanner.dmi deleted file mode 100644 index fd5b2bccee63..000000000000 Binary files a/icons/obj/item/cratescanner.dmi and /dev/null differ diff --git a/icons/obj/item/dest_tagger.dmi b/icons/obj/item/dest_tagger.dmi index 7cbb0324c6bc..52484cabfb74 100644 Binary files a/icons/obj/item/dest_tagger.dmi and b/icons/obj/item/dest_tagger.dmi differ diff --git a/icons/obj/item/export_scanner.dmi b/icons/obj/item/export_scanner.dmi deleted file mode 100644 index 3947c16e985b..000000000000 Binary files a/icons/obj/item/export_scanner.dmi and /dev/null differ diff --git a/icons/obj/item/healthanalyzer.dmi b/icons/obj/item/healthanalyzer.dmi deleted file mode 100644 index 7ee9c251d576..000000000000 Binary files a/icons/obj/item/healthanalyzer.dmi and /dev/null differ diff --git a/icons/obj/item/hydraulic_rescue_tool.dmi b/icons/obj/item/hydraulic_rescue_tool.dmi index ac40068a16f1..a6b7a32f9c7f 100644 Binary files a/icons/obj/item/hydraulic_rescue_tool.dmi and b/icons/obj/item/hydraulic_rescue_tool.dmi differ diff --git a/icons/obj/item/inflatables.dmi b/icons/obj/item/inflatables.dmi index 473b81a0237d..bb47bfe5500e 100644 Binary files a/icons/obj/item/inflatables.dmi and b/icons/obj/item/inflatables.dmi differ diff --git a/icons/obj/item/mass_spectrometer.dmi b/icons/obj/item/mass_spectrometer.dmi deleted file mode 100644 index 2df3712d33ed..000000000000 Binary files a/icons/obj/item/mass_spectrometer.dmi and /dev/null differ diff --git a/icons/obj/item/military_flamethrower.dmi b/icons/obj/item/military_flamethrower.dmi new file mode 100644 index 000000000000..e7d1dfb58e92 Binary files /dev/null and b/icons/obj/item/military_flamethrower.dmi differ diff --git a/icons/obj/item/mining_scanner.dmi b/icons/obj/item/mining_scanner.dmi deleted file mode 100644 index 50573c041234..000000000000 Binary files a/icons/obj/item/mining_scanner.dmi and /dev/null differ diff --git a/icons/obj/item/paint_sprayer.dmi b/icons/obj/item/paint_sprayer.dmi index 324d59e01b51..eb34246db220 100644 Binary files a/icons/obj/item/paint_sprayer.dmi and b/icons/obj/item/paint_sprayer.dmi differ diff --git a/icons/obj/item/pipe_painter.dmi b/icons/obj/item/pipe_painter.dmi deleted file mode 100644 index a0fcb7accea4..000000000000 Binary files a/icons/obj/item/pipe_painter.dmi and /dev/null differ diff --git a/icons/obj/item/plant_analyzer.dmi b/icons/obj/item/plant_analyzer.dmi deleted file mode 100644 index 7b13bbab2c51..000000000000 Binary files a/icons/obj/item/plant_analyzer.dmi and /dev/null differ diff --git a/icons/obj/item/price_scanner.dmi b/icons/obj/item/price_scanner.dmi deleted file mode 100644 index 6cee1b4cc7cd..000000000000 Binary files a/icons/obj/item/price_scanner.dmi and /dev/null differ diff --git a/icons/obj/item/reagent_containers/food/cultural/human.dmi b/icons/obj/item/reagent_containers/food/cultural/human.dmi index 03f1e4aec88b..8163e265019a 100644 Binary files a/icons/obj/item/reagent_containers/food/cultural/human.dmi and b/icons/obj/item/reagent_containers/food/cultural/human.dmi differ diff --git a/icons/obj/item/reagent_containers/food/cultural/tajara.dmi b/icons/obj/item/reagent_containers/food/cultural/tajara.dmi index 356aca941ded..25b320a2b738 100644 Binary files a/icons/obj/item/reagent_containers/food/cultural/tajara.dmi and b/icons/obj/item/reagent_containers/food/cultural/tajara.dmi differ diff --git a/icons/obj/item/reagent_containers/food/drinks/soda.dmi b/icons/obj/item/reagent_containers/food/drinks/soda.dmi index 3d9703b8f0f4..503d0a598682 100644 Binary files a/icons/obj/item/reagent_containers/food/drinks/soda.dmi and b/icons/obj/item/reagent_containers/food/drinks/soda.dmi differ diff --git a/icons/obj/item/reagent_containers/food/egg.dmi b/icons/obj/item/reagent_containers/food/egg.dmi index b01f00f6c76d..a332370b4e4b 100644 Binary files a/icons/obj/item/reagent_containers/food/egg.dmi and b/icons/obj/item/reagent_containers/food/egg.dmi differ diff --git a/icons/obj/item/reagent_containers/food/fryer.dmi b/icons/obj/item/reagent_containers/food/fryer.dmi index 4a25c3ba776d..dcd071a6d49a 100644 Binary files a/icons/obj/item/reagent_containers/food/fryer.dmi and b/icons/obj/item/reagent_containers/food/fryer.dmi differ diff --git a/icons/obj/item/reagent_containers/food/pizza.dmi b/icons/obj/item/reagent_containers/food/pizza.dmi index 7e9b874f97db..532696f9951e 100644 Binary files a/icons/obj/item/reagent_containers/food/pizza.dmi and b/icons/obj/item/reagent_containers/food/pizza.dmi differ diff --git a/icons/obj/item/reagent_containers/food/processed.dmi b/icons/obj/item/reagent_containers/food/processed.dmi index 5c40cd9a0447..a93429504b59 100644 Binary files a/icons/obj/item/reagent_containers/food/processed.dmi and b/icons/obj/item/reagent_containers/food/processed.dmi differ diff --git a/icons/obj/item/reagent_containers/weldpack.dmi b/icons/obj/item/reagent_containers/weldpack.dmi index fe3f29ae04f7..a6901e001043 100644 Binary files a/icons/obj/item/reagent_containers/weldpack.dmi and b/icons/obj/item/reagent_containers/weldpack.dmi differ diff --git a/icons/obj/item/reagent_scanner.dmi b/icons/obj/item/reagent_scanner.dmi deleted file mode 100644 index cdd9077b7d9c..000000000000 Binary files a/icons/obj/item/reagent_scanner.dmi and /dev/null differ diff --git a/icons/obj/item/robotanalyzer.dmi b/icons/obj/item/robotanalyzer.dmi deleted file mode 100644 index 6ed501d5f92a..000000000000 Binary files a/icons/obj/item/robotanalyzer.dmi and /dev/null differ diff --git a/icons/obj/item/scanner.dmi b/icons/obj/item/scanner.dmi new file mode 100644 index 000000000000..cbc6186420b9 Binary files /dev/null and b/icons/obj/item/scanner.dmi differ diff --git a/icons/obj/item/slime_scanner.dmi b/icons/obj/item/slime_scanner.dmi deleted file mode 100644 index c2930820dfa4..000000000000 Binary files a/icons/obj/item/slime_scanner.dmi and /dev/null differ diff --git a/icons/obj/item/t_scanner.dmi b/icons/obj/item/t_scanner.dmi deleted file mode 100644 index 96d995f90938..000000000000 Binary files a/icons/obj/item/t_scanner.dmi and /dev/null differ diff --git a/icons/obj/item/taperecorder.dmi b/icons/obj/item/taperecorder.dmi index b83eae6cfd6b..044427aaa9a7 100644 Binary files a/icons/obj/item/taperecorder.dmi and b/icons/obj/item/taperecorder.dmi differ diff --git a/icons/obj/library.dmi b/icons/obj/library.dmi index 2108e719c523..aeea835eaf38 100644 Binary files a/icons/obj/library.dmi and b/icons/obj/library.dmi differ diff --git a/icons/obj/lighting.dmi b/icons/obj/lighting.dmi index 3c5b87a7219b..084dbd70495e 100644 Binary files a/icons/obj/lighting.dmi and b/icons/obj/lighting.dmi differ diff --git a/icons/obj/machinery/smartfridge.dmi b/icons/obj/machinery/smartfridge.dmi index 57f69f2d154c..55cc13591db3 100644 Binary files a/icons/obj/machinery/smartfridge.dmi and b/icons/obj/machinery/smartfridge.dmi differ diff --git a/icons/obj/marketsigns.dmi b/icons/obj/marketsigns.dmi index 7ba176936c77..02a174840597 100644 Binary files a/icons/obj/marketsigns.dmi and b/icons/obj/marketsigns.dmi differ diff --git a/icons/obj/modular_components.dmi b/icons/obj/modular_computers/modular_components.dmi similarity index 100% rename from icons/obj/modular_components.dmi rename to icons/obj/modular_computers/modular_components.dmi diff --git a/icons/obj/machinery/modular_console.dmi b/icons/obj/modular_computers/modular_console.dmi similarity index 100% rename from icons/obj/machinery/modular_console.dmi rename to icons/obj/modular_computers/modular_console.dmi diff --git a/icons/obj/modular_laptop.dmi b/icons/obj/modular_computers/modular_laptop.dmi similarity index 100% rename from icons/obj/modular_laptop.dmi rename to icons/obj/modular_computers/modular_laptop.dmi diff --git a/icons/obj/modular_tablet.dmi b/icons/obj/modular_computers/modular_tablet.dmi similarity index 100% rename from icons/obj/modular_tablet.dmi rename to icons/obj/modular_computers/modular_tablet.dmi diff --git a/icons/obj/modular_telescreen.dmi b/icons/obj/modular_computers/modular_telescreen.dmi similarity index 100% rename from icons/obj/modular_telescreen.dmi rename to icons/obj/modular_computers/modular_telescreen.dmi diff --git a/icons/obj/machinery/modular_terminal.dmi b/icons/obj/modular_computers/modular_terminal.dmi similarity index 100% rename from icons/obj/machinery/modular_terminal.dmi rename to icons/obj/modular_computers/modular_terminal.dmi diff --git a/icons/obj/modular_wristbound.dmi b/icons/obj/modular_computers/modular_wristbound.dmi similarity index 100% rename from icons/obj/modular_wristbound.dmi rename to icons/obj/modular_computers/modular_wristbound.dmi diff --git a/icons/obj/pda.dmi b/icons/obj/modular_computers/pda.dmi similarity index 100% rename from icons/obj/pda.dmi rename to icons/obj/modular_computers/pda.dmi diff --git a/icons/obj/pda_old.dmi b/icons/obj/modular_computers/pda_old.dmi similarity index 100% rename from icons/obj/pda_old.dmi rename to icons/obj/modular_computers/pda_old.dmi diff --git a/icons/obj/pda_rugged.dmi b/icons/obj/modular_computers/pda_rugged.dmi similarity index 100% rename from icons/obj/pda_rugged.dmi rename to icons/obj/modular_computers/pda_rugged.dmi diff --git a/icons/obj/pda_slate.dmi b/icons/obj/modular_computers/pda_slate.dmi similarity index 100% rename from icons/obj/pda_slate.dmi rename to icons/obj/modular_computers/pda_slate.dmi diff --git a/icons/obj/pda_smart.dmi b/icons/obj/modular_computers/pda_smart.dmi similarity index 100% rename from icons/obj/pda_smart.dmi rename to icons/obj/modular_computers/pda_smart.dmi diff --git a/icons/obj/module.dmi b/icons/obj/module.dmi index 75c4a2a3d8de..97fe37fb56d2 100644 Binary files a/icons/obj/module.dmi and b/icons/obj/module.dmi differ diff --git a/icons/obj/pipe-item.dmi b/icons/obj/pipe-item.dmi index 00984305fc40..4ce6b034d5c8 100644 Binary files a/icons/obj/pipe-item.dmi and b/icons/obj/pipe-item.dmi differ diff --git a/icons/obj/storage/courierbag.dmi b/icons/obj/storage/courierbag.dmi index 60bd541e82cd..915b4051e421 100644 Binary files a/icons/obj/storage/courierbag.dmi and b/icons/obj/storage/courierbag.dmi differ diff --git a/icons/obj/storage/satchel.dmi b/icons/obj/storage/satchel.dmi index 15b08a4b4481..1ade73ad694b 100644 Binary files a/icons/obj/storage/satchel.dmi and b/icons/obj/storage/satchel.dmi differ diff --git a/icons/obj/structure/flags.dmi b/icons/obj/structure/flags.dmi index 40fbbbe2dc49..c87c8567eb47 100644 Binary files a/icons/obj/structure/flags.dmi and b/icons/obj/structure/flags.dmi differ diff --git a/icons/obj/tajara_items.dmi b/icons/obj/tajara_items.dmi index c3b7d127a5ce..41ef49c3a0e8 100644 Binary files a/icons/obj/tajara_items.dmi and b/icons/obj/tajara_items.dmi differ diff --git a/icons/obj/tank.dmi b/icons/obj/tank.dmi index e59a05128cea..e7d7cf8f1e19 100644 Binary files a/icons/obj/tank.dmi and b/icons/obj/tank.dmi differ diff --git a/icons/obj/toy.dmi b/icons/obj/toy.dmi index 59e45a01ea1b..15e86c4fc896 100644 Binary files a/icons/obj/toy.dmi and b/icons/obj/toy.dmi differ diff --git a/icons/obj/xenoarchaeology.dmi b/icons/obj/xenoarchaeology.dmi index 68940b269959..aa80feb11909 100644 Binary files a/icons/obj/xenoarchaeology.dmi and b/icons/obj/xenoarchaeology.dmi differ diff --git a/interface/skin.dmf b/interface/skin.dmf index 73fb059bafd4..9607bf370640 100644 --- a/interface/skin.dmf +++ b/interface/skin.dmf @@ -1281,6 +1281,7 @@ window "output_browser" size = 640x456 anchor1 = 0,0 anchor2 = 100,100 + background-color = none saved-params = "" window "preferences_window" diff --git a/libprof-disk.so b/libprof-disk.so index ce9016ce1133..516f793c9ded 100644 Binary files a/libprof-disk.so and b/libprof-disk.so differ diff --git a/libprof.so b/libprof.so deleted file mode 100644 index 716b1b73929f..000000000000 Binary files a/libprof.so and /dev/null differ diff --git a/maps/away/away_site/abandoned_industrial/abandoned_industrial_station.dmm b/maps/away/away_site/abandoned_industrial/abandoned_industrial_station.dmm index 798435298c44..8348f1e5b625 100644 --- a/maps/away/away_site/abandoned_industrial/abandoned_industrial_station.dmm +++ b/maps/away/away_site/abandoned_industrial/abandoned_industrial_station.dmm @@ -10261,7 +10261,7 @@ "Gp" = ( /obj/machinery/constructable_frame/temp_deco{ dir = 4; - icon = 'icons/obj/machinery/modular_console.dmi'; + icon = 'icons/obj/modular_computers/modular_console.dmi'; icon_state = "1" }, /turf/simulated/floor/tiled/dark, @@ -13101,7 +13101,7 @@ "Py" = ( /obj/machinery/constructable_frame/temp_deco{ dir = 4; - icon = 'icons/obj/machinery/modular_console.dmi'; + icon = 'icons/obj/modular_computers/modular_console.dmi'; icon_state = "computer-broken" }, /turf/simulated/floor/tiled/dark, diff --git a/maps/away/away_site/crystal_planet_outpost/crystal_planet_outpost_.dmm b/maps/away/away_site/crystal_planet_outpost/crystal_planet_outpost_.dmm index f1c581ed2580..c747dea89819 100644 --- a/maps/away/away_site/crystal_planet_outpost/crystal_planet_outpost_.dmm +++ b/maps/away/away_site/crystal_planet_outpost/crystal_planet_outpost_.dmm @@ -1260,7 +1260,7 @@ pixel_x = -9; pixel_y = 1 }, -/obj/item/reagent_containers/food/snacks/clams_casino{ +/obj/item/reagent_containers/food/snacks/bowl/clams_casino{ pixel_x = 7; pixel_y = 5 }, diff --git a/maps/away/away_site/cult_base/cult_base_areas.dm b/maps/away/away_site/cult_base/cult_base_areas.dm index 31db8636f30d..9861a35c87ce 100644 --- a/maps/away/away_site/cult_base/cult_base_areas.dm +++ b/maps/away/away_site/cult_base/cult_base_areas.dm @@ -19,25 +19,21 @@ /area/cult_base/hallways_north name = "Hallways North" icon_state = "hallC" - area_blurb_category = "cult_base_hallway" area_blurb = "A faint scent of copper or metal is present here." /area/cult_base/hallways_south name = "Hallways South" icon_state = "hallC" - area_blurb_category = "cult_base_hallway" area_blurb = "A faint scent of copper or metal is present here." /area/cult_base/hallways_east name = "Hallways East" icon_state = "hallC" - area_blurb_category = "cult_base_hallway" area_blurb = "A faint scent of copper or metal is present here." /area/cult_base/hallways_west name = "Hallways West" icon_state = "hallC" - area_blurb_category = "cult_base_hallway" area_blurb = "A faint scent of copper or metal is present here." // ---- living diff --git a/maps/away/away_site/konyang/point_verdant/point_verdant_areas.dm b/maps/away/away_site/konyang/point_verdant/point_verdant_areas.dm index b78c54ab7fdd..8b96e3baf222 100644 --- a/maps/away/away_site/konyang/point_verdant/point_verdant_areas.dm +++ b/maps/away/away_site/konyang/point_verdant/point_verdant_areas.dm @@ -24,7 +24,6 @@ name = "Point Verdant - Waterside" ambience = AMBIENCE_KONYANG_WATER area_blurb = "The crashing sounds of waves on the shore punctuates the air. The vast ocean spreads out as far as the eye can see, looking almost flat." - area_blurb_category = "verdant_shore" lighting = TRUE /area/point_verdant/reservoir @@ -37,7 +36,6 @@ name = "Point Verdant - Sewers" sound_environment = SOUND_ENVIRONMENT_SEWER_PIPE area_blurb = "Tainted water flows through these dark and grimy sewers, it smells utterly horrible down here. It's best not to think what you are breathing in, or touching." - area_blurb_category = "verdant_sewers" //All walls and interior stuff uses this area, otherwise rain will appear over walls. suboptimal! /area/point_verdant/interior name = "Point Verdant - Indoors" @@ -66,7 +64,6 @@ /area/point_verdant/interior/arcade name = "Point Verdant - Arcade" area_blurb = "The deafening avalanche of arcade machines begging for your attention fill the air, all promising fantastic gaming experiences for fun and prizes." - area_blurb_category = "verdant_arcade" /area/point_verdant/interior/minimart name = "Point Verdant - Convenience Store" @@ -93,7 +90,6 @@ /area/point_verdant/interior/decrepit name = "Point Verdant - Decrepit Apartments" area_blurb = "A damp smell lingers in the air inside these dusty apartments, it might be wise to keep an eye out for mold." - area_blurb_category = "verdant_decrepit_apartment" /area/point_verdant/interior/pharmacy name = "Point Verdant - Pharmacy" @@ -126,7 +122,6 @@ /area/point_verdant/interior/tunnels name = "Point Verdant - Tunnels" area_blurb = "Sounds echo impressively through these tunnels." - area_blurb_category = "verdant_tunnels" /area/point_verdant/interior/shallow//For open-walled areas, like awnings and balconies sound_environment = SOUND_ENVIRONMENT_CITY @@ -134,7 +129,6 @@ /area/point_verdant/outdoors name = "Point Verdant - Outdoors" area_blurb = "The sounds and smells of Point Verdant bombard you from all directions. Skyscrapers tower up further into the city." - area_blurb_category = "verdant_outdoors" lighting = TRUE /area/point_verdant/water diff --git a/maps/away/away_site/konyang/point_verdant/point_verdant_ghostroles.dm b/maps/away/away_site/konyang/point_verdant/point_verdant_ghostroles.dm index 768caf530db6..19c42f5a2e96 100644 --- a/maps/away/away_site/konyang/point_verdant/point_verdant_ghostroles.dm +++ b/maps/away/away_site/konyang/point_verdant/point_verdant_ghostroles.dm @@ -128,7 +128,7 @@ /obj/outfit/admin/konyang/goon name = "5-Cheung Thug" - uniform = /obj/item/clothing/pants/tan + uniform = /obj/item/clothing/pants/jeans shoes = /obj/item/clothing/shoes/sneakers/black id = null l_pocket = /obj/item/storage/wallet/random diff --git a/maps/away/away_site/pirate_base/pirate_base.dmm b/maps/away/away_site/pirate_base/pirate_base.dmm index 03fc5892f44d..463701268cc5 100644 --- a/maps/away/away_site/pirate_base/pirate_base.dmm +++ b/maps/away/away_site/pirate_base/pirate_base.dmm @@ -8117,7 +8117,7 @@ /obj/structure/window/reinforced{ dir = 4 }, -/obj/item/gun/projectile/automatic/rifle/dpra/gold, +/obj/item/gun/projectile/automatic/rifle/dpra, /turf/simulated/floor/tiled, /area/piratebase/hallway_north) "OI" = ( diff --git a/maps/away/away_site/quarantined_outpost/quarantined_outpost_objects.dm b/maps/away/away_site/quarantined_outpost/quarantined_outpost_objects.dm index 6cb8b4c3b10f..71f3bcdf1698 100644 --- a/maps/away/away_site/quarantined_outpost/quarantined_outpost_objects.dm +++ b/maps/away/away_site/quarantined_outpost/quarantined_outpost_objects.dm @@ -291,7 +291,7 @@ GLOBAL_LIST_EMPTY(trackables_pool) maxHealth = 50 health = 50 - speed = 2 + speed = 1 melee_damage_lower = 5 melee_damage_upper = 10 diff --git a/maps/away/away_site/tajara/peoples_station/peoples_station.dmm b/maps/away/away_site/tajara/peoples_station/peoples_station.dmm index 39ef000a6210..86785a3c5911 100644 --- a/maps/away/away_site/tajara/peoples_station/peoples_station.dmm +++ b/maps/away/away_site/tajara/peoples_station/peoples_station.dmm @@ -5737,15 +5737,15 @@ name = "gun cabinet (rifle ammo)" }, /obj/effect/floor_decal/industrial/outline/security, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, /turf/simulated/floor/tiled/dark, /area/peoples_station/armory) "uP" = ( diff --git a/maps/away/away_site/tajara/saniorios_outpost/saniorios_outpost.dmm b/maps/away/away_site/tajara/saniorios_outpost/saniorios_outpost.dmm index 03db6f949e5d..b0daac328ad1 100644 --- a/maps/away/away_site/tajara/saniorios_outpost/saniorios_outpost.dmm +++ b/maps/away/away_site/tajara/saniorios_outpost/saniorios_outpost.dmm @@ -1130,12 +1130,12 @@ req_access = list(214); name = "gun cabinet (rifle ammo)" }, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, /turf/simulated/floor/tiled{ temperature = 278.15 }, @@ -1423,12 +1423,12 @@ req_access = list(214); name = "gun cabinet (assault rifle ammo)" }, -/obj/item/ammo_magazine/c762/dpra, -/obj/item/ammo_magazine/c762/dpra, -/obj/item/ammo_magazine/c762/dpra, -/obj/item/ammo_magazine/c762/dpra, -/obj/item/ammo_magazine/c762/dpra, -/obj/item/ammo_magazine/c762/dpra, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, /obj/machinery/alarm/cold/north{ req_one_access = list(214) }, diff --git a/maps/away/ships/casino/casino.dm b/maps/away/ships/casino/casino.dm index 4ddb8847e765..b8079c6ee810 100644 --- a/maps/away/ships/casino/casino.dm +++ b/maps/away/ships/casino/casino.dm @@ -7,6 +7,7 @@ sectors = list(ALL_TAU_CETI_SECTORS, SECTOR_VALLEY_HALE, SECTOR_BADLANDS, SECTOR_TABITI, SECTOR_AEMAQ, SECTOR_SRANDMARR, SECTOR_NRRAHRAHUL, SECTOR_GAKAL, SECTOR_UUEOAESA, ALL_COALITION_SECTORS) spawn_weight = 1 + template_flags = TEMPLATE_FLAG_RUIN_STARTS_DISALLOWED // Disabled for debloating. Feel free to enable again if reworked or relevant. spawn_cost = 1 id = "awaysite_casino" shuttles_to_initialise = list(/datum/shuttle/autodock/overmap/casino_cutter) diff --git a/maps/away/ships/coc/coc_ranger/coc_ship.dm b/maps/away/ships/coc/coc_ranger/coc_ship.dm index a368a1a6998a..c4624fd66c74 100644 --- a/maps/away/ships/coc/coc_ranger/coc_ship.dm +++ b/maps/away/ships/coc/coc_ranger/coc_ship.dm @@ -19,6 +19,14 @@ map = "Ranger Gunboat" descriptor = "The Xansan-class is not, in fact, a distinct design in of itself. It is instead Xanu Prime’s variant of the Lagos-class gunboat, a Solarian light attack ship design. While the Lagos-class has been out of service with the Alliance’s navy for centuries, the blueprints were captured during the Interstellar war by Xanu Prime militiamen from a regional naval shipyard during the opening stages of the conflict, and were immediately used to construct ships of the class for use by Xanu Prime’s burgeoning military. While the Xansan-class has been retired from Xanu service, the leftover ships were donated en masse to the Frontier Marshal Bureau, and the Rangers make use of the craft to this day, in spite of their advanced age." +//armory submap +/obj/effect/map_effect/marker/mapmanip/submap/extract/coc_ranger_lockers + name = "Ranger armory, lockers" + +/obj/effect/map_effect/marker/mapmanip/submap/insert/coc_ranger_lockers + name = "Ranger armory, lockers" + + //areas /area/ship/ranger_corvette name = "Ranger Gunboat" diff --git a/maps/away/ships/coc/coc_ranger/coc_ship.dmm b/maps/away/ships/coc/coc_ranger/coc_ship.dmm index fc5e7d8a7d0f..64f6e8d5de4a 100644 --- a/maps/away/ships/coc/coc_ranger/coc_ship.dmm +++ b/maps/away/ships/coc/coc_ranger/coc_ship.dmm @@ -1,37 +1,10 @@ //MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE "abx" = ( -/obj/structure/lattice/catwalk/indoor/grate/dark, -/obj/structure/table/steel, -/obj/machinery/button/remote/blast_door{ - id = "coc_fore"; - name = "fore blast door-control"; - pixel_x = -6; - pixel_y = 6; - req_one_access = list(221,222) - }, -/obj/machinery/button/remote/blast_door{ - id = "coc_midship"; - name = "midship blast door-control"; - pixel_x = -6; - pixel_y = -3; - req_one_access = list(221,222) - }, -/obj/machinery/button/remote/blast_door{ - id = "coc_aft"; - name = "aft blast door-control"; - pixel_x = 4; - pixel_y = -3; - req_one_access = list(221,222) - }, -/obj/machinery/button/remote/blast_door{ - id = "coc_bridge"; - name = "bridge blast door-control"; - pixel_x = 4; - pixel_y = 6; - req_one_access = list(221,222) +/obj/machinery/light{ + dir = 1 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/foyer) "aei" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 9 @@ -60,16 +33,6 @@ }, /turf/simulated/floor/plating, /area/ship/ranger_corvette/foyer) -"aho" = ( -/obj/machinery/embedded_controller/radio/simple_docking_controller{ - pixel_y = 21; - pixel_x = -4; - id_tag = "ranger_shuttle_dock"; - name = "Ranger Shuttle docking port controller"; - req_one_access = list(221,222) - }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) "aiD" = ( /obj/effect/floor_decal/corner/red/diagonal, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ @@ -111,11 +74,17 @@ /turf/simulated/floor/carpet/red, /area/ship/ranger_corvette/crew) "aqk" = ( -/obj/structure/lattice/catwalk/indoor/grate/dark, -/obj/structure/table/steel, -/obj/item/clothing/head/helmet/pilot, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 10 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 + }, +/obj/structure/cable/green{ + icon_state = "2-8" + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/leader) "asD" = ( /obj/effect/map_effect/window_spawner/full/borosilicate/reinforced/firedoor, /obj/machinery/atmospherics/pipe/simple/hidden{ @@ -148,9 +117,13 @@ /turf/simulated/wall/shuttle/space_ship/mercenary, /area/ship/ranger_corvette/engine1) "ayi" = ( -/obj/machinery/atmospherics/unary/vent_scrubber/on, +/obj/structure/lattice/catwalk/indoor/grate/dark, +/obj/machinery/computer/ship/targeting{ + dir = 1; + req_one_access = list(221,222) + }, /turf/simulated/floor/tiled/dark, -/area/ship/ranger_corvette/gunnery) +/area/ship/ranger_corvette/bridge) "ayD" = ( /obj/machinery/atmospherics/pipe/manifold/hidden/fuel{ dir = 8 @@ -189,8 +162,16 @@ /turf/simulated/floor/tiled, /area/shuttle/ranger_shuttle) "aKd" = ( -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) +/obj/effect/floor_decal/industrial/outline/yellow, +/obj/structure/railing/mapped{ + dir = 1 + }, +/obj/structure/railing/mapped{ + dir = 4 + }, +/obj/machinery/portable_atmospherics/canister/air, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/engine1) "aMl" = ( /obj/effect/floor_decal/industrial/hatch/yellow, /obj/machinery/door/blast/regular/open{ @@ -220,21 +201,27 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/janitor) "aRl" = ( -/obj/machinery/door/airlock/external{ +/obj/effect/floor_decal/corner/black/full{ + dir = 8 + }, +/obj/structure/bed/stool/chair/office/bridge/generic{ + icon_state = "bridge" + }, +/obj/machinery/atmospherics/unary/vent_pump/on{ dir = 4 }, -/obj/effect/map_effect/marker_helper/airlock/exterior, -/obj/structure/cable{ - icon_state = "4-8" +/obj/machinery/light{ + dir = 8; + icon_state = "tube_empty" }, -/obj/effect/map_effect/marker/airlock/docking{ - name = "ranger_shuttle_dock"; - master_tag = "ranger_shuttle_dock"; - landmark_tag = "nav_hangar_ranger"; - req_one_access = null +/obj/structure/cable/green{ + icon_state = "0-4" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) +/obj/machinery/power/apc/high/west{ + req_access = null + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/bridge) "aWb" = ( /obj/structure/lattice/catwalk/indoor/grate/dark, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, @@ -244,6 +231,11 @@ }, /turf/simulated/floor/plating, /area/ship/ranger_corvette/foyer) +"aXi" = ( +/obj/structure/lattice/catwalk, +/obj/item/hullbeacon/red, +/turf/template_noop, +/area/ship/ranger_corvette/engine1) "aXC" = ( /obj/machinery/atmospherics/pipe/simple/hidden/universal{ dir = 4 @@ -269,18 +261,10 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/foyer) "aZS" = ( -/obj/effect/floor_decal/corner/dark_blue{ - dir = 6 - }, -/obj/effect/floor_decal/corner/white{ - dir = 8 - }, -/obj/structure/railing/mapped, -/obj/machinery/computer/ship/helm{ - dir = 1; - req_one_access = list(221,222) +/obj/effect/floor_decal/corner/black{ + dir = 10 }, -/turf/simulated/floor/tiled/dark/full, +/turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/bridge) "bbM" = ( /obj/machinery/atmospherics/pipe/manifold/visible/fuel, @@ -388,7 +372,7 @@ /turf/simulated/floor/plating, /area/ship/ranger_corvette/foyer) "boM" = ( -/obj/machinery/ammunition_loader/francisca{ +/obj/machinery/ammunition_loader/autocannon{ weapon_id = "Ranger Francisca Rotary Gun" }, /turf/simulated/floor/tiled/dark, @@ -417,29 +401,21 @@ /turf/simulated/floor/tiled, /area/shuttle/ranger_shuttle) "bsV" = ( -/obj/machinery/door/blast/regular/open{ - dir = 4; - id = "coc_bridge" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/machinery/door/blast/regular/open{ - dir = 4; - id = "coc_bridge" - }, -/obj/machinery/door/airlock/glass_command{ - name = "Bridge"; +/obj/machinery/door/airlock{ + name = "EVA Storage"; dir = 1; req_one_access = list(221,222) }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/machinery/door/firedoor{ req_one_access = list(221,222) }, /obj/structure/cable/green{ icon_state = "1-2" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/voidsuits) "btv" = ( /obj/effect/floor_decal/spline/plain/black, /obj/structure/railing/mapped, @@ -469,16 +445,23 @@ /turf/simulated/wall/shuttle/space_ship/mercenary, /area/ship/ranger_corvette/engine2) "bzo" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/effect/floor_decal/corner/dark_blue/full{ + dir = 1 + }, +/obj/structure/bed/stool/chair/office/bridge/pilot, +/obj/machinery/atmospherics/unary/vent_scrubber/on{ + dir = 8 + }, /obj/machinery/light{ - dir = 8; + dir = 4; icon_state = "tube_empty" }, -/obj/structure/cable/green{ - icon_state = "1-2" +/obj/machinery/button/distress{ + pixel_x = 5; + pixel_y = 25 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/leader) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/bridge) "bCt" = ( /obj/structure/bed/stool/chair/sofa/left/brown, /turf/simulated/floor/carpet, @@ -503,10 +486,11 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/foyer) "bHV" = ( -/obj/machinery/suit_cycler/offship/coc, -/obj/effect/floor_decal/industrial/outline/yellow, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/voidsuits) +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 10 + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/crew) "bIQ" = ( /obj/machinery/atmospherics/binary/pump/fuel{ dir = 8 @@ -577,12 +561,20 @@ /turf/simulated/floor/tiled/white, /area/ship/ranger_corvette/canteen) "bYx" = ( -/obj/structure/sign/flag/coalition{ - pixel_x = -32 +/obj/effect/floor_decal/corner/dark_blue{ + dir = 6 }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/leader) +/obj/effect/floor_decal/corner/white{ + dir = 1 + }, +/obj/effect/floor_decal/spline/plain/black{ + dir = 1 + }, +/obj/structure/closet/crate/bin{ + name = "trashbin" + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/bridge) "cdr" = ( /obj/effect/floor_decal/corner/brown/diagonal, /obj/machinery/light{ @@ -604,9 +596,25 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/gunnery) "cij" = ( -/obj/effect/decal/cleanable/dirt, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/crew) +/obj/machinery/door/airlock/engineering{ + dir = 4; + req_one_access = list(221,222); + name = "Rotary Cannon Chamber/Starboard Propulsion" + }, +/obj/machinery/door/firedoor{ + req_one_access = list(221,222) + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/structure/cable/green{ + icon_state = "4-8" + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/engine1) "cjg" = ( /obj/structure/filingcabinet/chestdrawer, /obj/item/storage/box/bodybags{ @@ -633,23 +641,13 @@ /turf/simulated/floor/carpet, /area/ship/ranger_corvette/foyer) "ckP" = ( -/obj/effect/floor_decal/corner/white{ - dir = 4 - }, -/obj/effect/floor_decal/corner/white{ - dir = 8 - }, -/obj/structure/railing/mapped, -/obj/structure/railing/mapped{ - dir = 8 - }, -/obj/structure/table/steel, -/obj/item/binoculars, -/obj/item/binoculars{ - pixel_y = 5 +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/structure/cable/green{ + icon_state = "1-2" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/foyer) "cmI" = ( /obj/machinery/atmospherics/unary/vent_scrubber/on{ dir = 1 @@ -704,15 +702,17 @@ /turf/simulated/floor/tiled/white, /area/ship/ranger_corvette/canteen) "cxr" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers, -/obj/structure/cable/green{ - icon_state = "4-8" +/obj/structure/table/rack, +/obj/effect/floor_decal/industrial/outline/red, +/obj/machinery/door/window/eastleft{ + dir = 2 }, -/turf/simulated/floor/tiled/dark, -/area/ship/ranger_corvette/gunnery) +/obj/item/ship_ammunition/grauwolf_bundle, +/obj/item/ship_ammunition/grauwolf_bundle, +/obj/item/ship_ammunition/grauwolf_bundle, +/obj/item/ship_ammunition/grauwolf_bundle, +/turf/simulated/floor/reinforced, +/area/ship/ranger_corvette/munitions) "cHm" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 9 @@ -737,25 +737,32 @@ /turf/simulated/floor/tiled/white, /area/ship/ranger_corvette/canteen) "cJN" = ( -/obj/machinery/door/airlock/external, -/obj/effect/map_effect/marker_helper/airlock/interior, -/obj/machinery/atmospherics/pipe/simple/hidden/aux, -/obj/effect/map_effect/marker/airlock/docking/ranger_corvette/aft, -/turf/simulated/floor/plating, -/area/ship/ranger_corvette/atmospherics) +/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ + dir = 4 + }, +/obj/structure/cable/green{ + icon_state = "1-2" + }, +/obj/structure/cable/green{ + icon_state = "1-8" + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/foyer) "cZR" = ( -/obj/machinery/door/airlock/external, -/obj/machinery/access_button{ - pixel_x = -28; - pixel_y = 12; - dir = 1; - frequency = 2137 +/obj/item/clothing/head/bearpelt{ + anchored = 1; + name = "bear pelt wall rug"; + pixel_x = 32; + pixel_y = 5 }, -/obj/effect/map_effect/marker_helper/airlock/exterior, -/obj/effect/map_effect/marker/airlock/docking/ranger_corvette/aft, -/obj/effect/shuttle_landmark/ranger_corvette/dock_aft, -/turf/simulated/floor/plating, -/area/ship/ranger_corvette/atmospherics) +/obj/structure/closet/crate/bin{ + name = "trashbin" + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/leader) "cZV" = ( /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/wood, @@ -790,23 +797,19 @@ /turf/simulated/floor/carpet/rubber, /area/ship/ranger_corvette/crew) "dgH" = ( -/obj/effect/floor_decal/corner/dark_blue/full{ - dir = 1 - }, -/obj/structure/bed/stool/chair/office/bridge/pilot, -/obj/machinery/atmospherics/unary/vent_scrubber/on{ - dir = 8 +/obj/effect/floor_decal/industrial/warning, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 }, -/obj/machinery/light{ - dir = 4; - icon_state = "tube_empty" +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 }, -/obj/machinery/button/distress{ - pixel_x = 5; - pixel_y = 25 +/obj/structure/cable/green{ + icon_state = "4-8" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/foyer) "dhX" = ( /obj/machinery/vending/dinnerware, /obj/effect/floor_decal/corner/brown/diagonal, @@ -830,11 +833,14 @@ /turf/simulated/floor/plating, /area/ship/ranger_corvette/atmospherics) "doJ" = ( -/obj/machinery/atmospherics/unary/vent_pump/on{ - dir = 4 +/obj/effect/floor_decal/industrial/warning, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/structure/cable/green{ + icon_state = "1-2" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/crew) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/foyer) "drF" = ( /obj/effect/floor_decal/corner/brown/diagonal, /obj/effect/floor_decal/industrial/warning/corner{ @@ -1002,14 +1008,18 @@ /turf/simulated/floor/reinforced, /area/ship/ranger_corvette/gunnery) "eov" = ( -/obj/effect/floor_decal/industrial/warning, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 6 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 5 + }, /obj/structure/cable/green{ - icon_state = "1-2" + icon_state = "4-8" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/crew) "epG" = ( /obj/structure/curtain/black{ icon_state = "open"; @@ -1037,27 +1047,6 @@ /obj/effect/floor_decal/corner_wide/blue/diagonal, /turf/simulated/floor/tiled, /area/shuttle/ranger_shuttle) -"eue" = ( -/obj/machinery/door/airlock/security{ - dir = 4; - req_one_access = list(221,222); - name = "Brig" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 - }, -/obj/machinery/door/firedoor{ - dir = 4; - req_one_access = list(221,222) - }, -/obj/structure/cable/green{ - icon_state = "4-8" - }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/brig) "euV" = ( /obj/effect/landmark/entry_point/port{ name = "port, medbay" @@ -1144,49 +1133,21 @@ /turf/simulated/floor/tiled/white, /area/ship/ranger_corvette/medbay) "eFo" = ( -/obj/effect/floor_decal/industrial/outline/yellow, -/obj/structure/table/rack, -/obj/item/gps, -/obj/item/gps, -/obj/item/gps, -/obj/item/gps, -/obj/item/gps, -/obj/item/gps, -/obj/item/tank/emergency_oxygen/double, -/obj/item/tank/emergency_oxygen/double, -/obj/item/tank/emergency_oxygen/double, -/obj/item/tank/emergency_oxygen/double, -/obj/item/tank/emergency_oxygen/double, -/obj/item/tank/jetpack/carbondioxide, -/obj/item/tank/jetpack/carbondioxide, -/obj/item/tank/jetpack/carbondioxide, -/obj/item/tank/jetpack/carbondioxide, -/obj/item/tank/jetpack/carbondioxide, -/obj/item/tank/jetpack/carbondioxide, -/obj/item/suit_cooling_unit, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/voidsuits) -"eFH" = ( -/obj/machinery/door/airlock/command{ - dir = 4; - name = "Ranger Leader Quarters"; - req_one_access = list(221,222) - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/door/firedoor{ - dir = 4; - req_one_access = list(221,222) - }, -/obj/structure/cable/green{ - icon_state = "4-8" +/obj/structure/table/steel, +/obj/item/modular_computer/laptop/preset/civilian, +/obj/machinery/photocopier/faxmachine{ + req_one_access = null; + pixel_y = 11 }, -/turf/simulated/floor/tiled/dark/full, +/turf/simulated/floor/carpet/brown, /area/ship/ranger_corvette/leader) +"eFH" = ( +/obj/machinery/light{ + dir = 8; + icon_state = "tube_empty" + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/voidsuits) "eGi" = ( /turf/simulated/wall/shuttle/space_ship/mercenary, /area/ship/ranger_corvette/janitor) @@ -1241,25 +1202,39 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/crew) "eSo" = ( -/obj/effect/floor_decal/industrial/warning{ - dir = 1 +/obj/effect/floor_decal/industrial/outline/yellow, +/obj/structure/closet/crate, +/obj/item/tank/phoron/shuttle, +/obj/item/storage/bag/inflatable, +/obj/item/storage/bag/inflatable, +/obj/item/storage/box/lights/mixed, +/obj/item/tape_roll, +/obj/item/tape_roll, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/engine1) +"eSB" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers, /obj/structure/cable/green{ - icon_state = "1-2" + icon_state = "4-8" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) -"eSB" = ( -/obj/effect/floor_decal/corner/white{ - dir = 4 +/obj/machinery/power/apc/south, +/obj/structure/cable/green{ + icon_state = "0-4" }, -/obj/effect/floor_decal/spline/plain/black{ - dir = 1 +/obj/structure/table/rack/folding_table, +/obj/item/plastique{ + pixel_y = 8; + pixel_x = -2 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/obj/item/plastique{ + pixel_y = 1; + pixel_x = 8 + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) "eZx" = ( /obj/machinery/power/portgen/basic/fusion, /obj/machinery/door/window, @@ -1288,25 +1263,12 @@ /turf/template_noop, /area/space) "feE" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/door/airlock/highsecurity{ - name = "Ship Munitions Storage"; - dir = 4; - req_one_access = list(221,222) - }, -/obj/machinery/door/firedoor{ - req_one_access = list(221,222) - }, -/obj/structure/cable/green{ - icon_state = "4-8" +/obj/effect/floor_decal/industrial/warning/corner{ + dir = 8 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/munitions) +/obj/effect/map_effect/marker/mapmanip/submap/insert/coc_ranger_lockers, +/turf/template_noop, +/area/space) "fkm" = ( /obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ dir = 8 @@ -1321,56 +1283,144 @@ /turf/simulated/floor/plating, /area/ship/ranger_corvette/foyer) "fkX" = ( -/obj/effect/floor_decal/industrial/outline/yellow, -/obj/effect/floor_decal/industrial/warning/corner{ - dir = 4 +/obj/effect/floor_decal/industrial/hatch/blue, +/obj/structure/closet, +/obj/item/clothing/accessory/armband/sec{ + name = "Frontier Protection Bureau armband"; + desc = "An armband, commonly worn by the Rangers of the Frontier Protection Bureau as a inexpensive means to tell friend from foe. This one is navy blue, with the flag of the Coalition of Colonies emblazoned in the center." + }, +/obj/item/clothing/accessory/armband/sec{ + name = "Frontier Protection Bureau armband"; + desc = "An armband, commonly worn by the Rangers of the Frontier Protection Bureau as a inexpensive means to tell friend from foe. This one is navy blue, with the flag of the Coalition of Colonies emblazoned in the center." + }, +/obj/item/clothing/accessory/armband/sec{ + name = "Frontier Protection Bureau armband"; + desc = "An armband, commonly worn by the Rangers of the Frontier Protection Bureau as a inexpensive means to tell friend from foe. This one is navy blue, with the flag of the Coalition of Colonies emblazoned in the center." + }, +/obj/item/clothing/accessory/armband/sec{ + name = "Frontier Protection Bureau armband"; + desc = "An armband, commonly worn by the Rangers of the Frontier Protection Bureau as a inexpensive means to tell friend from foe. This one is navy blue, with the flag of the Coalition of Colonies emblazoned in the center." + }, +/obj/item/clothing/accessory/armband/sec{ + name = "Frontier Protection Bureau armband"; + desc = "An armband, commonly worn by the Rangers of the Frontier Protection Bureau as a inexpensive means to tell friend from foe. This one is navy blue, with the flag of the Coalition of Colonies emblazoned in the center." + }, +/obj/item/clothing/accessory/armband/sec{ + name = "Frontier Protection Bureau armband"; + desc = "An armband, commonly worn by the Rangers of the Frontier Protection Bureau as a inexpensive means to tell friend from foe. This one is navy blue, with the flag of the Coalition of Colonies emblazoned in the center." + }, +/obj/item/clothing/accessory/armband/sec{ + name = "Frontier Protection Bureau armband"; + desc = "An armband, commonly worn by the Rangers of the Frontier Protection Bureau as a inexpensive means to tell friend from foe. This one is navy blue, with the flag of the Coalition of Colonies emblazoned in the center." + }, +/obj/item/clothing/accessory/armband/sec{ + name = "Frontier Protection Bureau armband"; + desc = "An armband, commonly worn by the Rangers of the Frontier Protection Bureau as a inexpensive means to tell friend from foe. This one is navy blue, with the flag of the Coalition of Colonies emblazoned in the center." + }, +/obj/item/storage/belt/military, +/obj/item/storage/belt/military, +/obj/item/storage/belt/military, +/obj/item/storage/belt/military, +/obj/item/storage/belt/military, +/obj/item/storage/belt/military, +/obj/item/clothing/accessory/holster, +/obj/item/clothing/accessory/holster, +/obj/item/clothing/accessory/holster, +/obj/item/clothing/accessory/holster/thigh/fluff, +/obj/item/clothing/accessory/holster/thigh/fluff, +/obj/item/clothing/accessory/holster/thigh/fluff, +/obj/item/clothing/head/helmet{ + name = "Cheap-looking helmet"; + desc = "A cheap helmet, most likely purchased off the aftermarket for some raggedy band of Frontier law enforcement. It might, **might** be able to stop a 9mm and some shrapnel." + }, +/obj/item/clothing/head/helmet{ + name = "Cheap-looking helmet"; + desc = "A cheap helmet, most likely purchased off the aftermarket for some raggedy band of Frontier law enforcement. It might, **might** be able to stop a 9mm and some shrapnel." + }, +/obj/item/clothing/head/helmet{ + name = "Cheap-looking helmet"; + desc = "A cheap helmet, most likely purchased off the aftermarket for some raggedy band of Frontier law enforcement. It might, **might** be able to stop a 9mm and some shrapnel." + }, +/obj/item/clothing/head/helmet{ + name = "Cheap-looking helmet"; + desc = "A cheap helmet, most likely purchased off the aftermarket for some raggedy band of Frontier law enforcement. It might, **might** be able to stop a 9mm and some shrapnel." + }, +/obj/item/clothing/head/helmet{ + name = "Cheap-looking helmet"; + desc = "A cheap helmet, most likely purchased off the aftermarket for some raggedy band of Frontier law enforcement. It might, **might** be able to stop a 9mm and some shrapnel." + }, +/obj/item/clothing/head/helmet{ + name = "Cheap-looking helmet"; + desc = "A cheap helmet, most likely purchased off the aftermarket for some raggedy band of Frontier law enforcement. It might, **might** be able to stop a 9mm and some shrapnel." + }, +/obj/item/clothing/head/helmet{ + name = "Cheap-looking helmet"; + desc = "A cheap helmet, most likely purchased off the aftermarket for some raggedy band of Frontier law enforcement. It might, **might** be able to stop a 9mm and some shrapnel." + }, +/obj/item/clothing/suit/armor/carrier/heavy{ + name = "cheap-looking plate carrier"; + desc = "A cheap-looking aftermarket plate carrier that was most likely bought for a raggedy bunch of Frontier law enforcement. Usually carrying similarly generic and cheap heavy-duty inserts. You *might* be able to hold yourself against anything short of 5.56, with this." + }, +/obj/item/clothing/suit/armor/carrier/heavy{ + name = "cheap-looking plate carrier"; + desc = "A cheap-looking aftermarket plate carrier that was most likely bought for a raggedy bunch of Frontier law enforcement. Usually carrying similarly generic and cheap heavy-duty inserts. You *might* be able to hold yourself against anything short of 5.56, with this." + }, +/obj/item/clothing/suit/armor/carrier/heavy{ + name = "cheap-looking plate carrier"; + desc = "A cheap-looking aftermarket plate carrier that was most likely bought for a raggedy bunch of Frontier law enforcement. Usually carrying similarly generic and cheap heavy-duty inserts. You *might* be able to hold yourself against anything short of 5.56, with this." + }, +/obj/item/clothing/suit/armor/carrier/heavy{ + name = "cheap-looking plate carrier"; + desc = "A cheap-looking aftermarket plate carrier that was most likely bought for a raggedy bunch of Frontier law enforcement. Usually carrying similarly generic and cheap heavy-duty inserts. You *might* be able to hold yourself against anything short of 5.56, with this." + }, +/obj/item/clothing/suit/armor/carrier/heavy{ + name = "cheap-looking plate carrier"; + desc = "A cheap-looking aftermarket plate carrier that was most likely bought for a raggedy bunch of Frontier law enforcement. Usually carrying similarly generic and cheap heavy-duty inserts. You *might* be able to hold yourself against anything short of 5.56, with this." + }, +/obj/item/clothing/suit/armor/carrier/heavy{ + name = "cheap-looking plate carrier"; + desc = "A cheap-looking aftermarket plate carrier that was most likely bought for a raggedy bunch of Frontier law enforcement. Usually carrying similarly generic and cheap heavy-duty inserts. You *might* be able to hold yourself against anything short of 5.56, with this." }, -/obj/effect/decal/cleanable/cobweb, -/obj/machinery/vending/sovietsoda, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/engine1) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) "fmB" = ( -/obj/effect/floor_decal/corner/red/diagonal, -/obj/structure/sign/flag/gadpathur{ - pixel_y = 32 +/obj/effect/floor_decal/industrial/warning{ + dir = 1 }, -/obj/structure/closet/crate/bin{ - name = "trashbin" +/obj/structure/sign/securearea{ + desc = "A warning sign which reads 'WARNING: BLAST DOOR'."; + name = "\improper WARNING: BLAST DOOR sign"; + pixel_x = 32 }, -/obj/machinery/light{ - dir = 4; - icon_state = "tube_empty" +/obj/effect/floor_decal/industrial/warning{ + dir = 1 }, -/obj/structure/sign/flag/heph{ - pixel_x = 32 +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/structure/cable/green{ + icon_state = "1-2" }, -/turf/simulated/floor/tiled/white, -/area/ship/ranger_corvette/canteen) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/foyer) "fmF" = ( /obj/structure/extinguisher_cabinet/west, /turf/simulated/floor/carpet, /area/ship/ranger_corvette/foyer) "fmY" = ( -/obj/machinery/door/airlock/highsecurity{ - name = "Gunnery Comparment"; - dir = 4; - req_one_access = list(221,222) - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 +/obj/effect/floor_decal/corner/dark_blue{ + dir = 5 }, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 + dir = 5 }, -/obj/machinery/door/firedoor{ - dir = 4; - req_one_access = list(221,222) +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 9 }, /obj/structure/cable/green{ - icon_state = "4-8" + icon_state = "1-8" }, /turf/simulated/floor/tiled/dark, -/area/ship/ranger_corvette/gunnery) +/area/ship/ranger_corvette/bridge) "fnq" = ( /obj/structure/bed/padded, /obj/item/towel_flat{ @@ -1400,11 +1450,22 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/foyer) "fro" = ( -/obj/structure/cable/green{ - icon_state = "1-4" +/obj/machinery/door/airlock/external{ + dir = 4 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/crew) +/obj/machinery/atmospherics/pipe/manifold/hidden/aux, +/obj/effect/map_effect/marker_helper/airlock/interior, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/effect/map_effect/marker/airlock/docking{ + name = "ranger_shuttle_dock"; + master_tag = "ranger_shuttle_dock"; + landmark_tag = "nav_hangar_ranger"; + req_one_access = null + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/foyer) "frC" = ( /obj/effect/floor_decal/industrial/warning{ dir = 1 @@ -1474,22 +1535,25 @@ /turf/simulated/floor/wood, /area/ship/ranger_corvette/leader) "fHL" = ( -/obj/structure/bed/stool/chair, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/leader) -"fJC" = ( -/obj/effect/floor_decal/industrial/warning/corner{ - dir = 1 +/obj/effect/floor_decal/corner/dark_blue{ + dir = 5 }, -/obj/structure/cable/green{ - icon_state = "0-4" +/obj/structure/sign/flag/coalition{ + pixel_y = 32 }, -/obj/machinery/power/apc/north{ - req_access = null; - req_one_access = list(221,222) +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 }, /turf/simulated/floor/tiled/dark, -/area/ship/ranger_corvette/engine1) +/area/ship/ranger_corvette/bridge) +"fJC" = ( +/obj/machinery/light{ + dir = 4; + icon_state = "tube_empty" + }, +/obj/machinery/fabricator/autolathe/hacked, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) "fJE" = ( /obj/effect/floor_decal/corner/red/diagonal, /obj/machinery/media/jukebox{ @@ -1572,50 +1636,18 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/brig) "gjg" = ( -/obj/structure/lattice/catwalk/indoor/grate/dark, -/obj/structure/closet/cabinet, -/obj/item/clothing/accessory/badge/passcard/coalition, -/obj/item/gun/projectile/revolver/derringer, -/obj/item/ammo_casing/a357, -/obj/item/ammo_casing/a357, -/obj/item/ammo_casing/a357, -/obj/item/ammo_casing/a357, -/obj/item/spacecash/c100, -/obj/item/spacecash/c100, -/obj/item/spacecash/c10, -/obj/item/spacecash/c10, -/obj/item/spacecash/c10, -/obj/item/spacecash/c10, -/obj/item/spacecash/c200, -/obj/item/spacecash/c20, -/obj/item/spacecash/c20, -/obj/item/spacecash/c1, -/obj/item/spacecash/c1, -/obj/item/spacecash/c1, -/obj/item/clothing/accessory/armband/gadpathur, -/obj/item/clothing/under/uniform/gadpathur, -/obj/item/clothing/suit/storage/toggle/himeo/grey, -/obj/item/clothing/accessory/assunzione, -/obj/item/clothing/under/konyang/male/shortsleeve, -/obj/item/clothing/suit/storage/toggle/leather_jacket/military/old/alt, -/obj/item/clothing/suit/storage/toggle/leather_jacket/military, -/turf/simulated/floor/plating, -/area/ship/ranger_corvette/leader) -"gkq" = ( -/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ - dir = 4 +/obj/effect/floor_decal/corner/black{ + dir = 10 }, -/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ +/obj/structure/bed/stool/chair/office/bridge/generic{ dir = 4 }, -/obj/structure/cable/green{ - icon_state = "1-2" - }, -/obj/structure/cable/green{ - icon_state = "1-8" - }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/bridge) +"gkq" = ( +/obj/structure/bed/stool/chair, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/leader) "gkw" = ( /obj/machinery/vending/tool, /turf/simulated/floor/tiled/dark, @@ -1711,28 +1743,25 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/brig) "gEg" = ( -/obj/structure/bookcase/libraryspawn/fiction, -/obj/effect/decal/cleanable/cobweb2, -/turf/simulated/floor/carpet, -/area/ship/ranger_corvette/foyer) +/obj/machinery/door/airlock/external, +/obj/effect/map_effect/marker_helper/airlock/exterior, +/obj/effect/map_effect/marker/airlock/docking/ranger_corvette/aft, +/obj/machinery/door/blast/shutters/open{ + id = "coc_aft" + }, +/turf/simulated/floor/plating, +/area/ship/ranger_corvette/atmospherics) "gJZ" = ( /turf/simulated/wall/shuttle/space_ship/mercenary, /area/ship/ranger_corvette/engine2) "gLb" = ( -/obj/effect/floor_decal/corner/dark_blue{ - dir = 5 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 5 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 9 - }, -/obj/structure/cable/green{ - icon_state = "1-8" +/obj/machinery/atmospherics/unary/vent_pump/on{ + dir = 4 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/obj/effect/floor_decal/industrial/outline/yellow, +/obj/machinery/suit_cycler/offship/coc, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/voidsuits) "gLv" = ( /obj/machinery/atmospherics/unary/vent_pump/high_volume/aux{ dir = 1 @@ -1753,20 +1782,24 @@ /turf/simulated/floor/airless, /area/shuttle/ranger_shuttle) "gMK" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 6 +/obj/machinery/door/airlock/hatch{ + name = "Cryogenics"; + dir = 4 }, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 10 + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/machinery/door/firedoor{ + req_one_access = list(221,222) }, /obj/structure/cable/green{ - d1 = 2; - d2 = 4; - icon_state = "2-4" + icon_state = "4-8" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/voidsuits) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/cryo) "gNW" = ( /obj/effect/shuttle_landmark/ranger_corvette/nav3, /turf/template_noop, @@ -1784,6 +1817,13 @@ /obj/structure/lattice/catwalk/indoor/grate/dark, /turf/simulated/floor/plating, /area/ship/ranger_corvette/foyer) +"gSr" = ( +/obj/structure/ship_weapon_dummy{ + is_barrel = 1 + }, +/obj/structure/lattice/catwalk, +/turf/template_noop, +/area/ship/ranger_corvette/engine1) "gUj" = ( /obj/machinery/door/firedoor{ req_one_access = list(221,222) @@ -1888,24 +1928,16 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/engineering) "hmX" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 - }, -/obj/machinery/door/firedoor{ - req_one_access = list(221,222) - }, -/obj/machinery/door/airlock/engineering{ - dir = 4; - req_one_access = list(221,222) - }, +/obj/machinery/atmospherics/pipe/manifold/hidden/supply, +/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers, /obj/structure/cable/green{ icon_state = "4-8" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/engine2) +/obj/structure/cable/green{ + icon_state = "1-8" + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/foyer) "hnE" = ( /obj/machinery/hologram/holopad/long_range, /obj/effect/overmap/visitable/ship/landable/ranger_shuttle, @@ -1914,25 +1946,13 @@ /turf/simulated/floor/tiled, /area/shuttle/ranger_shuttle) "hqB" = ( -/obj/machinery/door/airlock/engineering{ - dir = 4; - req_one_access = list(221,222); - name = "Rotary Cannon Chamber/Starboard Propulsion" - }, +/obj/effect/floor_decal/industrial/hatch/yellow, /obj/machinery/door/firedoor{ + dir = 4; req_one_access = list(221,222) }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 - }, -/obj/structure/cable/green{ - icon_state = "4-8" - }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/engine1) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/foyer) "htX" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 @@ -1953,12 +1973,13 @@ /turf/simulated/floor/plating, /area/ship/ranger_corvette/atmospherics) "hvo" = ( -/obj/machinery/light{ - dir = 8; - icon_state = "tube_empty" +/obj/structure/railing/mapped, +/obj/structure/railing/mapped{ + dir = 4 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/voidsuits) +/obj/structure/table/steel, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/bridge) "hwT" = ( /obj/structure/table/stone/marble, /obj/item/reagent_containers/glass/beaker/large{ @@ -1993,11 +2014,17 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/brig) "hFA" = ( -/obj/machinery/light{ - dir = 4; - icon_state = "tube_empty" +/obj/machinery/portable_atmospherics/canister/oxygen, +/obj/effect/floor_decal/industrial/outline/blue, +/obj/structure/cable/green{ + d2 = 8; + icon_state = "0-8" }, -/turf/simulated/floor/tiled/dark/full, +/obj/machinery/power/apc/east{ + req_access = null; + req_one_access = list(221,222) + }, +/turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/voidsuits) "hPo" = ( /obj/structure/ship_weapon_dummy, @@ -2102,29 +2129,26 @@ /turf/simulated/floor/tiled/white, /area/ship/ranger_corvette/canteen) "imn" = ( -/obj/machinery/door/airlock/external{ +/obj/machinery/door/airlock/security{ + dir = 4; + req_one_access = list(221,222); + name = "Brig" + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, -/obj/machinery/access_button{ - pixel_x = 12; - pixel_y = 28; - dir = 4; - frequency = 1394 +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 }, -/obj/effect/shuttle_landmark/ranger_shuttle/hangar{ - dir = 8; - base_area = null; - base_turf = null +/obj/machinery/door/firedoor{ + dir = 4; + req_one_access = list(221,222) }, -/obj/effect/map_effect/marker_helper/airlock/exterior, -/obj/effect/map_effect/marker/airlock/docking{ - name = "ranger_shuttle_dock"; - master_tag = "ranger_shuttle_dock"; - landmark_tag = "nav_hangar_ranger"; - req_one_access = null +/obj/structure/cable/green{ + icon_state = "4-8" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/brig) "ioq" = ( /obj/effect/floor_decal/corner/red/diagonal, /obj/structure/sign/flag/himeo{ @@ -2135,15 +2159,15 @@ /turf/simulated/floor/tiled/white, /area/ship/ranger_corvette/canteen) "ioB" = ( -/obj/structure/flora/pottedplant{ - icon_state = "plant-21" +/obj/effect/floor_decal/corner/black{ + dir = 9 }, -/obj/machinery/light{ - dir = 4; - icon_state = "tube_empty" +/obj/structure/railing/mapped, +/obj/machinery/computer/ship/engines{ + dir = 1 }, /turf/simulated/floor/tiled/dark, -/area/ship/ranger_corvette/gunnery) +/area/ship/ranger_corvette/bridge) "itg" = ( /obj/effect/floor_decal/industrial/warning, /turf/simulated/floor/carpet, @@ -2205,17 +2229,12 @@ /turf/simulated/floor/wood, /area/ship/ranger_corvette/leader) "iGg" = ( -/obj/item/clothing/head/bearpelt{ - anchored = 1; - name = "bear pelt wall rug"; - pixel_x = 32; - pixel_y = 5 - }, -/obj/structure/closet/crate/bin{ - name = "trashbin" +/obj/effect/floor_decal/corner/black{ + dir = 10 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/leader) +/obj/machinery/hologram/holopad/long_range, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/bridge) "iHC" = ( /obj/effect/floor_decal/industrial/hatch/yellow, /obj/machinery/door/blast/regular/open{ @@ -2237,20 +2256,20 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/engine1) "iQH" = ( -/obj/effect/floor_decal/corner/black{ - dir = 10 +/obj/machinery/embedded_controller/radio/simple_docking_controller{ + pixel_y = 21; + pixel_x = -4; + id_tag = "ranger_shuttle_dock"; + name = "Ranger Shuttle docking port controller"; + req_one_access = list(221,222) }, -/obj/machinery/hologram/holopad/long_range, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/foyer) "iTN" = ( -/obj/structure/railing/mapped, -/obj/structure/railing/mapped{ - dir = 4 - }, -/obj/structure/table/steel, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/obj/machinery/suit_cycler/offship/coc, +/obj/effect/floor_decal/industrial/outline/yellow, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/voidsuits) "iVL" = ( /obj/structure/extinguisher_cabinet/east, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, @@ -2284,6 +2303,18 @@ /obj/machinery/atmospherics/unary/vent_pump/on{ dir = 1 }, +/obj/structure/closet/secure_closet/guncabinet, +/obj/item/gun/projectile/revolver/lemat, +/obj/item/gun/projectile/revolver/lemat, +/obj/item/gun/projectile/revolver/lemat, +/obj/item/gun/projectile/revolver/lemat, +/obj/item/ammo_magazine/c38, +/obj/item/ammo_magazine/c38, +/obj/item/ammo_magazine/c38, +/obj/item/ammo_magazine/c38, +/obj/item/ammo_magazine/c38, +/obj/item/ammo_magazine/c38, +/obj/item/ammo_magazine/c38, /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/gunnery) "jcc" = ( @@ -2309,21 +2340,20 @@ /turf/simulated/floor/carpet/lightblue, /area/ship/ranger_corvette/crew) "jjc" = ( -/obj/effect/floor_decal/corner/dark_blue{ - dir = 5 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/structure/extinguisher_cabinet/west{ +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/machinery/door/airlock/glass_command{ + name = "Bridge"; dir = 1; - pixel_x = 0; - pixel_y = 28 + req_one_access = list(221,222) + }, +/obj/machinery/door/firedoor{ + req_one_access = list(221,222) }, /obj/structure/cable/green{ - icon_state = "4-8" + icon_state = "1-2" }, -/turf/simulated/floor/tiled/dark/full, +/turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/bridge) "jmN" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ @@ -2352,14 +2382,21 @@ /turf/simulated/floor/holofloor/tiled/ramp, /area/ship/ranger_corvette/gunnery) "jpQ" = ( -/obj/effect/floor_decal/corner/black{ - dir = 10 - }, -/obj/structure/bed/stool/chair/office/bridge/generic{ +/obj/machinery/door/airlock/external{ dir = 4 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/obj/effect/map_effect/marker_helper/airlock/exterior, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/effect/map_effect/marker/airlock/docking{ + name = "ranger_shuttle_dock"; + master_tag = "ranger_shuttle_dock"; + landmark_tag = "nav_hangar_ranger"; + req_one_access = null + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/foyer) "jrY" = ( /obj/effect/floor_decal/spline/plain/black{ dir = 6 @@ -2417,50 +2454,48 @@ /turf/simulated/floor/plating, /area/ship/ranger_corvette/atmospherics) "jyf" = ( -/obj/effect/floor_decal/corner/black/full{ - dir = 8 - }, -/obj/structure/bed/stool/chair/office/bridge/generic{ - icon_state = "bridge" - }, -/obj/machinery/atmospherics/unary/vent_pump/on{ - dir = 4 - }, -/obj/machinery/light{ - dir = 8; - icon_state = "tube_empty" +/obj/effect/floor_decal/industrial/warning/corner{ + dir = 1 }, /obj/structure/cable/green{ icon_state = "0-4" }, -/obj/machinery/power/apc/high/west{ - req_access = null +/obj/machinery/power/apc/north{ + req_access = null; + req_one_access = list(221,222) }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/obj/structure/cargo_receptacle, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/engine1) "jyA" = ( -/obj/machinery/atmospherics/unary/vent_scrubber/on{ - dir = 8 +/obj/machinery/door/airlock/highsecurity{ + name = "Ship Munitions Storage"; + dir = 4; + req_one_access = list(221,222) }, -/obj/structure/cable/green{ - icon_state = "4-8" +/obj/machinery/door/firedoor{ + req_one_access = list(221,222) }, -/obj/structure/dispenser/oxygen, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/voidsuits) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/munitions) "jyH" = ( -/obj/machinery/portable_atmospherics/canister/oxygen, -/obj/effect/floor_decal/industrial/outline/blue, -/obj/structure/cable/green{ - d2 = 8; - icon_state = "0-8" +/obj/effect/floor_decal/corner/white{ + dir = 4 }, -/obj/machinery/power/apc/east{ - req_access = null; - req_one_access = list(221,222) +/obj/effect/floor_decal/corner/white{ + dir = 8 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/voidsuits) +/obj/structure/railing/mapped, +/obj/structure/railing/mapped{ + dir = 8 + }, +/obj/structure/table/steel, +/obj/item/binoculars, +/obj/item/binoculars{ + pixel_y = 5 + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/bridge) "jzV" = ( /obj/structure/bed/stool/chair/shuttle{ dir = 8 @@ -2495,36 +2530,18 @@ }, /turf/simulated/floor/plating, /area/ship/ranger_corvette/engine1) -"jJP" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/structure/cable/green{ - icon_state = "1-2" - }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) "jMZ" = ( /obj/effect/floor_decal/industrial/outline/yellow, /obj/machinery/portable_atmospherics/canister/carbon_dioxide, /turf/simulated/floor/plating, /area/ship/ranger_corvette/engine2) "jPm" = ( -/obj/structure/lattice/catwalk/indoor/grate/dark, -/obj/structure/table/steel, -/obj/item/reagent_containers/food/drinks/drinkingglass/newglass/coffeecup/metal/coc{ - pixel_x = 8; - pixel_y = 5 - }, -/obj/item/reagent_containers/glass/beaker/pitcher{ - pixel_x = -5; - reagents_to_add = list(/singleton/reagent/drink/coffee=30) - }, -/obj/item/reagent_containers/food/drinks/drinkingglass/newglass/coffeecup/metal/coc{ - pixel_x = 6 +/obj/structure/sign/flag/coalition{ + pixel_x = -32 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/leader) "jRF" = ( /obj/machinery/atmospherics/pipe/simple/hidden/aux{ dir = 4 @@ -2585,20 +2602,21 @@ /obj/structure/ship_weapon_dummy{ is_barrel = 1 }, +/obj/structure/lattice/catwalk, /turf/simulated/floor/airless, /area/ship/ranger_corvette/engine1) "kaR" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 +/obj/structure/sign/directions/com{ + dir = 4; + pixel_x = 32; + pixel_y = 10 }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/structure/cable/green{ - icon_state = "4-8" + icon_state = "1-2" }, -/turf/simulated/floor/tiled/dark/full, +/turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/foyer) "kcS" = ( /obj/effect/decal/cleanable/blood/oil, @@ -2619,23 +2637,22 @@ /turf/simulated/floor/tiled/white, /area/ship/ranger_corvette/medbay) "kji" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 6 +/obj/effect/floor_decal/industrial/outline/yellow, +/obj/structure/closet/crate/freezer/rations, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/engine1) +"kku" = ( +/obj/effect/floor_decal/corner/black{ + dir = 10 }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 5 +/obj/effect/floor_decal/corner/white{ + dir = 1 }, -/obj/structure/cable/green{ - icon_state = "4-8" +/obj/structure/bed/stool/chair/office/bridge/generic{ + dir = 8 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/crew) -"kku" = ( -/obj/effect/floor_decal/industrial/outline/yellow, -/obj/machinery/suit_cycler/offship/coc, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/voidsuits) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/bridge) "kkN" = ( /obj/structure/sign/directions/com{ pixel_x = -32 @@ -2652,11 +2669,28 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/foyer) "kpi" = ( -/obj/machinery/door/airlock/external, -/obj/effect/map_effect/marker_helper/airlock/exterior, -/obj/effect/map_effect/marker/airlock/docking/ranger_corvette/aft, -/turf/simulated/floor/plating, -/area/ship/ranger_corvette/atmospherics) +/obj/effect/floor_decal/industrial/outline/yellow, +/obj/structure/table/rack, +/obj/item/gps, +/obj/item/gps, +/obj/item/gps, +/obj/item/gps, +/obj/item/gps, +/obj/item/gps, +/obj/item/tank/emergency_oxygen/double, +/obj/item/tank/emergency_oxygen/double, +/obj/item/tank/emergency_oxygen/double, +/obj/item/tank/emergency_oxygen/double, +/obj/item/tank/emergency_oxygen/double, +/obj/item/tank/jetpack/carbondioxide, +/obj/item/tank/jetpack/carbondioxide, +/obj/item/tank/jetpack/carbondioxide, +/obj/item/tank/jetpack/carbondioxide, +/obj/item/tank/jetpack/carbondioxide, +/obj/item/tank/jetpack/carbondioxide, +/obj/item/suit_cooling_unit, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/voidsuits) "kxo" = ( /obj/machinery/portable_atmospherics/powered/pump/filled, /obj/structure/cable/green{ @@ -2678,47 +2712,36 @@ }, /turf/simulated/floor/plating, /area/ship/ranger_corvette/bridge) -"kFU" = ( -/obj/effect/floor_decal/industrial/outline/yellow, -/obj/structure/railing/mapped{ - dir = 1 - }, -/obj/machinery/portable_atmospherics/canister/carbon_dioxide, -/obj/machinery/light{ - dir = 8; - icon_state = "tube_empty" - }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/engine1) "kJM" = ( /obj/effect/floor_decal/industrial/outline/yellow, -/obj/structure/railing/mapped{ - dir = 1 - }, -/obj/machinery/portable_atmospherics/canister/carbon_dioxide, -/turf/simulated/floor/tiled/dark/full, +/obj/structure/closet/crate/loot, +/obj/item/clothing/wrists/watch, +/turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/engine1) "kLL" = ( -/obj/effect/floor_decal/industrial/outline/yellow, -/obj/structure/railing/mapped{ - dir = 1 +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/crew) +"kTh" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 }, -/obj/structure/railing/mapped{ +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, -/obj/machinery/portable_atmospherics/canister/air, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/engine1) -"kTh" = ( -/obj/effect/floor_decal/corner/white{ - dir = 5 +/obj/machinery/door/airlock/highsecurity{ + name = "Ship Munitions Storage"; + dir = 4; + req_one_access = list(221,222) }, -/obj/structure/railing/mapped, -/obj/machinery/computer/ship/sensors{ - dir = 1 +/obj/machinery/door/firedoor{ + req_one_access = list(221,222) }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/obj/structure/cable/green{ + icon_state = "4-8" + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/munitions) "kYl" = ( /obj/effect/floor_decal/industrial/loading/yellow, /obj/machinery/alarm/east{ @@ -2764,12 +2787,25 @@ /turf/simulated/floor/plating, /area/ship/ranger_corvette/canteen) "lgK" = ( -/obj/effect/floor_decal/industrial/hatch/yellow, -/obj/machinery/door/firedoor{ - dir = 4; - req_one_access = list(221,222) +/obj/machinery/door/airlock/external{ + dir = 4 }, -/turf/simulated/floor/tiled/dark/full, +/obj/machinery/atmospherics/pipe/simple/hidden/aux{ + dir = 6 + }, +/obj/effect/map_effect/marker/airlock/docking{ + name = "ranger_shuttle_dock"; + master_tag = "ranger_shuttle_dock"; + landmark_tag = "nav_hangar_ranger"; + req_one_access = null + }, +/obj/machinery/access_button{ + pixel_x = -23; + pixel_y = 22; + frequency = 1394 + }, +/obj/effect/map_effect/marker_helper/airlock/interior, +/turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/foyer) "lhJ" = ( /obj/structure/ship_weapon_dummy, @@ -2809,12 +2845,26 @@ /turf/simulated/floor/tiled/white, /area/ship/ranger_corvette/medbay) "lut" = ( -/obj/item/modular_computer/console/preset/civilian{ +/obj/structure/table/rack, +/obj/effect/floor_decal/industrial/outline/red, +/obj/machinery/door/window/eastleft{ dir = 1 }, -/obj/structure/lattice/catwalk/indoor/grate/dark, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/obj/machinery/light/small/emergency{ + dir = 8 + }, +/obj/machinery/light{ + dir = 8; + icon_state = "tube_empty" + }, +/obj/item/ship_ammunition/autocannon, +/obj/item/ship_ammunition/autocannon, +/obj/item/ship_ammunition/autocannon, +/obj/item/ship_ammunition/autocannon, +/obj/item/ship_ammunition/autocannon, +/obj/item/ship_ammunition/autocannon, +/turf/simulated/floor/reinforced, +/area/ship/ranger_corvette/munitions) "lvN" = ( /obj/machinery/computer/shuttle_control/explore/ranger_shuttle{ req_one_access = list(221,222) @@ -2842,36 +2892,28 @@ /turf/simulated/floor/tiled/white, /area/ship/ranger_corvette/canteen) "lCo" = ( -/obj/effect/floor_decal/corner/dark_blue{ - dir = 5 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 - }, -/obj/machinery/alarm/north{ - req_one_access = list(221,222) +/obj/item/modular_computer/console/preset/civilian{ + dir = 1 }, -/turf/simulated/floor/tiled/dark/full, +/obj/structure/lattice/catwalk/indoor/grate/dark, +/turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/bridge) "lGa" = ( /obj/machinery/atmospherics/pipe/manifold4w/visible/fuel, /turf/simulated/wall/shuttle/space_ship/mercenary, /area/shuttle/ranger_shuttle) "lGr" = ( -/obj/effect/floor_decal/corner/black{ - dir = 9 - }, -/obj/effect/floor_decal/corner/white{ - dir = 4 - }, -/obj/effect/floor_decal/spline/plain/black{ - dir = 1 +/obj/structure/table/rack, +/obj/effect/floor_decal/industrial/outline/red, +/obj/machinery/door/window/eastright{ + dir = 2 }, -/obj/structure/table/steel, -/obj/item/clipboard, -/obj/item/paper, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/obj/item/ship_ammunition/grauwolf_bundle, +/obj/item/ship_ammunition/grauwolf_bundle, +/obj/item/ship_ammunition/grauwolf_bundle, +/obj/item/ship_ammunition/grauwolf_bundle, +/turf/simulated/floor/reinforced, +/area/ship/ranger_corvette/munitions) "lGB" = ( /obj/machinery/atmospherics/pipe/manifold/hidden/supply{ dir = 4 @@ -2947,10 +2989,20 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/engine2) "lWH" = ( -/obj/structure/table/steel, -/obj/item/modular_computer/laptop/preset/civilian, -/turf/simulated/floor/carpet/brown, -/area/ship/ranger_corvette/leader) +/obj/machinery/door/airlock/external, +/obj/effect/map_effect/marker_helper/airlock/interior, +/obj/machinery/access_button{ + pixel_x = 24; + pixel_y = -32; + dir = 8; + frequency = 2137 + }, +/obj/effect/map_effect/marker/airlock/docking/ranger_corvette/aft, +/obj/machinery/door/blast/shutters/open{ + id = "coc_aft" + }, +/turf/simulated/floor/plating, +/area/ship/ranger_corvette/atmospherics) "lXU" = ( /obj/effect/floor_decal/corner/red/diagonal, /obj/structure/bed/stool/padded, @@ -3038,17 +3090,21 @@ /turf/simulated/floor/plating, /area/ship/ranger_corvette/atmospherics) "mdX" = ( -/obj/machinery/atmospherics/unary/vent_scrubber/on{ - dir = 8 +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 6 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 6 + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) "mgl" = ( -/obj/effect/floor_decal/corner/black{ - dir = 10 +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable/green{ + icon_state = "1-2" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/crew) "mhA" = ( /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/gunnery) @@ -3059,13 +3115,14 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/engineering) "mkT" = ( -/obj/machinery/atmospherics/unary/vent_pump/on{ +/obj/effect/floor_decal/corner/white{ dir = 4 }, -/obj/effect/floor_decal/industrial/outline/yellow, -/obj/machinery/suit_cycler/offship/coc, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/voidsuits) +/obj/effect/floor_decal/spline/plain/black{ + dir = 1 + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/bridge) "mlG" = ( /obj/structure/cable/green, /obj/machinery/power/terminal, @@ -3097,14 +3154,17 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/gunnery) "moB" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/structure/cable/green, -/obj/machinery/power/apc/west{ - req_access = null; - req_one_access = list(221,222) +/obj/machinery/light{ + dir = 8; + icon_state = "tube_empty" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/leader) +/obj/structure/cable/green{ + icon_state = "1-2" + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/foyer) "mun" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 @@ -3146,11 +3206,17 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/foyer) "mzO" = ( -/obj/machinery/light{ - dir = 1 +/obj/effect/floor_decal/corner/dark_blue{ + dir = 5 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/machinery/alarm/north{ + req_one_access = list(221,222) + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/bridge) "mzY" = ( /obj/structure/closet/walllocker{ pixel_x = 32; @@ -3198,16 +3264,17 @@ /turf/simulated/floor/tiled/white, /area/ship/ranger_corvette/canteen) "mHw" = ( -/obj/effect/floor_decal/corner/black/full, -/obj/machinery/computer/ship/navigation{ +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 }, -/obj/machinery/light{ - dir = 8; - icon_state = "tube_empty" +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/obj/structure/cable/green{ + icon_state = "4-8" + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/foyer) "mLK" = ( /obj/machinery/atmospherics/portables_connector/aux{ dir = 8 @@ -3253,19 +3320,13 @@ /turf/simulated/floor/tiled/full, /area/shuttle/ranger_shuttle) "mVV" = ( -/obj/effect/floor_decal/corner/dark_blue{ - dir = 5 - }, -/obj/structure/sign/flag/coalition{ - pixel_y = 32 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 +/obj/effect/floor_decal/corner/white{ + dir = 10 }, -/obj/structure/cable/green{ - icon_state = "4-8" +/obj/effect/floor_decal/spline/plain/black{ + dir = 1 }, -/turf/simulated/floor/tiled/dark/full, +/turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/bridge) "mWY" = ( /obj/effect/floor_decal/corner/red/diagonal, @@ -3359,36 +3420,20 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/engine2) "ntW" = ( -/obj/effect/floor_decal/corner/white{ - dir = 8 - }, -/obj/effect/floor_decal/corner/white{ - dir = 4 - }, -/obj/effect/floor_decal/spline/plain/corner/black{ - dir = 1 - }, -/obj/effect/floor_decal/spline/plain/black{ - dir = 1 +/obj/item/deck/cards, +/obj/structure/table/wood/gamblingtable, +/obj/item/lore_radio{ + pixel_y = 9 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/turf/simulated/floor/wood, +/area/ship/ranger_corvette/foyer) "nCd" = ( -/obj/effect/floor_decal/industrial/warning{ - dir = 1 - }, -/obj/structure/sign/securearea{ - desc = "A warning sign which reads 'WARNING: BLAST DOOR'."; - name = "\improper WARNING: BLAST DOOR sign"; - pixel_x = 32 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/structure/cable/green{ - icon_state = "1-2" +/obj/machinery/light{ + dir = 4; + icon_state = "tube_empty" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/voidsuits) "nDb" = ( /obj/structure/bed/stool/chair/padded/brown{ dir = 1 @@ -3420,11 +3465,21 @@ /turf/simulated/floor/carpet, /area/ship/ranger_corvette/foyer) "nGj" = ( -/obj/effect/floor_decal/industrial/outline/yellow, -/obj/structure/closet/crate/loot, -/obj/item/clothing/wrists/watch, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/engine1) +/obj/structure/lattice/catwalk/indoor/grate/dark, +/obj/structure/table/steel, +/obj/item/reagent_containers/food/drinks/drinkingglass/newglass/coffeecup/metal/coc{ + pixel_x = 8; + pixel_y = 5 + }, +/obj/item/reagent_containers/glass/beaker/pitcher{ + pixel_x = -5; + reagents_to_add = list(/singleton/reagent/drink/coffee=30) + }, +/obj/item/reagent_containers/food/drinks/drinkingglass/newglass/coffeecup/metal/coc{ + pixel_x = 6 + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/bridge) "nIu" = ( /obj/structure/ship_weapon_dummy, /turf/simulated/wall/shuttle/space_ship/mercenary, @@ -3477,16 +3532,14 @@ /turf/simulated/floor/tiled/full, /area/shuttle/ranger_shuttle) "nTM" = ( -/obj/effect/floor_decal/industrial/outline/yellow, -/obj/structure/closet/crate, -/obj/item/tank/phoron/shuttle, -/obj/item/storage/bag/inflatable, -/obj/item/storage/bag/inflatable, -/obj/item/storage/box/lights/mixed, -/obj/item/tape_roll, -/obj/item/tape_roll, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/engine1) +/obj/machinery/atmospherics/unary/vent_scrubber/on{ + dir = 4 + }, +/obj/structure/cable/green{ + icon_state = "1-2" + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/crew) "nVM" = ( /obj/structure/sign/flag/coalition{ pixel_y = 32 @@ -3506,19 +3559,16 @@ /turf/simulated/floor/tiled, /area/shuttle/ranger_shuttle) "oey" = ( -/obj/effect/floor_decal/industrial/outline/yellow, -/obj/structure/closet/crate, -/obj/item/stack/material/plasteel/full, -/obj/item/stack/material/steel/full, -/obj/item/stack/material/steel/full, -/obj/item/stack/material/glass/reinforced/full, -/obj/item/stack/material/glass/full, -/obj/item/grenade/chem_grenade/metalfoam, -/obj/item/grenade/chem_grenade/metalfoam, -/obj/item/grenade/chem_grenade/metalfoam, -/obj/item/grenade/chem_grenade/metalfoam, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/engine1) +/obj/effect/floor_decal/corner/black/full, +/obj/machinery/computer/ship/navigation{ + dir = 4 + }, +/obj/machinery/light{ + dir = 8; + icon_state = "tube_empty" + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/bridge) "ojz" = ( /obj/structure/cable/green{ icon_state = "0-4" @@ -3558,10 +3608,20 @@ /turf/simulated/floor/plating, /area/ship/ranger_corvette/atmospherics) "oAK" = ( -/obj/effect/floor_decal/industrial/outline/yellow, -/obj/structure/closet/crate/freezer/rations, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/engine1) +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 6 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 10 + }, +/obj/structure/cable/green{ + d1 = 2; + d2 = 4; + icon_state = "2-4" + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/voidsuits) "oAP" = ( /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/tiled/dark, @@ -3580,21 +3640,21 @@ /turf/simulated/floor/airless, /area/shuttle/ranger_shuttle) "oEN" = ( -/obj/machinery/door/airlock{ - name = "EVA Storage"; +/obj/machinery/door/airlock/external, +/obj/machinery/access_button{ + pixel_x = -28; + pixel_y = 12; dir = 1; - req_one_access = list(221,222) - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/machinery/door/firedoor{ - req_one_access = list(221,222) + frequency = 2137 }, -/obj/structure/cable/green{ - icon_state = "1-2" +/obj/effect/map_effect/marker_helper/airlock/exterior, +/obj/effect/map_effect/marker/airlock/docking/ranger_corvette/aft, +/obj/effect/shuttle_landmark/ranger_corvette/dock_aft, +/obj/machinery/door/blast/shutters/open{ + id = "coc_aft" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/voidsuits) +/turf/simulated/floor/plating, +/area/ship/ranger_corvette/atmospherics) "oIF" = ( /turf/simulated/wall/shuttle/space_ship/mercenary, /area/ship/ranger_corvette/engineering) @@ -3652,51 +3712,18 @@ /turf/simulated/wall/shuttle/space_ship/mercenary, /area/ship/ranger_corvette/engineering) "oOX" = ( -/obj/structure/closet/secure_closet/kitchen_cabinet/standard, -/obj/item/reagent_containers/food/snacks/meat, -/obj/item/reagent_containers/food/snacks/meat, -/obj/item/reagent_containers/food/snacks/meat, -/obj/item/reagent_containers/food/snacks/meat, -/obj/item/reagent_containers/food/snacks/meat, -/obj/item/reagent_containers/food/snacks/meat, -/obj/item/reagent_containers/food/snacks/meat, -/obj/item/reagent_containers/food/snacks/meat, -/obj/item/storage/box/large/produce{ - pixel_x = 3; - pixel_y = -11 - }, -/obj/item/storage/box/fancy/egg_box, -/obj/item/storage/box/fancy/egg_box, -/obj/item/reagent_containers/food/drinks/carton/milk, -/obj/item/reagent_containers/food/drinks/carton/milk, -/obj/item/reagent_containers/food/condiment/enzyme{ - pixel_x = -9; - pixel_y = 5 - }, -/obj/item/reagent_containers/food/condiment/enzyme{ - pixel_x = -9; - pixel_y = 5 - }, -/obj/item/reagent_containers/food/condiment/enzyme{ - pixel_x = -9; - pixel_y = 5 - }, -/obj/item/reagent_containers/food/condiment/enzyme{ - pixel_x = -9; - pixel_y = 5 +/obj/effect/floor_decal/corner/dark_blue/full{ + dir = 4 }, -/obj/item/reagent_containers/food/condiment/enzyme{ - pixel_x = -9; - pixel_y = 5 +/obj/machinery/computer/ship/engines{ + dir = 8 }, -/obj/effect/decal/cleanable/cobweb2, -/obj/effect/floor_decal/corner/brown/diagonal, /obj/machinery/light{ dir = 4; icon_state = "tube_empty" }, -/turf/simulated/floor/tiled/white, -/area/ship/ranger_corvette/canteen) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/bridge) "oSw" = ( /obj/effect/floor_decal/industrial/warning, /obj/structure/sign/securearea{ @@ -3837,34 +3864,29 @@ /turf/simulated/floor/tiled/white, /area/ship/ranger_corvette/canteen) "pia" = ( -/obj/machinery/ship_weapon/francisca{ - pixel_x = -64; - pixel_y = -162; - weapon_id = "Ranger Francisca Rotary Gun" +/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ + dir = 4 }, -/obj/structure/ship_weapon_dummy, -/turf/simulated/floor/airless, -/area/ship/ranger_corvette/engine1) -"plP" = ( -/turf/simulated/floor/tiled/dark, -/area/ship/ranger_corvette/brig) -"pmD" = ( -/obj/machinery/door/airlock/external{ +/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ dir = 4 }, -/obj/machinery/atmospherics/pipe/manifold/hidden/aux, -/obj/effect/map_effect/marker_helper/airlock/interior, -/obj/structure/cable{ - icon_state = "4-8" +/obj/machinery/light{ + dir = 4; + icon_state = "tube_empty" }, -/obj/effect/map_effect/marker/airlock/docking{ - name = "ranger_shuttle_dock"; - master_tag = "ranger_shuttle_dock"; - landmark_tag = "nav_hangar_ranger"; - req_one_access = null +/obj/structure/cable/green{ + icon_state = "1-2" }, -/turf/simulated/floor/tiled/dark/full, +/turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/foyer) +"plP" = ( +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/brig) +"pmD" = ( +/obj/structure/ship_weapon_dummy/barrel, +/obj/structure/lattice/catwalk, +/turf/simulated/floor/airless, +/area/ship/ranger_corvette/engine1) "ppM" = ( /obj/structure/sign/directions/medical{ dir = 4; @@ -3910,34 +3932,37 @@ }, /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/engine2) -"pBA" = ( -/obj/effect/floor_decal/corner/dark_blue/full{ - dir = 4 - }, -/obj/machinery/computer/ship/engines{ - dir = 8 - }, -/obj/machinery/light{ - dir = 4; - icon_state = "tube_empty" - }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) "pBE" = ( -/obj/effect/floor_decal/industrial/warning{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 - }, -/obj/structure/cable/green{ - icon_state = "4-8" - }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) +/obj/structure/lattice/catwalk/indoor/grate/dark, +/obj/structure/closet/cabinet, +/obj/item/clothing/accessory/badge/passcard/coalition, +/obj/item/gun/projectile/revolver/derringer, +/obj/item/ammo_casing/a357, +/obj/item/ammo_casing/a357, +/obj/item/ammo_casing/a357, +/obj/item/ammo_casing/a357, +/obj/item/spacecash/c100, +/obj/item/spacecash/c100, +/obj/item/spacecash/c10, +/obj/item/spacecash/c10, +/obj/item/spacecash/c10, +/obj/item/spacecash/c10, +/obj/item/spacecash/c200, +/obj/item/spacecash/c20, +/obj/item/spacecash/c20, +/obj/item/spacecash/c1, +/obj/item/spacecash/c1, +/obj/item/spacecash/c1, +/obj/item/clothing/accessory/armband/gadpathur, +/obj/item/clothing/under/uniform/gadpathur, +/obj/item/clothing/suit/storage/toggle/himeo/grey, +/obj/item/clothing/accessory/assunzione, +/obj/item/clothing/under/konyang/male/shortsleeve, +/obj/item/clothing/suit/storage/toggle/leather_jacket/military/old/alt, +/obj/item/clothing/suit/storage/toggle/leather_jacket/military, +/obj/item/spacecash/c1000, +/turf/simulated/floor/plating, +/area/ship/ranger_corvette/leader) "pDY" = ( /obj/machinery/atmospherics/pipe/tank/air{ dir = 4 @@ -4044,6 +4069,11 @@ /obj/effect/floor_decal/corner_wide/blue/diagonal, /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/telecomms) +"pZW" = ( +/obj/structure/lattice/catwalk, +/obj/structure/ship_weapon_dummy, +/turf/template_noop, +/area/ship/ranger_corvette/engine1) "qbp" = ( /obj/effect/floor_decal/industrial/hatch/yellow, /obj/machinery/door/blast/regular/open{ @@ -4105,17 +4135,21 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/telecomms) "qqG" = ( -/obj/effect/floor_decal/corner/dark_blue{ - dir = 5 - }, -/obj/structure/sign/flag/coalition{ - pixel_y = 32 +/obj/effect/floor_decal/industrial/warning, +/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ + dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ +/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ dir = 4 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/obj/structure/cable/green{ + icon_state = "1-2" + }, +/obj/structure/cable/green{ + icon_state = "1-8" + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/foyer) "qrd" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 @@ -4143,12 +4177,20 @@ /turf/simulated/floor/airless, /area/shuttle/ranger_shuttle) "qtL" = ( -/obj/structure/closet/walllocker/firecloset{ - pixel_x = -32 +/obj/effect/floor_decal/corner/white{ + dir = 8 }, -/obj/effect/floor_decal/industrial/outline/firefighting_closet, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/gunnery) +/obj/effect/floor_decal/corner/white{ + dir = 4 + }, +/obj/effect/floor_decal/spline/plain/corner/black{ + dir = 1 + }, +/obj/effect/floor_decal/spline/plain/black{ + dir = 1 + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/bridge) "qtV" = ( /obj/effect/floor_decal/corner/green/diagonal, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ @@ -4167,19 +4209,26 @@ /turf/space/transit/north, /area/space) "quw" = ( -/obj/machinery/atmospherics/pipe/manifold4w/hidden/supply, -/obj/machinery/atmospherics/pipe/manifold4w/hidden/scrubbers, -/obj/structure/cable/green{ - icon_state = "1-2" +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 }, -/obj/structure/cable/green{ - icon_state = "1-8" +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/machinery/door/firedoor{ + dir = 4; + req_one_access = list(221,222) }, /obj/structure/cable/green{ - icon_state = "1-4" + icon_state = "4-8" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) +/obj/machinery/door/airlock/highsecurity{ + name = "Armory"; + dir = 4; + req_one_access = list(221,222) + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) "qyq" = ( /obj/effect/floor_decal/spline/plain/black{ dir = 4 @@ -4238,15 +4287,15 @@ /turf/simulated/floor/tiled/white, /area/ship/ranger_corvette/canteen) "qCZ" = ( -/obj/effect/floor_decal/corner/black{ - dir = 9 - }, -/obj/structure/railing/mapped, -/obj/machinery/computer/ship/engines{ - dir = 1 +/obj/machinery/door/airlock/external, +/obj/effect/map_effect/marker_helper/airlock/interior, +/obj/machinery/atmospherics/pipe/simple/hidden/aux, +/obj/effect/map_effect/marker/airlock/docking/ranger_corvette/aft, +/obj/machinery/door/blast/shutters/open{ + id = "coc_aft" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/turf/simulated/floor/plating, +/area/ship/ranger_corvette/atmospherics) "qGl" = ( /obj/machinery/alarm/south{ req_one_access = list(221,222) @@ -4260,15 +4309,13 @@ /turf/simulated/floor/tiled/white, /area/ship/ranger_corvette/canteen) "qHO" = ( -/obj/effect/floor_decal/industrial/outline/yellow, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 6 - }, -/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ - dir = 8 +/obj/machinery/ship_weapon/autocannon{ + weapon_id = "Ranger Francisca Rotary Gun" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/gunnery) +/obj/structure/lattice/catwalk, +/obj/item/hullbeacon/red, +/turf/template_noop, +/area/ship/ranger_corvette/engine1) "qMt" = ( /obj/effect/map_effect/map_helper/ruler_tiles_3{ dir = 4 @@ -4379,14 +4426,11 @@ /turf/space/transit/north, /area/space) "rfo" = ( -/obj/effect/floor_decal/corner/white{ - dir = 10 - }, -/obj/effect/floor_decal/spline/plain/black{ - dir = 1 +/obj/machinery/atmospherics/unary/vent_scrubber/on{ + dir = 8 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/foyer) "rgL" = ( /obj/effect/floor_decal/industrial/warning/corner, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ @@ -4429,21 +4473,34 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/brig) "rli" = ( -/obj/item/deck/cards, -/obj/structure/table/wood/gamblingtable, -/turf/simulated/floor/wood, -/area/ship/ranger_corvette/foyer) -"roN" = ( -/obj/machinery/atmospherics/pipe/manifold/hidden/supply, -/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, /obj/structure/cable/green{ icon_state = "4-8" }, +/obj/structure/table/rack/folding_table, +/obj/item/grenade/flashbang/clusterbang, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"roN" = ( +/obj/effect/floor_decal/industrial/warning{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ + dir = 1 + }, /obj/structure/cable/green{ - icon_state = "1-8" + icon_state = "4-8" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) "rpr" = ( /obj/structure/cable/green{ icon_state = "1-2" @@ -4456,17 +4513,18 @@ /turf/simulated/floor/tiled, /area/shuttle/ranger_shuttle) "rpP" = ( -/obj/structure/sign/directions/com{ - dir = 4; - pixel_x = 32; - pixel_y = 10 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/machinery/atmospherics/pipe/manifold4w/hidden/supply, +/obj/machinery/atmospherics/pipe/manifold4w/hidden/scrubbers, /obj/structure/cable/green{ icon_state = "1-2" }, -/turf/simulated/floor/tiled/dark/full, +/obj/structure/cable/green{ + icon_state = "1-8" + }, +/obj/structure/cable/green{ + icon_state = "1-4" + }, +/turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/foyer) "rro" = ( /obj/machinery/atmospherics/unary/vent_pump/on{ @@ -4533,21 +4591,11 @@ /turf/template_noop, /area/ship/ranger_corvette/gunnery) "rMA" = ( -/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ - dir = 4 - }, -/obj/machinery/light{ - dir = 4; - icon_state = "tube_empty" - }, -/obj/structure/cable/green{ - icon_state = "1-2" +/obj/effect/floor_decal/industrial/warning{ + dir = 8 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) "rQB" = ( /obj/effect/floor_decal/corner_wide/blue/diagonal, /turf/simulated/floor/tiled/dark, @@ -4564,25 +4612,6 @@ /turf/simulated/floor/reinforced/carbon_dioxide, /area/ship/ranger_corvette/engine2) "rVd" = ( -/obj/effect/floor_decal/industrial/warning{ - dir = 1 - }, -/obj/structure/sign/securearea{ - desc = "A warning sign which reads 'WARNING: BLAST DOOR'."; - name = "\improper WARNING: BLAST DOOR sign"; - pixel_x = 32 - }, -/obj/effect/floor_decal/industrial/warning{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/structure/cable/green{ - icon_state = "1-2" - }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) -"rVo" = ( /obj/structure/table/rack, /obj/effect/floor_decal/industrial/outline/red, /obj/machinery/door/window/eastright{ @@ -4591,8 +4620,33 @@ /obj/item/ship_ammunition/grauwolf_bundle/ap, /obj/item/ship_ammunition/grauwolf_bundle/ap, /obj/item/ship_ammunition/grauwolf_bundle/ap, +/obj/item/ship_ammunition/grauwolf_bundle/ap, /turf/simulated/floor/reinforced, /area/ship/ranger_corvette/munitions) +"rVo" = ( +/obj/machinery/door/airlock/external{ + dir = 4 + }, +/obj/machinery/access_button{ + pixel_x = 12; + pixel_y = 28; + dir = 4; + frequency = 1394 + }, +/obj/effect/shuttle_landmark/ranger_shuttle/hangar{ + dir = 8; + base_area = null; + base_turf = null + }, +/obj/effect/map_effect/marker_helper/airlock/exterior, +/obj/effect/map_effect/marker/airlock/docking{ + name = "ranger_shuttle_dock"; + master_tag = "ranger_shuttle_dock"; + landmark_tag = "nav_hangar_ranger"; + req_one_access = null + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/foyer) "scg" = ( /obj/effect/floor_decal/corner/green/diagonal, /obj/machinery/atmospherics/unary/vent_pump/on{ @@ -4625,12 +4679,11 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/telecomms) "siv" = ( -/obj/effect/decal/cleanable/dirt, -/obj/structure/cable/green{ - icon_state = "1-2" +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 6 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/crew) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) "slH" = ( /obj/effect/floor_decal/corner_wide/blue/diagonal, /obj/machinery/telecomms/allinone/ship/coalition_navy, @@ -4640,36 +4693,75 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/telecomms) "slN" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/machinery/alarm/south{ + req_one_access = list(221,222) + }, /obj/structure/cable/green{ - icon_state = "1-2" + icon_state = "4-8" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) -"smG" = ( -/obj/structure/closet/secure_closet/guncabinet{ - req_access = null +/obj/structure/table/rack/folding_table, +/obj/item/storage/toolbox{ + pixel_y = 6 + }, +/obj/effect/decal/cleanable/blood/oil, +/obj/item/screwdriver{ + pixel_y = -2 }, -/obj/effect/floor_decal/industrial/outline/security, -/obj/item/gun/projectile/pistol/adhomai, -/obj/item/ammo_magazine/mc9mm, -/obj/item/ammo_magazine/mc9mm, -/obj/item/gun/energy/pistol/hegemony, -/obj/item/gun/projectile/xanupistol, -/obj/item/ammo_magazine/c46m, -/obj/item/ammo_magazine/c46m, -/obj/item/gun/energy/blaster, -/obj/item/gun/projectile/revolver/lemat, -/obj/item/ammo_magazine/c38, -/obj/item/ammo_magazine/c38, -/obj/item/gun/energy/retro, /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/gunnery) +"smG" = ( +/obj/effect/floor_decal/industrial/warning{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/structure/cable/green{ + icon_state = "4-8" + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/foyer) "smZ" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/crew) +/obj/effect/decal/cleanable/dirt, +/obj/machinery/light{ + dir = 8; + icon_state = "tube_empty" + }, +/obj/structure/closet/cabinet, +/obj/item/reagent_containers/food/drinks/cans/beer/rice, +/obj/item/reagent_containers/food/drinks/cans/beer/rice, +/obj/item/reagent_containers/food/drinks/cans/beer/rice, +/obj/item/reagent_containers/food/drinks/cans/beer/rice, +/obj/item/reagent_containers/food/drinks/cans/beer/rice, +/obj/item/reagent_containers/food/drinks/cans/beer/rice, +/obj/item/reagent_containers/food/drinks/cans/beer/whistlingforest, +/obj/item/reagent_containers/food/drinks/cans/beer/whistlingforest, +/obj/item/reagent_containers/food/drinks/cans/beer/whistlingforest, +/obj/item/reagent_containers/food/drinks/cans/beer/whistlingforest, +/obj/item/reagent_containers/food/drinks/cans/beer/whistlingforest, +/obj/item/reagent_containers/food/drinks/cans/beer/whistlingforest, +/obj/item/reagent_containers/food/drinks/cans/beer/whistlingforest, +/obj/item/reagent_containers/food/drinks/cans/beer/rice/shimauma, +/obj/item/reagent_containers/food/drinks/cans/beer/rice/shimauma, +/obj/item/reagent_containers/food/drinks/cans/beer/rice/shimauma, +/obj/item/reagent_containers/food/drinks/cans/beer/rice/shimauma, +/obj/item/reagent_containers/food/drinks/cans/beer/rice/shimauma, +/obj/item/reagent_containers/food/drinks/cans/beer/rice/shimauma, +/obj/item/reagent_containers/food/drinks/cans/beer/rice/shimauma, +/obj/item/reagent_containers/food/drinks/cans/beer/rice/shimauma, +/obj/item/reagent_containers/food/drinks/bottle/saintjacques, +/turf/simulated/floor/wood, +/area/ship/ranger_corvette/foyer) "spv" = ( /obj/machinery/atmospherics/pipe/manifold/hidden/supply{ dir = 4 @@ -4686,17 +4778,11 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/foyer) "sqh" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/light{ - dir = 8; - icon_state = "tube_empty" - }, -/obj/structure/cable/green{ - icon_state = "1-2" +/obj/machinery/atmospherics/unary/vent_pump/on{ + dir = 4 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/crew) "stJ" = ( /obj/structure/table/steel, /obj/item/shovel/gadpathur, @@ -4719,16 +4805,20 @@ /turf/simulated/floor/plating, /area/ship/ranger_corvette/atmospherics) "swi" = ( -/obj/structure/table/rack, -/obj/effect/floor_decal/industrial/outline/red, -/obj/machinery/door/window/eastleft{ - dir = 2 +/obj/effect/floor_decal/corner/black{ + dir = 9 }, -/obj/item/ship_ammunition/grauwolf_bundle, -/obj/item/ship_ammunition/grauwolf_bundle, -/obj/item/ship_ammunition/grauwolf_bundle, -/turf/simulated/floor/reinforced, -/area/ship/ranger_corvette/munitions) +/obj/effect/floor_decal/corner/white{ + dir = 4 + }, +/obj/effect/floor_decal/spline/plain/black{ + dir = 1 + }, +/obj/structure/table/steel, +/obj/item/clipboard, +/obj/item/paper, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/bridge) "sCd" = ( /obj/structure/lattice/catwalk/indoor/grate/dark, /obj/machinery/airlock_sensor{ @@ -4816,25 +4906,11 @@ /turf/simulated/floor/wood, /area/ship/ranger_corvette/foyer) "sMm" = ( -/obj/structure/filingcabinet{ - desc = "A large cabinet with drawers. Those are some fancy cabinets, High-Speed."; - name = "gun parts cabinet"; - pixel_x = -6 - }, -/obj/structure/filingcabinet{ - desc = "A large cabinet with drawers. Those are some fancy cabinets, High-Speed."; - name = "gun parts cabinet"; - pixel_x = 6 - }, -/obj/item/receivergun{ - desc = "The PTR-7 is man-portable anti-armor rifle fitted with a high-powered scope, capable of penetrating through most windows, airlocks, and non-reinforced walls with ease. Fires armor piercing 14.5mm shells. This one has suffered extensive wear and battle damage - the most noteworthy of which being a shot to the receiver that has destroyed it, rendering it useful as a paperweight at most."; - icon = 'icons/obj/guns/heavysniper.dmi'; - icon_state = "heavysniper"; - name = "anti-material rifle"; - pixel_y = 14 - }, -/turf/simulated/floor/tiled/dark, -/area/ship/ranger_corvette/gunnery) +/obj/structure/bookcase/libraryspawn/fiction, +/obj/effect/decal/cleanable/cobweb2, +/obj/item/toy/comic/magazine, +/turf/simulated/floor/carpet, +/area/ship/ranger_corvette/foyer) "sMD" = ( /obj/machinery/shower{ dir = 1 @@ -5162,13 +5238,15 @@ /turf/simulated/floor/tiled/full, /area/shuttle/ranger_shuttle) "tAd" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/structure/cable/green{ - icon_state = "1-2" +/obj/effect/floor_decal/corner/white{ + dir = 5 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) +/obj/structure/railing/mapped, +/obj/machinery/computer/ship/sensors{ + dir = 1 + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/bridge) "tBK" = ( /obj/machinery/atmospherics/unary/vent_pump/on{ dir = 1 @@ -5194,16 +5272,15 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/foyer) "tFs" = ( -/obj/effect/floor_decal/corner/white{ - dir = 1 +/obj/machinery/atmospherics/unary/vent_scrubber/on{ + dir = 8 }, -/obj/effect/floor_decal/corner/white, -/obj/effect/floor_decal/spline/plain/black{ - dir = 1 +/obj/structure/cable/green{ + icon_state = "4-8" }, -/obj/effect/overmap/visitable/ship/ranger_corvette, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/obj/structure/dispenser/oxygen, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/voidsuits) "tGV" = ( /obj/effect/floor_decal/spline/plain/black{ dir = 9 @@ -5233,41 +5310,29 @@ /turf/simulated/wall/shuttle/space_ship/mercenary, /area/ship/ranger_corvette/gunnery) "tOx" = ( -/obj/structure/table/rack, -/obj/effect/floor_decal/industrial/outline/red, -/obj/machinery/door/window/eastleft{ - dir = 2 - }, -/obj/machinery/light/small/emergency{ - dir = 8 - }, -/obj/machinery/light{ - dir = 8; - icon_state = "tube_empty" - }, -/obj/item/ship_ammunition/francisca/frag{ - pixel_y = 4 - }, -/obj/item/ship_ammunition/francisca/frag{ - pixel_y = 4 - }, -/obj/item/ship_ammunition/francisca/frag{ - pixel_y = 4 - }, -/turf/simulated/floor/reinforced, -/area/ship/ranger_corvette/munitions) -"tQD" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 +/obj/effect/floor_decal/corner/dark_blue{ + dir = 5 }, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, +/obj/structure/extinguisher_cabinet/west{ + dir = 1; + pixel_x = 0; + pixel_y = 28 + }, /obj/structure/cable/green{ icon_state = "4-8" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/bridge) +"tQD" = ( +/obj/structure/closet/walllocker/firecloset{ + pixel_x = -32 + }, +/obj/effect/floor_decal/industrial/outline/firefighting_closet, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) "tQJ" = ( /obj/structure/bed/stool/chair{ dir = 1 @@ -5295,32 +5360,15 @@ }, /turf/simulated/floor/tiled/white, /area/ship/ranger_corvette/medbay) -"tUu" = ( -/obj/structure/table/rack, -/obj/effect/floor_decal/industrial/outline/red, -/obj/machinery/door/window/eastright{ - dir = 2 - }, -/obj/item/ship_ammunition/grauwolf_bundle, -/obj/item/ship_ammunition/grauwolf_bundle, -/obj/item/ship_ammunition/grauwolf_bundle, -/turf/simulated/floor/reinforced, -/area/ship/ranger_corvette/munitions) "tUC" = ( -/obj/effect/floor_decal/industrial/warning{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 9 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 9 - }, -/obj/structure/cable/green{ - icon_state = "4-8" +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/structure/cable/green, +/obj/machinery/power/apc/west{ + req_access = null; + req_one_access = list(221,222) }, /turf/simulated/floor/tiled/dark, -/area/ship/ranger_corvette/gunnery) +/area/ship/ranger_corvette/leader) "tVB" = ( /obj/effect/floor_decal/industrial/warning{ dir = 1 @@ -5355,12 +5403,25 @@ /turf/simulated/floor/plating, /area/ship/ranger_corvette/foyer) "tXz" = ( -/obj/structure/bed/stool/chair, -/obj/machinery/alarm/east{ - req_one_access = list(221,222) +/obj/structure/table/rack, +/obj/effect/floor_decal/industrial/outline/red, +/obj/machinery/door/window/eastleft{ + dir = 2 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/leader) +/obj/machinery/light{ + dir = 1 + }, +/obj/machinery/light/small/emergency{ + dir = 8 + }, +/obj/item/ship_ammunition/autocannon/he, +/obj/item/ship_ammunition/autocannon/he, +/obj/item/ship_ammunition/autocannon/he, +/obj/item/ship_ammunition/autocannon/he, +/obj/item/ship_ammunition/autocannon/he, +/obj/item/ship_ammunition/autocannon/he, +/turf/simulated/floor/reinforced, +/area/ship/ranger_corvette/munitions) "tYR" = ( /obj/structure/railing/mapped{ dir = 8 @@ -5370,42 +5431,9 @@ /turf/simulated/floor/airless, /area/ship/ranger_corvette) "udj" = ( -/obj/structure/closet/secure_closet/guncabinet{ - req_access = null - }, -/obj/effect/floor_decal/industrial/outline/security, -/obj/effect/floor_decal/industrial/warning/corner{ +/obj/machinery/atmospherics/unary/vent_scrubber/on{ dir = 8 }, -/obj/item/gun/projectile/automatic/rifle/shorty, -/obj/item/gun/projectile/automatic/rifle/shorty, -/obj/item/ammo_magazine/c762, -/obj/item/ammo_magazine/c762, -/obj/item/gun/projectile/shotgun/pump, -/obj/item/storage/box/shells/buckshot, -/obj/item/storage/box/shells/flashshells, -/obj/item/storage/box/shells/beanbags, -/obj/item/gun/projectile/automatic/tommygun, -/obj/item/ammo_magazine/submachinemag, -/obj/item/ammo_magazine/submachinemag, -/obj/item/gun/projectile/tanto, -/obj/item/ammo_magazine/mc10mm, -/obj/item/ammo_magazine/mc10mm, -/obj/item/ammo_magazine/mc10mm, -/obj/item/gun/projectile/gauss, -/obj/item/ammo_magazine/gauss, -/obj/machinery/light{ - dir = 8; - icon_state = "tube_empty" - }, -/obj/item/grenade/frag{ - desc = "A military fragmentation grenade, designed to explode in a deadly shower of fragments. This one has the word 'CATCH!!' written on it in white paint." - }, -/obj/machinery/power/apc/high/north, -/obj/structure/cable/green{ - d2 = 2; - icon_state = "0-2" - }, /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/gunnery) "ueq" = ( @@ -5437,17 +5465,19 @@ /turf/simulated/wall/shuttle/space_ship/mercenary, /area/ship/ranger_corvette/bathroom) "ulR" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/aux{ - dir = 4 +/obj/effect/floor_decal/corner/dark_blue{ + dir = 6 }, -/obj/structure/sign/vacuum{ - pixel_y = -32 +/obj/effect/floor_decal/corner/white{ + dir = 8 }, -/obj/structure/cable{ - icon_state = "4-8" +/obj/structure/railing/mapped, +/obj/machinery/computer/ship/helm{ + dir = 1; + req_one_access = list(221,222) }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/bridge) "umS" = ( /obj/structure/bed, /obj/structure/sign/flag/vysoka/large/north{ @@ -5483,16 +5513,15 @@ /turf/simulated/floor/plating, /area/ship/ranger_corvette/bridge) "uoa" = ( -/obj/effect/floor_decal/corner/black{ - dir = 10 - }, /obj/effect/floor_decal/corner/white{ dir = 1 }, -/obj/structure/bed/stool/chair/office/bridge/generic{ - dir = 8 +/obj/effect/floor_decal/corner/white, +/obj/effect/floor_decal/spline/plain/black{ + dir = 1 }, -/turf/simulated/floor/tiled/dark/full, +/obj/effect/overmap/visitable/ship/ranger_corvette, +/turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/bridge) "uon" = ( /obj/structure/lattice/catwalk/indoor/grate/dark, @@ -5533,41 +5562,29 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/brig) "usz" = ( -/obj/machinery/door/airlock/external{ +/obj/effect/floor_decal/industrial/outline/yellow, +/obj/effect/floor_decal/industrial/warning/corner{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/hidden/aux{ - dir = 6 - }, -/obj/effect/map_effect/marker/airlock/docking{ - name = "ranger_shuttle_dock"; - master_tag = "ranger_shuttle_dock"; - landmark_tag = "nav_hangar_ranger"; - req_one_access = null - }, -/obj/machinery/access_button{ - pixel_x = -23; - pixel_y = 22; - frequency = 1394 - }, -/obj/effect/map_effect/marker_helper/airlock/interior, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) +/obj/effect/decal/cleanable/cobweb, +/obj/machinery/vending/sovietsoda, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/engine1) +"usZ" = ( +/obj/structure/lattice/catwalk, +/turf/template_noop, +/area/ship/ranger_corvette/engine1) "uty" = ( -/obj/structure/table/steel, -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/item/screwdriver{ - pixel_y = 9 +/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ + dir = 1 }, -/obj/item/laser_components/modifier/bayonet, -/obj/item/laser_components/modifier/grip{ - pixel_y = 8 +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 }, -/obj/machinery/recharger/wallcharger{ - pixel_x = 4; - pixel_y = 32 +/obj/structure/cable/green{ + d1 = 2; + d2 = 4; + icon_state = "2-4" }, /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/gunnery) @@ -5626,11 +5643,23 @@ /turf/simulated/floor/tiled/white, /area/ship/ranger_corvette/canteen) "uzb" = ( -/obj/machinery/atmospherics/unary/vent_pump/on{ - dir = 8 +/obj/effect/floor_decal/corner/white{ + dir = 1 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/leader) +/obj/effect/floor_decal/corner/white, +/obj/structure/railing/mapped, +/obj/structure/table/steel, +/obj/item/paper_bin, +/obj/item/pen, +/obj/item/folder/blue{ + pixel_x = -16 + }, +/obj/item/folder/yellow{ + pixel_x = -15; + pixel_y = 2 + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/bridge) "uzX" = ( /obj/machinery/atmospherics/unary/vent_scrubber/on{ dir = 8 @@ -5666,6 +5695,7 @@ /area/ship/ranger_corvette/foyer) "uFD" = ( /obj/structure/ship_weapon_dummy, +/obj/structure/lattice/catwalk, /turf/simulated/floor/airless, /area/ship/ranger_corvette/engine1) "uGk" = ( @@ -5718,22 +5748,37 @@ /turf/simulated/floor/tiled/white, /area/ship/ranger_corvette/canteen) "uYQ" = ( -/obj/effect/floor_decal/corner/white{ - dir = 1 - }, -/obj/effect/floor_decal/corner/white, -/obj/structure/railing/mapped, +/obj/structure/lattice/catwalk/indoor/grate/dark, /obj/structure/table/steel, -/obj/item/paper_bin, -/obj/item/pen, -/obj/item/folder/blue{ - pixel_x = -16 +/obj/machinery/button/remote/blast_door{ + id = "coc_fore"; + name = "fore blast door-control"; + pixel_x = -6; + pixel_y = 6; + req_one_access = list(221,222) }, -/obj/item/folder/yellow{ - pixel_x = -15; - pixel_y = 2 +/obj/machinery/button/remote/blast_door{ + id = "coc_midship"; + name = "midship blast door-control"; + pixel_x = -6; + pixel_y = -3; + req_one_access = list(221,222) }, -/turf/simulated/floor/tiled/dark/full, +/obj/machinery/button/remote/blast_door{ + id = "coc_aft"; + name = "aft blast door-control"; + pixel_x = 4; + pixel_y = -3; + req_one_access = list(221,222) + }, +/obj/machinery/button/remote/blast_door{ + id = "coc_bridge"; + name = "bridge blast door-control"; + pixel_x = 4; + pixel_y = 6; + req_one_access = list(221,222) + }, +/turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/bridge) "vdX" = ( /obj/machinery/atmospherics/unary/vent_pump/on{ @@ -5748,14 +5793,11 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/crew) "viF" = ( -/obj/machinery/atmospherics/unary/vent_scrubber/on{ - dir = 4 - }, -/obj/structure/cable/green{ - icon_state = "1-2" - }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/crew) +/obj/structure/lattice/catwalk/indoor/grate/dark, +/obj/structure/table/steel, +/obj/item/clothing/head/helmet/pilot, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/bridge) "vpx" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /turf/simulated/floor/tiled/dark, @@ -5768,16 +5810,12 @@ /turf/simulated/floor/tiled, /area/shuttle/ranger_shuttle) "vtO" = ( -/obj/machinery/door/airlock/highsecurity{ - name = "Ship Munitions Storage"; - dir = 4; - req_one_access = list(221,222) - }, -/obj/machinery/door/firedoor{ +/obj/structure/bed/stool/chair, +/obj/machinery/alarm/east{ req_one_access = list(221,222) }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/munitions) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/leader) "vtU" = ( /obj/machinery/atmospherics/pipe/simple/hidden/aux{ dir = 9 @@ -5792,57 +5830,95 @@ /turf/template_noop, /area/space) "vwc" = ( -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/gunnery) -"vyi" = ( -/obj/structure/bed/stool/chair/office/dark{ +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 6 + dir = 4 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/gunnery) -"vyy" = ( -/obj/structure/table/steel, -/obj/structure/window/reinforced{ - name = "adjusted reinforced window" +/obj/structure/cable/green{ + icon_state = "4-8" }, -/obj/machinery/door/window/northleft{ - dir = 4 +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/foyer) +"vyi" = ( +/obj/effect/floor_decal/corner/red/diagonal, +/obj/structure/sign/flag/gadpathur{ + pixel_y = 33; + pixel_x = -10 }, -/obj/machinery/atmospherics/unary/vent_scrubber/on{ - dir = 8 +/obj/structure/closet/crate/bin{ + name = "trashbin" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/gunnery) -"vyC" = ( -/obj/effect/floor_decal/industrial/loading/yellow{ - dir = 8 +/obj/machinery/light{ + dir = 4; + icon_state = "tube_empty" }, -/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ - dir = 1 +/obj/structure/sign/flag/burzsia{ + pixel_x = 33 + }, +/obj/item/clothing/head/dominia/fleet/officer{ + pixel_y = 32; + pixel_x = 5 + }, +/obj/item/material/knife/bayonet{ + pixel_y = 29; + pixel_x = -1 + }, +/turf/simulated/floor/tiled/white, +/area/ship/ranger_corvette/canteen) +"vyy" = ( +/obj/effect/floor_decal/industrial/outline/yellow, +/obj/structure/closet/crate, +/obj/item/stack/material/plasteel/full, +/obj/item/stack/material/steel/full, +/obj/item/stack/material/steel/full, +/obj/item/stack/material/glass/reinforced/full, +/obj/item/stack/material/glass/full, +/obj/item/grenade/chem_grenade/metalfoam, +/obj/item/grenade/chem_grenade/metalfoam, +/obj/item/grenade/chem_grenade/metalfoam, +/obj/item/grenade/chem_grenade/metalfoam, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/engine1) +"vyC" = ( +/obj/machinery/door/airlock/command{ + dir = 4; + name = "Ranger Leader Quarters"; + req_one_access = list(221,222) }, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 + }, +/obj/machinery/door/firedoor{ + dir = 4; + req_one_access = list(221,222) + }, /obj/structure/cable/green{ - d1 = 2; - d2 = 4; - icon_state = "2-4" + icon_state = "4-8" }, /turf/simulated/floor/tiled/dark, -/area/ship/ranger_corvette/gunnery) +/area/ship/ranger_corvette/leader) "vzk" = ( /obj/effect/floor_decal/industrial/warning{ - dir = 8 + dir = 1 }, +/obj/structure/sign/securearea{ + desc = "A warning sign which reads 'WARNING: BLAST DOOR'."; + name = "\improper WARNING: BLAST DOOR sign"; + pixel_x = 32 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/structure/cable/green{ icon_state = "1-2" }, -/obj/machinery/atmospherics/unary/vent_pump/on, /turf/simulated/floor/tiled/dark, -/area/ship/ranger_corvette/gunnery) +/area/ship/ranger_corvette/foyer) "vzU" = ( /obj/machinery/light{ dir = 4; @@ -5854,71 +5930,51 @@ /turf/simulated/wall/shuttle/space_ship/mercenary, /area/ship/ranger_corvette/atmospherics) "vKn" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 - }, -/obj/machinery/door/firedoor{ - dir = 4; - req_one_access = list(221,222) +/obj/effect/floor_decal/industrial/warning{ + dir = 1 }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/structure/cable/green{ - icon_state = "4-8" - }, -/obj/machinery/door/airlock/highsecurity{ - name = "Armory"; - dir = 4; - req_one_access = list(221,222) + icon_state = "1-2" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/gunnery) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/foyer) "vLy" = ( /obj/effect/floor_decal/corner/dark_blue{ - dir = 6 - }, -/obj/effect/floor_decal/corner/white{ - dir = 1 - }, -/obj/effect/floor_decal/spline/plain/black{ - dir = 1 + dir = 5 }, -/obj/structure/closet/crate/bin{ - name = "trashbin" +/obj/structure/sign/flag/coalition{ + pixel_y = 32 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) -"vOd" = ( -/obj/effect/floor_decal/industrial/warning, -/obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 - }, /obj/structure/cable/green{ icon_state = "4-8" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) -"vPn" = ( -/obj/effect/floor_decal/industrial/warning, -/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ - dir = 4 +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/bridge) +"vOd" = ( +/obj/effect/floor_decal/industrial/outline/yellow, +/obj/structure/railing/mapped{ + dir = 1 }, -/obj/structure/cable/green{ - icon_state = "1-2" +/obj/machinery/portable_atmospherics/canister/carbon_dioxide, +/obj/machinery/light{ + dir = 8; + icon_state = "tube_empty" }, -/obj/structure/cable/green{ - icon_state = "1-8" +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/engine1) +"vPn" = ( +/obj/effect/floor_decal/industrial/outline/yellow, +/obj/structure/railing/mapped{ + dir = 1 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) +/obj/machinery/portable_atmospherics/canister/carbon_dioxide, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/engine1) "vUr" = ( /obj/effect/floor_decal/industrial/warning, /obj/machinery/button/remote/blast_door{ @@ -5964,36 +6020,11 @@ /turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/foyer) "vZn" = ( -/obj/machinery/door/airlock/hatch{ - name = "Cryogenics"; - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 - }, -/obj/machinery/door/firedoor{ - req_one_access = list(221,222) - }, -/obj/structure/cable/green{ - icon_state = "4-8" - }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/cryo) -"vZZ" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 - }, /obj/structure/cable/green{ - icon_state = "4-8" + icon_state = "1-4" }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/foyer) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/crew) "waI" = ( /obj/effect/floor_decal/corner/red/diagonal, /obj/structure/table/steel, @@ -6026,11 +6057,67 @@ /turf/simulated/floor/tiled/white, /area/ship/ranger_corvette/bathroom) "wlo" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 10 +/obj/structure/closet/secure_closet/kitchen_cabinet/standard, +/obj/item/reagent_containers/food/snacks/meat, +/obj/item/reagent_containers/food/snacks/meat, +/obj/item/reagent_containers/food/snacks/meat, +/obj/item/reagent_containers/food/snacks/meat, +/obj/item/reagent_containers/food/snacks/meat, +/obj/item/reagent_containers/food/snacks/meat, +/obj/item/reagent_containers/food/snacks/meat, +/obj/item/reagent_containers/food/snacks/meat, +/obj/item/storage/box/large/produce{ + pixel_x = 3; + pixel_y = -11 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/crew) +/obj/item/storage/box/fancy/egg_box, +/obj/item/storage/box/fancy/egg_box, +/obj/item/reagent_containers/food/drinks/carton/milk, +/obj/item/reagent_containers/food/drinks/carton/milk, +/obj/item/reagent_containers/food/condiment/enzyme{ + pixel_x = -9; + pixel_y = 5 + }, +/obj/item/reagent_containers/food/condiment/enzyme{ + pixel_x = -9; + pixel_y = 5 + }, +/obj/item/reagent_containers/food/condiment/enzyme{ + pixel_x = -9; + pixel_y = 5 + }, +/obj/item/reagent_containers/food/condiment/enzyme{ + pixel_x = -9; + pixel_y = 5 + }, +/obj/item/reagent_containers/food/condiment/enzyme{ + pixel_x = -9; + pixel_y = 5 + }, +/obj/effect/decal/cleanable/cobweb2, +/obj/effect/floor_decal/corner/brown/diagonal, +/obj/machinery/light{ + dir = 4; + icon_state = "tube_empty" + }, +/obj/item/storage/box/large/produce{ + pixel_x = 3; + pixel_y = -11 + }, +/obj/item/storage/box/large/produce{ + pixel_x = 3; + pixel_y = -11 + }, +/obj/item/storage/box/large/produce{ + pixel_x = 3; + pixel_y = -11 + }, +/obj/item/storage/box/large/produce{ + pixel_x = 3; + pixel_y = -11 + }, +/turf/simulated/floor/tiled/white, +/area/ship/ranger_corvette/canteen) "wlw" = ( /obj/machinery/atmospherics/pipe/simple/hidden/aux, /turf/simulated/wall/shuttle/space_ship/mercenary, @@ -6063,13 +6150,19 @@ /turf/simulated/floor/airless, /area/ship/ranger_corvette) "wmN" = ( -/obj/structure/lattice/catwalk/indoor/grate/dark, -/obj/machinery/computer/ship/targeting{ - dir = 1; - req_one_access = list(221,222) +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 9 }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/bridge) +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 9 + }, +/obj/structure/cable/green{ + icon_state = "4-8" + }, +/obj/structure/table/rack/folding_table, +/obj/machinery/recharger, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) "wpk" = ( /obj/machinery/atmospherics/unary/vent_scrubber/on{ dir = 4 @@ -6165,21 +6258,16 @@ /turf/simulated/floor/tiled/white, /area/ship/ranger_corvette/bathroom) "wzK" = ( -/obj/effect/floor_decal/industrial/warning{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/manifold4w/hidden/supply, -/obj/structure/cable/green{ - icon_state = "4-8" +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/light{ + dir = 8; + icon_state = "tube_empty" }, /obj/structure/cable/green{ - icon_state = "1-4" + icon_state = "1-2" }, /turf/simulated/floor/tiled/dark, -/area/ship/ranger_corvette/gunnery) +/area/ship/ranger_corvette/leader) "wBq" = ( /obj/machinery/washing_machine{ pixel_x = -8 @@ -6227,17 +6315,17 @@ /turf/simulated/wall/shuttle/space_ship/mercenary, /area/shuttle/ranger_shuttle) "wNT" = ( -/obj/machinery/door/airlock/external, -/obj/effect/map_effect/marker_helper/airlock/interior, -/obj/machinery/access_button{ - pixel_x = 24; - pixel_y = -32; - dir = 8; - frequency = 2137 +/obj/machinery/atmospherics/pipe/simple/hidden/aux{ + dir = 4 }, -/obj/effect/map_effect/marker/airlock/docking/ranger_corvette/aft, -/turf/simulated/floor/plating, -/area/ship/ranger_corvette/atmospherics) +/obj/structure/sign/vacuum{ + pixel_y = -32 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/foyer) "wPe" = ( /obj/structure/bed/stool/bar/padded/brown, /obj/structure/noticeboard{ @@ -6296,32 +6384,18 @@ /area/ship/ranger_corvette/telecomms) "wZf" = ( /obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 - }, -/obj/machinery/alarm/south{ - req_one_access = list(221,222) - }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/structure/cable/green{ - icon_state = "4-8" + icon_state = "1-2" }, /turf/simulated/floor/tiled/dark, -/area/ship/ranger_corvette/gunnery) +/area/ship/ranger_corvette/foyer) "xdG" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 10 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/structure/cable/green{ - icon_state = "2-8" - }, -/turf/simulated/floor/tiled/dark/full, -/area/ship/ranger_corvette/leader) +/obj/effect/floor_decal/industrial/outline/yellow, +/obj/machinery/suit_cycler/offship/coc, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/voidsuits) "xfP" = ( /obj/machinery/atmospherics/unary/engine, /obj/effect/landmark/entry_point/aft{ @@ -6371,44 +6445,24 @@ /turf/simulated/floor/plating, /area/ship/ranger_corvette/atmospherics) "xtN" = ( -/obj/structure/table/rack, -/obj/effect/floor_decal/industrial/outline/red, -/obj/machinery/door/window/eastleft{ - dir = 1 - }, -/obj/machinery/light/small/emergency{ - dir = 8 - }, -/obj/machinery/light{ - dir = 8; - icon_state = "tube_empty" - }, -/obj/item/ship_ammunition/francisca/ap{ - pixel_y = 8 - }, -/obj/item/ship_ammunition/francisca/ap{ - pixel_y = 8 +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 }, -/obj/item/ship_ammunition/francisca/ap{ - pixel_y = 8 +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 }, -/obj/item/ship_ammunition/francisca/ap{ - pixel_y = 8 +/obj/machinery/door/firedoor{ + req_one_access = list(221,222) }, -/obj/item/ship_ammunition/francisca/ap{ - pixel_y = 8 +/obj/machinery/door/airlock/engineering{ + dir = 4; + req_one_access = list(221,222) }, -/obj/item/ship_ammunition/francisca/ap{ - pixel_y = 8 +/obj/structure/cable/green{ + icon_state = "4-8" }, -/obj/item/ship_ammunition/francisca, -/obj/item/ship_ammunition/francisca, -/obj/item/ship_ammunition/francisca, -/obj/item/ship_ammunition/francisca, -/obj/item/ship_ammunition/francisca, -/obj/item/ship_ammunition/francisca, -/turf/simulated/floor/reinforced, -/area/ship/ranger_corvette/munitions) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/engine2) "xuX" = ( /obj/machinery/atmospherics/portables_connector{ dir = 8 @@ -6417,7 +6471,7 @@ /turf/simulated/floor/plating, /area/ship/ranger_corvette/engine2) "xzg" = ( -/turf/simulated/floor/tiled/dark/full, +/turf/simulated/floor/tiled/dark, /area/ship/ranger_corvette/voidsuits) "xzl" = ( /obj/machinery/light{ @@ -6581,16 +6635,11 @@ /turf/simulated/wall/shuttle/space_ship/mercenary, /area/ship/ranger_corvette/foyer) "yfU" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/light{ - dir = 8; - icon_state = "tube_empty" - }, -/obj/structure/closet/secure_closet/cabinet/bar{ - req_access = null +/obj/machinery/atmospherics/unary/vent_pump/on{ + dir = 8 }, -/turf/simulated/floor/wood, -/area/ship/ranger_corvette/foyer) +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/leader) "yks" = ( /obj/effect/floor_decal/corner/green/diagonal, /obj/machinery/bodyscanner{ @@ -23827,155 +23876,155 @@ xRX xRX xRX xRX -"} -(68,1,1) = {" -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -vuD -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX +"} +(68,1,1) = {" +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX xRX xRX xRX @@ -24733,7 +24782,7 @@ xRX xRX xRX xRX -vuD +xRX xRX xRX xRX @@ -26498,7 +26547,7 @@ xRX xRX xRX xRX -xRX +vuD xRX xRX xRX @@ -27312,7 +27361,7 @@ xRX xRX xRX xRX -xRX +vuD xRX xRX xRX @@ -27483,7 +27532,7 @@ xRX xRX xRX xRX -vuD +xRX xRX xRX xRX @@ -29317,7 +29366,7 @@ xRX xRX xRX xRX -gNW +xRX xRX xRX xRX @@ -30062,7 +30111,7 @@ xRX xRX xRX xRX -xRX +vuD xRX xRX xRX @@ -31896,7 +31945,7 @@ xRX xRX xRX xRX -xRX +gNW xRX xRX xRX @@ -32605,7 +32654,7 @@ xRX xRX xRX xRX -vuD +xRX xRX xRX xRX @@ -34684,19 +34733,19 @@ xRX xRX xRX xRX -qMt xRX xRX -qMt xRX xRX -qMt xRX xRX -qMt xRX xRX -qMt +xRX +xRX +xRX +xRX +xRX xRX xRX xRX @@ -34965,11 +35014,11 @@ xRX xRX xRX xRX -uFD -uFD -uFD -uFD -jYf +xRX +xRX +xRX +xRX +xRX xRX xRX xRX @@ -35184,6 +35233,15 @@ xRX xRX xRX xRX +vuD +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX xRX xRX xRX @@ -35212,7 +35270,6 @@ xRX xRX xRX xRX -feu xRX xRX xRX @@ -35222,18 +35279,10 @@ xRX xRX xRX xRX -pia -uFD xRX xRX xRX xRX -rrQ -rrQ -okk -rrQ -rrQ -rrQ xRX xRX xRX @@ -35470,35 +35519,9 @@ xRX xRX xRX xRX -tWh -tWh -tWh -tWh -tWh -tWh -tWh -dYC -tWh -boM -tWh -tWh xRX xRX xRX -rrQ -swi -uVR -itk -rVo -rrQ -tLA -tLA -pFK -tLA -nIu -nIu -lhJ -lhJ xRX xRX xRX @@ -35649,8 +35672,6 @@ xRX xRX xRX xRX -"} -(114,1,1) = {" xRX xRX xRX @@ -35677,6 +35698,24 @@ xRX xRX xRX xRX +"} +(114,1,1) = {" +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX xRX xRX xRX @@ -35727,35 +35766,9 @@ xRX xRX xRX xRX -kfF -dul -fVq -ayD -bEt -tWh -fkX -dLB -kFU -iOe -nGj -tWh xRX xRX xRX -rrQ -tOx -vdX -wpk -xtN -rrQ -pSI -qtL -btv -han -deS -hPo -sXv -lhJ xRX xRX xRX @@ -35906,8 +35919,6 @@ xRX xRX xRX xRX -"} -(115,1,1) = {" xRX xRX xRX @@ -35944,6 +35955,8 @@ xRX xRX xRX xRX +"} +(115,1,1) = {" xRX xRX xRX @@ -35983,36 +35996,9 @@ xRX xRX xRX xRX -feu -kfF -bbM -jHg -aEq -bIQ -eiR -frC -iOe -kJM -iPn -nTM -tWh xRX xRX xRX -rrQ -tUu -xVJ -wtd -rVo -rrQ -mZT -mhA -hbk -deS -deS -hPo -lhJ -lhJ xRX xRX xRX @@ -36163,8 +36149,6 @@ xRX xRX xRX xRX -"} -(116,1,1) = {" xRX xRX xRX @@ -36228,6 +36212,8 @@ xRX xRX xRX xRX +"} +(116,1,1) = {" xRX xRX xRX @@ -36241,33 +36227,9 @@ xRX xRX xRX xRX -bOF -bbM -asD -mQz -cnJ -tWh -fJC -iPn -kLL -maA -oey -tWh xRX xRX xRX -rrQ -rrQ -vtO -feE -rrQ -rrQ -rgL -aMB -jrY -enD -lfi -rKi xRX xRX xRX @@ -36420,8 +36382,6 @@ xRX xRX xRX xRX -"} -(117,1,1) = {" xRX xRX xRX @@ -36498,33 +36458,9 @@ xRX xRX xRX xRX -kfF -ayf -ajL -aYD -coK -tWh -gep -iVL -kYl -mcD -oAK -tWh xRX xRX xRX -tLA -udj -vzk -wzK -xZA -mnX -cfi -jmW -qyq -dcS -cmI -tLA xRX xRX xRX @@ -36533,6 +36469,8 @@ xRX xRX xRX xRX +"} +(117,1,1) = {" xRX xRX xRX @@ -36677,8 +36615,6 @@ xRX xRX xRX xRX -"} -(118,1,1) = {" xRX xRX xRX @@ -36754,42 +36690,6 @@ xRX xRX xRX xRX -feu -tWh -tWh -tWh -tWh -tWh -tWh -tWh -tWh -tWh -hqB -tWh -tWh -rBK -wlN -rBK -tLA -smG -vwc -wZf -tLA -tLA -tLA -tLA -tLA -tLA -tLA -mAx -mAx -bNr -mAx -mAx -mAx -mAx -mAx -mAx xRX xRX xRX @@ -36826,6 +36726,8 @@ xRX xRX xRX xRX +"} +(118,1,1) = {" xRX xRX xRX @@ -36934,8 +36836,6 @@ xRX xRX xRX xRX -"} -(119,1,1) = {" xRX xRX xRX @@ -37011,50 +36911,6 @@ xRX xRX xRX xRX -vFS -vFS -vFS -vFS -vFS -vFS -exg -stX -pDY -vFS -gOp -jmN -rBK -jwy -lNh -rzM -tLA -sMm -vyi -cxr -tLA -yfU -lKs -fmF -wsA -bhp -nFy -mAx -umS -aqe -eRR -gwg -tqM -ttk -sSQ -hdp -hdp -hdp -hdp -brx -hdp -hdp -hdp -tYR xRX xRX xRX @@ -37127,6 +36983,8 @@ xRX xRX xRX xRX +"} +(119,1,1) = {" xRX xRX xRX @@ -37191,8 +37049,6 @@ xRX xRX xRX xRX -"} -(120,1,1) = {" xRX xRX xRX @@ -37222,6 +37078,11 @@ xRX xRX xRX xRX +tWh +tWh +tWh +tWh +xRX xRX xRX xRX @@ -37244,7 +37105,6 @@ xRX xRX xRX xRX -tJG xRX xRX xRX @@ -37268,56 +37128,6 @@ xRX xRX xRX xRX -cZR -dFf -lkY -cJN -thB -thB -eCy -vVQ -qGl -vFS -gXD -jsa -rBK -wYR -pVf -rQB -tLA -uty -vyy -fmY -tLA -wPe -rli -tQJ -bCt -bhp -gUN -mAx -eJp -bjx -viF -siv -fro -doJ -oAP -hdp -gzc -avV -dun -gin -rki -fnq -dNG -dNG -dNG -mDK -dNG -dNG -eGi -eGi xRX xRX xRX @@ -37430,6 +37240,16 @@ xRX xRX xRX xRX +"} +(120,1,1) = {" +xRX +xRX +xRX +xRX +xRX +xRX +xRX +xRX xRX xRX xRX @@ -37448,8 +37268,6 @@ xRX xRX xRX xRX -"} -(121,1,1) = {" xRX xRX xRX @@ -37494,7 +37312,19 @@ xRX xRX xRX xRX +qMt +xRX +xRX +qMt +xRX +xRX +qMt +xRX xRX +qMt +xRX +xRX +qMt xRX xRX xRX @@ -37505,6 +37335,14 @@ xRX xRX xRX xRX +tWh +pZW +gSr +gSr +usZ +qHO +xRX +xRX xRX xRX xRX @@ -37525,63 +37363,6 @@ xRX xRX xRX xRX -kpi -oyB -wHL -wNT -dIx -dIx -mcN -dmm -jsq -vFS -mzO -jsa -rBK -sCu -uwG -rQB -tLA -ayi -qHO -tUC -tLA -sMg -ebD -ckj -ian -bhp -itg -gUj -vfX -cij -wlo -smZ -kji -tGV -dgw -hdp -qXP -vpx -lyg -gin -oUG -nRI -dNG -uvJ -xzq -dMX -oTC -dNG -rwS -eGi -eGi -tas -tas -unz -uAk -tas -tas xRX xRX xRX @@ -37705,12 +37486,6 @@ xRX xRX xRX xRX -"} -(122,1,1) = {" -xRX -xRX -xRX -xRX xRX xRX xRX @@ -37722,6 +37497,8 @@ xRX xRX xRX xRX +"} +(121,1,1) = {" xRX xRX xRX @@ -37782,64 +37559,6 @@ xRX xRX xRX xRX -vFS -vFS -vFS -vFS -vFS -vFS -riA -aXC -wDN -vFS -gXD -vZZ -rBK -pXU -mun -sfw -tLA -ioB -vyC -iXs -tLA -eQS -cZV -bVs -niD -cZV -gEg -mAx -vVv -hjK -jih -jVf -mMP -ieN -stJ -hdp -cjg -ust -tlC -xKE -plP -hAt -dNG -qQd -dUu -dBx -tBK -eGi -ndT -gWX -aRc -tas -jyf -qCZ -lGr -mHw -tas -tas xRX xRX xRX @@ -37873,6 +37592,12 @@ xRX xRX xRX xRX +tWh +uFD +uFD +uFD +uFD +pmD xRX xRX xRX @@ -37962,8 +37687,6 @@ xRX xRX xRX xRX -"} -(123,1,1) = {" xRX xRX xRX @@ -38031,6 +37754,8 @@ xRX xRX xRX xRX +"} +(122,1,1) = {" xRX xRX xRX @@ -38039,64 +37764,6 @@ xRX xRX xRX xRX -feu -oIF -eZx -mlG -ojz -vFS -mLK -xsE -jwX -vFS -gXD -jsa -rBK -qhi -qkP -slH -tLA -cos -vKn -tLA -tLA -gqU -jgn -riF -jgn -jgn -yfz -mAx -mAx -mAx -mAx -mAx -hZi -mAx -mAx -hdp -hdp -hdp -eue -hdp -hdp -hdp -dNG -dNG -dNG -vZn -dNG -dNG -bnz -eGi -eGi -tas -mVV -iTN -eSB -uoa -wmN -kyh xRX xRX xRX @@ -38127,7 +37794,6 @@ xRX xRX xRX xRX -vuD xRX xRX xRX @@ -38174,6 +37840,7 @@ xRX xRX xRX xRX +feu xRX xRX xRX @@ -38182,7 +37849,19 @@ xRX xRX xRX xRX +tWh +jYf +jYf +gSr +usZ +aXi xRX +rrQ +rrQ +okk +rrQ +rrQ +rrQ xRX xRX xRX @@ -38219,8 +37898,6 @@ xRX xRX xRX xRX -"} -(124,1,1) = {" xRX xRX xRX @@ -38297,63 +37974,6 @@ xRX xRX xRX xRX -oIF -hXP -qBd -eQz -vFS -vFS -htX -vFS -vFS -aKd -jsa -rBK -rBK -qrd -rBK -yfz -fPZ -vOd -qbp -sYH -oKe -aYE -bnu -aYE -aYE -eLC -mvd -aMl -wri -tEO -tEO -tQD -wjI -oTa -nkQ -tEO -jCi -vZZ -tEO -tEO -oSw -hSp -cpO -ghM -vZZ -tEO -wMK -tQD -bGA -kkN -tas -jjc -qcP -teP -mgl -abx -kyh xRX xRX xRX @@ -38391,6 +38011,8 @@ xRX xRX xRX xRX +"} +(123,1,1) = {" xRX xRX xRX @@ -38476,11 +38098,35 @@ xRX xRX xRX xRX -"} -(125,1,1) = {" +tWh +tWh +tWh +tWh +tWh +tWh +tWh +dYC +tWh +boM +tWh +tWh xRX xRX xRX +rrQ +cxr +uVR +itk +rVd +rrQ +tLA +tLA +pFK +tLA +nIu +nIu +lhJ +lhJ xRX xRX xRX @@ -38554,63 +38200,6 @@ xRX xRX xRX xRX -oIF -oXh -xFA -awG -wPn -fqT -spv -dGE -lsl -slN -oZS -pHQ -tnO -quw -sqh -thI -uon -vPn -xnk -eSo -iWc -xWp -rMA -tAd -fkm -ezi -eov -wpP -rVd -jJP -tAd -oTH -ezi -tAd -tAd -ppM -gtw -gkq -tAd -aWb -tXd -iHC -nCd -ezi -ezP -rpP -tAd -lGB -uCz -tAd -bsV -gLb -ckP -tFs -iQH -aqk -sJP xRX xRX xRX @@ -38679,6 +38268,8 @@ xRX xRX xRX xRX +"} +(124,1,1) = {" xRX xRX xRX @@ -38733,8 +38324,6 @@ xRX xRX xRX xRX -"} -(126,1,1) = {" xRX xRX xRX @@ -38766,9 +38355,35 @@ xRX xRX xRX xRX +kfF +dul +fVq +ayD +bEt +tWh +usz +dLB +vOd +iOe +kJM +tWh xRX xRX xRX +rrQ +tXz +vdX +wpk +lut +rrQ +pSI +tQD +btv +han +deS +hPo +sXv +lhJ xRX xRX xRX @@ -38810,64 +38425,6 @@ xRX xRX xRX xRX -feu -oNK -hmD -dfi -uzX -hdZ -mzY -vzU -tEO -maj -tEO -vZZ -vzU -tEO -vZZ -oTa -tlv -bkP -vUr -qbp -tVB -mdX -sLq -fwA -fwA -aiD -mFt -mFt -fwA -fwA -tEO -vXi -pBE -bxY -eCV -xJk -xJk -pHP -xJk -xJk -xJk -xJk -jCF -jCF -jCF -eFH -jCF -jCF -jCF -jCF -jCF -tas -lCo -uYQ -ntW -mgl -jPm -kyh xRX xRX xRX @@ -38968,6 +38525,8 @@ xRX xRX xRX xRX +"} +(125,1,1) = {" xRX xRX xRX @@ -38990,8 +38549,6 @@ xRX xRX xRX xRX -"} -(127,1,1) = {" xRX xRX xRX @@ -39054,6 +38611,41 @@ xRX xRX xRX xRX +feu +kfF +bbM +jHg +aEq +bIQ +eiR +frC +iOe +vPn +iPn +eSo +tWh +xRX +xRX +xRX +rrQ +lGr +xVJ +wtd +rVd +rrQ +mZT +mhA +hbk +deS +deS +hPo +lhJ +lhJ +xRX +xRX +xRX +xRX +xRX xRX xRX xRX @@ -39068,63 +38660,6 @@ xRX xRX xRX xRX -oIF -mhD -sTc -gpc -uOy -uOy -uOy -uOy -uOy -tEO -wlA -wUT -wUT -qRJ -wUT -wUT -wUT -wUT -wUT -wUT -lgK -jRF -fwA -tmL -iwS -lym -lym -fJE -fwA -fwA -fwA -mbp -fwA -fwA -xJk -kiF -wrD -yks -xJk -wVa -fxx -jCF -bSt -gnW -xdG -bzo -moB -bYx -sEf -gor -tas -qqG -kTh -rfo -jpQ -lut -kyh xRX xRX xRX @@ -39248,7 +38783,7 @@ xRX xRX xRX "} -(128,1,1) = {" +(126,1,1) = {" xRX xRX xRX @@ -39325,63 +38860,6 @@ xRX xRX xRX xRX -oIF -gkw -uhA -qSB -uOy -kku -hvo -eFo -uOy -tEO -wlA -wUT -wBq -qUy -sIh -lNa -tsn -wkO -xzl -wUT -aho -ulR -fwA -paq -qza -lIp -mWY -lym -maw -ghp -qCp -trH -drF -wSM -xJk -lso -fDx -mBK -xJk -scg -vUw -jCF -fFV -gnW -uzb -fHL -lWH -nDb -epG -gjg -tas -dgH -aZS -vLy -pBA -tas -tas xRX xRX xRX @@ -39391,9 +38869,33 @@ xRX xRX xRX xRX +bOF +bbM +asD +mQz +cnJ +tWh +jyf +iPn +aKd +maA +vyy +tWh xRX xRX xRX +rrQ +rrQ +jyA +kTh +rrQ +rrQ +rgL +aMB +jrY +enD +lfi +rKi xRX xRX xRX @@ -39504,8 +39006,6 @@ xRX xRX xRX xRX -"} -(129,1,1) = {" xRX xRX xRX @@ -39539,6 +39039,8 @@ xRX xRX xRX xRX +"} +(127,1,1) = {" xRX xRX xRX @@ -39581,63 +39083,6 @@ xRX xRX xRX xRX -feu -oIF -oIF -oIF -oIF -uOy -bHV -xzg -mkT -uOy -tEO -kaR -wUT -qjk -rro -sJD -sJD -sJD -lpY -sJD -wUT -usz -pmD -fwA -crw -ilB -mmT -lym -lym -cIm -qHn -ori -hwT -qHn -uyn -xJk -tUl -fwP -qtV -xJk -dHT -pPX -jCF -iFw -esZ -iGg -tXz -aoI -qSw -jCF -jCF -tas -tas -muQ -uAk -tas -tas xRX xRX xRX @@ -39681,10 +39126,33 @@ xRX xRX xRX xRX +kfF +ayf +ajL +aYD +coK +tWh +gep +iVL +kYl +mcD +kji +tWh xRX xRX xRX xRX +feE +rMA +roN +xZA +mnX +cfi +jmW +qyq +dcS +cmI +tLA xRX xRX xRX @@ -39761,8 +39229,6 @@ xRX xRX xRX xRX -"} -(130,1,1) = {" xRX xRX xRX @@ -39830,6 +39296,8 @@ xRX xRX xRX xRX +"} +(128,1,1) = {" xRX xRX xRX @@ -39843,51 +39311,6 @@ xRX xRX xRX xRX -uOy -bHV -xzg -gMK -oEN -tAd -roN -wUT -gec -rsO -goI -wUT -uwT -wUT -uwT -wUT -bom -agA -fwA -ioq -waI -mmT -lym -uWT -tEs -thd -puV -aDL -qHn -jBp -xJk -eEL -iee -qZS -nnM -xBz -tHU -jCF -jCF -jCF -hUx -jCF -jCF -jCF -jCF xRX xRX xRX @@ -39959,6 +39382,42 @@ xRX xRX xRX xRX +feu +tWh +tWh +tWh +tWh +tWh +tWh +tWh +tWh +tWh +cij +tWh +tWh +rBK +wlN +rBK +xRX +xRX +mhA +slN +tLA +tLA +tLA +tLA +tLA +tLA +tLA +mAx +mAx +bNr +mAx +mAx +mAx +mAx +mAx +mAx xRX xRX xRX @@ -40018,8 +39477,6 @@ xRX xRX xRX xRX -"} -(131,1,1) = {" xRX xRX xRX @@ -40081,65 +39538,23 @@ xRX xRX xRX xRX -qMt xRX xRX -qMt xRX xRX -qMt xRX xRX -qMt xRX xRX -qMt xRX xRX xRX xRX xRX xRX -sTf -bHV -xzg -jyA -uOy -tEO -wlA -wUT -ntn -ruB -sMD -wUT -uyk -wUT -wve -wUT -sCd -grA -fwA -fmB -lXU -nmy -lym -lYK -dhX -cdr -ufB -bXG -qHn -oOX -xJk -xJk -xJk -xJk -euV -xJk -xJk -jCF -wmz xRX +"} +(129,1,1) = {" xRX xRX xRX @@ -40224,8 +39639,50 @@ xRX xRX xRX xRX +vFS +vFS +vFS +vFS +vFS +vFS +exg +stX +pDY +vFS +gOp +jmN +rBK +jwy +lNh +rzM xRX xRX +siv +eSB +tLA +smZ +lKs +fmF +wsA +bhp +nFy +mAx +umS +aqe +eRR +gwg +tqM +ttk +sSQ +hdp +hdp +hdp +hdp +brx +hdp +hdp +hdp +tYR xRX xRX xRX @@ -40275,8 +39732,6 @@ xRX xRX xRX xRX -"} -(132,1,1) = {" xRX xRX xRX @@ -40353,43 +39808,10 @@ xRX xRX xRX xRX -gJZ -gJZ -gJZ -gJZ -uOy -bHV -hFA -jyH -uOy -vzU -wlA -wUT -wUT -uiz -wUT -jcc -wUT -uiz -jcc -wUT -imn -aRl -jXh -fvO -xnY -xnY -lgJ -fwA -xrl -fwA -fwA -fwA -fwA -fwA -fwA xRX xRX +"} +(130,1,1) = {" xRX xRX xRX @@ -40450,6 +39872,7 @@ xRX xRX xRX xRX +tJG xRX xRX xRX @@ -40473,8 +39896,56 @@ xRX xRX xRX xRX +oEN +dFf +lkY +qCZ +thB +thB +eCy +vVQ +qGl +vFS +gXD +jsa +rBK +wYR +pVf +rQB xRX xRX +udj +rli +tLA +wPe +ntW +tQJ +bCt +bhp +gUN +mAx +eJp +bjx +nTM +mgl +vZn +sqh +oAP +hdp +gzc +avV +dun +gin +rki +fnq +dNG +dNG +dNG +mDK +dNG +dNG +eGi +eGi xRX xRX xRX @@ -40532,8 +40003,6 @@ xRX xRX xRX xRX -"} -(133,1,1) = {" xRX xRX xRX @@ -40598,6 +40067,8 @@ xRX xRX xRX xRX +"} +(131,1,1) = {" xRX xRX xRX @@ -40610,18 +40081,6 @@ xRX xRX xRX xRX -ueq -niC -rRu -oXn -gJZ -gJZ -gJZ -uOy -gJZ -gJZ -hmX -gJZ xRX xRX xRX @@ -40629,10 +40088,6 @@ xRX xRX xRX xRX -yau -wrJ -uGk -yau xRX xRX xRX @@ -40698,6 +40153,63 @@ xRX xRX xRX xRX +gEg +oyB +wHL +lWH +dIx +dIx +mcN +dmm +jsq +vFS +abx +jsa +rBK +sCu +uwG +rQB +tLA +fkX +mdX +wmN +tLA +sMg +ebD +ckj +ian +bhp +itg +gUj +vfX +oAP +bHV +kLL +eov +tGV +dgw +hdp +qXP +vpx +lyg +gin +oUG +nRI +dNG +uvJ +xzq +dMX +oTC +dNG +rwS +eGi +eGi +tas +tas +unz +uAk +tas +tas xRX xRX xRX @@ -40789,8 +40301,6 @@ xRX xRX xRX xRX -"} -(134,1,1) = {" xRX xRX xRX @@ -40814,6 +40324,8 @@ xRX xRX xRX xRX +"} +(132,1,1) = {" xRX xRX xRX @@ -40867,35 +40379,9 @@ xRX xRX xRX xRX -xfP -byX -scs -diy -gJZ -gJZ -ibp -jMZ -jMZ -mNJ -ptP -gJZ xRX -feu xRX -kYm -yau -yau -yau -yau -xFa -bgA -wlw -wlw -wlw -wlw -gLv xRX -feu xRX xRX xRX @@ -40924,6 +40410,64 @@ xRX xRX xRX xRX +vFS +vFS +vFS +vFS +vFS +vFS +riA +aXC +wDN +vFS +gXD +jsa +rBK +pXU +mun +sfw +tLA +fJC +uty +iXs +tLA +eQS +cZV +bVs +niD +cZV +sMm +mAx +vVv +hjK +jih +jVf +mMP +ieN +stJ +hdp +cjg +ust +tlC +xKE +plP +hAt +dNG +qQd +dUu +dBx +tBK +eGi +ndT +gWX +aRc +tas +aRl +ioB +swi +oey +tas +tas xRX xRX xRX @@ -41037,6 +40581,8 @@ xRX xRX xRX xRX +"} +(133,1,1) = {" xRX xRX xRX @@ -41046,8 +40592,6 @@ xRX xRX xRX xRX -"} -(135,1,1) = {" xRX xRX xRX @@ -41123,34 +40667,68 @@ xRX xRX xRX xRX +feu +oIF +eZx +mlG +ojz +vFS +mLK +xsE +jwX +vFS +gXD +jsa +rBK +qhi +qkP +slH +tLA +cos +quw +tLA +tLA +gqU +jgn +riF +jgn +jgn +yfz +mAx +mAx +mAx +mAx +mAx +hZi +mAx +mAx +hdp +hdp +hdp +imn +hdp +hdp +hdp +dNG +dNG +dNG +gMK +dNG +dNG +bnz +eGi +eGi +tas +vLy +hvo +mkT +kku +ayi +kyh xRX -ueq -byX -xuX -bex -dwE -fbf -itr -kcS -lxT -mPM -pzP -gJZ xRX xRX xRX -yau -yau -nVM -tbY -yau -jXb -nPq -yau -nTL -xPl -yau -yau xRX xRX xRX @@ -41177,6 +40755,7 @@ xRX xRX xRX xRX +vuD xRX xRX xRX @@ -41259,6 +40838,8 @@ xRX xRX xRX xRX +"} +(134,1,1) = {" xRX xRX xRX @@ -41303,8 +40884,6 @@ xRX xRX xRX xRX -"} -(136,1,1) = {" xRX xRX xRX @@ -41346,6 +40925,63 @@ xRX xRX xRX xRX +oIF +hXP +qBd +eQz +vFS +vFS +htX +vFS +vFS +tEO +jsa +rBK +rBK +qrd +rBK +yfz +fPZ +dgH +qbp +sYH +oKe +aYE +bnu +aYE +aYE +eLC +mvd +aMl +wri +tEO +tEO +mHw +wjI +oTa +nkQ +tEO +jCi +jsa +tEO +tEO +oSw +hSp +cpO +ghM +jsa +tEO +wMK +mHw +bGA +kkN +tas +tOx +qcP +teP +aZS +uYQ +kyh xRX xRX xRX @@ -41381,33 +41017,9 @@ xRX xRX xRX xRX -ueq -nQz -bph -bld -dHA -gJZ -iCX -kxo -lTc -ntw -pFY -gJZ xRX xRX xRX -bLh -lvN -nZU -tcC -etR -vtU -bsL -oJk -aHv -cHm -oUC -qsf xRX xRX xRX @@ -41483,6 +41095,8 @@ xRX xRX xRX xRX +"} +(135,1,1) = {" xRX xRX xRX @@ -41560,50 +41174,6 @@ xRX xRX xRX xRX -"} -(137,1,1) = {" -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX xRX xRX xRX @@ -41612,6 +41182,63 @@ xRX xRX xRX xRX +oIF +oXh +xFA +awG +wPn +fqT +spv +dGE +lsl +lsl +oZS +pHQ +tnO +rpP +moB +thI +uon +qqG +xnk +vKn +iWc +xWp +pia +ckP +fkm +ezi +doJ +wpP +fmB +wZf +ckP +oTH +ezi +ckP +ckP +ppM +gtw +cJN +ckP +aWb +tXd +iHC +vzk +ezi +ezP +kaR +ckP +lGB +uCz +ckP +jjc +fmY +jyH +uoa +iGg +viF +sJP xRX xRX xRX @@ -41638,35 +41265,9 @@ xRX xRX xRX xRX -gJZ -gJZ -gJZ -gJZ -gJZ -gJZ -gJZ -omu -gJZ -gJZ -gJZ -gJZ xRX -feu xRX -duC -twl -bMK -hnE -yep -iDh -pVw -fqt -aei -pRf -lGa -fAg xRX -feu xRX xRX xRX @@ -41751,6 +41352,8 @@ xRX xRX xRX xRX +"} +(136,1,1) = {" xRX xRX xRX @@ -41817,8 +41420,6 @@ xRX xRX xRX xRX -"} -(138,1,1) = {" xRX xRX xRX @@ -41837,6 +41438,64 @@ xRX xRX xRX xRX +feu +oNK +hmD +dfi +uzX +hdZ +mzY +vzU +tEO +maj +tEO +jsa +vzU +tEO +jsa +oTa +tlv +bkP +vUr +qbp +tVB +rfo +sLq +fwA +fwA +aiD +mFt +mFt +fwA +fwA +tEO +vXi +smG +bxY +eCV +xJk +xJk +pHP +xJk +xJk +xJk +xJk +jCF +jCF +jCF +vyC +jCF +jCF +jCF +jCF +jCF +tas +mzO +uzb +qtL +aZS +nGj +kyh xRX xRX xRX @@ -41910,18 +41569,6 @@ xRX xRX xRX xRX -bLh -aFp -xCw -xCw -xCw -xCw -uHL -vpY -vpY -dCS -jYe -qsf xRX xRX xRX @@ -41962,6 +41609,8 @@ xRX xRX xRX xRX +"} +(137,1,1) = {" xRX xRX xRX @@ -42047,6 +41696,63 @@ xRX xRX xRX xRX +oIF +mhD +sTc +gpc +uOy +uOy +uOy +uOy +uOy +tEO +wlA +wUT +wUT +qRJ +wUT +wUT +wUT +wUT +wUT +wUT +hqB +jRF +fwA +tmL +iwS +lym +lym +fJE +fwA +fwA +fwA +mbp +fwA +fwA +xJk +kiF +wrD +yks +xJk +wVa +fxx +jCF +bSt +gnW +aqk +wzK +tUC +jPm +sEf +gor +tas +fHL +tAd +mVV +gjg +lCo +kyh xRX xRX xRX @@ -42074,9 +41780,6 @@ xRX xRX xRX xRX -"} -(139,1,1) = {" -xRX xRX xRX xRX @@ -42163,24 +41866,12 @@ xRX xRX xRX xRX +"} +(138,1,1) = {" xRX xRX xRX xRX -yau -yau -xHi -jzV -nou -eBG -rEq -mQF -rpr -qcF -yau -yau -xRX -xRX xRX xRX xRX @@ -42262,6 +41953,63 @@ xRX xRX xRX xRX +oIF +gkw +uhA +qSB +uOy +xdG +eFH +kpi +uOy +tEO +wlA +wUT +wBq +qUy +sIh +lNa +tsn +wkO +xzl +wUT +iQH +wNT +fwA +paq +qza +lIp +mWY +lym +maw +ghp +qCp +trH +drF +wSM +xJk +lso +fDx +mBK +xJk +scg +vUw +jCF +fFV +gnW +yfU +gkq +eFo +nDb +epG +pBE +tas +bzo +ulR +bYx +oOX +tas +tas xRX xRX xRX @@ -42331,8 +42079,6 @@ xRX xRX xRX xRX -"} -(140,1,1) = {" xRX xRX xRX @@ -42377,6 +42123,8 @@ xRX xRX xRX xRX +"} +(139,1,1) = {" xRX xRX xRX @@ -42422,22 +42170,9 @@ xRX xRX xRX xRX -feu xRX -oBx -yau -yau -yau -yau -wNO -yau -yau -yau -yau -yau xRX xRX -feu xRX xRX xRX @@ -42474,6 +42209,63 @@ xRX xRX xRX xRX +feu +oIF +oIF +oIF +oIF +uOy +iTN +xzg +gLb +uOy +tEO +vwc +wUT +qjk +rro +sJD +sJD +sJD +lpY +sJD +wUT +lgK +fro +fwA +crw +ilB +mmT +lym +lym +cIm +qHn +ori +hwT +qHn +uyn +xJk +tUl +fwP +qtV +xJk +dHT +pPX +jCF +iFw +esZ +cZR +vtO +aoI +qSw +jCF +jCF +tas +tas +muQ +uAk +tas +tas xRX xRX xRX @@ -42589,20 +42381,7 @@ xRX xRX xRX "} -(141,1,1) = {" -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX -xRX +(140,1,1) = {" xRX xRX xRX @@ -42692,6 +42471,51 @@ xRX xRX xRX xRX +uOy +iTN +xzg +oAK +bsV +ckP +hmX +wUT +gec +rsO +goI +wUT +uwT +wUT +uwT +wUT +bom +agA +fwA +ioq +waI +mmT +lym +uWT +tEs +thd +puV +aDL +qHn +jBp +xJk +eEL +iee +qZS +nnM +xBz +tHU +jCF +jCF +jCF +hUx +jCF +jCF +jCF +jCF xRX xRX xRX @@ -42813,6 +42637,8 @@ xRX xRX xRX xRX +"} +(141,1,1) = {" xRX xRX xRX @@ -42845,9 +42671,6 @@ xRX xRX xRX xRX -"} -(142,1,1) = {" -xRX xRX xRX xRX @@ -42886,20 +42709,64 @@ xRX xRX xRX xRX +qMt xRX xRX +qMt xRX xRX +qMt xRX xRX +qMt xRX xRX +qMt xRX xRX xRX xRX xRX xRX +sTf +iTN +xzg +tFs +uOy +tEO +wlA +wUT +ntn +ruB +sMD +wUT +uyk +wUT +wve +wUT +sCd +grA +fwA +vyi +lXU +nmy +lym +lYK +dhX +cdr +ufB +bXG +qHn +wlo +xJk +xJk +xJk +xJk +euV +xJk +xJk +jCF +wmz xRX xRX xRX @@ -43027,6 +42894,8 @@ xRX xRX xRX xRX +"} +(142,1,1) = {" xRX xRX xRX @@ -43102,10 +42971,6 @@ xRX xRX xRX xRX -"} -(143,1,1) = {" -xRX -xRX xRX xRX xRX @@ -43116,6 +42981,41 @@ xRX xRX xRX xRX +gJZ +gJZ +gJZ +gJZ +uOy +iTN +nCd +hFA +uOy +vzU +wlA +wUT +wUT +uiz +wUT +jcc +wUT +uiz +jcc +wUT +rVo +jpQ +jXh +fvO +xnY +xnY +lgJ +fwA +xrl +fwA +fwA +fwA +fwA +fwA +fwA xRX xRX xRX @@ -43193,7 +43093,6 @@ xRX xRX xRX xRX -feu xRX xRX xRX @@ -43208,7 +43107,6 @@ xRX xRX xRX xRX -feu xRX xRX xRX @@ -43253,6 +43151,8 @@ xRX xRX xRX xRX +"} +(143,1,1) = {" xRX xRX xRX @@ -43338,6 +43238,18 @@ xRX xRX xRX xRX +ueq +niC +rRu +oXn +gJZ +gJZ +gJZ +uOy +gJZ +gJZ +xtN +gJZ xRX xRX xRX @@ -43345,6 +43257,10 @@ xRX xRX xRX xRX +yau +wrJ +uGk +yau xRX xRX xRX @@ -43359,8 +43275,6 @@ xRX xRX xRX xRX -"} -(144,1,1) = {" xRX xRX xRX @@ -43401,8 +43315,6 @@ xRX xRX xRX xRX -vuD -xRX xRX xRX xRX @@ -43496,6 +43408,8 @@ xRX xRX xRX xRX +"} +(144,1,1) = {" xRX xRX xRX @@ -43581,9 +43495,35 @@ xRX xRX xRX xRX +xfP +byX +scs +diy +gJZ +gJZ +ibp +jMZ +jMZ +mNJ +ptP +gJZ xRX +feu xRX +kYm +yau +yau +yau +yau +xFa +bgA +wlw +wlw +wlw +wlw +gLv xRX +feu xRX xRX xRX @@ -43616,8 +43556,6 @@ xRX xRX xRX xRX -"} -(145,1,1) = {" xRX xRX xRX @@ -43727,6 +43665,8 @@ xRX xRX xRX xRX +"} +(145,1,1) = {" xRX xRX xRX @@ -43812,9 +43752,33 @@ xRX xRX xRX xRX +ueq +byX +xuX +bex +dwE +fbf +itr +kcS +lxT +mPM +pzP +gJZ xRX xRX xRX +yau +yau +nVM +tbY +yau +jXb +nPq +yau +nTL +xPl +yau +yau xRX xRX xRX @@ -43873,8 +43837,6 @@ xRX xRX xRX xRX -"} -(146,1,1) = {" xRX xRX xRX @@ -43960,11 +43922,12 @@ xRX xRX xRX xRX +"} +(146,1,1) = {" xRX xRX xRX xRX -feu xRX xRX xRX @@ -43979,7 +43942,6 @@ xRX xRX xRX xRX -feu xRX xRX xRX @@ -44047,9 +44009,33 @@ xRX xRX xRX xRX +ueq +nQz +bph +bld +dHA +gJZ +iCX +kxo +lTc +ntw +pFY +gJZ xRX xRX xRX +bLh +lvN +nZU +tcC +etR +vtU +bsL +oJk +aHv +cHm +oUC +qsf xRX xRX xRX @@ -44130,8 +44116,6 @@ xRX xRX xRX xRX -"} -(147,1,1) = {" xRX xRX xRX @@ -44195,6 +44179,8 @@ xRX xRX xRX xRX +"} +(147,1,1) = {" xRX xRX xRX @@ -44280,9 +44266,35 @@ xRX xRX xRX xRX +gJZ +gJZ +gJZ +gJZ +gJZ +gJZ +gJZ +omu +gJZ +gJZ +gJZ +gJZ xRX +feu xRX +duC +twl +bMK +hnE +yep +iDh +pVw +fqt +aei +pRf +lGa +fAg xRX +feu xRX xRX xRX @@ -44387,8 +44399,6 @@ xRX xRX xRX xRX -"} -(148,1,1) = {" xRX xRX xRX @@ -44426,6 +44436,8 @@ xRX xRX xRX xRX +"} +(148,1,1) = {" xRX xRX xRX @@ -44526,6 +44538,18 @@ xRX xRX xRX xRX +bLh +aFp +xCw +xCw +xCw +xCw +uHL +vpY +vpY +dCS +jYe +qsf xRX xRX xRX @@ -44644,8 +44668,6 @@ xRX xRX xRX xRX -"} -(149,1,1) = {" xRX xRX xRX @@ -44671,6 +44693,8 @@ xRX xRX xRX xRX +"} +(149,1,1) = {" xRX xRX xRX @@ -44771,6 +44795,18 @@ xRX xRX xRX xRX +yau +yau +xHi +jzV +nou +eBG +rEq +mQF +rpr +qcF +yau +yau xRX xRX xRX @@ -44901,8 +44937,6 @@ xRX xRX xRX xRX -"} -(150,1,1) = {" xRX xRX xRX @@ -44916,6 +44950,8 @@ xRX xRX xRX xRX +"} +(150,1,1) = {" xRX xRX xRX @@ -45014,9 +45050,22 @@ xRX xRX xRX xRX +feu xRX +oBx +yau +yau +yau +yau +wNO +yau +yau +yau +yau +yau xRX xRX +feu xRX xRX xRX @@ -45772,6 +45821,7 @@ xRX xRX xRX xRX +feu xRX xRX xRX @@ -45786,8 +45836,7 @@ xRX xRX xRX xRX -xRX -xRX +feu xRX xRX xRX @@ -45980,7 +46029,7 @@ xRX xRX xRX xRX -xRX +vuD xRX xRX xRX @@ -46543,6 +46592,7 @@ xRX xRX xRX xRX +feu xRX xRX xRX @@ -46557,8 +46607,7 @@ xRX xRX xRX xRX -xRX -xRX +feu xRX xRX xRX @@ -47058,7 +47107,7 @@ xRX xRX xRX xRX -bxl +xRX xRX xRX xRX @@ -49322,7 +49371,7 @@ xRX xRX xRX xRX -vuD +xRX xRX xRX xRX @@ -49637,7 +49686,7 @@ xRX xRX xRX xRX -xRX +bxl xRX xRX xRX @@ -51901,7 +51950,7 @@ xRX xRX xRX xRX -xRX +vuD xRX xRX xRX @@ -52251,7 +52300,7 @@ xRX xRX xRX xRX -vuD +xRX xRX xRX xRX @@ -54830,7 +54879,7 @@ xRX xRX xRX xRX -xRX +vuD xRX xRX xRX @@ -55533,7 +55582,7 @@ xRX xRX xRX xRX -vuD +xRX xRX xRX xRX @@ -58112,7 +58161,7 @@ xRX xRX xRX xRX -xRX +vuD xRX xRX xRX diff --git a/maps/away/ships/coc/coc_ranger/coc_ship.jsonc b/maps/away/ships/coc/coc_ranger/coc_ship.jsonc new file mode 100644 index 000000000000..9952b6da3431 --- /dev/null +++ b/maps/away/ships/coc/coc_ranger/coc_ship.jsonc @@ -0,0 +1,12 @@ +[ + { + "type": "SubmapExtractInsert", + "submap_size_x": 4, + "submap_size_y": 2, + "submap_size_z": 1, + "submaps_dmm": "coc_ship_submaps.dmm", + "marker_extract": "/obj/effect/map_effect/marker/mapmanip/submap/extract/coc_ranger_lockers", + "marker_insert": "/obj/effect/map_effect/marker/mapmanip/submap/insert/coc_ranger_lockers", + "submaps_can_repeat": false + } +] diff --git a/maps/away/ships/coc/coc_ranger/coc_ship_submaps.dmm b/maps/away/ships/coc/coc_ranger/coc_ship_submaps.dmm new file mode 100644 index 000000000000..d327f0f20c71 --- /dev/null +++ b/maps/away/ships/coc/coc_ranger/coc_ship_submaps.dmm @@ -0,0 +1,837 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/template_noop, +/area/space) +"c" = ( +/obj/structure/weapons_rack{ + req_access = list(13,221,222) + }, +/obj/item/gun/projectile/automatic/rifle/carbine{ + name = "ballistic police carbine"; + desc_extended = "The ST24-T is often considered the cousin of the little brother of its larger and fully automatic counterpart, the STS-35. Built and manufactured for the swathes of law enforcement in the Human Frontier who simply could not afford any better. When compared with it's baseline model, It offers several distinct, but rather unimporant niceities for long-range patrolling and extended use. This particular rifle's proof marks have simply been replaced with a flag of the Coalition of Colonies, as well as stentch of cordite and cheap beer. " + }, +/obj/item/gun/projectile/automatic/rifle/dnac, +/obj/item/gun/projectile/automatic/rifle/dnac, +/obj/effect/map_effect/marker/mapmanip/submap/extract/coc_ranger_lockers, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"e" = ( +/obj/structure/weapons_rack{ + req_access = list(13,221,222) + }, +/obj/item/gun/projectile/automatic/rifle/carbine{ + name = "ballistic police carbine"; + desc_extended = "The ST24-T is often considered the cousin of the little brother of its larger and fully automatic counterpart, the STS-35. Built and manufactured for the swathes of law enforcement in the Human Frontier who simply could not afford any better. When compared with it's baseline model, It offers several distinct, but rather unimporant niceities for long-range patrolling and extended use. This particular rifle's proof marks have simply been replaced with a flag of the Coalition of Colonies, as well as stentch of cordite and cheap beer. " + }, +/obj/item/gun/projectile/automatic/rifle/dpra, +/obj/item/gun/projectile/automatic/rifle/adhomian, +/obj/effect/map_effect/marker/mapmanip/submap/extract/coc_ranger_lockers, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"f" = ( +/obj/structure/weapons_rack{ + req_access = list(13,221,222) + }, +/obj/item/gun/projectile/revolver/knife, +/obj/item/gun/projectile/automatic/tommygun, +/obj/item/gun/projectile/automatic/tommygun, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"h" = ( +/obj/structure/weapons_rack{ + req_access = list(13,221,222) + }, +/obj/item/gun/projectile/automatic/rifle/adhomian, +/obj/item/gun/projectile/automatic/rifle/dnac, +/obj/item/gun/projectile/automatic/rifle/dominia{ + desc_extended = "The Moroz Pattern Rifle, Year of 2424 has been the standard-issue rifle of the Imperial Army for decades thanks to its durable construction and ease of use. The Imperial Army has repeatedly modernized and updated the MPR-24 over the past 40 years, and the rifle is now in its fifth modernization: one that they hope will keep it competitive well into the 2470s. This particular rifle, however, is marked with several dark-red stains along it's wooden furniture. And the usual proofing marks of Dominian manufacture has been filed off and replaced with the flag of the Coalition of Colonies. "; + name = "Captured dominian rifle"; + desc = "The standard-issue rifle of the Empire of Dominia's Imperial Army that was obviously siezed from the cold, dead hands of it's origional user. Loads from 30 round 5.56 magazines." + }, +/obj/effect/map_effect/marker/mapmanip/submap/extract/coc_ranger_lockers, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"i" = ( +/obj/structure/closet/crate{ + name = "Ammo Crate" + }, +/obj/item/ammo_magazine/a65, +/obj/item/ammo_magazine/a65, +/obj/item/ammo_magazine/a65, +/obj/item/ammo_magazine/a65, +/obj/item/ammo_magazine/a65, +/obj/item/ammo_magazine/a65, +/obj/item/ammo_magazine/c46m, +/obj/item/ammo_magazine/c46m, +/obj/item/ammo_magazine/c46m, +/obj/item/ammo_magazine/c46m, +/obj/item/ammo_magazine/c46m, +/obj/item/ammo_magazine/c46m, +/obj/item/ammo_magazine/c46m, +/obj/item/ammo_magazine/c46m/extended, +/obj/item/ammo_magazine/c46m/extended, +/obj/item/ammo_magazine/c46m/extended, +/obj/item/ammo_magazine/c46m/extended, +/obj/item/ammo_magazine/c46m/extended, +/obj/item/ammo_magazine/mc9mm, +/obj/item/ammo_magazine/mc9mm, +/obj/item/ammo_magazine/mc9mm, +/obj/item/ammo_magazine/mc9mm, +/obj/item/ammo_magazine/mc9mm, +/obj/item/ammo_magazine/mc9mm, +/obj/item/paper{ + name = "Armory notice no. 1"; + info = "Our old shorties and most of our PDWs and sidearms are busted. I don't know how we did we even manage to get our hands on half of the shit that's stored in these lockers, and I'm too afraid to ask." + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"j" = ( +/obj/structure/weapons_rack{ + req_access = list(13,221,222) + }, +/obj/item/gun/projectile/automatic/rifle/carbine{ + name = "ballistic police carbine"; + desc_extended = "The ST24-T is often considered the cousin of the little brother of its larger and fully automatic counterpart, the STS-35. Built and manufactured for the swathes of law enforcement in the Human Frontier who simply could not afford any better. When compared with it's baseline model, It offers several distinct, but rather unimporant niceities for long-range patrolling and extended use. This particular rifle's proof marks have simply been replaced with a flag of the Coalition of Colonies, as well as stentch of cordite and cheap beer. " + }, +/obj/item/gun/projectile/automatic/rifle/sol, +/obj/item/gun/projectile/automatic/rifle/konyang/k556, +/obj/effect/map_effect/marker/mapmanip/submap/extract/coc_ranger_lockers, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"k" = ( +/obj/structure/weapons_rack{ + req_access = list(13,221,222) + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"m" = ( +/obj/structure/weapons_rack{ + req_access = list(13,221,222) + }, +/obj/item/gun/projectile/dragunov, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"q" = ( +/obj/item/paper{ + name = "Armory notice no. 1"; + info = "Our old shorties and most of our PDWs and sidearms are busted. So we lifted some stuff from some local 'taj smuggler who calls himself Sergei or something. The rifle with the curved mag (I can't pronounce the name for shit) can't take any lathed mags, so hold on to what we have. You'll have to handload the other rifle (again, can't pronounce the name for shit) with 7.62 clips or by hand." + }, +/turf/template_noop, +/area/space) +"r" = ( +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/structure/closet/crate{ + name = "Ammo Crate" + }, +/obj/item/ammo_magazine/submachinemag, +/obj/item/ammo_magazine/submachinemag, +/obj/item/ammo_magazine/submachinemag, +/obj/item/ammo_magazine/submachinedrum, +/obj/item/ammo_magazine/submachinedrum, +/obj/item/ammo_magazine/mc9mm, +/obj/item/ammo_magazine/mc9mm, +/obj/item/ammo_magazine/mc9mm, +/obj/item/ammo_magazine/mc9mm, +/obj/item/ammo_magazine/mc9mm, +/obj/item/ammo_magazine/mc9mm, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"s" = ( +/obj/structure/weapons_rack{ + req_access = list(13,221,222) + }, +/obj/item/gun/projectile/recoilless_rifle, +/obj/item/gun/projectile/recoilless_rifle, +/obj/item/gun/projectile/recoilless_rifle, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"t" = ( +/obj/structure/weapons_rack{ + req_access = list(13,221,222) + }, +/obj/item/gun/projectile/pistol, +/obj/item/gun/projectile/pistol/dominia, +/obj/item/gun/projectile/automatic/tommygun, +/obj/item/gun/projectile/automatic/tommygun/dom{ + name = "Captured dominian submachine gun"; + desc = "A submachine gun featuring a novel top loading configuration, though intended to used by the Empire of Dominia's armed forces. This gun appears to have been pressed into the service of it's enemies instead."; + desc_extended = "The Moroz Pattern Machine Carbine, Model of 2430 is a lightweight, handy weapon intended for use by vehicle crews, airborne troops, and other units that do not require a full-length rifle. Simplistic in design and function, the MPMC-30 is highly reliable in nearly all environments, lending itself well to use by colonial forces. In particular, the Imperial Fisanduhian Gendarmerie are known to make heavy use of the weapon. This particular gun, however, seems to have been vandalized with maroon-colored stains along it's wooden furniture. And the magazine well has been defaced with a hastily knife-scrawn flag of the Coalition of Colonies." + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"u" = ( +/obj/structure/weapons_rack{ + req_access = list(13,221,222) + }, +/obj/item/gun/projectile/automatic/rifle/carbine{ + name = "ballistic police carbine"; + desc_extended = "The ST24-T is often considered the cousin of the little brother of its larger and fully automatic counterpart, the STS-35. Built and manufactured for the swathes of law enforcement in the Human Frontier who simply could not afford any better. When compared with it's baseline model, It offers several distinct, but rather unimporant niceities for long-range patrolling and extended use. This particular rifle's proof marks have simply been replaced with a flag of the Coalition of Colonies, as well as stentch of cordite and cheap beer. " + }, +/obj/item/gun/projectile/automatic/rifle/dominia{ + desc_extended = "The Moroz Pattern Rifle, Year of 2424 has been the standard-issue rifle of the Imperial Army for decades thanks to its durable construction and ease of use. The Imperial Army has repeatedly modernized and updated the MPR-24 over the past 40 years, and the rifle is now in its fifth modernization: one that they hope will keep it competitive well into the 2470s. This particular rifle, however, is marked with several dark-red stains along it's wooden furniture. And the usual proofing marks of Dominian manufacture has been filed off and replaced with the flag of the Coalition of Colonies. "; + name = "Captured dominian rifle"; + desc = "The standard-issue rifle of the Empire of Dominia's Imperial Army that was obviously siezed from the cold, dead hands of it's origional user. Loads from 30 round 5.56 magazines." + }, +/obj/item/gun/projectile/automatic/rifle/dominia{ + desc_extended = "The Moroz Pattern Rifle, Year of 2424 has been the standard-issue rifle of the Imperial Army for decades thanks to its durable construction and ease of use. The Imperial Army has repeatedly modernized and updated the MPR-24 over the past 40 years, and the rifle is now in its fifth modernization: one that they hope will keep it competitive well into the 2470s. This particular rifle, however, is marked with several dark-red stains along it's wooden furniture. And the usual proofing marks of Dominian manufacture has been filed off and replaced with the flag of the Coalition of Colonies. "; + name = "Captured dominian rifle"; + desc = "The standard-issue rifle of the Empire of Dominia's Imperial Army that was obviously siezed from the cold, dead hands of it's origional user. Loads from 30 round 5.56 magazines." + }, +/obj/effect/map_effect/marker/mapmanip/submap/extract/coc_ranger_lockers, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"w" = ( +/obj/structure/weapons_rack{ + req_access = list(13,221,222) + }, +/obj/item/gun/projectile/silenced, +/obj/item/gun/projectile/automatic/tommygun, +/obj/item/gun/projectile/pistol, +/obj/item/gun/projectile/automatic/c20r/sol, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"x" = ( +/turf/simulated/wall/shuttle/space_ship/mercenary, +/area/ship/ranger_corvette/gunnery) +"z" = ( +/obj/structure/closet/crate{ + name = "Ammo Crate" + }, +/obj/item/ammo_magazine/mc9mm, +/obj/item/ammo_magazine/mc9mm, +/obj/item/ammo_magazine/mc9mm, +/obj/item/ammo_magazine/mc9mm, +/obj/item/ammo_magazine/a556, +/obj/item/ammo_magazine/a556, +/obj/item/ammo_magazine/a556, +/obj/item/ammo_magazine/a65, +/obj/item/ammo_magazine/a65, +/obj/item/ammo_magazine/a65, +/obj/item/ammo_magazine/a65, +/obj/item/ammo_magazine/d762, +/obj/item/ammo_magazine/d762, +/obj/item/ammo_magazine/d762, +/obj/item/ammo_magazine/d762, +/obj/item/ammo_magazine/submachinemag, +/obj/item/ammo_magazine/submachinemag, +/obj/item/ammo_magazine/a10mm, +/obj/item/ammo_magazine/a10mm, +/obj/item/ammo_casing/c45, +/obj/item/ammo_casing/c45, +/obj/item/ammo_casing/c45, +/obj/item/ammo_casing/c45, +/obj/item/ammo_magazine/c45m, +/obj/item/ammo_magazine/c45m, +/obj/item/ammo_magazine/c45m, +/obj/item/paper{ + name = "Armory notice no. 1"; + info = "Our old shorties and most of our PDWs and sidearms are busted. I don't even know how we got half of the stuff we got as a replacement, and I'm too afraid to ask." + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"B" = ( +/obj/structure/closet/crate{ + name = "Ammo Crate" + }, +/obj/item/ammo_magazine/c762/sol, +/obj/item/ammo_magazine/c762/sol, +/obj/item/ammo_magazine/c762/sol, +/obj/item/ammo_magazine/c762/sol, +/obj/item/ammo_magazine/a556/k556, +/obj/item/ammo_magazine/a556/k556, +/obj/item/ammo_magazine/a556/k556, +/obj/item/ammo_magazine/a556/k556, +/obj/item/ammo_magazine/a10mm, +/obj/item/ammo_magazine/a10mm, +/obj/item/ammo_magazine/a10mm, +/obj/item/ammo_magazine/a10mm, +/obj/item/ammo_magazine/a10mm, +/obj/item/ammo_magazine/a10mm, +/obj/item/ammo_magazine/mc9mm, +/obj/item/ammo_magazine/mc9mm, +/obj/item/ammo_magazine/mc9mm, +/obj/item/ammo_magazine/mc9mm, +/obj/item/ammo_magazine/mc9mm, +/obj/item/ammo_magazine/mc9mm, +/obj/item/ammo_magazine/mc9mm, +/obj/item/ammo_magazine/a556/carbine, +/obj/item/ammo_magazine/a556/carbine, +/obj/item/paper{ + name = "Armory notice no. 1"; + info = "Our old shorties and most of our PDWs and sidearms are busted. We had to use a few rifles and shit we captured off the 'imps as a backstop. They aren't too bad, once you get used to the wood furniture and the blood stains." + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"F" = ( +/obj/structure/weapons_rack{ + req_access = list(13,221,222) + }, +/obj/item/gun/projectile/recoilless_rifle, +/obj/item/grenade, +/obj/item/grenade, +/obj/item/grenade, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"H" = ( +/obj/structure/weapons_rack{ + req_access = list(13,221,222) + }, +/obj/item/gun/projectile/automatic/rifle/carbine{ + name = "ballistic police carbine"; + desc_extended = "The ST24-T is often considered the cousin of the little brother of its larger and fully automatic counterpart, the STS-35. Built and manufactured for the swathes of law enforcement in the Human Frontier who simply could not afford any better. When compared with it's baseline model, It offers several distinct, but rather unimporant niceities for long-range patrolling and extended use. This particular rifle's proof marks have simply been replaced with a flag of the Coalition of Colonies, as well as stentch of cordite and cheap beer. " + }, +/obj/item/gun/projectile/automatic/rifle/shorty, +/obj/item/gun/projectile/automatic/rifle/shorty, +/obj/item/gun/projectile/shotgun/pump, +/obj/effect/map_effect/marker/mapmanip/submap/extract/coc_ranger_lockers, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"I" = ( +/obj/structure/weapons_rack{ + req_access = list(13,221,222) + }, +/obj/item/gun/projectile/automatic/xanusmg, +/obj/item/gun/projectile/xanupistol, +/obj/item/gun/projectile/pistol, +/obj/item/gun/projectile/pistol, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"J" = ( +/obj/structure/weapons_rack{ + req_access = list(13,221,222) + }, +/obj/item/gun/projectile/automatic/c20r/sol, +/obj/item/gun/projectile/pistol/sol/konyang, +/obj/item/gun/projectile/pistol/sol, +/obj/item/gun/projectile/automatic/c20r, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"Q" = ( +/obj/structure/weapons_rack{ + req_access = list(13,221,222) + }, +/obj/item/gun/projectile/shotgun/pump/combat/sol, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"R" = ( +/obj/structure/closet/crate{ + name = "Ammo Crate" + }, +/obj/item/ammo_magazine/a556, +/obj/item/ammo_magazine/a556, +/obj/item/ammo_magazine/a556, +/obj/item/ammo_magazine/a556, +/obj/item/ammo_magazine/a556, +/obj/item/ammo_magazine/a556, +/obj/item/ammo_magazine/a556/carbine, +/obj/item/ammo_magazine/a556/carbine, +/obj/item/ammo_magazine/boltaction, +/obj/item/ammo_magazine/boltaction, +/obj/item/ammo_magazine/boltaction, +/obj/item/ammo_magazine/boltaction, +/obj/item/ammo_magazine/c45m/dominia, +/obj/item/ammo_magazine/c45m/dominia, +/obj/item/ammo_magazine/c45m/dominia, +/obj/item/ammo_magazine/c45m/dominia, +/obj/item/ammo_magazine/c45m/dominia, +/obj/item/paper{ + name = "Armory notice no. 1"; + info = "Our old shorties and most of our PDWs and sidearms are bused. So we're using some old Solarian stuff and some kit that was donated from the KAF as a holdover. The mags for our new rifles can't be printed by a 'lathe. So hold on to what you got." + }, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"U" = ( +/obj/structure/weapons_rack{ + req_access = list(13,221,222) + }, +/obj/item/gun/projectile/automatic/tommygun, +/obj/item/gun/projectile/silenced, +/obj/item/gun/projectile/pistol/adhomai, +/obj/item/gun/projectile/automatic/tommygun, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"V" = ( +/obj/structure/closet/crate{ + name = "Ammo Crate" + }, +/obj/item/ammo_magazine/a556/carbine, +/obj/item/ammo_magazine/a556/carbine, +/obj/item/ammo_magazine/a556/carbine, +/obj/item/ammo_magazine/c762, +/obj/item/ammo_magazine/c762, +/obj/item/ammo_magazine/c762, +/obj/item/ammo_magazine/c762, +/obj/item/ammo_magazine/c762, +/obj/item/ammo_magazine/c762, +/obj/item/ammo_magazine/c38, +/obj/item/ammo_magazine/c38, +/obj/item/ammo_magazine/c38, +/obj/item/ammo_magazine/c38, +/obj/item/ammo_magazine/c38, +/obj/item/ammo_magazine/c38, +/obj/item/ammo_magazine/c38, +/obj/item/ammo_magazine/c38, +/obj/item/ammo_magazine/c38, +/obj/item/ammo_magazine/c38, +/obj/item/ammo_magazine/c38, +/obj/item/ammo_magazine/c38, +/obj/item/ammo_magazine/submachinemag, +/obj/item/ammo_magazine/submachinemag, +/obj/item/ammo_magazine/submachinemag, +/obj/item/ammo_magazine/submachinemag, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) +"Z" = ( +/obj/structure/weapons_rack{ + req_access = list(13,221,222) + }, +/obj/item/gun/projectile/shotgun/pump/rifle/dominia, +/turf/simulated/floor/tiled/dark, +/area/ship/ranger_corvette/gunnery) + +(1,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(2,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(3,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(4,1,1) = {" +a +a +a +a +a +a +a +a +a +x +u +a +a +x +H +a +a +a +a +a +"} +(5,1,1) = {" +a +a +a +a +a +a +a +a +a +x +t +a +a +x +f +a +a +a +a +a +"} +(6,1,1) = {" +a +a +a +a +a +a +a +a +a +x +Z +a +a +x +F +a +a +a +a +a +"} +(7,1,1) = {" +a +a +a +a +a +a +a +a +a +x +R +a +a +x +V +a +a +a +a +a +"} +(8,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(9,1,1) = {" +a +a +a +a +a +a +a +a +a +x +j +a +a +x +e +a +a +a +a +a +"} +(10,1,1) = {" +a +a +a +a +a +a +a +a +a +x +J +a +a +x +U +a +a +a +a +a +"} +(11,1,1) = {" +a +a +a +a +a +a +a +a +a +x +Q +a +a +x +s +a +a +a +a +a +"} +(12,1,1) = {" +a +a +a +a +a +a +a +a +a +x +B +a +a +x +r +q +a +a +a +a +"} +(13,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(14,1,1) = {" +a +a +a +a +a +a +a +a +a +x +h +a +a +x +c +a +a +a +a +a +"} +(15,1,1) = {" +a +a +a +a +a +a +a +a +a +x +w +a +a +x +I +a +a +a +a +a +"} +(16,1,1) = {" +a +a +a +a +a +a +a +a +a +x +m +a +a +x +k +a +a +a +a +a +"} +(17,1,1) = {" +a +a +a +a +a +a +a +a +a +x +z +a +a +x +i +a +a +a +a +a +"} +(18,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(19,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(20,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} diff --git a/maps/away/ships/coc/coc_surveyor/coc_surveyor.dm b/maps/away/ships/coc/coc_surveyor/coc_surveyor.dm index c3d0242f4b3e..bdabede3a82e 100644 --- a/maps/away/ships/coc/coc_surveyor/coc_surveyor.dm +++ b/maps/away/ships/coc/coc_surveyor/coc_surveyor.dm @@ -9,6 +9,7 @@ spawn_weight_sector_dependent = list(ALL_BADLAND_SECTORS = 0.3) sectors_blacklist = list(SECTOR_HANEUNIM, SECTOR_BURZSIA, SECTOR_XANU) spawn_weight = 1 + template_flags = TEMPLATE_FLAG_RUIN_STARTS_DISALLOWED // Disabled for debloating. Feel free to enable again if reworked or relevant. ship_cost = 1 id = "coc_surveyor" shuttles_to_initialise = list(/datum/shuttle/autodock/overmap/coc_survey_shuttle) diff --git a/maps/away/ships/dominia/dominian_science_vessel/dominian_science_vessel.dm b/maps/away/ships/dominia/dominian_science_vessel/dominian_science_vessel.dm index 60b5f5148fe0..8eaa4f6c9cce 100644 --- a/maps/away/ships/dominia/dominian_science_vessel/dominian_science_vessel.dm +++ b/maps/away/ships/dominia/dominian_science_vessel/dominian_science_vessel.dm @@ -7,6 +7,7 @@ sectors = list(ALL_TAU_CETI_SECTORS, SECTOR_BADLANDS, SECTOR_VALLEY_HALE) spawn_weight = 1 + template_flags = TEMPLATE_FLAG_RUIN_STARTS_DISALLOWED // Disabled for debloating. Feel free to enable again if reworked or relevant. ship_cost = 1 id = "dominian_science_vessel" shuttles_to_initialise = list(/datum/shuttle/autodock/overmap/dominian_science_shuttle) diff --git a/maps/away/ships/dominia/dominian_unathi_privateer/dominian_unathi_privateer.dm b/maps/away/ships/dominia/dominian_unathi_privateer/dominian_unathi_privateer.dm index f376a451831d..3d80d51762f8 100644 --- a/maps/away/ships/dominia/dominian_unathi_privateer/dominian_unathi_privateer.dm +++ b/maps/away/ships/dominia/dominian_unathi_privateer/dominian_unathi_privateer.dm @@ -7,6 +7,7 @@ sectors = list(SECTOR_BADLANDS, SECTOR_WEEPING_STARS, SECTOR_VALLEY_HALE) spawn_weight = 1 + template_flags = TEMPLATE_FLAG_RUIN_STARTS_DISALLOWED // Disabled for debloating. Feel free to enable again if reworked or relevant. ship_cost = 1 id = "dominian_unathi" shuttles_to_initialise = list(/datum/shuttle/autodock/overmap/dominian_unathi_shuttle) diff --git a/maps/away/ships/dpra/hailstorm/hailstorm_ship.dmm b/maps/away/ships/dpra/hailstorm/hailstorm_ship.dmm index efd81b201725..cd57b0e14cf2 100644 --- a/maps/away/ships/dpra/hailstorm/hailstorm_ship.dmm +++ b/maps/away/ships/dpra/hailstorm/hailstorm_ship.dmm @@ -3611,10 +3611,10 @@ req_access = list(214); name = "Personal Arms" }, -/obj/item/gun/projectile/automatic/rifle/dpra/gold, -/obj/item/ammo_magazine/c762/dpra, -/obj/item/ammo_magazine/c762/dpra, -/obj/item/ammo_magazine/c762/dpra, +/obj/item/gun/projectile/automatic/rifle/dpra, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, /obj/item/clothing/suit/armor/carrier/heavy, /obj/item/clothing/head/helmet/merc, /obj/item/gun/projectile/silenced, @@ -3947,9 +3947,9 @@ /obj/item/ammo_magazine/boltaction, /obj/item/ammo_magazine/boltaction, /obj/item/gun/projectile/automatic/rifle/dpra, -/obj/item/ammo_magazine/c762/dpra, -/obj/item/ammo_magazine/c762/dpra, -/obj/item/ammo_magazine/c762/dpra, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, /obj/item/gun/projectile/shotgun/foldable, /obj/item/storage/box/shells/buckshot, /obj/item/storage/box/shells/buckshot, diff --git a/maps/away/ships/elyra/elyra_corvette/elyra_corvette.dm b/maps/away/ships/elyra/elyra_corvette/elyra_corvette.dm index f8e2f7a96d35..7ea200838e10 100644 --- a/maps/away/ships/elyra/elyra_corvette/elyra_corvette.dm +++ b/maps/away/ships/elyra/elyra_corvette/elyra_corvette.dm @@ -124,7 +124,7 @@ name = "shuttle control console" shuttle_tag = "Elyran Naval Shuttle" req_access = list(ACCESS_ELYRAN_NAVAL_INFANTRY_SHIP) - icon = 'icons/obj/machinery/modular_terminal.dmi' + icon = 'icons/obj/modular_computers/modular_terminal.dmi' icon_screen = "helm" icon_keyboard = "security_key" icon_keyboard_emis = "security_key_mask" diff --git a/maps/away/ships/freebooter/freebooter_salvager/freebooter_salvager.dm b/maps/away/ships/freebooter/freebooter_salvager/freebooter_salvager.dm index 717e949b5f6b..57dfeeeb974c 100644 --- a/maps/away/ships/freebooter/freebooter_salvager/freebooter_salvager.dm +++ b/maps/away/ships/freebooter/freebooter_salvager/freebooter_salvager.dm @@ -12,7 +12,7 @@ ) ship_cost = 1 - spawn_weight = 0.5 // halved from 1 as this is a variation + spawn_weight = 1 shuttles_to_initialise = list(/datum/shuttle/autodock/overmap/freebooter_salvager, /datum/shuttle/autodock/multi/lift/freebooter_salvager) sectors = list(ALL_POSSIBLE_SECTORS) diff --git a/maps/away/ships/freebooter/freebooter_ship/freebooter_ship_.dm b/maps/away/ships/freebooter/freebooter_ship/freebooter_ship_.dm index be8af4916d5b..05e807a618c2 100644 --- a/maps/away/ships/freebooter/freebooter_ship/freebooter_ship_.dm +++ b/maps/away/ships/freebooter/freebooter_ship/freebooter_ship_.dm @@ -9,7 +9,8 @@ suffix = "freebooter_ship_.dmm" sectors = list(ALL_POSSIBLE_SECTORS) - spawn_weight = 0.5 // halved from 1 as this is a variation + spawn_weight = 1 + template_flags = TEMPLATE_FLAG_RUIN_STARTS_DISALLOWED // Disabled for debloating. Feel free to enable again if reworked or relevant. ship_cost = 1 id = "freebooter_ship" shuttles_to_initialise = list(/datum/shuttle/autodock/overmap/freebooter_shuttle) diff --git a/maps/away/ships/hegemony/miners_guild/miners_guild_station.dm b/maps/away/ships/hegemony/miners_guild/miners_guild_station.dm index d0bcd132c288..fee4b6b2d62e 100644 --- a/maps/away/ships/hegemony/miners_guild/miners_guild_station.dm +++ b/maps/away/ships/hegemony/miners_guild/miners_guild_station.dm @@ -6,6 +6,7 @@ suffix = "miners_guild_station.dmm" spawn_weight = 1 + template_flags = TEMPLATE_FLAG_RUIN_STARTS_DISALLOWED // Disabled for debloating. Feel free to enable again if reworked or relevant. ship_cost = 1 sectors = list(SECTOR_BADLANDS, SECTOR_UUEOAESA) spawn_weight_sector_dependent = list(SECTOR_UUEOAESA = 1.5) diff --git a/maps/away/ships/nka/nka_merchant/nka_merchant.dm b/maps/away/ships/nka/nka_merchant/nka_merchant.dm index 5d1d7a461762..e9c9f035ecb9 100644 --- a/maps/away/ships/nka/nka_merchant/nka_merchant.dm +++ b/maps/away/ships/nka/nka_merchant/nka_merchant.dm @@ -8,6 +8,7 @@ ship_cost = 1 spawn_weight = 1 + template_flags = TEMPLATE_FLAG_RUIN_STARTS_DISALLOWED // Disabled for debloating. Feel free to enable again if reworked or relevant. shuttles_to_initialise = list(/datum/shuttle/autodock/overmap/nka_merchant_shuttle) spawn_weight_sector_dependent = list(SECTOR_SRANDMARR = 2, SECTOR_BADLANDS = 0.5) sectors = list(SECTOR_BADLANDS, SECTOR_SRANDMARR, SECTOR_VALLEY_HALE, SECTOR_CORP_ZONE, SECTOR_TAU_CETI) diff --git a/maps/away/ships/orion/orion_express_ship/orion_express_ship.dmm b/maps/away/ships/orion/orion_express_ship/orion_express_ship.dmm index 313767b7f876..0d97a60194cf 100644 --- a/maps/away/ships/orion/orion_express_ship/orion_express_ship.dmm +++ b/maps/away/ships/orion/orion_express_ship/orion_express_ship.dmm @@ -3799,8 +3799,8 @@ /obj/item/clothing/suit/storage/toggle/supply_dep_jacket, /obj/item/clothing/suit/storage/toggle/supply_dep_jacket, /obj/item/clothing/suit/storage/toggle/bomber, -/obj/item/clothing/pants/shorts/khaki, -/obj/item/clothing/pants/shorts/khaki/short, +/obj/item/clothing/pants/shorts/black, +/obj/item/clothing/pants/shorts/black/short, /obj/item/clothing/shoes/workboots/dark, /obj/item/clothing/shoes/workboots/toeless/dark, /obj/item/clothing/gloves/brown, diff --git a/maps/away/ships/pra/database_freighter/database_freighter.dm b/maps/away/ships/pra/database_freighter/database_freighter.dm index bafc75ee9935..26d32ec4178b 100644 --- a/maps/away/ships/pra/database_freighter/database_freighter.dm +++ b/maps/away/ships/pra/database_freighter/database_freighter.dm @@ -8,6 +8,7 @@ ship_cost = 1 spawn_weight = 1 + template_flags = TEMPLATE_FLAG_RUIN_STARTS_DISALLOWED // Disabled for debloating. Feel free to enable again if reworked or relevant. shuttles_to_initialise = list(/datum/shuttle/autodock/overmap/database_freighter_shuttle) sectors = list(SECTOR_BADLANDS, SECTOR_SRANDMARR, SECTOR_NRRAHRAHUL) spawn_weight_sector_dependent = list(SECTOR_BADLANDS = 0.5) diff --git a/maps/away/ships/pra/headmaster/headmaster_ship.dmm b/maps/away/ships/pra/headmaster/headmaster_ship.dmm index 8f44c774a60f..3575f22be88c 100644 --- a/maps/away/ships/pra/headmaster/headmaster_ship.dmm +++ b/maps/away/ships/pra/headmaster/headmaster_ship.dmm @@ -7215,12 +7215,12 @@ req_access = list(209); name = "gun cabinet (rifle ammo)" }, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, /obj/item/ammo_magazine/submachinedrum, /obj/item/ammo_magazine/submachinedrum, /obj/item/ammo_magazine/submachinedrum, diff --git a/maps/away/ships/sadar_scout/sadar_scout.dm b/maps/away/ships/sadar_scout/sadar_scout.dm index 94b58fa3d70f..9cd19e17cf73 100644 --- a/maps/away/ships/sadar_scout/sadar_scout.dm +++ b/maps/away/ships/sadar_scout/sadar_scout.dm @@ -159,7 +159,7 @@ /obj/machinery/computer/shuttle_control/explore/sadar_shuttle name = "shuttle control console" shuttle_tag = "Modified Salvage Skiff" - icon = 'icons/obj/machinery/modular_terminal.dmi' + icon = 'icons/obj/modular_computers/modular_terminal.dmi' icon_state = "computer" icon_screen = "helm" icon_keyboard = "security_key" diff --git a/maps/away/ships/scc/scc_scout_ship.dmm b/maps/away/ships/scc/scc_scout_ship.dmm index 83da9dfca465..d84e4cc72d71 100644 --- a/maps/away/ships/scc/scc_scout_ship.dmm +++ b/maps/away/ships/scc/scc_scout_ship.dmm @@ -7546,7 +7546,7 @@ /obj/item/clothing/suit/storage/toggle/brown_jacket/scc, /obj/item/clothing/under/color/grey, /obj/item/clothing/pants/shorts/black, -/obj/item/clothing/pants/tan, +/obj/item/clothing/pants/black, /obj/item/clothing/pants/track, /obj/item/clothing/under/color/lightred, /obj/item/clothing/pants/camo, diff --git a/maps/away/ships/sol/sol_frigate/sol_frigate.dmm b/maps/away/ships/sol/sol_frigate/sol_frigate.dmm index 1c54da515198..b3da22a8109c 100644 --- a/maps/away/ships/sol/sol_frigate/sol_frigate.dmm +++ b/maps/away/ships/sol/sol_frigate/sol_frigate.dmm @@ -57,6 +57,9 @@ /obj/machinery/atmospherics/unary/vent_pump/on{ dir = 4 }, +/obj/structure/mirror{ + pixel_y = 35 + }, /turf/simulated/floor/tiled/white, /area/ship/sol_frigate/captain_cabin) "ar" = ( @@ -249,7 +252,9 @@ /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 }, -/obj/machinery/vending/medical, +/obj/machinery/vending/medical{ + req_access = list(203) + }, /turf/simulated/floor/tiled/white, /area/ship/sol_frigate/sickbay) "bb" = ( @@ -311,7 +316,8 @@ /obj/structure/cable/blue{ icon_state = "2-8" }, -/turf/unsimulated/floor/wood, +/obj/structure/lattice/catwalk/indoor/grate/dark, +/turf/simulated/floor/plating, /area/ship/sol_frigate/starboard_gunnery) "bx" = ( /obj/effect/floor_decal/corner/grey/diagonal, @@ -427,6 +433,25 @@ }, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/eva_storage) +"ca" = ( +/obj/structure/table/wood, +/obj/item/storage/box/unique/tea{ + pixel_x = -8 + }, +/obj/item/storage/box/unique/tea/jaekseol{ + pixel_x = -8; + pixel_y = 5 + }, +/obj/item/reagent_containers/glass/beaker/teapot{ + pixel_y = 10 + }, +/obj/item/reagent_containers/food/drinks/drinkingglass/newglass/coffeecup/teacup, +/obj/item/reagent_containers/food/drinks/drinkingglass/newglass/coffeecup/teacup, +/obj/item/reagent_containers/food/drinks/drinkingglass/newglass/coffeecup/teacup{ + pixel_y = -4 + }, +/turf/simulated/floor/wood, +/area/ship/sol_frigate/oquarters) "cc" = ( /obj/effect/floor_decal/corner/lime{ dir = 10 @@ -572,16 +597,7 @@ /turf/simulated/wall/shuttle/raider, /area/ship/sol_frigate/sickbay) "cN" = ( -/obj/structure/closet, -/obj/item/clothing/under/rank/sol/dress/subofficer, -/obj/item/clothing/under/rank/sol/dress/subofficer, -/obj/item/clothing/head/sol/dress/officer, -/obj/item/clothing/head/sol/dress/officer, -/obj/item/clothing/shoes/jackboots, -/obj/item/clothing/shoes/jackboots, -/obj/machinery/light{ - dir = 4 - }, +/obj/structure/filingcabinet/filingcabinet, /turf/simulated/floor/wood, /area/ship/sol_frigate/oquarters) "cO" = ( @@ -656,7 +672,7 @@ }, /obj/structure/lattice/catwalk/indoor/grate/dark, /obj/structure/cable/blue{ - icon_state = "2-8" + icon_state = "4-8" }, /turf/simulated/floor/plating, /area/ship/sol_frigate/hallway_fore) @@ -765,6 +781,15 @@ }, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/starboard_gunnery) +"ds" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/effect/floor_decal/corner/yellow{ + dir = 6 + }, +/obj/machinery/door/firedoor/noid, +/turf/simulated/floor/tiled/dark, +/area/ship/sol_frigate/hallway_fore) "dt" = ( /obj/machinery/door/airlock/external, /obj/effect/map_effect/marker_helper/airlock/exterior, @@ -857,9 +882,6 @@ /turf/unsimulated/floor/wood, /area/ship/sol_frigate/starboard_gunnery) "dL" = ( -/obj/structure/cable/blue{ - icon_state = "1-8" - }, /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 5 @@ -1233,15 +1255,17 @@ /turf/simulated/floor/wood, /area/ship/sol_frigate/captain_office) "fq" = ( -/obj/structure/cable/blue{ - icon_state = "4-8" - }, /obj/effect/floor_decal/corner/dark_blue{ dir = 5 }, /obj/machinery/light{ dir = 1 }, +/obj/structure/cable/green{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/hangar) "fs" = ( @@ -1301,6 +1325,9 @@ /obj/random_produce/box, /obj/random_produce/box, /obj/random_produce/box, +/obj/item/storage/box/large/produce, +/obj/item/storage/box/large/produce, +/obj/item/storage/box/large/produce, /turf/simulated/floor/tiled/freezer{ name = "cooled tiles"; temperature = 253.15 @@ -1803,6 +1830,7 @@ /obj/machinery/light{ dir = 8 }, +/obj/structure/closet/walllocker/emerglocker/west, /turf/simulated/floor/wood, /area/ship/sol_frigate/oquarters) "hV" = ( @@ -2139,15 +2167,16 @@ /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/eva_storage) "jp" = ( -/obj/structure/cable/blue{ - icon_state = "0-4" - }, /obj/effect/floor_decal/corner/dark_blue{ dir = 5 }, /obj/machinery/power/apc/north{ req_access = list(203) }, +/obj/structure/cable/green{ + icon_state = "0-2"; + dir = 4 + }, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/hangar) "jt" = ( @@ -2221,6 +2250,9 @@ pixel_x = 12 }, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/structure/mirror{ + pixel_x = 32 + }, /turf/simulated/floor/tiled/white, /area/ship/sol_frigate/oquarters) "jP" = ( @@ -2473,6 +2505,10 @@ /obj/structure/cable/blue{ icon_state = "2-4" }, +/obj/item/mecha_equipment/mounted_system/combat/grenadesmoke{ + pixel_y = 13 + }, +/obj/item/mecha_equipment/mounted_system/combat/blaster, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/Exo_Bay) "kU" = ( @@ -2584,6 +2620,12 @@ /obj/machinery/light{ dir = 1 }, +/obj/item/grenade, +/obj/item/grenade, +/obj/item/plastique, +/obj/item/plastique, +/obj/item/plastique, +/obj/item/grenade, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/armoury) "lh" = ( @@ -3021,7 +3063,7 @@ /obj/machinery/door/airlock/multi_tile/glass{ door_color = "#304b77"; req_access = list(203); - name = "Cargo Bay Storage" + name = "Midships hallway" }, /obj/machinery/door/firedoor/noid{ dir = 8 @@ -3281,7 +3323,7 @@ dir = 8 }, /obj/structure/cable/blue{ - icon_state = "1-2" + icon_state = "1-8" }, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/hallway_fore) @@ -3422,10 +3464,13 @@ id = "solfrig_workshop"; name = "Garage door" }, +/obj/structure/closet/crate/bin, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/Exo_Bay) "pd" = ( -/obj/structure/filingcabinet/chestdrawer, +/obj/structure/bed/stool/chair/office/light{ + dir = 1 + }, /turf/simulated/floor/wood, /area/ship/sol_frigate/oquarters) "pe" = ( @@ -3610,6 +3655,12 @@ }, /turf/simulated/floor/tiled/dark, /area/shuttle/solfrig_shuttle) +"pU" = ( +/obj/item/sticker/flagpole/assn{ + pixel_x = 24 + }, +/turf/template_noop, +/area/space) "pW" = ( /obj/effect/floor_decal/corner/grey/diagonal, /obj/machinery/light{ @@ -3657,6 +3708,14 @@ }, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/armoury) +"qc" = ( +/obj/structure/cable/green{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/turf/simulated/floor/tiled/dark, +/area/ship/sol_frigate/hallway_fore) "qg" = ( /obj/effect/floor_decal/corner/orange{ dir = 9 @@ -3799,6 +3858,9 @@ /obj/structure/sink{ pixel_y = 16 }, +/obj/structure/mirror{ + pixel_y = 35 + }, /turf/simulated/floor/tiled/white, /area/ship/sol_frigate/head) "qT" = ( @@ -4105,9 +4167,12 @@ /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/hallway_fore) "sJ" = ( -/obj/structure/mirror, -/turf/simulated/wall/shuttle/raider, -/area/ship/sol_frigate/captain_cabin) +/obj/effect/floor_decal/corner/yellow{ + dir = 10 + }, +/obj/structure/closet/crate/bin, +/turf/simulated/floor/tiled/dark, +/area/ship/sol_frigate/starboard_gunnery) "sN" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -4168,10 +4233,12 @@ "sZ" = ( /obj/structure/sign/kiddieplaque{ name = "Solarian Navy commissioning plaque"; - desc = "A silver-plated plaque dating the date of the commissioning of a Cuirassier-Class frigate in the Solarian Navy. The name of the shipbuilder and naval yards that helped build and bring this ship into commission. A waving Solarian flag and naval ensign is proudly stamped at the bottom." + desc = "A silver-plated plaque that cites the date of the commissioning of a Cuirassier (Revised)-frigate into the Solarian Navy. The name of the shipbuilder and naval yards that helped build and bring this ship into commission. A waving Solarian flag and naval ensign is proudly stamped at the bottom."; + pixel_y = 32; + pixel_x = -3 }, /turf/simulated/wall/shuttle/raider, -/area/ship/sol_frigate/cic) +/area/ship/sol_frigate/port_battery) "tc" = ( /obj/effect/floor_decal/corner/paleblue/diagonal, /obj/structure/cable/blue{ @@ -4218,11 +4285,11 @@ /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/engineering) "tr" = ( -/obj/machinery/seed_storage, /obj/effect/floor_decal/corner/green/diagonal, /obj/machinery/light{ dir = 1 }, +/obj/machinery/vending/hydroseeds, /turf/simulated/floor/tiled/freezer{ name = "cooled tiles"; temperature = 253.15 @@ -4484,8 +4551,8 @@ /turf/simulated/floor/tiled/white, /area/ship/sol_frigate/canteen) "uk" = ( -/obj/structure/cable/blue{ - icon_state = "4-8" +/obj/structure/cable/green{ + icon_state = "1-8" }, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/hangar) @@ -4509,6 +4576,7 @@ dir = 8; level = 2 }, +/obj/structure/bed/stool/chair/office/light, /turf/simulated/floor/wood, /area/ship/sol_frigate/oquarters) "up" = ( @@ -4620,6 +4688,9 @@ /obj/random_produce/box, /obj/random_produce/box, /obj/random_produce/box, +/obj/item/storage/box/large/produce, +/obj/item/storage/box/large/produce, +/obj/item/storage/box/large/produce, /turf/simulated/floor/tiled/freezer{ name = "cooled tiles"; temperature = 253.15 @@ -4939,14 +5010,18 @@ /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/canteen) "wd" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/effect/floor_decal/corner/yellow{ + dir = 9 + }, /obj/structure/cable/blue{ icon_state = "1-2" }, -/obj/structure/cable/blue{ - icon_state = "2-4" +/obj/machinery/door/airlock/multi_tile/glass{ + dir = 8; + name = "Midships hallway"; + req_access = list(203) }, +/obj/machinery/door/firedoor/noid, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/hallway_fore) "we" = ( @@ -4963,6 +5038,7 @@ dir = 4 }, /obj/machinery/alarm/north, +/obj/structure/closet/crate/bin, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/Starboard_docking_port) "wn" = ( @@ -5025,7 +5101,6 @@ /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/armoury) "wE" = ( -/obj/structure/closet/walllocker/emerglocker/west, /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 6 }, @@ -5100,7 +5175,7 @@ /obj/machinery/door/airlock/multi_tile/glass{ door_color = "#304b77"; req_access = list(203); - name = "Cargo Bay Storage" + name = "Aft quarter hallway" }, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/starboard_gunnery) @@ -5148,6 +5223,13 @@ "xs" = ( /turf/simulated/floor/airless, /area/space) +"xt" = ( +/obj/structure/bed/stool/chair/padded/beige, +/obj/structure/weapon_rack{ + pixel_y = 32 + }, +/turf/simulated/floor/wood, +/area/ship/sol_frigate/oquarters) "xy" = ( /obj/machinery/atmospherics/pipe/simple/hidden{ dir = 8 @@ -5684,6 +5766,12 @@ /obj/effect/floor_decal/corner/dark_blue{ dir = 5 }, +/obj/structure/sign/kiddieplaque{ + name = "Solarian Navy commissioning plaque"; + desc = "A silver-plated plaque that cites the date of the commissioning of a Cuirassier (Revised)-frigate into the Solarian Navy. The name of the shipbuilder and naval yards that helped build and bring this ship into commission. A waving Solarian flag and naval ensign is proudly stamped at the bottom."; + pixel_y = 32; + pixel_x = -3 + }, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/cic) "Ar" = ( @@ -5885,6 +5973,10 @@ req_access = list(222) }, /obj/effect/floor_decal/industrial/hatch/red, +/obj/machinery/door/blast/shutters/open{ + id = "SFLD"; + dir = 4 + }, /turf/simulated/floor/plating, /area/ship/sol_frigate/Port_docking_port) "Bg" = ( @@ -6250,6 +6342,7 @@ /obj/structure/cable/blue{ icon_state = "0-8" }, +/obj/structure/closet/crate/bin, /turf/simulated/floor/wood, /area/ship/sol_frigate/captain_office) "CG" = ( @@ -6484,6 +6577,12 @@ /obj/item/synthesized_instrument/violin, /turf/simulated/floor/carpet, /area/ship/sol_frigate/captain_cabin) +"DP" = ( +/obj/structure/bed/stool/chair/padded/beige{ + dir = 1 + }, +/turf/simulated/floor/wood, +/area/ship/sol_frigate/oquarters) "DT" = ( /obj/machinery/vending/engineering, /obj/effect/floor_decal/corner/orange{ @@ -6781,12 +6880,13 @@ /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/hallway_fore) "Fv" = ( -/obj/structure/table/wood, -/obj/item/modular_computer/laptop, /obj/machinery/light{ dir = 4; status = 2 }, +/obj/structure/bed/stool/chair/office/light{ + dir = 1 + }, /turf/simulated/floor/wood, /area/ship/sol_frigate/oquarters) "Fy" = ( @@ -7589,6 +7689,10 @@ req_access = list(203) }, /obj/effect/floor_decal/industrial/hatch/red, +/obj/machinery/door/blast/shutters/open{ + id = "SFLD"; + dir = 4 + }, /turf/simulated/floor/plating, /area/ship/sol_frigate/Starboard_docking_port) "IZ" = ( @@ -8006,6 +8110,9 @@ /obj/random_produce/box, /obj/random_produce/box, /obj/random_produce/box, +/obj/item/storage/box/large/produce, +/obj/item/storage/box/large/produce, +/obj/item/storage/box/large/produce, /turf/simulated/floor/tiled/freezer{ name = "cooled tiles"; temperature = 253.15 @@ -8093,7 +8200,7 @@ /obj/machinery/light{ dir = 8 }, -/obj/structure/flora/pottedplant/woodyshrubdying, +/obj/structure/closet/crate/bin, /turf/simulated/floor/tiled/white, /area/ship/sol_frigate/canteen) "Ld" = ( @@ -8178,6 +8285,11 @@ id = "SFLD" }, /obj/machinery/door/firedoor/noid, +/obj/structure/cable/green{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/hangar) "Lp" = ( @@ -8457,8 +8569,8 @@ }, /obj/machinery/atmospherics/unary/vent_pump/on, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/light{ - dir = 4 +/obj/structure/mirror{ + pixel_x = 32 }, /turf/simulated/floor/tiled/white, /area/ship/sol_frigate/oquarters) @@ -8476,6 +8588,10 @@ /obj/effect/map_effect/marker_helper/airlock/exterior, /obj/effect/map_effect/marker/airlock/docking/sol_frigate/port_dock, /obj/effect/floor_decal/industrial/hatch/red, +/obj/machinery/door/blast/shutters/open{ + id = "SFLD"; + dir = 4 + }, /turf/simulated/floor/plating, /area/ship/sol_frigate/Port_docking_port) "Mo" = ( @@ -8534,7 +8650,7 @@ /obj/structure/cable/blue{ icon_state = "4-8" }, -/obj/machinery/portable_atmospherics/canister/empty/oxygen, +/obj/machinery/portable_atmospherics/canister/oxygen, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/eva_storage) "MO" = ( @@ -8579,6 +8695,10 @@ /obj/effect/map_effect/marker_helper/airlock/exterior, /obj/effect/map_effect/marker/airlock/docking/sol_frigate/starboard_dock, /obj/effect/floor_decal/industrial/hatch/red, +/obj/machinery/door/blast/shutters/open{ + id = "SFLD"; + dir = 4 + }, /turf/simulated/floor/plating, /area/ship/sol_frigate/Starboard_docking_port) "MV" = ( @@ -8623,6 +8743,7 @@ "Nl" = ( /obj/effect/floor_decal/corner/grey/diagonal, /obj/machinery/light, +/obj/structure/closet/crate/bin, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/bunks) "Nr" = ( @@ -8735,6 +8856,7 @@ /obj/structure/cable/blue{ icon_state = "0-2" }, +/obj/structure/closet/crate/bin, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/brig) "NP" = ( @@ -8826,13 +8948,18 @@ /turf/simulated/floor/plating, /area/ship/sol_frigate/starboard_gunnery) "Oi" = ( -/obj/structure/bed/stool/chair, /obj/machinery/power/apc/east{ req_access = list(203) }, /obj/structure/cable/blue{ icon_state = "0-8" }, +/obj/structure/table/wood/maple, +/obj/item/pen/fountain, +/obj/item/paper_bin{ + pixel_y = 2; + pixel_x = -7 + }, /turf/simulated/floor/wood, /area/ship/sol_frigate/oquarters) "Ok" = ( @@ -8971,7 +9098,7 @@ /obj/machinery/door/airlock/multi_tile/glass{ door_color = "#304b77"; req_access = list(203); - name = "Cargo Bay Storage" + name = "Aft quarter hallway" }, /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/machinery/door/firedoor/noid, @@ -9167,6 +9294,7 @@ /obj/structure/cable/blue{ icon_state = "1-8" }, +/obj/structure/table/wood/maple, /turf/simulated/floor/wood, /area/ship/sol_frigate/oquarters) "PN" = ( @@ -9186,9 +9314,15 @@ /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/brig) "Qc" = ( -/obj/structure/mirror, -/turf/simulated/wall/shuttle/raider, -/area/ship/sol_frigate/head) +/obj/effect/floor_decal/corner/yellow{ + dir = 9 + }, +/obj/structure/cable/blue{ + icon_state = "1-2" + }, +/obj/structure/closet/crate/bin, +/turf/simulated/floor/tiled/dark, +/area/ship/sol_frigate/hallway_fore) "Qd" = ( /obj/structure/lattice, /turf/template_noop, @@ -9303,7 +9437,7 @@ /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/engineering) "QD" = ( -/obj/structure/sign/flag/sol, +/obj/item/melee/ceremonial_sword, /turf/simulated/wall/shuttle/raider, /area/ship/sol_frigate/oquarters) "QG" = ( @@ -9471,6 +9605,13 @@ }, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/engineering) +"RI" = ( +/obj/structure/cable/blue{ + icon_state = "4-8" + }, +/obj/structure/closet/crate/bin, +/turf/simulated/floor/tiled/dark, +/area/ship/sol_frigate/engineering) "RJ" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, @@ -9547,6 +9688,9 @@ icon_state = "4-8" }, /obj/structure/closet/walllocker/emerglocker/north, +/obj/structure/cable/green{ + icon_state = "2-4" + }, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/hallway_fore) "Sa" = ( @@ -9584,7 +9728,7 @@ /obj/machinery/door/airlock/multi_tile/glass{ door_color = "#304b77"; req_access = list(203); - name = "Cargo Bay Storage" + name = "Aft quarter hallway" }, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/starboard_gunnery) @@ -9639,7 +9783,7 @@ "SB" = ( /obj/structure/table/wood, /obj/structure/closet/walllocker/emerglocker/west, -/obj/item/modular_computer/laptop, +/obj/item/modular_computer/laptop/preset, /turf/simulated/floor/wood, /area/ship/sol_frigate/captain_office) "SD" = ( @@ -9647,6 +9791,7 @@ dir = 5 }, /obj/machinery/light, +/obj/structure/closet/crate/bin, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/hallway_fore) "SF" = ( @@ -9697,9 +9842,9 @@ /turf/simulated/wall/shuttle/raider, /area/ship/sol_frigate/Port_docking_port) "SR" = ( -/obj/structure/mirror, -/turf/simulated/wall/shuttle/raider, -/area/ship/sol_frigate/oquarters) +/obj/structure/closet/crate/bin, +/turf/simulated/floor/tiled/dark, +/area/ship/sol_frigate/cic) "SV" = ( /obj/structure/filingcabinet/chestdrawer, /obj/item/flashlight/lamp{ @@ -9957,7 +10102,7 @@ "UJ" = ( /obj/machinery/door/airlock/multi_tile/glass{ dir = 8; - name = "Mess Hall"; + name = "Fore quarter hallway"; req_access = list(203) }, /obj/machinery/door/firedoor/noid, @@ -10085,6 +10230,7 @@ /obj/structure/cable/blue{ icon_state = "0-2" }, +/obj/structure/closet/crate/bin, /turf/simulated/floor/wood, /area/ship/sol_frigate/ocountry) "Vi" = ( @@ -10766,11 +10912,16 @@ /area/ship/sol_frigate/cic) "YB" = ( /obj/structure/closet, -/obj/item/clothing/accessory/badge/passcard/sol, -/obj/item/clothing/accessory/badge/passcard/sol, +/obj/item/clothing/under/rank/sol/dress/subofficer, +/obj/item/clothing/under/rank/sol/dress/subofficer, +/obj/item/clothing/head/sol/dress/officer, +/obj/item/clothing/head/sol/dress/officer, +/obj/item/clothing/shoes/jackboots, +/obj/item/clothing/shoes/jackboots, /obj/machinery/light{ - dir = 1 + dir = 4 }, +/obj/item/clothing/accessory/badge/passcard/sol, /turf/simulated/floor/wood, /area/ship/sol_frigate/oquarters) "YC" = ( @@ -10932,6 +11083,10 @@ /obj/machinery/light{ dir = 1 }, +/obj/item/gun/projectile/automatic/rifle/sol, +/obj/item/ammo_magazine/c762/sol, +/obj/item/ammo_magazine/c762/sol, +/obj/item/ammo_magazine/c762/sol, /turf/simulated/floor/tiled/dark, /area/ship/sol_frigate/armoury) "Zj" = ( @@ -11069,7 +11224,7 @@ "ZI" = ( /obj/machinery/door/airlock/multi_tile/glass{ dir = 8; - name = "Mess Hall"; + name = "Midships hallway"; req_access = list(203) }, /obj/machinery/door/firedoor/noid, @@ -43925,7 +44080,7 @@ JF jZ JF in -MO +pU MO MO MO @@ -44131,7 +44286,7 @@ Tw uX Cm BV -sJ +EA aq EA cx @@ -44419,7 +44574,7 @@ hy BB vI vI -vI +SR QX yt uf @@ -44672,7 +44827,7 @@ lb ie ob AA -sZ +yt Ap YQ TS @@ -45138,7 +45293,7 @@ SM WS SM aC -Rl +RI iE tF SM @@ -45168,9 +45323,9 @@ Fh MG hU QD -hU -MG -hU +xt +ca +DP MG ZE DI @@ -45658,7 +45813,7 @@ WH mw kF FF -jB +sJ Kp ek eC @@ -45708,7 +45863,7 @@ yt yt yt RZ -PD +qc Lo uk Hw @@ -45933,8 +46088,8 @@ dr XX MG MG -SR -SR +MG +MG MG MG YB @@ -45965,7 +46120,7 @@ yt yt we dg -wd +nm xi dL Ta @@ -46206,7 +46361,7 @@ oW nt jH Hd -Nv +wd bL GD Nv @@ -46215,14 +46370,14 @@ Nv Nv TV Hy -Nv +Qc Nv ky Hy UJ Vn or -Zz +hl pK HF iJ @@ -46463,7 +46618,7 @@ uO vv Jp fO -lw +ds BO Ok lw @@ -46750,7 +46905,7 @@ Xf Xf Xf Xf -Xf +sZ Xf Xf bI @@ -47490,7 +47645,7 @@ TE xf Ih aW -Qc +IT qS Nc IT @@ -47747,7 +47902,7 @@ pW iM Wv uR -Qc +IT qS Nc xG @@ -48004,7 +48159,7 @@ aW In Ih aW -Qc +IT qS iP IT diff --git a/maps/away/ships/sol/sol_pirate/sfa_patrol_ship.dm b/maps/away/ships/sol/sol_pirate/sfa_patrol_ship.dm index b6b4b2f2666d..04178d0b289e 100644 --- a/maps/away/ships/sol/sol_pirate/sfa_patrol_ship.dm +++ b/maps/away/ships/sol/sol_pirate/sfa_patrol_ship.dm @@ -7,6 +7,7 @@ sectors = list(SECTOR_VALLEY_HALE, SECTOR_BADLANDS) spawn_weight = 0.5 // Lowered to represent increasing scarcity of faction. + template_flags = TEMPLATE_FLAG_RUIN_STARTS_DISALLOWED // Disabled for debloating. Feel free to enable again if reworked or relevant. ship_cost = 1 id = "sfa_patrol_ship" shuttles_to_initialise = list(/datum/shuttle/autodock/overmap/sfa_shuttle) diff --git a/maps/away/ships/sol/sol_ssrm/ssrm_ship.dmm b/maps/away/ships/sol/sol_ssrm/ssrm_ship.dmm index 4edc8eb0d528..c766d5748e65 100644 --- a/maps/away/ships/sol/sol_ssrm/ssrm_ship.dmm +++ b/maps/away/ships/sol/sol_ssrm/ssrm_ship.dmm @@ -2061,10 +2061,6 @@ /obj/item/reagent_containers/pill/nicotine{ pixel_y = -1 }, -/obj/item/reagent_containers/inhaler/space_drugs{ - pixel_y = 6; - pixel_x = -4 - }, /turf/simulated/floor/tiled/dark, /area/ship/ssrm_corvette/port_thrusters) "emc" = ( @@ -2135,6 +2131,12 @@ }, /turf/simulated/floor/tiled/dark, /area/ship/ssrm_corvette/synthroom) +"eqW" = ( +/obj/structure/filingcabinet/chestdrawer{ + pixel_x = -7 + }, +/turf/template_noop, +/area/space) "esV" = ( /obj/effect/floor_decal/corner/paleblue/diagonal, /obj/structure/table/wood, @@ -3678,6 +3680,10 @@ pixel_x = -7; pixel_y = 20 }, +/obj/item/storage/chewables/tobacco/bad{ + pixel_y = 20; + pixel_x = -5 + }, /turf/simulated/floor/tiled/dark, /area/ship/ssrm_corvette/eva_preperation) "hFY" = ( @@ -4713,6 +4719,11 @@ req_access = list(203); dir = 1 }, +/obj/structure/cable{ + icon_state = "1-2"; + d1 = 1; + d2 = 2 + }, /turf/simulated/floor/tiled/dark/full, /area/ship/ssrm_corvette/port_gunnery) "kaR" = ( @@ -5163,6 +5174,10 @@ pixel_y = 5; pixel_x = 3 }, +/obj/item/storage/box/fancy/cigarettes/nicotine{ + pixel_y = 14; + pixel_x = -9 + }, /turf/simulated/floor/tiled/dark, /area/ship/ssrm_corvette/eva_preperation) "lfX" = ( @@ -7374,6 +7389,7 @@ pixel_x = 27 }, /obj/effect/map_effect/marker/airlock/shuttle/ssrm_shuttle, +/obj/effect/map_effect/marker_helper/airlock/exterior, /turf/simulated/floor/reinforced/airless, /area/shuttle/ssrm_shuttle) "que" = ( @@ -8224,6 +8240,8 @@ }, /obj/structure/table/wood, /obj/item/modular_computer/laptop/preset/civilian, +/obj/item/clothing/head/sol, +/obj/item/device/radio/headset/ship, /turf/simulated/floor/tiled/dark, /area/ship/ssrm_corvette/cpo_cabin) "sIJ" = ( @@ -49023,7 +49041,7 @@ xRX xRX xRX xRX -xRX +eqW xRX xRX xRX diff --git a/maps/away/ships/sol/sol_ssrm/ssrm_ship_ghostroles.dm b/maps/away/ships/sol/sol_ssrm/ssrm_ship_ghostroles.dm index 24c115ed3056..49aaafbe0a54 100644 --- a/maps/away/ships/sol/sol_ssrm/ssrm_ship_ghostroles.dm +++ b/maps/away/ships/sol/sol_ssrm/ssrm_ship_ghostroles.dm @@ -91,9 +91,14 @@ name = "Sol Navy Recon Chief Petty Officer" uniform = /obj/item/clothing/under/rank/sol/dress/pettyofficer - shoes = /obj/item/clothing/shoes/laceup - back = /obj/item/storage/backpack/satchel/leather - head = /obj/item/clothing/head/sol/dress + shoes = /obj/item/clothing/shoes/jackboots + back = /obj/item/storage/backpack/satchel + head = /obj/item/clothing/head/sol + + id = /obj/item/card/id/ssrm_ship + +/obj/outfit/admin/ssrm_navy_chief_petty_officer/get_id_access() + return list(ACCESS_SOL_SHIPS, ACCESS_EXTERNAL_AIRLOCKS) /datum/ghostspawner/human/ssrm_marine_pilot short_name = "ssrm_marine_pilot" diff --git a/maps/away/ships/tajara/taj_smuggler/tajaran_smuggler.dm b/maps/away/ships/tajara/taj_smuggler/tajaran_smuggler.dm index 1662df412933..4b59be3d366a 100644 --- a/maps/away/ships/tajara/taj_smuggler/tajaran_smuggler.dm +++ b/maps/away/ships/tajara/taj_smuggler/tajaran_smuggler.dm @@ -8,6 +8,7 @@ sectors = list(SECTOR_ROMANOVICH, SECTOR_CORP_ZONE, ALL_BADLAND_SECTORS, SECTOR_WEEPING_STARS) spawn_weight_sector_dependent = list(SECTOR_BADLANDS = 0.5) spawn_weight = 1 + template_flags = TEMPLATE_FLAG_RUIN_STARTS_DISALLOWED // Disabled for debloating. Feel free to enable again if reworked or relevant. ship_cost = 1 id = "tajaran_smuggler" shuttles_to_initialise = list(/datum/shuttle/autodock/overmap/tajaran_smuggler_shuttle, /datum/shuttle/autodock/overmap/tajaran_smuggler_cargo) diff --git a/maps/away/ships/tirakqi_smuggler/tirakqi_smuggler.dm b/maps/away/ships/tirakqi_smuggler/tirakqi_smuggler.dm index e2583dfa3acf..6034bb39dbf3 100644 --- a/maps/away/ships/tirakqi_smuggler/tirakqi_smuggler.dm +++ b/maps/away/ships/tirakqi_smuggler/tirakqi_smuggler.dm @@ -159,7 +159,7 @@ // wall nav console /obj/machinery/computer/ship/navigation/wall - icon = 'icons/obj/modular_telescreen.dmi' + icon = 'icons/obj/modular_computers/modular_telescreen.dmi' icon_state = "telescreen" icon_screen = "command" density = FALSE diff --git a/maps/away/ships/unathi_pirate/izharshan/unathi_pirate_izharshan.dm b/maps/away/ships/unathi_pirate/izharshan/unathi_pirate_izharshan.dm index 8a8af5a9b5dd..4cdd24041301 100644 --- a/maps/away/ships/unathi_pirate/izharshan/unathi_pirate_izharshan.dm +++ b/maps/away/ships/unathi_pirate/izharshan/unathi_pirate_izharshan.dm @@ -7,6 +7,7 @@ suffix = "unathi_pirate_izharshan.dmm" spawn_weight = 1 + template_flags = TEMPLATE_FLAG_RUIN_STARTS_DISALLOWED // Disabled for debloating. Feel free to enable again if reworked or relevant. ship_cost = 1 shuttles_to_initialise = list(/datum/shuttle/autodock/overmap/unathi_pirate_izharshan) sectors = list(SECTOR_NRRAHRAHUL, SECTOR_BADLANDS, SECTOR_GAKAL, SECTOR_UUEOAESA) diff --git a/maps/away/ships/unathi_pirate/tarwa/unathi_pirate_tarwa.dm b/maps/away/ships/unathi_pirate/tarwa/unathi_pirate_tarwa.dm index 39372ad7d0ba..dfef6e3ba0d5 100644 --- a/maps/away/ships/unathi_pirate/tarwa/unathi_pirate_tarwa.dm +++ b/maps/away/ships/unathi_pirate/tarwa/unathi_pirate_tarwa.dm @@ -7,6 +7,7 @@ sectors = list(SECTOR_BADLANDS, SECTOR_GAKAL, SECTOR_LIGHTS_EDGE, SECTOR_WEEPING_STARS) spawn_weight = 1 + template_flags = TEMPLATE_FLAG_RUIN_STARTS_DISALLOWED // Disabled for debloating. Feel free to enable again if reworked or relevant. ship_cost = 1 shuttles_to_initialise = list(/datum/shuttle/autodock/overmap/tarwa_shuttle) id = "tarwa_conglomerate" diff --git a/maps/away/ships/yacht/yacht.dm b/maps/away/ships/yacht/yacht.dm index 535b78e32dbb..baeb79fcaaaa 100644 --- a/maps/away/ships/yacht/yacht.dm +++ b/maps/away/ships/yacht/yacht.dm @@ -7,7 +7,8 @@ suffix = "yacht.dmm" spawn_cost = 0.5 - spawn_weight = 0.5 + spawn_weight = 1 + template_flags = TEMPLATE_FLAG_RUIN_STARTS_DISALLOWED // Disabled for debloating. Feel free to enable again if reworked or relevant. sectors = list(SECTOR_ROMANOVICH, SECTOR_TAU_CETI, SECTOR_CORP_ZONE, SECTOR_VALLEY_HALE, SECTOR_BADLANDS, ALL_COALITION_SECTORS, SECTOR_TABITI, SECTOR_AEMAQ, SECTOR_SRANDMARR, SECTOR_NRRAHRAHUL, SECTOR_GAKAL, SECTOR_UUEOAESA) unit_test_groups = list(3) diff --git a/maps/away/ships/yacht_civ/yacht_civ.dmm b/maps/away/ships/yacht_civ/yacht_civ.dmm index 962055f112a0..c0ccb834bf57 100644 --- a/maps/away/ships/yacht_civ/yacht_civ.dmm +++ b/maps/away/ships/yacht_civ/yacht_civ.dmm @@ -4865,7 +4865,7 @@ /obj/item/clothing/pants/jeans{ pixel_y = 4 }, -/obj/item/clothing/pants/white, +/obj/item/clothing/pants/black, /obj/item/clothing/pants/skirt/high{ color = "#4B381D" }, @@ -4898,7 +4898,7 @@ /obj/machinery/alarm/west{ req_one_access = null }, -/obj/item/clothing/pants/tan, +/obj/item/clothing/pants/black, /obj/item/clothing/pants/tailoredjeans{ color = "#2C3A7F"; pixel_y = 3 diff --git a/maps/event/generic_dock/generic_dock-1.dmm b/maps/event/generic_dock/generic_dock-1.dmm index 8f5da7288de0..b49115027891 100644 --- a/maps/event/generic_dock/generic_dock-1.dmm +++ b/maps/event/generic_dock/generic_dock-1.dmm @@ -17614,11 +17614,11 @@ /area/centcom/holding) "xkI" = ( /obj/structure/table/stone/marble, -/obj/item/reagent_containers/food/snacks/salad/tossedsalad{ +/obj/item/reagent_containers/food/snacks/salad/applesalad{ pixel_x = 18; pixel_y = 10 }, -/obj/item/reagent_containers/food/snacks/salad/tossedsalad{ +/obj/item/reagent_containers/food/snacks/salad/applesalad{ pixel_x = 16; pixel_y = 3 }, diff --git a/maps/random_ruins/exoplanets/adhomai/adhomai_silo.dm b/maps/random_ruins/exoplanets/adhomai/adhomai_silo.dm index 09eb0aff30cd..67003e5ecef0 100644 --- a/maps/random_ruins/exoplanets/adhomai/adhomai_silo.dm +++ b/maps/random_ruins/exoplanets/adhomai/adhomai_silo.dm @@ -66,7 +66,7 @@ belt_contents = list( /obj/item/gun/projectile/pistol/adhomai = 1, /obj/item/ammo_magazine/mc9mm = 2, - /obj/item/ammo_magazine/boltaction = 3, + /obj/item/ammo_magazine/a68 = 2, /obj/item/melee/baton/stunrod = 1, /obj/item/handcuffs = 1 ) diff --git a/maps/random_ruins/exoplanets/adhomai/ala_base.dmm b/maps/random_ruins/exoplanets/adhomai/ala_base.dmm index b935f72d9a9b..06d331a761bc 100644 --- a/maps/random_ruins/exoplanets/adhomai/ala_base.dmm +++ b/maps/random_ruins/exoplanets/adhomai/ala_base.dmm @@ -321,13 +321,13 @@ req_access = list(214); name = "ammunition cabinet (rifle)" }, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, /obj/machinery/light/small{ dir = 1 }, @@ -465,12 +465,12 @@ req_access = list(214); name = "ammunition cabinet (automatic rifle)" }, -/obj/item/ammo_magazine/c762/dpra, -/obj/item/ammo_magazine/c762/dpra, -/obj/item/ammo_magazine/c762/dpra, -/obj/item/ammo_magazine/c762/dpra, -/obj/item/ammo_magazine/c762/dpra, -/obj/item/ammo_magazine/c762/dpra, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, /turf/simulated/floor/exoplanet/tiled/dark, /area/ala_base) "vJ" = ( diff --git a/maps/random_ruins/exoplanets/adhomai/pra_base.dmm b/maps/random_ruins/exoplanets/adhomai/pra_base.dmm index 2567c938fc2b..4d2cde16929c 100644 --- a/maps/random_ruins/exoplanets/adhomai/pra_base.dmm +++ b/maps/random_ruins/exoplanets/adhomai/pra_base.dmm @@ -289,13 +289,13 @@ req_access = list(209); name = "ammunition cabinet (rifle)" }, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, -/obj/item/ammo_magazine/boltaction, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, +/obj/item/ammo_magazine/a68, /turf/simulated/floor/concrete/square{ temperature = 268.15 }, diff --git a/maps/random_ruins/exoplanets/biesel/biesel_camp_site.dmm b/maps/random_ruins/exoplanets/biesel/biesel_camp_site.dmm index 2485ad287bb1..9219b84a8707 100644 --- a/maps/random_ruins/exoplanets/biesel/biesel_camp_site.dmm +++ b/maps/random_ruins/exoplanets/biesel/biesel_camp_site.dmm @@ -64,8 +64,8 @@ /obj/item/reagent_containers/food/snacks/burger, /obj/item/reagent_containers/food/snacks/burger, /obj/item/reagent_containers/food/snacks/burger, -/obj/item/reagent_containers/food/snacks/salad/tossedsalad, -/obj/item/reagent_containers/food/snacks/salad/tossedsalad, +/obj/item/reagent_containers/food/snacks/salad/applesalad, +/obj/item/reagent_containers/food/snacks/salad/applesalad, /obj/item/storage/box/drinkingglasses, /obj/item/material/kitchen/utensil/fork/plastic, /obj/item/material/kitchen/utensil/fork/plastic, diff --git a/maps/random_ruins/exoplanets/ouerea/ouerea_bar.dm b/maps/random_ruins/exoplanets/ouerea/ouerea_bar.dm index 6eb1a708131f..24a638a8e397 100644 --- a/maps/random_ruins/exoplanets/ouerea/ouerea_bar.dm +++ b/maps/random_ruins/exoplanets/ouerea/ouerea_bar.dm @@ -85,7 +85,7 @@ /obj/outfit/admin/ouerea_human name = "Ouerean Human" uniform = list(/obj/item/clothing/under/dressshirt/silversun/random, /obj/item/clothing/under/dressshirt, /obj/item/clothing/under/dressshirt/tshirt, /obj/item/clothing/under/dressshirt/longsleeve) - pants = list(/obj/item/clothing/pants/tan, /obj/item/clothing/pants/jeans, /obj/item/clothing/pants/shorts/black, /obj/item/clothing/pants/shorts/jeans) + pants = list(/obj/item/clothing/pants/jeans, /obj/item/clothing/pants/shorts/black, /obj/item/clothing/pants/shorts/jeans) suit = list(/obj/item/clothing/suit/storage/toggle/track, /obj/item/clothing/suit/storage/toggle/asymmetriccoat/izharshan, /obj/item/clothing/accessory/poncho/unathimantle, /obj/item/clothing/suit/storage/toggle/corp/heph) shoes = list(/obj/item/clothing/shoes/sandals/caligae, /obj/item/clothing/shoes/sandals, /obj/item/clothing/shoes/workboots, /obj/item/clothing/shoes/jackboots) head = list(/obj/item/clothing/head/unathi, /obj/item/clothing/head/cowboy, /obj/item/clothing/head/cowboy/wide, /obj/item/clothing/head/bandana/colorable/random) @@ -97,7 +97,7 @@ /obj/outfit/admin/ouerea_skrell name = "Ouerean Skrell" uniform = list(/obj/item/clothing/under/dressshirt/tshirt/skrell/maelstrom, /obj/item/clothing/under/dressshirt/tshirt/skrell/nebula, /obj/item/clothing/under/dressshirt/tshirt/skrell/reef) - pants = list(/obj/item/clothing/pants/tan, /obj/item/clothing/pants/jeans, /obj/item/clothing/pants/shorts/black, /obj/item/clothing/pants/shorts/jeans) + pants = list(/obj/item/clothing/pants/jeans, /obj/item/clothing/pants/shorts/black, /obj/item/clothing/pants/shorts/jeans) shoes = list(/obj/item/clothing/shoes/sandals/caligae, /obj/item/clothing/shoes/sandals, /obj/item/clothing/shoes/workboots, /obj/item/clothing/shoes/jackboots) back = /obj/item/storage/backpack/satchel/leather l_pocket = /obj/item/storage/wallet/random diff --git a/maps/random_ruins/exoplanets/ouerea/ouerea_village.dmm b/maps/random_ruins/exoplanets/ouerea/ouerea_village.dmm index f76b4bc66f0c..33ab6063a1a8 100644 --- a/maps/random_ruins/exoplanets/ouerea/ouerea_village.dmm +++ b/maps/random_ruins/exoplanets/ouerea/ouerea_village.dmm @@ -483,7 +483,7 @@ color = "#100942" }, /obj/item/clothing/pants/jeans, -/obj/item/clothing/pants/tan, +/obj/item/clothing/pants/black, /obj/item/clothing/under/dressshirt/silversun/random, /obj/item/clothing/accessory/tshirt, /obj/item/clothing/under/dressshirt/tshirt/skrell/ocean, @@ -559,7 +559,7 @@ color = "#100942" }, /obj/item/clothing/pants/jeans, -/obj/item/clothing/pants/tan, +/obj/item/clothing/pants/black, /obj/item/clothing/under/dressshirt/silversun/random, /obj/item/clothing/accessory/tshirt, /obj/item/clothing/under/dressshirt/tshirt/skrell/nebula/teal, diff --git a/maps/runtime/code/runtime.dm b/maps/runtime/code/runtime.dm index 9bab817ccb5b..69ff11aef0a8 100644 --- a/maps/runtime/code/runtime.dm +++ b/maps/runtime/code/runtime.dm @@ -113,7 +113,6 @@ station_area = TRUE holomap_color = HOLOMAP_AREACOLOR_COMMAND area_blurb = "The sound here seems to carry more than others, every click of a shoe or clearing of a throat amplified. The smell of ink, written and printed, wafts notably through the air." - area_blurb_category = "command" /// ENGINEERING_AREAS /area/engineering @@ -130,7 +129,6 @@ no_light_control = 1 ambience = list(AMBIENCE_ENGINEERING, AMBIENCE_ATMOS) area_blurb = "Many volume tanks filled with gas reside here, some providing vital gases for the vessel's life support systems." - area_blurb_category = "atmos" /area/engineering/gravity_gen name = "Engineering - Gravity Generator" @@ -144,7 +142,6 @@ turf_initializer = new /datum/turf_initializer/maintenance() ambience = AMBIENCE_MAINTENANCE area_blurb = "Scarcely lit, cramped, and filled with stale, dusty air. Around you hisses compressed air through the pipes, a buzz of electrical charge through the wires, and muffled rumbles of the hull settling. This place may feel alien compared to the interior of the ship and is a place where one could get lost or badly hurt, but some may find the isolation comforting." - area_blurb_category = "maint" /area/maintenance/maintcentral name = "Bridge Maintenance" diff --git a/maps/sccv_horizon/areas/horizon_areas_command.dm b/maps/sccv_horizon/areas/horizon_areas_command.dm index cc67c14fa44e..1a4c8e1c1633 100644 --- a/maps/sccv_horizon/areas/horizon_areas_command.dm +++ b/maps/sccv_horizon/areas/horizon_areas_command.dm @@ -70,7 +70,6 @@ no_light_control = 1 area_blurb = "The sound here seems to carry more than others, every click of a shoe or clearing of a throat amplified. \ The smell of ink, written and printed, wafts notably through the air." - area_blurb_category = "command" horizon_deck = 3 /area/horizon/command/bridge/bridge_crew @@ -101,7 +100,6 @@ ambience = list() sound_environment = SOUND_AREA_MEDIUM_SOFTFLOOR area_blurb = "A place for behind-closed-doors meetings to get things done (or to argue for hours)." - area_blurb_category = "command_meeting" area_flags = AREA_FLAG_RAD_SHIELDED /area/horizon/command/bridge/cciaroom @@ -109,7 +107,6 @@ icon_state = "hr" sound_environment = SOUND_AREA_MEDIUM_SOFTFLOOR area_blurb = "You might feel dread when you enter this meeting room." - area_blurb_category = "hr_meeting" area_flags = AREA_FLAG_RAD_SHIELDED /area/horizon/command/bridge/cciaroom/lounge @@ -117,7 +114,6 @@ icon_state = "hrlounge" sound_environment = SOUND_AREA_SMALL_SOFTFLOOR area_blurb = "A place that may worsen any anxiety surrounding meetings with your bosses' bosses." - area_blurb_category = "hr_lounge" area_flags = AREA_FLAG_RAD_SHIELDED /area/horizon/command/bridge/selfdestruct @@ -129,7 +125,6 @@ /area/horizon/command/bridge/controlroom name = "Bridge Control Room" area_blurb = "The full expanse of space lies beyond a thick pane of reinforced glass, all that protects you from a cold and painful death. The computers hum, showing various displays and holographic signs. The sight would be overwhelming to one unused to such an environment. Even at full power, the sensors fail to map even a fraction of the dots of light making up the cosmic filament." - area_blurb_category = "bridge" area_flags = AREA_FLAG_RAD_SHIELDED //Teleporter @@ -138,4 +133,3 @@ icon_state = "teleporter" horizon_deck = 1 area_blurb = "The air in here always feels charged with the subdued crackle of electricity, tasting faintly of ozone." - area_blurb_category = "teleporter" diff --git a/maps/sccv_horizon/areas/horizon_areas_engineering.dm b/maps/sccv_horizon/areas/horizon_areas_engineering.dm index d08b88b29a3e..5042c39ed7e7 100644 --- a/maps/sccv_horizon/areas/horizon_areas_engineering.dm +++ b/maps/sccv_horizon/areas/horizon_areas_engineering.dm @@ -35,7 +35,6 @@ icon_state = "engineering_break" sound_environment = SOUND_AREA_MEDIUM_SOFTFLOOR area_blurb = "The intermixed odors of coffee and oil lingers in the air." - area_blurb_category = "engi_breakroom" horizon_deck = 3 /area/horizon/engineering/locker_room @@ -49,7 +48,6 @@ horizon_deck = 1 area_flags = AREA_FLAG_RAD_SHIELDED area_blurb = "The air in here tastes like copper, sour sugar, and smoke; none of the angles seem right. That probably means everything is working." - area_blurb_category = "engi_breakroom" /area/horizon/engineering/lobby name = "Lobby" @@ -117,7 +115,6 @@ ambience = list(AMBIENCE_ENGINEERING, AMBIENCE_ATMOS) area_blurb = "Many volume tanks filled with gas reside here, some providing vital gases for the vessel's life support systems. \ Through the aft windows, exterior stowage tanks filled mostly with hazardous or volatile gases loom patiently." - area_blurb_category = "atmos" horizon_deck = 1 subdepartment = SUBLOC_ATMOS diff --git a/maps/sccv_horizon/areas/horizon_areas_maintenance.dm b/maps/sccv_horizon/areas/horizon_areas_maintenance.dm index 31e66ebe59b9..502038d7760e 100644 --- a/maps/sccv_horizon/areas/horizon_areas_maintenance.dm +++ b/maps/sccv_horizon/areas/horizon_areas_maintenance.dm @@ -6,7 +6,6 @@ sound_environment = SOUND_AREA_TUNNEL_ENCLOSED turf_initializer = new /datum/turf_initializer/maintenance() area_blurb = "Scarcely lit, cramped, and filled with stale, dusty air. Around you hisses compressed air through the pipes, a buzz of electrical charge through the wires, and muffled rumbles of the hull settling. This place may feel alien compared to the interior of the ship and is a place where one could get lost or badly hurt, but some may find the isolation comforting." - area_blurb_category = "maint" ambience = AMBIENCE_MAINTENANCE department = LOC_MAINTENANCE @@ -246,7 +245,6 @@ sound_environment = SOUND_AREA_SMALL_ENCLOSED ambience = AMBIENCE_SUBSTATION area_blurb = "The hum of the substation's machinery fills the room, holding equipment made to transform voltage and manage power supply to various rooms, and to act as an emergency battery. In comparison to the maintenance tunnels, these stations are far less dusty." - area_blurb_category = "substation" /// Engineering (Main) /area/horizon/maintenance/substation/engineering diff --git a/maps/sccv_horizon/areas/horizon_areas_medical.dm b/maps/sccv_horizon/areas/horizon_areas_medical.dm index ba3fe8c3b180..ae7362c94de4 100644 --- a/maps/sccv_horizon/areas/horizon_areas_medical.dm +++ b/maps/sccv_horizon/areas/horizon_areas_medical.dm @@ -3,7 +3,6 @@ station_area = TRUE holomap_color = HOLOMAP_AREACOLOR_MEDICAL area_blurb = "Various smells waft through the sick bay: disinfectants, various medicines, sterile gloves, and gauze. It's not a pleasant smell, but one you could grow to ignore." - area_blurb_category = "mecical" department = LOC_MEDICAL /area/horizon/medical/paramedic @@ -24,7 +23,6 @@ icon_state = "medbay3" area_flags = AREA_FLAG_RAD_SHIELDED area_blurb = "Featuring wood floors and soft carpets, this room has a warmer feeling compared to the sterility of the rest of the medical department." - area_blurb_category = "psych" horizon_deck = 2 lightswitch = FALSE @@ -83,7 +81,6 @@ /area/horizon/medical/ward/isolation name = "Isolation Ward" area_blurb = "This seldom-used ward somehow smells sterile and musty at the same time." - area_blurb_category = "medical_isolation" horizon_deck = 3 /area/horizon/medical/morgue @@ -91,7 +88,6 @@ icon_state = "morgue" ambience = AMBIENCE_GHOSTLY area_blurb = "Morgue trays sit within this room, ready to hold the deceased until their postmortem wishes can be attended to." - area_blurb_category = "morgue" horizon_deck = 1 /area/horizon/medical/equipment @@ -102,7 +98,6 @@ /area/horizon/medical/smoking name = "Smoking Lounge" area_blurb = "The smell of cigarette smoke lingers within this room." - area_blurb_category = "medical_smoking" horizon_deck = 3 /area/horizon/medical/washroom diff --git a/maps/sccv_horizon/areas/horizon_areas_operations.dm b/maps/sccv_horizon/areas/horizon_areas_operations.dm index 7e69106f4f02..a69851a08046 100644 --- a/maps/sccv_horizon/areas/horizon_areas_operations.dm +++ b/maps/sccv_horizon/areas/horizon_areas_operations.dm @@ -12,7 +12,6 @@ icon_state = "dark160" sound_environment = SOUND_AREA_LARGE_ENCLOSED area_blurb = "Scuff marks scar the floor from the movement of many crates and stored goods." - area_blurb_category = "ops_warehouse" horizon_deck = 1 /area/horizon/operations/package_conveyors @@ -90,7 +89,6 @@ /area/horizon/hangar/intrepid name = "Primary Hangar" area_blurb = "A big, open room, home to the SCCV Horizon's largest shuttle, the Intrepid." - area_blurb_category = "hanger" /area/horizon/hangar/intrepid/interstitial name = "Intrepid Hangar Access" @@ -99,19 +97,16 @@ name = "Starboard Auxiliary Hangar" holomap_color = HOLOMAP_AREACOLOR_OPERATIONS area_blurb = "A big, open room, home to the SCCV Horizon's mining shuttle, the Spark." - area_blurb_category = "hanger" /area/horizon/hangar/auxiliary name = "Port Auxiliary Hangar" area_blurb = "A big, open room, home to two of the SCCV Horizon's shuttles, the Quark and the Canary." - area_blurb_category = "hanger" /// OPERATIONS_AREAS - MACHINIST_AREAS /area/horizon/operations/machinist name = "Machinist Workshop" icon_state = "machinist_workshop" area_blurb = "The scents of oil and mechanical lubricants fill the air in this workshop." - area_blurb_category = "robotics" subdepartment = SUBLOC_MACHINING horizon_deck = 2 @@ -119,7 +114,6 @@ name = "Machinist Surgical Bay" icon_state = "machinist_workshop" area_blurb = "Back in the workshop's surgical bay, the sharp-edged odor of sterilized equipment predominates." - area_blurb_category = "robotics" horizon_deck = 2 /// OPERATIONS_AREAS - MINING_AREAS diff --git a/maps/sccv_horizon/areas/horizon_areas_service.dm b/maps/sccv_horizon/areas/horizon_areas_service.dm index 82def1bb696a..68907ad00690 100644 --- a/maps/sccv_horizon/areas/horizon_areas_service.dm +++ b/maps/sccv_horizon/areas/horizon_areas_service.dm @@ -73,7 +73,6 @@ name = "Cafe" icon_state = "cafeteria" area_blurb = "The smell of coffee wafts over from the cafe. Patience, the tree, stands proudly in the centre of the atrium." - area_blurb_category = "d3_cafe" horizon_deck = 3 // Custodial areas @@ -84,7 +83,6 @@ sound_environment = SOUND_AREA_LARGE_ENCLOSED ambience = list(AMBIENCE_FOREBODING, AMBIENCE_ENGINEERING) area_blurb = "A strong, concentrated smell of many cleaning supplies linger within this room." - area_blurb_category = "janitor" horizon_deck = 1 area_flags = AREA_FLAG_PREVENT_PERSISTENT_TRASH @@ -93,7 +91,6 @@ icon_state = "disposal" ambience = list(AMBIENCE_ENGINEERING, AMBIENCE_ATMOS) // Industrial sounds. area_blurb = "A large trash compactor takes up much of the room, ready to crush the ship's rubbish." - area_blurb_category = "trash_compactor" /area/horizon/service/custodial/disposals/deck_1 name = "Disposals and Recycling" diff --git a/maps/sccv_horizon/sccv_horizon.dmm b/maps/sccv_horizon/sccv_horizon.dmm index 46d91a4909b4..60146f034bd9 100644 --- a/maps/sccv_horizon/sccv_horizon.dmm +++ b/maps/sccv_horizon/sccv_horizon.dmm @@ -2636,6 +2636,10 @@ pixel_x = -7; pixel_y = 8 }, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = 10; + pixel_y = -3 + }, /turf/simulated/floor/tiled/white, /area/horizon/rnd/lab) "apc" = ( @@ -7386,6 +7390,10 @@ pixel_x = 5; pixel_y = 5 }, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = 10; + pixel_y = -3 + }, /turf/simulated/floor/tiled/white, /area/horizon/security/forensic_laboratory) "aUW" = ( @@ -7614,6 +7622,9 @@ /obj/effect/floor_decal/corner_wide/grey/diagonal, /obj/machinery/atmospherics/unary/vent_scrubber/on, /obj/effect/floor_decal/spline/plain/brown, +/obj/effect/landmark/start{ + name = "Hangar Technician" + }, /turf/simulated/floor/tiled/white, /area/horizon/operations/break_room) "aWW" = ( @@ -7727,6 +7738,10 @@ pixel_y = 2 }, /obj/item/pen, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = 10; + pixel_y = -3 + }, /turf/simulated/floor/carpet/purple, /area/horizon/command/heads/rd) "aXu" = ( @@ -8917,6 +8932,10 @@ /obj/effect/floor_decal/corner/beige/full{ dir = 8 }, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = 10; + pixel_y = -3 + }, /turf/simulated/floor/tiled, /area/horizon/crew/vacantoffice) "bfN" = ( @@ -12172,6 +12191,10 @@ pixel_x = -6; pixel_y = 2 }, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = -10; + pixel_y = -3 + }, /turf/simulated/floor/wood, /area/horizon/security/meeting_room) "bBm" = ( @@ -12994,15 +13017,7 @@ }, /area/centcom/control) "bHP" = ( -/obj/machinery/door/airlock/glass_mining{ - dir = 1; - name = "Operations Bay"; - req_one_access = list(26,29,31,48,67,70) - }, /obj/machinery/door/firedoor, -/obj/structure/cable/green{ - icon_state = "1-2" - }, /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /obj/structure/disposalpipe/segment, @@ -13012,6 +13027,11 @@ /obj/effect/floor_decal/industrial/hatch_door/yellow{ dir = 8 }, +/obj/machinery/door/airlock/glass_mining{ + dir = 1; + name = "Operations Bay"; + req_one_access = list(26,29,31,48,67,70) + }, /turf/simulated/floor/tiled, /area/horizon/operations/office) "bHT" = ( @@ -16676,6 +16696,10 @@ /obj/machinery/atmospherics/unary/vent_pump/on{ dir = 1 }, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = 10; + pixel_y = -3 + }, /turf/simulated/floor/carpet, /area/horizon/command/heads/hos) "ciL" = ( @@ -21253,6 +21277,10 @@ /obj/machinery/atmospherics/unary/vent_scrubber/on{ dir = 4 }, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = 10; + pixel_y = -3 + }, /turf/simulated/floor/carpet, /area/horizon/repoffice/representative_two) "cPb" = ( @@ -23246,6 +23274,10 @@ /obj/item/pen{ pixel_y = 4 }, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = -10; + pixel_y = -3 + }, /turf/simulated/floor/tiled/white, /area/horizon/command/heads/cmo) "dbu" = ( @@ -25026,17 +25058,20 @@ /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/structure/disposalpipe/segment, /obj/machinery/door/firedoor, -/obj/machinery/door/airlock/glass_mining{ - dir = 1; - name = "Operations Bay"; - req_one_access = list(26,29,31,48,67,70) - }, /obj/effect/map_effect/door_helper/unres{ dir = 1 }, /obj/effect/floor_decal/industrial/hatch_door/yellow{ dir = 8 }, +/obj/structure/cable/green{ + icon_state = "1-2" + }, +/obj/machinery/door/airlock/glass_mining{ + dir = 1; + name = "Operations Bay"; + req_one_access = list(26,29,31,48,67,70) + }, /turf/simulated/floor/tiled/full, /area/horizon/operations/office) "dmJ" = ( @@ -26047,6 +26082,10 @@ /obj/item/folder/sec, /obj/item/pen, /obj/item/paper_bin, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = 10; + pixel_y = -3 + }, /turf/simulated/floor/tiled, /area/horizon/security/warden) "dsE" = ( @@ -27726,6 +27765,13 @@ }, /obj/machinery/atmospherics/pipe/simple/hidden, /obj/effect/floor_decal/industrial/hatch/grey, +/obj/machinery/button/remote/blast_door{ + id = "spark_bay_outer"; + name = "Airlock Shutters"; + pixel_x = 27; + pixel_y = 7; + dir = 1 + }, /turf/simulated/floor/tiled/dark/full, /area/horizon/shuttle/mining) "dDE" = ( @@ -29237,6 +29283,14 @@ pixel_x = -8; pixel_y = 1 }, +/obj/item/pen/fountain/black{ + pixel_x = 5; + pixel_y = 3 + }, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = -10; + pixel_y = -3 + }, /obj/item/folder/sec{ pixel_x = -8; pixel_y = 1 @@ -29245,10 +29299,6 @@ pixel_x = -8; pixel_y = 1 }, -/obj/item/pen/fountain/black{ - pixel_x = 5; - pixel_y = 3 - }, /turf/simulated/floor/carpet, /area/horizon/security/investigators_office) "dOH" = ( @@ -29718,9 +29768,6 @@ /obj/effect/floor_decal/industrial/warning{ dir = 10 }, -/obj/structure/sign/crush{ - pixel_y = -32 - }, /turf/simulated/floor/tiled/dark/full, /area/turbolift/scc_ship/robotics_lift) "dRX" = ( @@ -30605,6 +30652,10 @@ dir = 9 }, /obj/machinery/alarm/west, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = 10; + pixel_y = -3 + }, /turf/simulated/floor/tiled, /area/horizon/service/custodial) "dYW" = ( @@ -30675,6 +30726,19 @@ /obj/effect/landmark/entry_point/aft{ name = "aft, airlock" }, +/obj/machinery/door/blast/shutters/open{ + dir = 2; + id = "canary_bay_outer"; + name = "Canary Shutter" + }, +/obj/machinery/button/remote/blast_door{ + dir = 1; + id = "canary_bay_outer"; + name = "Airlock Shutters"; + pixel_x = -27; + pixel_y = 11; + req_access = list(12,31,73,77) + }, /turf/simulated/floor/plating, /area/horizon/shuttle/canary) "dZx" = ( @@ -31089,9 +31153,6 @@ /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 5 }, -/obj/effect/landmark/start{ - name = "Hangar Technician" - }, /obj/effect/floor_decal/corner/brown, /turf/simulated/floor/tiled, /area/horizon/operations/break_room) @@ -34116,9 +34177,6 @@ /obj/effect/floor_decal/corner/brown{ dir = 10 }, -/obj/structure/cable/green{ - icon_state = "1-2" - }, /obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ dir = 8 }, @@ -38218,6 +38276,10 @@ pixel_x = -4; pixel_y = 8 }, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = 10; + pixel_y = -3 + }, /turf/simulated/floor/tiled, /area/horizon/security/custodial) "fan" = ( @@ -39747,6 +39809,10 @@ pixel_y = 3; pixel_x = 5 }, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = -10; + pixel_y = -3 + }, /turf/simulated/floor/carpet, /area/horizon/command/heads/om) "flo" = ( @@ -40383,9 +40449,6 @@ /turf/simulated/floor/tiled/dark/full, /area/horizon/hallway/primary/deck_3/port) "fpB" = ( -/obj/structure/cable/green{ - icon_state = "1-4" - }, /obj/structure/disposalpipe/segment{ dir = 4 }, @@ -40772,6 +40835,10 @@ id = "bridgeconf"; pixel_x = -3 }, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = -10; + pixel_y = -3 + }, /turf/simulated/floor/carpet, /area/horizon/command/bridge/meeting_room) "fse" = ( @@ -46096,6 +46163,10 @@ /obj/machinery/light{ dir = 8 }, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = 10; + pixel_y = -3 + }, /turf/simulated/floor/carpet, /area/horizon/security/investigators_office) "gfC" = ( @@ -54633,9 +54704,6 @@ /obj/effect/floor_decal/corner/brown{ dir = 5 }, -/obj/structure/cable/green{ - icon_state = "1-2" - }, /obj/structure/disposalpipe/segment{ dir = 1; icon_state = "pipe-c" @@ -54669,6 +54737,10 @@ /obj/machinery/cell_charger, /obj/item/paper_scanner, /obj/item/paicard, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = 10; + pixel_y = -3 + }, /turf/simulated/floor/tiled, /area/horizon/storage/primary) "hmK" = ( @@ -54716,6 +54788,13 @@ /obj/structure/bed/handrail{ pixel_y = 2 }, +/obj/machinery/button/remote/blast_door{ + dir = 1; + id = "quark_bay_outer"; + name = "Airlock Shutters"; + pixel_y = 27; + pixel_x = 8 + }, /turf/simulated/floor/tiled/dark, /area/horizon/shuttle/quark/cargo_hold) "hmW" = ( @@ -55771,6 +55850,11 @@ /obj/effect/landmark/entry_point/aft{ name = "aft, airlock" }, +/obj/machinery/door/blast/shutters/open{ + dir = 2; + id = "quark_bay_outer"; + name = "Quark Shutter" + }, /turf/simulated/floor/plating, /area/horizon/shuttle/quark/cargo_hold) "htP" = ( @@ -57196,7 +57280,7 @@ /area/horizon/engineering/atmos/air) "hCX" = ( /obj/machinery/door/firedoor, -/obj/machinery/smartfridge/secure/medbay, +/obj/machinery/smartfridge/secure/medbay/horizon, /turf/simulated/floor/tiled/dark/full, /area/horizon/medical/pharmacy) "hCZ" = ( @@ -58591,6 +58675,11 @@ /obj/effect/landmark/entry_point/aft{ name = "aft, airlock" }, +/obj/machinery/door/blast/shutters/open{ + dir = 2; + id = "spark_bay_outer"; + name = "Spark Shutter" + }, /turf/simulated/floor/tiled/dark/full, /area/horizon/shuttle/mining) "hLZ" = ( @@ -61782,6 +61871,10 @@ dir = 8 }, /obj/structure/table/reinforced/steel, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = 10; + pixel_y = -3 + }, /turf/simulated/floor/tiled/dark, /area/horizon/command/bridge/controlroom) "ijE" = ( @@ -62135,6 +62228,10 @@ /obj/effect/floor_decal/corner/grey/diagonal, /obj/item/paper_bin, /obj/item/pen, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = 10; + pixel_y = -3 + }, /turf/simulated/floor/tiled/white, /area/horizon/medical/reception) "ilr" = ( @@ -63165,8 +63262,6 @@ name = "Storage"; req_one_access = list(20,30,56) }, -/obj/random/telecrystals, -/obj/random/telecrystals, /obj/random/finances{ pixel_y = 5 }, @@ -63557,6 +63652,10 @@ dir = 8 }, /obj/machinery/atmospherics/unary/vent_pump/on, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = 10; + pixel_y = -3 + }, /turf/simulated/floor/tiled, /area/horizon/service/custodial/auxiliary) "ivn" = ( @@ -64059,6 +64158,10 @@ req_access = null; req_one_access = list(72) }, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = -10; + pixel_y = -3 + }, /turf/simulated/floor/carpet, /area/horizon/repoffice/consular_two) "iyy" = ( @@ -70567,9 +70670,6 @@ /turf/simulated/floor/tiled/dark, /area/horizon/security/checkpoint) "jsO" = ( -/obj/effect/landmark/start{ - name = "Hangar Technician" - }, /obj/effect/floor_decal/corner/brown{ dir = 9 }, @@ -73004,6 +73104,10 @@ pixel_y = 14; pixel_x = -2 }, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = 10; + pixel_y = -3 + }, /turf/simulated/floor/carpet, /area/horizon/command/heads/xo) "jLa" = ( @@ -74979,6 +75083,7 @@ /obj/structure/cable/green{ icon_state = "0-2" }, +/obj/item/tape_roll, /turf/simulated/floor/tiled/dark, /area/horizon/operations/commissary) "jXA" = ( @@ -76512,6 +76617,10 @@ /obj/item/pen/black{ pixel_x = 7 }, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = -10; + pixel_y = -3 + }, /turf/simulated/floor/tiled, /area/horizon/operations/machinist) "khq" = ( @@ -78599,13 +78708,14 @@ dir = 8 }, /obj/machinery/atmospherics/pipe/manifold/hidden/supply, -/obj/structure/disposalpipe/junction{ - dir = 8; - icon_state = "pipe-j2" - }, /obj/structure/cable/green{ icon_state = "4-8" }, +/obj/structure/disposalpipe/sortjunction/flipped{ + sortType = "Commissary"; + name = "Commissary"; + dir = 8 + }, /turf/simulated/floor/tiled, /area/horizon/operations/commissary) "kuW" = ( @@ -82524,11 +82634,11 @@ /area/horizon/engineering/reactor/supermatter/waste) "kUB" = ( /obj/structure/table/stone/marble, -/obj/item/reagent_containers/food/snacks/salad/tossedsalad{ +/obj/item/reagent_containers/food/snacks/salad/applesalad{ pixel_x = 18; pixel_y = 10 }, -/obj/item/reagent_containers/food/snacks/salad/tossedsalad{ +/obj/item/reagent_containers/food/snacks/salad/applesalad{ pixel_x = 16; pixel_y = 3 }, @@ -83199,6 +83309,10 @@ dir = 4 }, /obj/machinery/firealarm/east, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = 10; + pixel_y = -3 + }, /turf/simulated/floor/tiled/white, /area/horizon/rnd/telesci) "kYT" = ( @@ -86379,9 +86493,6 @@ "ltg" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /obj/structure/disposalpipe/segment, -/obj/structure/cable/green{ - icon_state = "1-2" - }, /obj/machinery/atmospherics/pipe/manifold/hidden/supply{ dir = 8 }, @@ -87414,6 +87525,10 @@ "lAw" = ( /obj/structure/table/wood, /obj/item/taperecorder, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = 10; + pixel_y = -3 + }, /turf/simulated/floor/carpet, /area/horizon/crew/journalistoffice) "lAB" = ( @@ -91991,8 +92106,8 @@ "mho" = ( /obj/machinery/access_button{ dir = 1; - pixel_x = -28; - pixel_y = 11 + pixel_x = -26; + pixel_y = 3 }, /obj/machinery/door/airlock/external{ dir = 1; @@ -92007,6 +92122,18 @@ cycle_to_external_air = 1 }, /obj/effect/floor_decal/industrial/hatch/grey, +/obj/machinery/door/blast/shutters/open{ + dir = 2; + id = "spark_bay_outer"; + name = "Spark Shutter" + }, +/obj/machinery/button/remote/blast_door{ + id = "spark_bay_outer"; + name = "Airlock Shutters"; + pixel_x = -26; + pixel_y = 11; + req_access = list(12,31,73,77) + }, /turf/simulated/floor/tiled/dark/full, /area/horizon/shuttle/mining) "mht" = ( @@ -92465,6 +92592,10 @@ req_access = null; req_one_access = list(72) }, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = -10; + pixel_y = -3 + }, /turf/simulated/floor/carpet, /area/horizon/repoffice/consular_one) "mko" = ( @@ -99716,6 +99847,10 @@ pixel_x = 4; pixel_y = -7 }, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = -10; + pixel_y = -3 + }, /turf/simulated/floor/tiled/dark/full, /area/horizon/service/kitchen) "nkP" = ( @@ -103265,6 +103400,7 @@ /obj/effect/floor_decal/corner_wide/green{ dir = 10 }, +/obj/machinery/light/floor, /turf/simulated/floor/tiled/white, /area/horizon/medical/gen_treatment) "nKc" = ( @@ -107128,12 +107264,6 @@ }, /turf/simulated/floor/reinforced, /area/horizon/weapons/grauwolf) -"olw" = ( -/obj/structure/bed/stool/chair{ - dir = 4 - }, -/turf/simulated/floor/tiled, -/area/horizon/operations/break_room) "oly" = ( /obj/structure/cable{ icon_state = "4-8" @@ -107876,7 +108006,7 @@ dir = 5 }, /obj/structure/cable/green{ - icon_state = "2-8" + icon_state = "1-8" }, /turf/simulated/floor/tiled, /area/horizon/operations/office) @@ -108288,7 +108418,7 @@ frequency = 1380; id_tag = "mining_shuttle_dock"; name = "\improper Spark docking port controller"; - pixel_x = 6; + pixel_x = -6; pixel_y = -19; req_one_access = list(31,48,67,74); tag_door = "mining_shuttle_dock_doors" @@ -110096,6 +110226,11 @@ dir = 9 }, /obj/item/storage/toolbox/mechanical, +/obj/machinery/requests_console/west{ + department = "Machinist Workshop"; + departmentType = 2; + name = "Machinist Requests Console" + }, /turf/simulated/floor/carpet/rubber, /area/horizon/operations/machinist) "oFM" = ( @@ -114134,6 +114269,15 @@ }, /turf/simulated/floor/tiled, /area/horizon/command/bridge/upperdeck) +"pgA" = ( +/obj/structure/bed/stool/chair{ + dir = 4 + }, +/obj/effect/landmark/start{ + name = "Hangar Technician" + }, +/turf/simulated/floor/tiled, +/area/horizon/operations/break_room) "pgB" = ( /obj/effect/floor_decal/corner/dark_green/full{ dir = 1 @@ -116641,15 +116785,19 @@ /obj/item/pen{ pixel_x = -6 }, +/obj/structure/table/reinforced/steel, +/obj/machinery/light, +/obj/item/folder/yellow{ + pixel_x = -5 + }, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = 10; + pixel_y = -3 + }, /obj/item/paper_scanner{ pixel_x = 9; pixel_y = 3 }, -/obj/item/folder/yellow{ - pixel_x = -5 - }, -/obj/structure/table/reinforced/steel, -/obj/machinery/light, /turf/simulated/floor/carpet, /area/horizon/command/heads/chief) "pyY" = ( @@ -126257,6 +126405,10 @@ dir = 2 }, /obj/effect/floor_decal/industrial/hatch_door/yellow, +/obj/structure/sign/crush{ + pixel_y = -32; + pixel_x = 32 + }, /turf/simulated/floor/tiled/full, /area/horizon/stairwell/port/deck_2) "qPg" = ( @@ -127222,6 +127374,9 @@ /obj/structure/bed/stool/chair{ dir = 8 }, +/obj/effect/landmark/start{ + name = "Hangar Technician" + }, /turf/simulated/floor/tiled, /area/horizon/operations/break_room) "qWr" = ( @@ -128123,19 +128278,23 @@ pixel_y = 5; pixel_x = 6 }, -/obj/item/pen/black, -/obj/item/price_scanner{ - pixel_x = 6 - }, /obj/machinery/button/remote/blast_door{ dir = 6; id = "cargo_desk"; pixel_x = -7; pixel_y = 8 }, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = -10; + pixel_y = -3 + }, /obj/item/folder/yellow{ pixel_x = 6 }, +/obj/item/price_scanner{ + pixel_x = 6 + }, +/obj/item/pen/black, /turf/simulated/floor/tiled, /area/horizon/operations/office) "rcp" = ( @@ -135771,6 +135930,10 @@ pixel_x = -4 }, /obj/machinery/power/outlet, +/obj/item/clipboard{ + pixel_y = -2; + pixel_x = -6 + }, /turf/simulated/floor/tiled/full, /area/horizon/engineering/lobby) "sbq" = ( @@ -138690,6 +138853,18 @@ cycle_to_external_air = 1 }, /obj/effect/map_effect/marker_helper/airlock/exterior, +/obj/machinery/door/blast/shutters/open{ + dir = 2; + id = "quark_bay_outer"; + name = "Quark Shutter" + }, +/obj/machinery/button/remote/blast_door{ + id = "quark_bay_outer"; + name = "Airlock Shutters"; + pixel_y = 13; + pixel_x = 32; + req_access = list(12,31,73,77) + }, /turf/simulated/floor/plating, /area/horizon/shuttle/quark/cargo_hold) "svw" = ( @@ -140725,7 +140900,8 @@ /obj/structure/table/reinforced/steel, /obj/item/quikpay{ destinationact = "Operations"; - pixel_y = 3 + pixel_y = 3; + shop_name = "Commissary Quikpay" }, /obj/machinery/power/outlet, /obj/machinery/door/blast/shutters{ @@ -156029,6 +156205,12 @@ pixel_x = -3; pixel_y = 6 }, +/obj/machinery/requests_console/north{ + department = "Commissary"; + departmentType = 2; + name = "Commissary Requests Console"; + pixel_y = 32 + }, /obj/machinery/door/blast/shutters{ dir = 4; id = "horizon_commissary_desk" @@ -156533,9 +156715,6 @@ /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/structure/disposalpipe/segment, -/obj/structure/cable/green{ - icon_state = "1-2" - }, /turf/simulated/floor/tiled, /area/horizon/operations/office) "uNZ" = ( @@ -161102,6 +161281,10 @@ }, /obj/item/stack/packageWrap, /obj/item/hand_labeler, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = 10; + pixel_y = -3 + }, /turf/simulated/floor/tiled, /area/horizon/security/office) "vvQ" = ( @@ -162094,12 +162277,6 @@ }, /turf/simulated/floor/tiled/full, /area/horizon/storage/primary) -"vCr" = ( -/obj/effect/landmark/start{ - name = "Hangar Technician" - }, -/turf/simulated/floor/tiled, -/area/horizon/operations/break_room) "vCI" = ( /obj/structure/sign/poster{ pixel_y = 32 @@ -163183,6 +163360,10 @@ dir = 4 }, /obj/machinery/firealarm/west, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = -10; + pixel_y = -3 + }, /turf/simulated/floor/tiled/full, /area/horizon/command/bridge/cciaroom) "vKD" = ( @@ -165263,6 +165444,10 @@ }, /obj/item/paper_bin, /obj/item/pen/black, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = -10; + pixel_y = -3 + }, /turf/simulated/floor/tiled/white, /area/horizon/rnd/xenological) "vZH" = ( @@ -169348,6 +169533,10 @@ /obj/machinery/atmospherics/unary/vent_scrubber/on{ dir = 4 }, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = 10; + pixel_y = -3 + }, /turf/simulated/floor/carpet, /area/horizon/repoffice/representative_one) "wyD" = ( @@ -175766,10 +175955,10 @@ sortType = "Commissary"; name = "Commissary" }, -/obj/structure/lattice/catwalk/indoor/grate, /obj/structure/cable/green{ icon_state = "2-4" }, +/obj/structure/lattice/catwalk/indoor/grate, /turf/simulated/floor/plating, /area/horizon/hallway/primary/deck_2/fore) "xqH" = ( @@ -177001,6 +177190,31 @@ /obj/structure/flora/ausbushes/sparsegrass, /turf/simulated/floor/grass/no_edge, /area/centcom/bar) +"xzb" = ( +/obj/structure/lattice/catwalk/indoor/grate/dark, +/obj/machinery/atmospherics/unary/vent_pump/high_volume, +/obj/machinery/door/blast/shutters/open{ + dir = 2; + id = "intrepid_bay_outer"; + name = "Intrepid Shutter" + }, +/obj/effect/map_effect/marker/airlock/shuttle{ + cycle_to_external_air = 1; + master_tag = "airlock_shuttle_intrepid"; + name = "airlock_shuttle_intrepid"; + req_one_access = null; + shuttle_tag = "Intrepid" + }, +/obj/effect/map_effect/marker_helper/airlock/exterior, +/obj/machinery/button/remote/blast_door{ + id = "intrepid_bay_outer"; + name = "Airlock Shutters"; + pixel_x = 32; + pixel_y = 12; + req_access = list(12,31,73,77) + }, +/turf/simulated/floor/plating, +/area/horizon/shuttle/intrepid/main_compartment) "xzd" = ( /obj/effect/floor_decal/industrial/warning{ dir = 4 @@ -177921,6 +178135,10 @@ pixel_x = -8 }, /obj/item/card/id/captains_spare, +/obj/item/paper/monitorkey{ + pixel_y = -6; + pixel_x = 9 + }, /turf/simulated/floor/wood, /area/horizon/command/heads/captain) "xFl" = ( @@ -179593,6 +179811,9 @@ /obj/machinery/atmospherics/pipe/manifold/hidden/supply{ dir = 1 }, +/obj/structure/cable/green{ + icon_state = "2-8" + }, /turf/simulated/floor/tiled, /area/horizon/operations/office) "xQO" = ( @@ -182145,6 +182366,10 @@ /obj/effect/floor_decal/spline/fancy/wood{ dir = 5 }, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = -10; + pixel_y = -3 + }, /turf/simulated/floor/wood, /area/horizon/command/heads/captain) "yja" = ( @@ -182272,10 +182497,6 @@ pixel_x = 5; pixel_y = 9 }, -/obj/item/clipboard{ - pixel_y = -2; - pixel_x = -6 - }, /obj/item/paper_bin{ pixel_x = 4; pixel_y = 2 @@ -182284,6 +182505,10 @@ /obj/machinery/light_switch/south{ pixel_x = -6 }, +/obj/item/paper/stickynotes/pad/random{ + pixel_x = -10; + pixel_y = -3 + }, /turf/simulated/floor/tiled, /area/horizon/engineering/lobby) "yjX" = ( @@ -215588,7 +215813,7 @@ dvM dUU psx dUU -aPe +xzb ghP hdc bPS @@ -268000,7 +268225,7 @@ nwj kiJ nwj rNQ -vCr +uGE aOf gAJ uVm @@ -268257,7 +268482,7 @@ djR lNh nwj fSu -vCr +uGE aOf gAJ uVm @@ -269540,8 +269765,8 @@ jkr pyM nwj lhf -olw -olw +pgA +pgA mzm cGa mRn diff --git a/nano/templates/jukebox.tmpl b/nano/templates/jukebox.tmpl deleted file mode 100644 index f7fac89ff9f2..000000000000 --- a/nano/templates/jukebox.tmpl +++ /dev/null @@ -1,19 +0,0 @@ - - -

Current track: {{:data.current_track}}

-
- {{:helper.link('Play' , 'play', {'play' : 1}, data.playing == 1 ? 'disabled' : null, null)}} - {{:helper.link('Stop' , 'stop', {'stop' : 1}, data.playing == 0 ? 'disabled' : null, null)}} -
- -

Available tracks:

-
- {{for data.tracks}} -
- {{:helper.link( value.track, 'gear', {'change_track' : 1, 'title' : value.track}, value.track == data.current_track ? 'disabled' : null, null)}} -
- {{/for}} -
\ No newline at end of file diff --git a/nano/templates/partyalarm.tmpl b/nano/templates/partyalarm.tmpl deleted file mode 100644 index e3adb80ffdd3..000000000000 --- a/nano/templates/partyalarm.tmpl +++ /dev/null @@ -1,24 +0,0 @@ -The current alert level is: -{{if data.alertLevel == 'green'}} - Green -{{/if}} -{{if data.alertLevel == 'blue'}} - Blue -{{/if}} -{{if data.alertLevel == 'red'}} - Red -{{/if}} -{{if data.alertLevel == 'delta'}} - DELTA -{{/if}} -
-

State

-{{:helper.link('No Party :(', '', {'state': 'inactive'}, data.active ? null : 'selected')}} -{{:helper.link('PARTY!!!', '', {'state': 'active'}, data.active ? 'selected' : null)}} -

Timed Lockdown

-{{:helper.link('Set', '', {'tmr' : 'set'})}} -{{if data.timing}} -{{:helper.link('Stop', '', {'tmr' : 'stop'})}} -{{/if}} -{{if !(data.timing)}}{{:helper.link('Start', '', {'tmr' : 'start'})}}{{/if}}
-{{if data.time}}Time Left: {{:data.time}} seconds.{{/if}} \ No newline at end of file diff --git a/nano/templates/radio_basic.tmpl b/nano/templates/radio_basic.tmpl deleted file mode 100644 index ceb02b3644ab..000000000000 --- a/nano/templates/radio_basic.tmpl +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - -{{if data.useSyndMode}} - {{:helper.syndicateMode()}} -{{/if}} - -
-
- Microphone -
-
- {{if data.mic_cut}} - {{:helper.link('On', null, null, 'disabled')}} - {{:helper.link('Off', null, null, 'disabled')}} - {{else}} - {{:helper.link('On', null, {'talk' : 0}, data.mic_status ? 'selected' : null)}} - {{:helper.link('Off', null, {'talk' : 1}, data.mic_status ? null : 'selected')}} - {{/if}} -
-
- -
-
- Speaker -
-
- {{if data.spk_cut}} - {{:helper.link('On', null, null, 'disabled')}} - {{:helper.link('Off', null, null, 'disabled')}} - {{else}} - {{:helper.link('On', null, {'listen' : 0}, data.speaker ? 'selected' : null)}} - {{:helper.link('Off', null, {'listen' : 1}, data.speaker ? null : 'selected')}} - {{/if}} -
-
- -{{if data.has_subspace}} -
-
- Subspace Transmission: -
-
- {{:helper.link('On', null, {'mode' : 1}, data.subspace ? 'selected' : null)}} - {{:helper.link('Off', null, {'mode' : 0}, data.subspace ? null : 'selected')}} -
-
-{{/if}} - -{{if data.has_loudspeaker}} -
-
- Loudspeaker: -
-
- {{:helper.link('On', null, {'shutup' : 0}, data.loudspeaker ? 'selected' : null)}} - {{:helper.link('Off', null, {'shutup' : 1}, data.loudspeaker ? null : 'selected')}} -
-
-{{/if}} - -
-
- Frequency: {{:data.freq}} -
-
- {{:helper.link('--', null, {'freq' : -10})}} - {{:helper.link('-', null, {'freq' : -2})}} - {{:helper.link('+', null, {'freq' : 2})}} - {{:helper.link('++', null, {'freq' : 10})}} - {{if data.default_freq}} - {{:helper.link(data.default_freq, null, {'default_freq' : 1})}} - {{/if}} -
-
- -{{if data.chan_list_len >= 1}} -

Channels

-
- {{for data.chan_list}} -
- {{:value.display_name}} -
-
- {{if value.secure_channel}} - {{:helper.link('On', null, {'ch_name' : value.chan, 'listen' : value.sec_channel_listen}, value.sec_channel_listen ? null : 'selected')}} - {{:helper.link('Off', null, {'ch_name' : value.chan, 'listen' : value.sec_channel_listen}, value.sec_channel_listen ? 'selected' : null)}} - {{else}} - {{:helper.link('Switch', null, {'spec_freq' : value.chan}, data.rawfreq == value.chan ? 'selected' : null)}} - {{/if}} -
- {{/for}} -{{/if}} diff --git a/nano/templates/simple_airlock_console.tmpl b/nano/templates/simple_airlock_console.tmpl deleted file mode 100644 index ca49b20f6aec..000000000000 --- a/nano/templates/simple_airlock_console.tmpl +++ /dev/null @@ -1,36 +0,0 @@ -
-
-
- Chamber Pressure: -
-
- {{:helper.displayBar(data.chamber_pressure, 0, 200, (data.chamber_pressure < 80) || (data.chamber_pressure > 120) ? 'bad' : (data.chamber_pressure < 95) || (data.chamber_pressure > 110) ? 'average' : 'good')}} -
- {{:data.chamber_pressure}} kPa -
-
-
-
-
-
-
- {{:helper.link('Cycle to Exterior', 'arrowthickstop-1-w', {'command' : 'cycle_ext'}, data.processing ? 'disabled' : null)}} - {{:helper.link('Cycle to Interior', 'arrowthickstop-1-e', {'command' : 'cycle_int'}, data.processing ? 'disabled' : null)}} -
-
- {{if data.interior_status.state == "open"}} - {{:helper.link('Force exterior door', 'alert', {'command' : 'force_ext'}, null, 'redButton')}} - {{else}} - {{:helper.link('Force exterior door', 'alert', {'command' : 'force_ext'}, null, data.processing ? 'yellowButton' : null)}} - {{/if}} - {{if data.exterior_status.state == "open"}} - {{:helper.link('Force interior door', 'alert', {'command' : 'force_int'}, null, 'redButton')}} - {{else}} - {{:helper.link('Force interior door', 'alert', {'command' : 'force_int'}, null, data.processing ? 'yellowButton' : null)}} - {{/if}} -
-
-
- {{:helper.link('Abort', 'cancel', {'command' : 'abort'}, data.processing ? null : 'disabled', data.processing ? 'redButton' : null)}} -
-
\ No newline at end of file diff --git a/tgui/package.json b/tgui/package.json index 6a18c1efac2d..b6dd1a99eeec 100644 --- a/tgui/package.json +++ b/tgui/package.json @@ -56,7 +56,7 @@ "terser-webpack-plugin": "^5.1.4", "typescript": "^4.9.5", "url-loader": "^4.1.1", - "webpack": "^5.94.0", + "webpack": "^5.104.1", "webpack-bundle-analyzer": "^4.4.2", "webpack-cli": "^4.7.2" } diff --git a/tgui/packages/tgui-dev-server/package.json b/tgui/packages/tgui-dev-server/package.json index aba7aae098b3..b5cef21b718c 100644 --- a/tgui/packages/tgui-dev-server/package.json +++ b/tgui/packages/tgui-dev-server/package.json @@ -4,7 +4,7 @@ "version": "4.3.1", "type": "module", "dependencies": { - "axios": "^1.12.0", + "axios": "^1.13.5", "glob": "^7.1.7", "source-map": "^0.7.4", "stacktrace-parser": "^0.1.10", diff --git a/tgui/packages/tgui-panel/chat/renderer.js b/tgui/packages/tgui-panel/chat/renderer.js index 318388b568e3..59a1d0cddf0c 100644 --- a/tgui/packages/tgui-panel/chat/renderer.js +++ b/tgui/packages/tgui-panel/chat/renderer.js @@ -128,12 +128,17 @@ class ChatRenderer { /** @type {HTMLElement} */ this.scrollNode = null; this.scrollTracking = true; + this.lastScrollHeight = 0; this.handleScroll = (type) => { const node = this.scrollNode; + if (!node) { + return; + } const height = node.scrollHeight; const bottom = node.scrollTop + node.offsetHeight; const scrollTracking = - Math.abs(height - bottom) < SCROLL_TRACKING_TOLERANCE; + Math.abs(height - bottom) < SCROLL_TRACKING_TOLERANCE || + this.lastScrollHeight === 0; if (scrollTracking !== this.scrollTracking) { this.scrollTracking = scrollTracking; this.events.emit('scrollTrackingChanged', scrollTracking); @@ -160,12 +165,6 @@ class ChatRenderer { else { this.rootNode = node; } - // Find scrollable parent - this.scrollNode = findNearestScrollableParent(this.rootNode); - this.scrollNode.addEventListener('scroll', this.handleScroll); - setImmediate(() => { - this.scrollToBottom(); - }); // Flush the queue this.tryFlushQueue(); } @@ -179,6 +178,7 @@ class ChatRenderer { if (this.isReady() && this.queue.length > 0) { this.processBatch(this.queue); this.queue = []; + this.scrollToBottom(); } } @@ -268,6 +268,7 @@ class ChatRenderer { } scrollToBottom() { + this.tryFindScrollable(); // scrollHeight is always bigger than scrollTop and is // automatically clamped to the valid range. this.scrollNode.scrollTop = this.scrollNode.scrollHeight; @@ -322,6 +323,17 @@ class ChatRenderer { return null; } + tryFindScrollable() { + // Find scrollable parent + if (this.rootNode) { + if (!this.scrollNode || this.scrollNode.scrollHeight === undefined) { + this.scrollNode = findNearestScrollableParent(this.rootNode); + this.scrollNode.addEventListener('scroll', this.handleScroll); + logger.debug(`reset scrollNode to ${this.scrollNode}`); + } + } + } + processBatch(batch, options = {}) { const { prepend, notifyListeners = true } = options; const now = Date.now(); @@ -334,6 +346,10 @@ class ChatRenderer { } return; } + // Store last scroll position + if (this.scrollNode) { + this.lastScrollHeight = this.scrollNode.scrollHeight; + } // Insert messages const fragment = document.createDocumentFragment(); const countByType = {}; diff --git a/tgui/packages/tgui-panel/panelFocus.js b/tgui/packages/tgui-panel/panelFocus.ts similarity index 85% rename from tgui/packages/tgui-panel/panelFocus.js rename to tgui/packages/tgui-panel/panelFocus.ts index b7cea2293149..2ae69e0aa515 100644 --- a/tgui/packages/tgui-panel/panelFocus.js +++ b/tgui/packages/tgui-panel/panelFocus.ts @@ -19,9 +19,9 @@ const deferredFocusMap = () => setImmediate(() => focusMap()); export const setupPanelFocusHacks = () => { let focusStolen = false; - let clickStartPos = null; + let clickStartPos: number[] | null = null; window.addEventListener('focusin', (e) => { - focusStolen = canStealFocus(e.target); + focusStolen = canStealFocus(e.target as HTMLElement); }); window.addEventListener('mousedown', (e) => { clickStartPos = [e.screenX, e.screenY]; @@ -33,6 +33,9 @@ export const setupPanelFocusHacks = () => { if (dist >= MIN_SELECTION_DISTANCE) { focusStolen = true; } + if (document.activeElement?.className?.includes('Button')) { + focusStolen = true; + } } if (!focusStolen) { deferredFocusMap(); diff --git a/tgui/packages/tgui-panel/telemetry.js b/tgui/packages/tgui-panel/telemetry.js index d1f7346af60f..581d32f30697 100644 --- a/tgui/packages/tgui-panel/telemetry.js +++ b/tgui/packages/tgui-panel/telemetry.js @@ -11,12 +11,10 @@ const logger = createLogger('telemetry'); const MAX_CONNECTIONS_STORED = 10; -// prettier-ignore -const connectionsMatch = (a, b) => ( - a.ckey === b.ckey - && a.address === b.address - && a.computer_id === b.computer_id -); +const connectionsMatch = (a, b) => + a.ckey === b.ckey && + a.address === b.address && + a.computer_id === b.computer_id; export const telemetryMiddleware = (store) => { let telemetry; @@ -38,6 +36,14 @@ export const telemetryMiddleware = (store) => { Byond.sendMessage('telemetry', { connections }); return; } + // For whatever reason we didn't get the telemetry, re-request + if (type === 'testTelemetryCommand') { + setTimeout(() => { + if (!telemetry) { + Byond.sendMessage('ready'); + } + }, 500); + } // Keep telemetry up to date if (type === 'backend/update') { next(action); @@ -58,9 +64,10 @@ export const telemetryMiddleware = (store) => { } // Append a connection record let telemetryMutated = false; - // prettier-ignore - const duplicateConnection = telemetry.connections - .find(conn => connectionsMatch(conn, client)); + + const duplicateConnection = telemetry.connections.find((conn) => + connectionsMatch(conn, client), + ); if (!duplicateConnection) { telemetryMutated = true; telemetry.connections.unshift(client); diff --git a/tgui/packages/tgui-panel/themes.ts b/tgui/packages/tgui-panel/themes.ts index 4e083e29ae18..2393e8656e1e 100644 --- a/tgui/packages/tgui-panel/themes.ts +++ b/tgui/packages/tgui-panel/themes.ts @@ -4,7 +4,7 @@ * @license MIT */ -export const THEMES = ['light', 'dark']; +export const THEMES = ['dark', 'light']; const COLORS = { DARK: { diff --git a/tgui/packages/tgui/interfaces/AirlockConsoleAccess.tsx b/tgui/packages/tgui/interfaces/AirlockConsoleAccess.tsx index f82592588a61..1f3b1560ad33 100644 --- a/tgui/packages/tgui/interfaces/AirlockConsoleAccess.tsx +++ b/tgui/packages/tgui/interfaces/AirlockConsoleAccess.tsx @@ -1,15 +1,11 @@ import { useBackend } from '../backend'; import { Box, Button, LabeledList, Section } from '../components'; import { Window } from '../layouts'; - -export type StatusData = { - state: string; - lock: string; -}; +import { BooleanLike } from '../../common/react'; export type AccessAirlockConsoleData = { - exterior_status: StatusData; - interior_status: StatusData; + exterior_secured: BooleanLike; + interior_secured: BooleanLike; processing: boolean; }; @@ -22,18 +18,24 @@ export const AirlockConsoleAccess = (props, context) => {
- - {data.exterior_status.state === 'open' ? ( - Open + + {data.exterior_secured ? ( + Secured ) : ( - Locked + Unsecured )} - - {data.interior_status.state === 'open' ? ( - Open + + {data.interior_secured ? ( + Secured ) : ( - Locked + Unsecured )} @@ -44,12 +46,26 @@ export const AirlockConsoleAccess = (props, context) => {
diff --git a/tgui/packages/tgui/interfaces/Apc.tsx b/tgui/packages/tgui/interfaces/Apc.tsx index 121232b00038..9e73c0a1574b 100644 --- a/tgui/packages/tgui/interfaces/Apc.tsx +++ b/tgui/packages/tgui/interfaces/Apc.tsx @@ -184,22 +184,25 @@ export const APCWindow = (props, context) => {