diff --git a/.dockerignore b/.dockerignore index 2e6259d23d..9c6ac6b4aa 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,6 +1,5 @@ .dockerignore .editorconfig -.travis.yml GPLv3.txt LICENSE README.md @@ -26,5 +25,4 @@ tgstation.dyn.rsc libmariadb.dll rust_g.dll BSQL.dll -appveyor.yml Dockerfile diff --git a/.gitattributes b/.gitattributes index c447869d3e..b23dfe6932 100644 --- a/.gitattributes +++ b/.gitattributes @@ -38,5 +38,8 @@ *.dmm text eol=lf merge=dmm *.dmi binary merge=dmi +##Force tab indents on dm files +*.dm whitespace=indent-with-non-tab + ## Force changelog merging to use union html/changelog.html text eol=lf merge=union diff --git a/.github/workflows/ci_suite.yml b/.github/workflows/ci_suite.yml new file mode 100644 index 0000000000..76a1c26656 --- /dev/null +++ b/.github/workflows/ci_suite.yml @@ -0,0 +1,114 @@ +name: CI Suite +on: + push: + branches: + - master + pull_request: + branches: + - master +jobs: + run_linters: + if: "!contains(github.event.head_commit.message, '[ci skip]')" + name: Run Linters + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Setup cache + uses: actions/cache@v2 + with: + path: $HOME/SpacemanDMM + key: ${{ runner.os }}-spacemandmm + - name: Install Tools + run: | + pip3 install setuptools + bash tools/ci/install_build_tools.sh + bash tools/ci/install_spaceman_dmm.sh dreamchecker + pip3 install -r tools/mapmerge2/requirements.txt + - name: Run Linters + run: | + bash tools/ci/check_filedirs.sh tgstation.dme + bash tools/ci/check_changelogs.sh + find . -name "*.php" -print0 | xargs -0 -n1 php -l + find . -name "*.json" -not -path "*/node_modules/*" -print0 | xargs -0 python3 ./tools/json_verifier.py + bash tools/ci/build_tgui.sh + bash tools/ci/check_grep.sh + python3 tools/mapmerge2/dmi.py --test + ~/dreamchecker > ${GITHUB_WORKSPACE}/output-annotations.txt 2>&1 + - name: Annotate Lints + uses: yogstation13/DreamAnnotate@v1 + if: always() + with: + outputFile: output-annotations.txt + + compile_all_maps: + if: "!contains(github.event.head_commit.message, '[ci skip]')" + name: Compile Maps + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Setup cache + uses: actions/cache@v2 + with: + path: $HOME/BYOND + key: ${{ runner.os }}-byond + - name: Compile All Maps + run: | + bash tools/ci/install_byond.sh + source $HOME/BYOND/byond/bin/byondsetup + python3 tools/ci/template_dm_generator.py + bash tools/ci/dm.sh -DCIBUILDING -DCITESTING -DALL_MAPS tgstation.dme + run_all_tests: + if: "!contains(github.event.head_commit.message, '[ci skip]')" + name: Integration Tests + runs-on: ubuntu-latest + services: + mysql: + image: mysql:latest + env: + MYSQL_ROOT_PASSWORD: root + ports: + - 3306 + options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + steps: + - uses: actions/checkout@v2 + - name: Setup cache + uses: actions/cache@v2 + with: + path: $HOME/BYOND + key: ${{ runner.os }}-byond + - name: Setup database + run: | + sudo systemctl start mysql + mysql -u root -proot -e 'CREATE DATABASE tg_ci;' + mysql -u root -proot tg_ci < SQL/tgstation_schema.sql + mysql -u root -proot -e 'CREATE DATABASE tg_ci_prefixed;' + mysql -u root -proot tg_ci_prefixed < SQL/tgstation_schema_prefixed.sql + - name: Install rust-g + run: | + sudo dpkg --add-architecture i386 + sudo apt update || true + sudo apt install libssl1.1:i386 + bash tools/ci/install_rust_g.sh + # - name: Compile and run tests + # run: | + # bash tools/ci/install_byond.sh + # source $HOME/BYOND/byond/bin/byondsetup + # bash tools/ci/dm.sh -DCIBUILDING tgstation.dme + # bash tools/ci/run_server.sh + test_windows: + if: "!contains(github.event.head_commit.message, '[ci skip]')" + name: Windows Build + runs-on: windows-latest + steps: + - uses: actions/checkout@v2 + - name: Compile + run: pwsh tools/ci/build.ps1 + - name: Create artifact + run: | + md deploy + bash tools/deploy.sh ./deploy + - name: Deploy artifact + uses: actions/upload-artifact@v2 + with: + name: deploy + path: deploy diff --git a/.github/workflows/compile_changelogs.yml b/.github/workflows/compile_changelogs.yml index 4fd396f133..c8756f0d28 100644 --- a/.github/workflows/compile_changelogs.yml +++ b/.github/workflows/compile_changelogs.yml @@ -15,7 +15,7 @@ jobs: CHANGELOG_ENABLER: ${{ secrets.CHANGELOG_ENABLER }} run: | unset SECRET_EXISTS - if [-n $CHANGELOG_ENABLER]; then SECRET_EXISTS='true' ; fi + if [ -n $CHANGELOG_ENABLER ]; then SECRET_EXISTS='true' ; fi echo ::set-output name=CL_ENABLED::${SECRET_EXISTS} - name: "Setup python" if: steps.value_holder.outputs.CL_ENABLED diff --git a/.github/workflows/docker_publish.yml b/.github/workflows/docker_publish.yml new file mode 100644 index 0000000000..7417a382c4 --- /dev/null +++ b/.github/workflows/docker_publish.yml @@ -0,0 +1,22 @@ +name: Docker Build + +on: + push: + branches: + - master + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Build and Publish Docker Image to Registry + uses: elgohr/Publish-Docker-Github-Action@master + with: + name: tgstation/tgstation + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + dockerfile: Dockerfile + tags: "latest" + cache: true diff --git a/.github/workflows/generate_documentation.yml b/.github/workflows/generate_documentation.yml new file mode 100644 index 0000000000..d0d61be073 --- /dev/null +++ b/.github/workflows/generate_documentation.yml @@ -0,0 +1,31 @@ +name: Generate documentation +on: + push: + branches: + - master +jobs: + generate_documentation: + if: "!contains(github.event.head_commit.message, '[ci skip]')" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Setup cache + uses: actions/cache@v2 + with: + path: $HOME/SpacemanDMM + key: ${{ runner.os }}-spacemandmm + - name: Install SpacemanDMM + run: bash tools/ci/install_spaceman_dmm.sh dmdoc + - name: Generate documentation + run: | + ~/dmdoc + touch dmdoc/.nojekyll + echo codedocs.tgstation13.org > dmdoc/CNAME + - name: Deploy + uses: JamesIves/github-pages-deploy-action@3.7.1 + with: + BRANCH: gh-pages + CLEAN: true + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SINGLE_COMMIT: true + FOLDER: dmdoc diff --git a/.github/workflows/update_tgs_dmapi.yml b/.github/workflows/update_tgs_dmapi.yml index 6fe53f700c..c7bb5c970c 100644 --- a/.github/workflows/update_tgs_dmapi.yml +++ b/.github/workflows/update_tgs_dmapi.yml @@ -26,6 +26,7 @@ jobs: library-path: 'code/modules/tgs' - name: Commit and Push + continue-on-error: true run: | git config user.name tgstation-server git config user.email tgstation-server@users.noreply.github.com @@ -35,6 +36,7 @@ jobs: - name: Create Pull Request uses: repo-sync/pull-request@v2 + if: ${{ success() }} with: source_branch: "tgs-dmapi-update" destination_branch: "master" @@ -42,4 +44,4 @@ jobs: pr_body: "This pull request updates the TGS DMAPI to the latest version. Please note any breaking or unimplemented changes before merging." pr_label: "Tools" pr_allow_empty: false - github_token: ${{ secrets.GITHUB_TOKEN }} + github_token: ${{ secrets.TGS_UPDATER }} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 83ef6fa8ff..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,102 +0,0 @@ -language: generic -os: linux -dist: xenial - -branches: - except: - - ___TGS3TempBranch - - ___TGSTempBranch - -jobs: - include: - - name: "Run Linters" - addons: - apt: - packages: - - python3 - - python3-pip - - python3-setuptools - - pcregrep - - rustc - - cargo - cache: - directories: - - $HOME/SpacemanDMM - install: - - tools/travis/install_build_tools.sh - - tools/travis/install_spaceman_dmm.sh dreamchecker - script: - - tools/travis/check_filedirs.sh tgstation.dme - - tools/travis/check_changelogs.sh - - find . -name "*.php" -print0 | xargs -0 -n1 php -l - - find . -name "*.json" -not -path "*/node_modules/*" -print0 | xargs -0 python3 ./tools/json_verifier.py - - tools/travis/build_tgui.sh - - tools/travis/check_grep.sh - - python3 tools/travis/check_line_endings.py - - ~/dreamchecker - - - name: "Compile All Maps" - addons: - apt: - packages: - - libstdc++6:i386 - cache: - directories: - - $HOME/BYOND - install: - - tools/travis/install_byond.sh - - source $HOME/BYOND/byond/bin/byondsetup - before_script: - - tools/travis/template_dm_generator.py - script: - - tools/travis/dm.sh -DTRAVISBUILDING -DTRAVISTESTING -DALL_MAPS tgstation.dme - - - name: "Compile and Run Tests" - addons: - mariadb: '10.2' - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - libstdc++6:i386 - - gcc-multilib - - g++-7 - - g++-7-multilib - - libmariadb-client-lgpl-dev:i386 - - libmariadbd-dev - cache: - directories: - - $HOME/BYOND - - $HOME/libmariadb - install: - - tools/travis/install_byond.sh - - source $HOME/BYOND/byond/bin/byondsetup - - tools/travis/install_libmariadb.sh - - tools/travis/install_rust_g.sh - before_script: - - mysql -u root -e 'CREATE DATABASE tg_travis;' - - mysql -u root tg_travis < SQL/tgstation_schema.sql - - mysql -u root -e 'CREATE DATABASE tg_travis_prefixed;' - - mysql -u root tg_travis_prefixed < SQL/tgstation_schema_prefixed.sql - - tools/travis/build_bsql.sh - script: - - tools/travis/dm.sh -DTRAVISBUILDING tgstation.dme || travis_terminate 1 - - tools/travis/run_server.sh - - # - name: "Generate Documentation" - # # Only run for non-PR commits to the real master branch. - # if: branch = master AND head_branch IS blank - # install: - # - tools/travis/install_spaceman_dmm.sh dmdoc - # before_script: - # # Travis checks out a hash, try to get back on a branch. - # - git checkout $TRAVIS_BRANCH || true - # script: - # - ~/dmdoc - # - touch dmdoc/.nojekyll - # deploy: - # provider: pages - # skip_cleanup: true - # local_dir: dmdoc - # token: $DMDOC_GITHUB_TOKEN - # fqdn: codedocs.tgstation13.org diff --git a/.vscode/extensions.json b/.vscode/extensions.json index f79100f563..bf0d9d2fb9 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,9 +1,10 @@ { - "recommendations": [ - "gbasood.byond-dm-language-support", - "platymuus.dm-langclient", + "recommendations": [ + "gbasood.byond-dm-language-support", + "platymuus.dm-langclient", "EditorConfig.EditorConfig", "arcanis.vscode-zipfs", - "dbaeumer.vscode-eslint" - ] + "dbaeumer.vscode-eslint", + "kevinkyang.auto-comment-blocks" + ] } diff --git a/Dockerfile b/Dockerfile index e8a5f44908..cca7e43a54 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,12 @@ -FROM tgstation/byond:513.1508 as base +FROM tgstation/byond:513.1533 as base -FROM base as build_base +FROM base as rust_g RUN apt-get update \ && apt-get install -y --no-install-recommends \ git \ ca-certificates -FROM build_base as rust_g - WORKDIR /rust_g RUN apt-get install -y --no-install-recommends \ @@ -27,36 +25,6 @@ RUN /bin/bash -c "source dependencies.sh \ && git checkout FETCH_HEAD \ && ~/.cargo/bin/cargo build --release -FROM build_base as bsql - -WORKDIR /bsql - -RUN apt-get install -y --no-install-recommends software-properties-common \ - && add-apt-repository ppa:ubuntu-toolchain-r/test \ - && apt-get update \ - && apt-get install -y --no-install-recommends \ - cmake \ - make \ - g++-7 \ - libmariadb-client-lgpl-dev \ - && git init \ - && git remote add origin https://github.com/tgstation/BSQL - -COPY dependencies.sh . - -RUN /bin/bash -c "source dependencies.sh \ - && git fetch --depth 1 origin \$BSQL_VERSION" \ - && git checkout FETCH_HEAD - -WORKDIR /bsql/artifacts - -ENV CC=gcc-7 CXX=g++-7 - -RUN ln -s /usr/include/mariadb /usr/include/mysql \ - && ln -s /usr/lib/i386-linux-gnu /root/MariaDB \ - && cmake .. \ - && make - FROM base as dm_base WORKDIR /tgstation @@ -65,26 +33,30 @@ FROM dm_base as build COPY . . -RUN DreamMaker -max_errors 0 tgstation.dme && tools/deploy.sh /deploy +RUN DreamMaker -max_errors 0 tgstation.dme \ + && tools/deploy.sh /deploy \ + && rm /deploy/*.dll FROM dm_base EXPOSE 1337 RUN apt-get update \ + && apt-get install -y --no-install-recommends software-properties-common \ + && add-apt-repository ppa:ubuntu-toolchain-r/test \ + && apt-get update \ + && apt-get upgrade -y \ + && apt-get dist-upgrade -y \ && apt-get install -y --no-install-recommends \ + libmariadb2 \ mariadb-client \ libssl1.0.0 \ && rm -rf /var/lib/apt/lists/* \ && mkdir -p /root/.byond/bin COPY --from=rust_g /rust_g/target/release/librust_g.so /root/.byond/bin/rust_g -COPY --from=bsql /bsql/artifacts/src/BSQL/libBSQL.so ./ COPY --from=build /deploy ./ -#bsql fexists memes -RUN ln -s /tgstation/libBSQL.so /root/.byond/bin/libBSQL.so - VOLUME [ "/tgstation/config", "/tgstation/data" ] ENTRYPOINT [ "DreamDaemon", "tgstation.dmb", "-port", "1337", "-trusted", "-close", "-verbose" ] diff --git a/SpacemanDMM.toml b/SpacemanDMM.toml index b827472254..eb25c8a0cd 100644 --- a/SpacemanDMM.toml +++ b/SpacemanDMM.toml @@ -1,2 +1,9 @@ [langserver] dreamchecker = true + +#[code_standards] +#disallow_relative_type_definitions = true +#disallow_relative_proc_definitions = true + +[dmdoc] +use_typepath_names = true diff --git a/TGS3.json b/TGS3.json index 39b75bd913..228854a166 100644 --- a/TGS3.json +++ b/TGS3.json @@ -1,22 +1,9 @@ { "documentation": "/tg/station server 3 configuration file", - "changelog": { - "script": "tools/ss13_genchangelog.py", - "arguments": "html/changelog.html html/changelogs", - "pip_dependancies": [ - "PyYaml", - "beautifulsoup4" - ] - }, - "synchronize_paths": [ - "html/changelog.html", - "html/changelogs/*" - ], + "synchronize_paths": [], "static_directories": [ "config", "data" ], - "dlls": [ - "libmariadb.dll" - ] + "dlls": [] } diff --git a/_maps/RandomRuins/SpaceRuins/crashedship.dmm b/_maps/RandomRuins/SpaceRuins/crashedship.dmm index 63e6770e42..beb93b319e 100644 --- a/_maps/RandomRuins/SpaceRuins/crashedship.dmm +++ b/_maps/RandomRuins/SpaceRuins/crashedship.dmm @@ -2372,7 +2372,7 @@ }, /area/awaymission/BMPship/Midship) "hh" = ( -/obj/item/caution, +/obj/item/clothing/suit/caution, /turf/open/floor/plating/airless, /area/awaymission/BMPship/Midship) "hi" = ( diff --git a/_maps/RandomRuins/SpaceRuins/skelter.dmm b/_maps/RandomRuins/SpaceRuins/skelter.dmm index f6e56a6348..77837392e4 100644 --- a/_maps/RandomRuins/SpaceRuins/skelter.dmm +++ b/_maps/RandomRuins/SpaceRuins/skelter.dmm @@ -2729,9 +2729,7 @@ /turf/open/floor/carpet, /area/ruin/space/has_grav/skelter/admin) "gx" = ( -/obj/machinery/door/firedoor{ - pixel_x = 0 - }, +/obj/machinery/door/firedoor, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/structure/cable/yellow{ icon_state = "1-2" @@ -2742,9 +2740,7 @@ /turf/open/floor/plasteel/showroomfloor, /area/ruin/space/has_grav/skelter/shields) "gy" = ( -/obj/machinery/door/firedoor{ - pixel_x = 0 - }, +/obj/machinery/door/firedoor, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/door/airlock/engineering{ name = "Shields" diff --git a/_maps/RandomRuins/StationRuins/Lavaland/Mining_Station/Mining_Station_Public_01.dmm b/_maps/RandomRuins/StationRuins/Lavaland/Mining_Station/Mining_Station_Public_01.dmm index 1aed2fdbb0..69cf7c0867 100644 --- a/_maps/RandomRuins/StationRuins/Lavaland/Mining_Station/Mining_Station_Public_01.dmm +++ b/_maps/RandomRuins/StationRuins/Lavaland/Mining_Station/Mining_Station_Public_01.dmm @@ -3170,7 +3170,9 @@ /turf/open/lava/smooth/lava_land_surface, /area/lavaland/surface/outdoors) "VY" = ( -/obj/structure/closet/emcloset, +/obj/structure/closet/emcloset{ + anchored = 1 + }, /obj/effect/turf_decal/tile/purple{ dir = 1 }, diff --git a/_maps/RandomZLevels/away_mission/Academy.dmm b/_maps/RandomZLevels/away_mission/Academy.dmm index 37b0098fd2..9b61f50600 100644 --- a/_maps/RandomZLevels/away_mission/Academy.dmm +++ b/_maps/RandomZLevels/away_mission/Academy.dmm @@ -2710,7 +2710,7 @@ /obj/structure/cable{ icon_state = "4-8" }, -/obj/item/caution, +/obj/item/clothing/suit/caution, /obj/effect/turf_decal/tile/green, /obj/effect/turf_decal/tile/green{ dir = 4 diff --git a/_maps/RandomZLevels/away_mission/SnowCabin.dmm b/_maps/RandomZLevels/away_mission/SnowCabin.dmm index 844a134d27..fbb83899fd 100644 --- a/_maps/RandomZLevels/away_mission/SnowCabin.dmm +++ b/_maps/RandomZLevels/away_mission/SnowCabin.dmm @@ -312,7 +312,7 @@ /obj/structure/janitorialcart, /obj/item/mop, /obj/item/reagent_containers/glass/bucket, -/obj/item/caution, +/obj/item/clothing/suit/caution, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/awaymission/cabin) diff --git a/_maps/_basemap.dm b/_maps/_basemap.dm index 213211fc42..bf5b4f7d49 100644 --- a/_maps/_basemap.dm +++ b/_maps/_basemap.dm @@ -13,7 +13,7 @@ #include "map_files\BoxStation\BoxStation.dmm" #include "map_files\LambdaStation\lambda.dmm" - #ifdef TRAVISBUILDING + #ifdef CIBUILDING #include "templates.dm" #endif #endif diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index bb372563cf..b81f55be21 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -69,35 +69,18 @@ /turf/closed/wall/r_wall, /area/security/prison) "aaj" = ( +/obj/structure/cable{ + icon_state = "1-4" + }, /obj/structure/cable{ icon_state = "4-8" }, -/turf/closed/wall/r_wall, -/area/security/prison) -"aak" = ( -/obj/structure/cable{ - icon_state = "0-4" - }, -/obj/effect/spawner/structure/window/reinforced, -/turf/open/floor/plating, -/area/security/prison) -"aal" = ( -/obj/structure/cable{ - icon_state = "0-4" - }, -/obj/structure/cable{ - icon_state = "0-8" - }, -/obj/effect/spawner/structure/window/reinforced, -/turf/open/floor/plating, +/turf/open/floor/plasteel, /area/security/prison) "aam" = ( /obj/structure/cable{ icon_state = "0-2" }, -/obj/structure/cable{ - icon_state = "0-8" - }, /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/security/prison) @@ -115,11 +98,17 @@ /obj/structure/sign/warning/electricshock{ pixel_y = 32 }, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/grass, /area/security/prison) "aap" = ( /obj/machinery/hydroponics/soil, /obj/item/seeds/carrot, +/obj/structure/cable{ + icon_state = "1-4" + }, /turf/open/floor/grass, /area/security/prison) "aaq" = ( @@ -140,17 +129,29 @@ /obj/structure/sink{ pixel_y = 20 }, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/plasteel, /area/security/prison) "aar" = ( /obj/machinery/hydroponics/soil, /obj/item/seeds/glowshroom, +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/grass, /area/security/prison) "aas" = ( /obj/structure/sign/warning/electricshock{ pixel_y = 32 }, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/plasteel, /area/security/prison) "aat" = ( @@ -5666,6 +5667,9 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/structure/cable{ + icon_state = "2-4" + }, /turf/open/floor/plasteel, /area/security/brig) "akw" = ( @@ -5845,10 +5849,13 @@ /area/science/xenobiology) "akQ" = ( /obj/structure/cable{ - icon_state = "4-8" + icon_state = "1-2" }, -/turf/closed/wall, -/area/security/brig) +/obj/structure/cable{ + icon_state = "2-8" + }, +/turf/open/floor/plasteel, +/area/security/prison) "akR" = ( /obj/machinery/camera{ c_tag = "Security Office"; @@ -6108,7 +6115,7 @@ "alq" = ( /obj/machinery/door/airlock/security/glass{ name = "Evidence Storage"; - req_access_txt = "4" + req_one_access_txt = "4;1" }, /obj/machinery/door/firedoor, /obj/machinery/atmospherics/pipe/simple/supply/hidden, @@ -6142,25 +6149,11 @@ /turf/open/floor/plasteel, /area/security/brig) "alt" = ( -/obj/machinery/door/airlock/security/glass{ - id_tag = "innerbrig"; - name = "Brig"; - req_access_txt = "63" - }, -/obj/machinery/door/firedoor, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper, -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/effect/turf_decal/tile/red{ - dir = 8 - }, -/obj/effect/turf_decal/tile/red{ - dir = 1 +/obj/structure/cable{ + icon_state = "1-2" }, /turf/open/floor/plasteel, /area/security/brig) @@ -6180,16 +6173,11 @@ /area/ai_monitored/nuke_storage) "alv" = ( /obj/effect/spawner/structure/window/reinforced, -/obj/structure/cable{ - icon_state = "0-8" - }, -/obj/structure/cable{ - icon_state = "0-4" - }, /obj/machinery/door/poddoor/preopen{ id = "Secure Gate"; name = "brig shutters" }, +/obj/structure/cable, /turf/open/floor/plating, /area/security/brig) "alw" = ( @@ -6272,6 +6260,9 @@ /obj/effect/turf_decal/tile/red{ dir = 4 }, +/obj/structure/cable{ + icon_state = "2-4" + }, /turf/open/floor/plasteel, /area/security/brig) "alB" = ( @@ -6572,9 +6563,6 @@ /turf/open/floor/engine, /area/science/xenobiology) "amm" = ( -/obj/structure/cable{ - icon_state = "0-8" - }, /obj/structure/cable{ icon_state = "0-4" }, @@ -6609,6 +6597,9 @@ /obj/effect/turf_decal/tile/red{ dir = 4 }, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/plasteel, /area/security/brig) "amq" = ( @@ -6661,9 +6652,6 @@ icon_state = "0-8" }, /obj/effect/spawner/structure/window/reinforced, -/obj/structure/cable{ - icon_state = "0-4" - }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plating, /area/security/brig) @@ -6763,6 +6751,12 @@ /obj/effect/turf_decal/tile/red{ dir = 1 }, +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/cable{ + icon_state = "2-8" + }, /turf/open/floor/plasteel, /area/security/brig) "amJ" = ( @@ -6853,25 +6847,15 @@ }, /turf/open/floor/plasteel, /area/science/xenobiology) -"amR" = ( -/obj/structure/cable{ - icon_state = "0-4" - }, -/obj/structure/cable{ - icon_state = "0-8" - }, -/obj/machinery/door/poddoor/preopen{ - id = "Secure Gate"; - name = "brig shutters" - }, -/obj/effect/spawner/structure/window/reinforced, -/turf/open/floor/plating, -/area/security/brig) "amS" = ( -/obj/structure/cable{ - icon_state = "4-8" +/obj/effect/turf_decal/tile/red, +/obj/effect/turf_decal/tile/red{ + dir = 8 }, -/turf/closed/wall/r_wall, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel, /area/security/brig) "amT" = ( /obj/structure/cable{ @@ -7271,9 +7255,11 @@ /obj/structure/cable{ icon_state = "0-4" }, -/obj/structure/cable, /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/structure/cable{ + icon_state = "1-4" + }, /turf/open/floor/plating, /area/security/brig) "anQ" = ( @@ -7281,9 +7267,6 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, -/obj/structure/cable{ - icon_state = "1-2" - }, /turf/open/floor/plasteel, /area/security/brig) "anR" = ( @@ -7514,14 +7497,13 @@ /obj/structure/cable{ icon_state = "0-4" }, -/obj/structure/cable, /obj/machinery/door/poddoor/preopen{ id = "Secure Gate"; name = "brig shutters" }, /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable{ - icon_state = "1-8" + icon_state = "0-8" }, /turf/open/floor/plating, /area/security/brig) @@ -7755,13 +7737,13 @@ /area/security/brig) "aoZ" = ( /obj/effect/spawner/structure/window/reinforced, -/obj/structure/cable{ - icon_state = "0-2" - }, /obj/machinery/door/poddoor/preopen{ id = "Secure Brig Control"; name = "brig shutters" }, +/obj/structure/cable{ + icon_state = "0-4" + }, /turf/open/floor/plating, /area/security/warden) "apa" = ( @@ -7780,6 +7762,9 @@ /area/science/xenobiology) "apc" = ( /obj/structure/chair/office/dark, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/plasteel/showroomfloor, /area/security/warden) "apd" = ( @@ -7933,6 +7918,12 @@ pixel_x = 6; pixel_y = 3 }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/cable{ + icon_state = "2-4" + }, /turf/open/floor/plasteel/showroomfloor, /area/security/warden) "apw" = ( @@ -8052,6 +8043,12 @@ pixel_y = -24; req_access_txt = "2" }, +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/plasteel/showroomfloor, /area/security/warden) "apI" = ( @@ -8133,9 +8130,6 @@ req_access_txt = "63" }, /obj/machinery/door/firedoor, -/obj/structure/cable{ - icon_state = "4-8" - }, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 1 }, @@ -8158,14 +8152,19 @@ /turf/open/floor/plating, /area/maintenance/fore) "apT" = ( +/obj/machinery/door/poddoor/preopen{ + id = "Cell Interior Shutters"; + name = "brig shutters" + }, +/obj/effect/spawner/structure/window/reinforced, /obj/structure/cable{ - icon_state = "4-8" + icon_state = "0-8" }, /obj/structure/cable{ - icon_state = "1-8" + icon_state = "0-4" }, -/turf/closed/wall/r_wall, -/area/security/warden) +/turf/open/floor/plating, +/area/security/brig) "apU" = ( /turf/open/floor/plating, /area/security/vacantoffice/b) @@ -8181,20 +8180,6 @@ }, /turf/open/floor/plating, /area/maintenance/fore) -"apX" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/cable{ - icon_state = "0-8" - }, -/obj/structure/cable{ - icon_state = "0-4" - }, -/obj/machinery/door/poddoor/preopen{ - id = "Secure Brig Control"; - name = "brig shutters" - }, -/turf/open/floor/plating, -/area/security/warden) "apY" = ( /obj/machinery/light/small{ dir = 1 @@ -8406,13 +8391,11 @@ /area/crew_quarters/fitness/pool) "aqt" = ( /obj/effect/spawner/structure/window/reinforced, -/obj/structure/cable{ - icon_state = "0-8" - }, /obj/machinery/door/poddoor/preopen{ id = "Secure Brig Control"; name = "brig shutters" }, +/obj/structure/cable, /turf/open/floor/plating, /area/security/warden) "aqu" = ( @@ -8858,6 +8841,9 @@ c_tag = "Brig Control"; dir = 1 }, +/obj/structure/cable{ + icon_state = "1-8" + }, /turf/open/floor/plasteel/showroomfloor, /area/security/warden) "arz" = ( @@ -11044,18 +11030,12 @@ /obj/structure/closet/crate/coffin, /turf/open/floor/plating, /area/maintenance/port/fore) -"axo" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/turf/open/floor/plating, -/area/maintenance/fore) "axp" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ dir = 1 }, /turf/open/floor/plating, -/area/maintenance/fore) +/area/maintenance/port/fore) "axq" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 @@ -11454,10 +11434,6 @@ }, /turf/open/floor/plating, /area/maintenance/fore) -"ayC" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/closed/wall, -/area/maintenance/fore) "ayD" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plasteel/dark, @@ -14269,10 +14245,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plating, /area/maintenance/fore) -"aGh" = ( -/obj/effect/landmark/event_spawn, -/turf/open/floor/plating, -/area/maintenance/fore) "aGi" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel/dark, @@ -29648,10 +29620,10 @@ /turf/open/floor/plasteel/white, /area/science/robotics/lab) "bsU" = ( -/mob/living/simple_animal/hostile/retaliate/ghost, /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 4 }, +/mob/living/simple_animal/hostile/retaliate/ghost, /turf/open/floor/wood, /area/maintenance/port/fore) "bsV" = ( @@ -45293,7 +45265,7 @@ /area/maintenance/aft) "cfq" = ( /obj/structure/mopbucket, -/obj/item/caution, +/obj/item/clothing/suit/caution, /turf/open/floor/plating, /area/maintenance/aft) "cfr" = ( @@ -52616,9 +52588,6 @@ /obj/effect/turf_decal/tile/blue{ dir = 8 }, -/obj/structure/cable{ - icon_state = "1-2" - }, /turf/open/floor/plasteel, /area/security/brig) "cLS" = ( @@ -53367,7 +53336,7 @@ }, /obj/structure/reagent_dispensers/fueltank, /turf/open/floor/plating, -/area/maintenance/fore) +/area/maintenance/port/fore) "ddM" = ( /obj/structure/sign/poster/official/the_owl{ pixel_x = 32 @@ -53519,11 +53488,23 @@ }, /turf/closed/wall, /area/science/circuit) +"dxF" = ( +/obj/machinery/gear_painter, +/turf/open/floor/wood, +/area/maintenance/bar) "dyE" = ( /obj/structure/cable{ - icon_state = "1-2" + icon_state = "0-4" }, -/turf/open/floor/plasteel, +/obj/structure/cable{ + icon_state = "0-8" + }, +/obj/machinery/door/poddoor/preopen{ + id = "Secure Gate"; + name = "brig shutters" + }, +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, /area/security/brig) "dyS" = ( /obj/effect/turf_decal/tile/green{ @@ -53583,9 +53564,6 @@ /turf/open/space, /area/space/nearstation) "dCV" = ( -/obj/structure/cable{ - icon_state = "1-4" - }, /obj/effect/turf_decal/tile/red{ dir = 1 }, @@ -53746,7 +53724,7 @@ dir = 1 }, /turf/open/floor/wood/wood_diagonal, -/area/maintenance/fore) +/area/maintenance/port/fore) "edA" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 @@ -54942,7 +54920,7 @@ "gKG" = ( /obj/structure/bedsheetbin/towel, /turf/open/floor/wood/wood_diagonal, -/area/maintenance/fore) +/area/maintenance/port/fore) "gLz" = ( /obj/structure/cable{ icon_state = "1-2" @@ -54994,11 +54972,11 @@ /obj/structure/cable{ icon_state = "0-8" }, -/obj/structure/cable{ - icon_state = "0-4" - }, /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/structure/cable{ + icon_state = "2-8" + }, /turf/open/floor/plating, /area/security/brig) "gOZ" = ( @@ -56220,7 +56198,7 @@ }, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, -/area/maintenance/fore) +/area/maintenance/port/fore) "jJF" = ( /obj/machinery/door/airlock/maintenance, /obj/structure/cable{ @@ -56342,15 +56320,15 @@ /obj/effect/turf_decal/tile/red{ dir = 8 }, -/obj/structure/cable{ - icon_state = "2-4" - }, /obj/effect/turf_decal/tile/red{ dir = 1 }, /obj/effect/turf_decal/tile/red{ dir = 4 }, +/obj/structure/cable{ + icon_state = "1-4" + }, /turf/open/floor/plasteel, /area/security/brig) "kcx" = ( @@ -56531,6 +56509,10 @@ }, /turf/open/floor/wood/wood_diagonal, /area/maintenance/port/fore) +"kqy" = ( +/obj/machinery/gear_painter, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness) "kqI" = ( /obj/structure/window, /turf/open/floor/wood, @@ -56869,9 +56851,6 @@ /turf/open/floor/plasteel, /area/security/brig) "laq" = ( -/obj/structure/cable{ - icon_state = "2-8" - }, /obj/structure/cable{ icon_state = "2-4" }, @@ -57013,7 +56992,7 @@ dir = 8 }, /turf/closed/wall, -/area/maintenance/fore) +/area/maintenance/port/fore) "lzt" = ( /obj/machinery/portable_atmospherics/pump, /obj/effect/turf_decal/stripes/line, @@ -57160,7 +57139,7 @@ /area/maintenance/starboard/aft) "lZn" = ( /obj/machinery/door/airlock/security/glass{ - id_tag = "innerbrig"; + id_tag = null; name = "Brig Infirmary"; req_access_txt = "2" }, @@ -57605,7 +57584,7 @@ }, /obj/structure/reagent_dispensers/watertank, /turf/open/floor/plating, -/area/maintenance/fore) +/area/maintenance/port/fore) "nbT" = ( /obj/structure/cable{ icon_state = "0-8" @@ -58195,9 +58174,6 @@ /area/hallway/primary/central) "ovv" = ( /obj/structure/table, -/obj/structure/cable{ - icon_state = "0-2" - }, /obj/effect/turf_decal/tile/red{ dir = 1 }, @@ -58540,9 +58516,6 @@ /obj/effect/turf_decal/tile/red{ dir = 8 }, -/obj/structure/cable{ - icon_state = "2-4" - }, /obj/effect/turf_decal/tile/red{ dir = 1 }, @@ -58586,6 +58559,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/machinery/gear_painter, /turf/open/floor/plasteel, /area/crew_quarters/locker) "pqR" = ( @@ -58671,9 +58645,6 @@ /obj/effect/turf_decal/tile/red{ dir = 8 }, -/obj/structure/cable{ - icon_state = "2-8" - }, /obj/effect/turf_decal/tile/red{ dir = 1 }, @@ -58681,7 +58652,10 @@ dir = 4 }, /obj/structure/cable{ - icon_state = "2-4" + icon_state = "4-8" + }, +/obj/structure/cable{ + icon_state = "1-4" }, /turf/open/floor/plasteel, /area/security/brig) @@ -58809,9 +58783,6 @@ /turf/open/floor/plating, /area/crew_quarters/fitness) "pQr" = ( -/obj/structure/cable{ - icon_state = "1-2" - }, /obj/effect/turf_decal/tile/green, /obj/effect/turf_decal/tile/green{ dir = 8 @@ -59081,7 +59052,7 @@ dir = 8 }, /turf/open/floor/wood/wood_diagonal, -/area/maintenance/fore) +/area/maintenance/port/fore) "qIw" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 @@ -59498,9 +59469,6 @@ /area/maintenance/bar) "rCl" = ( /obj/machinery/door/firedoor, -/obj/structure/cable{ - icon_state = "4-8" - }, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 1 }, @@ -59544,20 +59512,6 @@ }, /turf/open/floor/plating, /area/crew_quarters/abandoned_gambling_den) -"rJv" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/cable{ - icon_state = "0-4" - }, -/obj/structure/cable{ - icon_state = "0-8" - }, -/obj/machinery/door/poddoor/preopen{ - id = "Secure Gate"; - name = "brig shutters" - }, -/turf/open/floor/plating, -/area/security/brig) "rJw" = ( /obj/structure/table/glass, /obj/item/hemostat, @@ -59689,12 +59643,6 @@ }, /turf/open/floor/plasteel/dark, /area/medical/paramedic) -"rWw" = ( -/obj/machinery/atmospherics/pipe/heat_exchanging/simple{ - dir = 4 - }, -/turf/open/floor/wood/wood_diagonal, -/area/maintenance/fore) "rXl" = ( /obj/structure/chair/office/light, /obj/machinery/firealarm{ @@ -59764,9 +59712,6 @@ }, /area/crew_quarters/fitness) "seP" = ( -/obj/structure/cable{ - icon_state = "0-4" - }, /obj/structure/cable{ icon_state = "0-8" }, @@ -59817,7 +59762,7 @@ dir = 8 }, /turf/open/floor/wood/wood_diagonal, -/area/maintenance/fore) +/area/maintenance/port/fore) "sqg" = ( /obj/structure/table/wood, /obj/item/clothing/under/misc/pj/red, @@ -60254,7 +60199,7 @@ dir = 8 }, /turf/open/floor/wood/wood_diagonal, -/area/maintenance/fore) +/area/maintenance/port/fore) "trb" = ( /obj/machinery/light{ dir = 4 @@ -60672,7 +60617,7 @@ /obj/structure/girder, /obj/structure/grille, /turf/open/floor/plating, -/area/maintenance/fore) +/area/maintenance/port/fore) "ugu" = ( /obj/structure/cable{ icon_state = "1-4" @@ -61092,6 +61037,9 @@ /area/maintenance/starboard/aft) "uXt" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plasteel, /area/security/brig) "vae" = ( @@ -61332,13 +61280,13 @@ /area/crew_quarters/dorms) "vyK" = ( /obj/effect/spawner/structure/window/reinforced, -/obj/structure/cable{ - icon_state = "0-8" - }, /obj/machinery/door/poddoor/preopen{ id = "Secure Gate"; name = "brig shutters" }, +/obj/structure/cable{ + icon_state = "0-2" + }, /turf/open/floor/plating, /area/security/brig) "vzp" = ( @@ -82474,7 +82422,7 @@ lZN amC jIW ddI -arP +alU fgG rqW aGD @@ -82725,13 +82673,13 @@ amC htu alU edj -rWw +ygb gKG -arP -aqR -awb +alU +amC +ntt ugq -arP +alU rPU fne aGr @@ -82984,11 +82932,11 @@ alU tqG spR qGw -arP -aGh -awb -axo -arP +alU +aFJ +ntt +aAY +alU aCh pIf kCo @@ -83238,14 +83186,14 @@ ali ali ali alU -arP +alU lzk -arP -arP -arP -avZ +alU +alU +alU +atO axp -ayC +aue azH eEe aGv @@ -86395,7 +86343,7 @@ oKh oKh iiW iiW -iiW +dxF izv nfm bCq @@ -88087,7 +88035,7 @@ aaa aaa aag aaa -aak +aam aap saX aaD @@ -88344,7 +88292,7 @@ aaa aaa aag aaf -aaj +aai aao aax aaC @@ -88370,7 +88318,7 @@ alz cZe alg plS -dyE +afM pQr aou aqC @@ -88601,7 +88549,7 @@ aaa aaa aag aaa -aal +aam aar uGI aaF @@ -88858,7 +88806,7 @@ aaa aaa aag aaf -aaj +aai aaq dyS aaE @@ -88883,10 +88831,10 @@ agj agM sAk akp -akQ +agj amB amn -amS +aiX anz anz aov @@ -89115,8 +89063,8 @@ aaa aaa aag aaa -aal -aat +aam +aaj aat aat aat @@ -89143,7 +89091,7 @@ akM amm gyr anM -rJv +xal aqC anz aox @@ -89372,7 +89320,7 @@ aaa aaa aag aaf -aaj +aai aas aat aat @@ -89395,12 +89343,12 @@ akU afM lBz alA -ene -alg +alt +amS kbm -dyE +afM cKC -seP +dyE aqC anR aow @@ -89630,7 +89578,7 @@ aaa aag aaa aam -aav +akQ aav aav aav @@ -89657,7 +89605,7 @@ akT gNE gLz anB -amR +seP aqC anz aov @@ -89911,10 +89859,10 @@ fxx ako ene amj -akQ +agj amB amn -amS +aiX anz anz aov @@ -90171,7 +90119,7 @@ amk amm gyr mos -rJv +xal aqC anz aov @@ -90424,11 +90372,11 @@ akF aiy akv uXt -alg +amS pAK -dyE +afM anQ -seP +dyE aqC anz aov @@ -90685,7 +90633,7 @@ akT amx any arD -amR +seP aqC anz aov @@ -90939,10 +90887,10 @@ ajc akz ene als -akQ -amB +agj +apT amn -amS +aiX aqD anz aov @@ -91196,7 +91144,7 @@ ajc akz ene alg -alt +alw amp aot apR @@ -91455,7 +91403,7 @@ itD alg vyK amI -alg +amS alv aqE anS @@ -91970,7 +91918,7 @@ agn agn amN aoZ -apT +agn anw anz cXU @@ -92227,7 +92175,7 @@ akY alE amU apH -apX +aqt aqC anz gfC @@ -98410,7 +98358,7 @@ awB att azh fHG -fHG +kqy kxf ufD alP diff --git a/_maps/map_files/CogStation/CogStation.dmm b/_maps/map_files/CogStation/CogStation.dmm index c690f7ea88..1c6fb96aea 100644 --- a/_maps/map_files/CogStation/CogStation.dmm +++ b/_maps/map_files/CogStation/CogStation.dmm @@ -3643,7 +3643,7 @@ lootcount = 2; name = "2maintenance loot spawner" }, -/obj/item/caution, +/obj/item/clothing/suit/caution, /turf/open/floor/plating, /area/construction) "ajb" = ( @@ -4579,7 +4579,7 @@ /turf/open/floor/plasteel, /area/security/processing) "alk" = ( -/obj/item/caution, +/obj/item/clothing/suit/caution, /turf/open/floor/plating, /area/construction/secondary) "all" = ( @@ -6034,12 +6034,15 @@ /obj/effect/turf_decal/tile/red{ dir = 1 }, -/obj/machinery/door/firedoor, /obj/item/flashlight/lamp, /obj/machinery/door/window/westright{ name = "Security Checkpoint"; req_access_txt = "1" }, +/obj/machinery/door/firedoor/border_only{ + dir = 8; + name = "west facing firelock" + }, /turf/open/floor/plasteel, /area/security/checkpoint) "aoB" = ( @@ -9593,12 +9596,15 @@ /obj/effect/turf_decal/tile/red{ dir = 1 }, -/obj/machinery/door/firedoor, /obj/item/folder/red, /obj/machinery/door/window/westleft{ name = "Security Checkpoint"; req_access_txt = "1" }, +/obj/machinery/door/firedoor/border_only{ + dir = 8; + name = "west facing firelock" + }, /turf/open/floor/plasteel, /area/security/checkpoint) "awu" = ( @@ -23201,7 +23207,25 @@ /area/hallway/primary/port/fore) "aYW" = ( /obj/structure/table/reinforced, -/obj/machinery/door/firedoor, +/obj/item/pen/blue, +/obj/machinery/camera{ + c_tag = "Customs - Fore"; + dir = 4 + }, +/obj/structure/window/reinforced/spawner/north, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "HoPFore"; + name = "HoP Fore Desk Shutters" + }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/machinery/door/firedoor/border_only{ + dir = 1; + name = "north facing firelock" + }, +/turf/open/floor/plasteel/dark, +/area/security/checkpoint/customs) +"aYX" = ( +/obj/structure/table/reinforced, /obj/machinery/door/window/northright{ name = "Customs Desk"; req_access_txt = "57" @@ -23210,16 +23234,9 @@ id = "HoPFore"; name = "HoP Fore Desk Shutters" }, -/turf/open/floor/plasteel/dark, -/area/security/checkpoint/customs) -"aYX" = ( -/obj/structure/table/reinforced, -/obj/machinery/door/firedoor, -/obj/item/flashlight/lamp, -/obj/structure/window/reinforced/spawner/north, -/obj/machinery/door/poddoor/shutters/preopen{ - id = "HoPFore"; - name = "HoP Fore Desk Shutters" +/obj/machinery/door/firedoor/border_only{ + dir = 1; + name = "north facing firelock" }, /turf/open/floor/plasteel/dark, /area/security/checkpoint/customs) @@ -23323,19 +23340,19 @@ /obj/effect/turf_decal/stripes/line{ dir = 8 }, -/obj/item/caution{ +/obj/item/clothing/suit/caution{ pixel_x = 6; pixel_y = 3 }, -/obj/item/caution{ +/obj/item/clothing/suit/caution{ pixel_x = 6; pixel_y = 3 }, -/obj/item/caution{ +/obj/item/clothing/suit/caution{ pixel_x = 6; pixel_y = 3 }, -/obj/item/caution{ +/obj/item/clothing/suit/caution{ pixel_x = 6; pixel_y = 3 }, @@ -25051,15 +25068,15 @@ /turf/open/floor/plating, /area/ai_monitored/turret_protected/ai_upload_foyer) "bcZ" = ( -/obj/machinery/power/terminal{ - dir = 8 - }, /obj/structure/cable{ icon_state = "1-2" }, /obj/structure/cable{ icon_state = "0-2" }, +/obj/machinery/power/smes{ + charge = 5e+006 + }, /turf/open/floor/plating, /area/ai_monitored/turret_protected/ai_upload_foyer) "bda" = ( @@ -25410,7 +25427,7 @@ dir = 4 }, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bdM" = ( /turf/open/floor/plasteel, /area/quartermaster/office) @@ -25688,7 +25705,7 @@ /area/security/courtroom) "bey" = ( /turf/closed/wall/r_wall, -/area/science/server) +/area/science/server/compcore) "bez" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -25764,7 +25781,7 @@ }, /obj/machinery/atmospherics/pipe/simple/supplymain/hidden, /turf/open/floor/plating, -/area/science/server) +/area/science/server/compcore) "beI" = ( /obj/machinery/door/firedoor, /obj/structure/disposalpipe/segment, @@ -25778,7 +25795,7 @@ /obj/effect/turf_decal/delivery, /obj/machinery/atmospherics/pipe/simple/orange/hidden, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "beJ" = ( /turf/open/floor/plasteel, /area/hallway/primary/central) @@ -25967,7 +25984,7 @@ icon_state = "0-4" }, /turf/open/floor/plating, -/area/science/server) +/area/science/server/compcore) "bfi" = ( /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 10 @@ -25985,13 +26002,13 @@ icon_state = "0-4" }, /turf/open/floor/plating, -/area/science/server) +/area/science/server/compcore) "bfk" = ( /obj/structure/cable{ icon_state = "2-8" }, /turf/closed/wall/r_wall, -/area/science/server) +/area/science/server/compcore) "bfl" = ( /obj/effect/turf_decal/tile/green, /obj/effect/turf_decal/tile/green{ @@ -26793,7 +26810,7 @@ /area/quartermaster/sorting) "bgP" = ( /obj/item/analyzer, -/obj/item/caution, +/obj/item/clothing/suit/caution, /turf/open/floor/plating, /area/maintenance/disposal) "bgQ" = ( @@ -26841,9 +26858,6 @@ /turf/open/floor/plating, /area/crew_quarters/heads/hor) "bgY" = ( -/obj/structure/cable{ - icon_state = "1-2" - }, /obj/machinery/status_display, /turf/closed/wall/r_wall, /area/hallway/primary/central) @@ -26943,7 +26957,7 @@ icon_state = "2-4" }, /turf/closed/wall/r_wall, -/area/science/server) +/area/science/server/compcore) "bhm" = ( /obj/effect/landmark/event_spawn, /turf/open/floor/engine, @@ -27017,11 +27031,12 @@ /turf/open/floor/plasteel, /area/engine/secure_construction) "bht" = ( -/obj/structure/grille, /obj/structure/cable, /obj/structure/cable{ icon_state = "0-4" }, +/obj/machinery/power/terminal, +/obj/structure/grille, /obj/structure/window/reinforced/spawner, /turf/open/floor/plating, /area/ai_monitored/turret_protected/ai) @@ -27313,7 +27328,7 @@ icon_state = "4-8" }, /turf/closed/wall/r_wall, -/area/science/server) +/area/science/server/compcore) "bia" = ( /obj/effect/turf_decal/tile/yellow{ dir = 1 @@ -27399,7 +27414,7 @@ }, /obj/machinery/atmospherics/pipe/simple/supplymain/hidden, /turf/closed/wall/r_wall, -/area/science/server) +/area/science/server/compcore) "bik" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable, @@ -27415,7 +27430,7 @@ "bil" = ( /obj/structure/window/reinforced/spawner, /turf/open/floor/plasteel/dark, -/area/science/server) +/area/science/server/compcore) "bim" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, @@ -27513,7 +27528,7 @@ dir = 5 }, /turf/open/floor/plasteel/dark, -/area/science/server) +/area/science/server/compcore) "bix" = ( /obj/machinery/door/firedoor, /obj/effect/turf_decal/delivery, @@ -27576,7 +27591,7 @@ dir = 10 }, /turf/open/floor/plasteel/dark, -/area/science/server) +/area/science/server/compcore) "biF" = ( /obj/structure/cable{ icon_state = "4-8" @@ -27615,7 +27630,7 @@ icon_state = "1-2" }, /turf/closed/wall/r_wall, -/area/science/server) +/area/science/server/compcore) "biI" = ( /obj/machinery/light{ dir = 4; @@ -27638,6 +27653,9 @@ /area/quartermaster/office) "biK" = ( /obj/structure/closet/firecloset, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 10 + }, /turf/open/floor/plasteel, /area/science/mixing) "biL" = ( @@ -28416,7 +28434,7 @@ }, /obj/machinery/photocopier, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bku" = ( /obj/structure/closet, /turf/open/floor/plasteel, @@ -28455,7 +28473,7 @@ }, /obj/machinery/atmospherics/pipe/simple/supplymain/hidden, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bkA" = ( /obj/machinery/light_switch{ pixel_y = -24 @@ -28566,7 +28584,7 @@ pixel_y = 24 }, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bkK" = ( /obj/structure/disposalpipe/segment, /obj/structure/cable{ @@ -28674,7 +28692,7 @@ /area/maintenance/department/eva) "bkW" = ( /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bkX" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/disposalpipe/segment, @@ -28918,25 +28936,26 @@ "blv" = ( /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "blw" = ( /obj/structure/cable{ icon_state = "1-4" }, /obj/machinery/atmospherics/pipe/simple/orange/hidden, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "blx" = ( /obj/structure/cable{ icon_state = "0-8" }, /obj/machinery/power/apc{ + areastring = "/area/science/server/compcore"; dir = 1; name = "Computer Core APC"; pixel_y = 24 }, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bly" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -29001,7 +29020,7 @@ light_color = "#e8eaff" }, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "blE" = ( /obj/machinery/light{ dir = 8 @@ -29216,7 +29235,7 @@ dir = 4 }, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bma" = ( /obj/structure/chair{ dir = 8 @@ -29522,7 +29541,7 @@ icon_state = "1-2" }, /turf/closed/wall/r_wall, -/area/science/server) +/area/science/server/compcore) "bmG" = ( /turf/open/floor/engine, /area/gateway) @@ -29593,13 +29612,14 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "bmM" = ( -/obj/structure/grille, /obj/structure/cable{ icon_state = "0-2" }, /obj/structure/cable{ icon_state = "0-8" }, +/obj/machinery/power/terminal, +/obj/structure/grille, /obj/structure/window/reinforced/spawner, /turf/open/floor/plating, /area/ai_monitored/turret_protected/ai) @@ -30215,7 +30235,7 @@ pixel_y = 1 }, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bnT" = ( /obj/effect/turf_decal/tile/green{ dir = 8 @@ -30228,7 +30248,7 @@ dir = 9 }, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bnU" = ( /obj/structure/rack, /obj/item/clothing/suit/space/fragile, @@ -30280,18 +30300,16 @@ /area/engine/teg) "bnZ" = ( /obj/structure/table/reinforced, -/obj/machinery/door/firedoor, -/obj/item/pen/blue, -/obj/machinery/camera{ - c_tag = "Customs - Fore"; - dir = 4 - }, +/obj/item/flashlight/lamp, /obj/structure/window/reinforced/spawner/north, /obj/machinery/door/poddoor/shutters/preopen{ id = "HoPFore"; name = "HoP Fore Desk Shutters" }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/machinery/door/firedoor/border_only{ + dir = 1; + name = "north facing firelock" + }, /turf/open/floor/plasteel/dark, /area/security/checkpoint/customs) "boa" = ( @@ -30314,24 +30332,22 @@ /area/crew_quarters/heads/chief) "bod" = ( /obj/structure/table/reinforced, -/obj/effect/turf_decal/tile/yellow, -/obj/effect/turf_decal/tile/yellow{ +/obj/item/stack/packageWrap, +/obj/item/hand_labeler, +/obj/machinery/camera{ + c_tag = "Customs - Aft"; dir = 4 }, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 +/obj/structure/window/reinforced/spawner, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "HoPAft"; + name = "HoP Aft Desk Shutters" }, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 +/obj/machinery/door/firedoor/border_only{ + name = "south facing firelock" }, -/obj/machinery/door/firedoor, -/obj/machinery/door/window/southleft{ - name = "Primary Tool Storage Desk"; - req_access_txt = "11" - }, -/obj/item/folder/yellow, -/turf/open/floor/plasteel, -/area/storage/primary) +/turf/open/floor/plasteel/dark, +/area/security/checkpoint/customs) "boe" = ( /obj/machinery/door/airlock/vault{ name = "Vault Door"; @@ -30351,7 +30367,7 @@ req_access = list(16) }, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bog" = ( /obj/machinery/atmospherics/pipe/simple/supply/visible, /obj/machinery/door/airlock/engineering/glass{ @@ -30380,7 +30396,7 @@ dir = 5 }, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "boj" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -30451,7 +30467,7 @@ dir = 8 }, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "boq" = ( /obj/effect/turf_decal/tile/green, /obj/effect/turf_decal/tile/green{ @@ -30464,7 +30480,7 @@ dir = 8 }, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bor" = ( /obj/structure/closet/crate, /obj/effect/spawner/lootdrop/maintenance, @@ -30503,7 +30519,7 @@ dir = 8 }, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bou" = ( /obj/effect/turf_decal/plaque{ icon_state = "L2" @@ -30637,8 +30653,11 @@ /turf/open/floor/plating, /area/quartermaster/miningoffice) "boL" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/hidden, -/turf/open/floor/plasteel, +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 4 + }, +/turf/open/floor/plating, /area/science/mixing) "boM" = ( /obj/machinery/mineral/ore_redemption{ @@ -30859,7 +30878,7 @@ }, /obj/item/book/manual/wiki/robotics_cyborgs, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bpi" = ( /obj/machinery/firealarm{ pixel_y = 26 @@ -31095,7 +31114,7 @@ dir = 4 }, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bpL" = ( /obj/effect/turf_decal/tile/green{ dir = 8 @@ -31105,7 +31124,7 @@ dir = 1 }, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bpM" = ( /obj/effect/turf_decal/stripes/corner, /turf/open/floor/plasteel, @@ -31116,7 +31135,7 @@ }, /obj/effect/turf_decal/tile/green, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bpO" = ( /obj/structure/disposalpipe/segment{ dir = 10 @@ -31164,7 +31183,7 @@ /obj/effect/turf_decal/tile/green, /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bpW" = ( /obj/structure/cable{ icon_state = "1-2" @@ -31350,7 +31369,7 @@ dir = 4 }, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bqu" = ( /obj/structure/disposalpipe/segment, /obj/structure/cable{ @@ -31546,7 +31565,7 @@ }, /obj/item/storage/box/disks, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bqP" = ( /obj/machinery/camera{ c_tag = "Engine Room - Port Quarter"; @@ -33585,6 +33604,10 @@ /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 4 }, +/obj/item/kirbyplants{ + icon_state = "plant-20"; + pixel_y = 3 + }, /turf/open/floor/plasteel, /area/crew_quarters/locker) "bvu" = ( @@ -33778,7 +33801,7 @@ /turf/open/floor/plasteel/dark, /area/chapel/office) "bvU" = ( -/obj/item/caution, +/obj/item/clothing/suit/caution, /obj/effect/decal/cleanable/dirt, /obj/structure/sign/warning/biohazard{ pixel_x = -32 @@ -34882,7 +34905,7 @@ }, /obj/structure/window/reinforced/spawner, /turf/open/floor/plasteel/dark, -/area/science/server) +/area/science/server/compcore) "byf" = ( /obj/machinery/door/airlock/engineering/glass{ name = "Telecommunications Mainframe"; @@ -35576,7 +35599,7 @@ "bzN" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, -/area/science/server) +/area/science/server/compcore) "bzO" = ( /obj/machinery/conveyor_switch/oneway{ id = "recycler"; @@ -35605,7 +35628,7 @@ }, /obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bzS" = ( /obj/structure/table, /obj/machinery/light/small{ @@ -35651,7 +35674,9 @@ name = "Toxins Launch Room"; req_access_txt = "7;8" }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 5 + }, /turf/open/floor/plasteel, /area/science/mixing) "bzY" = ( @@ -35785,7 +35810,6 @@ /obj/effect/turf_decal/tile/blue{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden, /turf/open/floor/plasteel, /area/science/mixing) "bAm" = ( @@ -35924,7 +35948,7 @@ /obj/structure/disposalpipe/segment, /obj/machinery/holopad, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bAz" = ( /obj/structure/disposalpipe/junction/flip{ dir = 1 @@ -36026,7 +36050,6 @@ /obj/effect/turf_decal/tile/red{ dir = 1 }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden, /turf/open/floor/plasteel, /area/science/mixing) "bAH" = ( @@ -36037,7 +36060,7 @@ }, /obj/structure/window/reinforced/spawner, /turf/open/floor/plasteel/dark, -/area/science/server) +/area/science/server/compcore) "bAI" = ( /obj/machinery/photocopier, /obj/machinery/requests_console{ @@ -36116,6 +36139,9 @@ /obj/effect/turf_decal/tile/blue{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/science/mixing) "bAQ" = ( @@ -36143,10 +36169,16 @@ /obj/effect/turf_decal/stripes/line{ dir = 6 }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/science/mixing) "bAV" = ( /obj/machinery/atmospherics/components/unary/portables_connector/visible, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 4 + }, /turf/open/floor/plasteel/white, /area/science/mixing) "bAW" = ( @@ -36545,7 +36577,7 @@ /obj/effect/turf_decal/delivery, /obj/machinery/rnd/server, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bBT" = ( /obj/structure/disposalpipe/segment, /obj/structure/cable{ @@ -36623,10 +36655,10 @@ name = "RD Server Lockup" }, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bCb" = ( /turf/open/floor/circuit/green, -/area/science/server) +/area/science/server/compcore) "bCc" = ( /obj/effect/turf_decal/delivery, /obj/structure/cable{ @@ -36998,7 +37030,7 @@ "bCW" = ( /obj/structure/disposalpipe/segment, /turf/open/floor/circuit/green, -/area/science/server) +/area/science/server/compcore) "bCX" = ( /obj/machinery/rnd/production/circuit_imprinter/department/science, /obj/item/reagent_containers/glass/beaker/sulphuric, @@ -37355,10 +37387,11 @@ /turf/open/floor/plating, /area/hallway/secondary/service) "bDL" = ( +/obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 4 + dir = 10 }, -/turf/open/floor/plasteel, +/turf/open/floor/plating, /area/science/mixing) "bDM" = ( /obj/structure/table/reinforced, @@ -38170,12 +38203,7 @@ /turf/open/floor/plasteel, /area/science/xenobiology) "bFp" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 4 - }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, /turf/open/floor/plasteel, /area/science/mixing) "bFq" = ( @@ -38771,9 +38799,9 @@ /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet/restrooms) "bGv" = ( -/obj/item/caution, +/obj/item/clothing/suit/caution, /turf/open/floor/plasteel, -/area/science/server) +/area/science/server/compcore) "bGw" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/public/glass{ @@ -38897,7 +38925,7 @@ /obj/item/circuitboard/machine/rdserver, /obj/item/disk/tech_disk, /turf/open/floor/circuit/green, -/area/science/server) +/area/science/server/compcore) "bGL" = ( /obj/structure/chair{ dir = 1 @@ -38912,10 +38940,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/item/kirbyplants{ - icon_state = "plant-20"; - pixel_y = 3 - }, +/obj/machinery/gear_painter, /turf/open/floor/plasteel, /area/crew_quarters/locker) "bGN" = ( @@ -38946,7 +38971,7 @@ /obj/machinery/light, /obj/structure/disposalpipe/segment, /turf/open/floor/circuit/green, -/area/science/server) +/area/science/server/compcore) "bGQ" = ( /obj/structure/lattice/catwalk, /obj/structure/disposalpipe/segment{ @@ -39522,7 +39547,7 @@ network = list("minisat") }, /turf/open/floor/circuit/green, -/area/science/server) +/area/science/server/compcore) "bIh" = ( /obj/machinery/disposal/bin, /obj/effect/turf_decal/delivery/white, @@ -40062,7 +40087,7 @@ icon_state = "1-4" }, /turf/closed/wall/r_wall, -/area/science/server) +/area/science/server/compcore) "bJo" = ( /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel, @@ -40124,9 +40149,6 @@ /area/space/nearstation) "bJw" = ( /obj/machinery/holopad, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 4 - }, /turf/open/floor/plasteel/white, /area/science/mixing) "bJx" = ( @@ -40233,7 +40255,7 @@ icon_state = "0-4" }, /turf/open/floor/plating, -/area/science/server) +/area/science/server/compcore) "bJG" = ( /obj/structure/extinguisher_cabinet{ pixel_y = -32 @@ -40328,9 +40350,7 @@ /turf/open/floor/plating, /area/maintenance/disposal) "bJT" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 10 - }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, /turf/open/floor/plasteel/white, /area/science/mixing) "bJU" = ( @@ -40574,7 +40594,7 @@ icon_state = "1-8" }, /turf/closed/wall/r_wall, -/area/science/server) +/area/science/server/compcore) "bKt" = ( /obj/structure/cable{ icon_state = "1-4" @@ -40980,7 +41000,7 @@ dir = 1; pixel_y = -26 }, -/obj/item/caution, +/obj/item/clothing/suit/caution, /obj/item/shovel, /obj/item/stack/tile/plasteel{ pixel_x = 10; @@ -42597,7 +42617,7 @@ icon_state = "0-2" }, /turf/open/floor/plating, -/area/science/server) +/area/science/server/compcore) "bOA" = ( /obj/effect/turf_decal/tile/green{ dir = 4 @@ -42646,9 +42666,6 @@ light_color = "#e8eaff" }, /obj/machinery/atmospherics/pipe/simple/orange/hidden, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 4 - }, /turf/open/floor/plasteel, /area/science/mixing) "bOF" = ( @@ -42830,18 +42847,23 @@ /area/science/xenobiology) "bOY" = ( /obj/structure/table/reinforced, -/obj/machinery/door/firedoor, -/obj/item/stack/packageWrap, -/obj/item/hand_labeler, -/obj/machinery/camera{ - c_tag = "Customs - Aft"; - dir = 4 +/obj/item/clipboard, +/obj/item/stamp/denied{ + pixel_x = 4; + pixel_y = 4 + }, +/obj/item/stamp, +/obj/machinery/door/window/southright{ + name = "Customs Desk"; + req_access_txt = "57" }, -/obj/structure/window/reinforced/spawner, /obj/machinery/door/poddoor/shutters/preopen{ id = "HoPAft"; name = "HoP Aft Desk Shutters" }, +/obj/machinery/door/firedoor/border_only{ + name = "south facing firelock" + }, /turf/open/floor/plasteel/dark, /area/security/checkpoint/customs) "bOZ" = ( @@ -43300,9 +43322,6 @@ /obj/effect/turf_decal/stripes/line{ dir = 1 }, -/obj/structure/cable{ - icon_state = "2-4" - }, /obj/machinery/camera/motion{ c_tag = "AI Foyer"; network = list("minisat"); @@ -43320,7 +43339,7 @@ dir = 6 }, /turf/open/floor/plasteel, -/area/ai_monitored/turret_protected/ai) +/area/ai_monitored/turret_protected/ai_upload_foyer) "bQc" = ( /obj/structure/bodycontainer/morgue{ dir = 8 @@ -43383,9 +43402,6 @@ /obj/structure/cable{ icon_state = "1-4" }, -/obj/structure/cable{ - icon_state = "4-8" - }, /obj/machinery/atmospherics/pipe/manifold/supplymain/hidden, /turf/open/floor/plasteel, /area/ai_monitored/turret_protected/ai_upload_foyer) @@ -43756,9 +43772,7 @@ /turf/open/floor/plating, /area/router) "bQX" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 5 - }, +/obj/machinery/atmospherics/pipe/manifold/cyan/hidden, /turf/open/floor/plasteel/white, /area/science/mixing) "bQY" = ( @@ -44254,9 +44268,6 @@ /area/science/robotics/lab) "bRW" = ( /obj/effect/turf_decal/bot, -/obj/structure/cable{ - icon_state = "2-4" - }, /obj/machinery/status_display/ai{ pixel_y = 32 }, @@ -44384,9 +44395,6 @@ /area/science/xenobiology) "bSk" = ( /obj/machinery/door/firedoor, -/obj/structure/cable{ - icon_state = "4-8" - }, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 4 }, @@ -44439,7 +44447,7 @@ }, /obj/structure/cable, /turf/open/floor/plating, -/area/science/server) +/area/science/server/compcore) "bSp" = ( /obj/machinery/conveyor_switch/oneway{ id = "cargoload" @@ -44473,9 +44481,6 @@ /turf/open/floor/plasteel, /area/quartermaster/storage) "bSr" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, /obj/machinery/light, /obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ dir = 4 @@ -44483,18 +44488,12 @@ /turf/open/floor/mineral/titanium/blue, /area/ai_monitored/turret_protected/ai_upload_foyer) "bSs" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, /obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ dir = 4 }, /turf/open/floor/mineral/titanium/blue, /area/ai_monitored/turret_protected/ai_upload_foyer) "bSt" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, /obj/machinery/light{ dir = 1 }, @@ -44696,9 +44695,6 @@ /area/science/lab) "bSO" = ( /obj/machinery/door/firedoor, -/obj/structure/cable{ - icon_state = "4-8" - }, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 8 }, @@ -45219,9 +45215,6 @@ /obj/structure/cable{ icon_state = "1-2" }, -/obj/structure/cable{ - icon_state = "4-8" - }, /obj/machinery/status_display/ai{ pixel_y = 32 }, @@ -45319,9 +45312,6 @@ /obj/machinery/light_switch{ pixel_y = 24 }, -/obj/structure/cable{ - icon_state = "4-8" - }, /obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ dir = 4 }, @@ -46094,9 +46084,6 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bVF" = ( -/obj/structure/cable{ - icon_state = "1-4" - }, /obj/structure/cable{ icon_state = "1-2" }, @@ -46307,26 +46294,17 @@ /area/engine/atmos) "bVY" = ( /obj/structure/table/reinforced, -/obj/effect/turf_decal/tile/yellow, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 +/obj/item/flashlight/lamp, +/obj/structure/window/reinforced/spawner, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "HoPAft"; + name = "HoP Aft Desk Shutters" }, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 +/obj/machinery/door/firedoor/border_only{ + name = "south facing firelock" }, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 - }, -/obj/machinery/door/firedoor, -/obj/machinery/door/window/southright{ - name = "Primary Tool Storage Desk"; - req_access_txt = "11" - }, -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/open/floor/plasteel, -/area/storage/primary) +/turf/open/floor/plasteel/dark, +/area/security/checkpoint/customs) "bVZ" = ( /obj/machinery/power/apc{ name = "Cargo Bay APC"; @@ -46455,9 +46433,6 @@ /area/science/mixing) "bWm" = ( /obj/machinery/door/firedoor, -/obj/structure/cable{ - icon_state = "4-8" - }, /obj/machinery/door/airlock/engineering{ name = "AI SMES Access"; req_one_access_txt = "10;24" @@ -46559,9 +46534,6 @@ /turf/open/floor/plasteel/white, /area/science/mixing) "bWv" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, /obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 8 }, @@ -48793,7 +48765,7 @@ /turf/open/floor/engine, /area/science/storage) "cbh" = ( -/obj/machinery/rnd/experimentor, +/obj/effect/landmark/event_spawn, /turf/open/floor/engine, /area/science/explab) "cbi" = ( @@ -49146,6 +49118,9 @@ /obj/effect/turf_decal/stripes/line{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/science/mixing) "cbQ" = ( @@ -49637,13 +49612,11 @@ /turf/open/floor/plasteel, /area/hallway/secondary/exit/departure_lounge) "ccL" = ( -/obj/effect/landmark/event_spawn, -/obj/machinery/light{ - dir = 8; - light_color = "#e8eaff" +/obj/effect/turf_decal/stripes/line, +/obj/machinery/computer/rdconsole/experiment{ + dir = 1 }, -/obj/machinery/rnd/bepis, -/turf/open/floor/engine, +/turf/open/floor/plasteel, /area/science/explab) "ccM" = ( /obj/structure/disposalpipe/segment{ @@ -51474,8 +51447,8 @@ /area/quartermaster/warehouse) "cgt" = ( /obj/structure/rack, -/obj/item/caution, -/obj/item/caution, +/obj/item/clothing/suit/caution, +/obj/item/clothing/suit/caution, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel, /area/quartermaster/warehouse) @@ -51557,7 +51530,6 @@ /obj/structure/disposalpipe/segment{ dir = 10 }, -/obj/structure/cable, /obj/structure/cable{ icon_state = "0-2" }, @@ -51950,9 +51922,6 @@ /turf/open/floor/plasteel, /area/engine/atmos) "chy" = ( -/obj/structure/cable{ - icon_state = "2-8" - }, /obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 10 }, @@ -52060,24 +52029,16 @@ /obj/structure/cable{ icon_state = "4-8" }, -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 6 - }, /turf/open/floor/plasteel, /area/engine/atmos) "chM" = ( /obj/structure/cable{ icon_state = "1-8" }, -/obj/machinery/atmospherics/pipe/manifold/cyan/visible{ - dir = 4 - }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible, /turf/open/floor/plasteel, /area/engine/atmos) "chN" = ( -/obj/structure/cable{ - icon_state = "1-2" - }, /obj/machinery/atmospherics/pipe/simple/orange/hidden, /turf/closed/wall/r_wall, /area/engine/teg/hotloop) @@ -52907,7 +52868,7 @@ dir = 4; pixel_x = -28 }, -/obj/item/kirbyplants/random, +/obj/machinery/gear_painter, /turf/open/floor/plasteel, /area/quartermaster/office) "cjB" = ( @@ -54609,26 +54570,26 @@ /turf/open/floor/plasteel, /area/science/robotics/lab) "cmT" = ( -/obj/structure/table/reinforced, -/obj/machinery/door/firedoor, -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ - dir = 8 - }, -/obj/effect/turf_decal/tile/red{ - dir = 4 - }, -/obj/effect/turf_decal/tile/red{ +/obj/machinery/disposal/bin, +/obj/structure/disposalpipe/trunk, +/obj/effect/turf_decal/tile/yellow, +/obj/effect/turf_decal/tile/yellow{ dir = 1 }, -/obj/item/folder/red, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden, -/obj/machinery/door/window/northright{ - name = "Security Checkpoint"; - req_access_txt = "1" +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/white/full, +/obj/structure/window/reinforced/spawner/north, +/obj/machinery/door/firedoor/border_only{ + dir = 1; + name = "north facing firelock" }, /turf/open/floor/plasteel, -/area/security/checkpoint/supply) +/area/engine/workshop) "cmU" = ( /obj/structure/disposalpipe/segment, /obj/structure/cable{ @@ -55042,6 +55003,9 @@ /obj/item/target/alien, /obj/item/target, /obj/item/target/clown, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 5 + }, /turf/open/floor/plasteel, /area/science/mixing) "cnM" = ( @@ -55085,9 +55049,6 @@ /turf/open/space/basic, /area/quartermaster/warehouse) "cnR" = ( -/obj/structure/cable{ - icon_state = "1-8" - }, /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 4 }, @@ -55112,7 +55073,8 @@ /turf/open/floor/plating, /area/maintenance/solars/starboard/aft) "cnT" = ( -/obj/machinery/atmospherics/pipe/manifold/cyan/hidden, +/obj/effect/turf_decal/stripes/line, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, /turf/open/floor/plasteel, /area/science/mixing) "cnU" = ( @@ -56727,9 +56689,6 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "cqS" = ( -/obj/machinery/computer/rdconsole/experiment{ - dir = 4 - }, /obj/effect/turf_decal/stripes/line, /obj/machinery/requests_console{ department = "Science"; @@ -56738,6 +56697,8 @@ pixel_x = -30; receive_ore_updates = 1 }, +/obj/structure/table, +/obj/item/book/manual/wiki/experimentor, /turf/open/floor/plasteel, /area/science/explab) "cqT" = ( @@ -57988,20 +57949,25 @@ /turf/open/floor/plasteel, /area/engine/atmos) "ctl" = ( -/obj/machinery/disposal/bin, -/obj/structure/disposalpipe/trunk, -/obj/effect/turf_decal/tile/yellow, /obj/effect/turf_decal/tile/yellow{ dir = 1 }, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, /obj/effect/turf_decal/tile/yellow{ dir = 8 }, -/obj/effect/turf_decal/stripes/white/full, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow, +/obj/machinery/modular_computer/console/preset/engineering, +/obj/structure/cable{ + icon_state = "1-2" + }, /obj/structure/window/reinforced/spawner/north, +/obj/machinery/door/firedoor/border_only{ + dir = 1; + name = "north facing firelock" + }, /turf/open/floor/plasteel, /area/engine/workshop) "ctm" = ( @@ -58202,21 +58168,17 @@ /turf/open/floor/plating, /area/medical/virology) "ctE" = ( -/obj/effect/turf_decal/tile/yellow{ - dir = 1 +/obj/structure/table/reinforced, +/obj/machinery/door/window/southleft{ + name = "Workshop Desk"; + req_access_txt = "11" }, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 +/obj/item/paper_bin, +/obj/item/pen, +/obj/structure/disposalpipe/segment, +/obj/machinery/door/firedoor/border_only{ + name = "south facing firelock" }, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, -/obj/effect/turf_decal/tile/yellow, -/obj/machinery/modular_computer/console/preset/engineering, -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/structure/window/reinforced/spawner/north, /turf/open/floor/plasteel, /area/engine/workshop) "ctF" = ( @@ -59567,34 +59529,38 @@ /area/science/xenobiology) "cvZ" = ( /obj/structure/table/reinforced, -/obj/machinery/door/firedoor, -/obj/item/clipboard, -/obj/item/stamp/denied{ - pixel_x = 4; - pixel_y = 4 - }, -/obj/item/stamp, /obj/machinery/door/window/southright{ - name = "Customs Desk"; - req_access_txt = "57" + name = "Workshop Desk"; + req_access_txt = "11" }, -/obj/machinery/door/poddoor/shutters/preopen{ - id = "HoPAft"; - name = "HoP Aft Desk Shutters" +/obj/item/folder/yellow, +/obj/machinery/door/firedoor/border_only{ + name = "south facing firelock" }, -/turf/open/floor/plasteel/dark, -/area/security/checkpoint/customs) +/turf/open/floor/plasteel, +/area/engine/workshop) "cwa" = ( /obj/structure/table/reinforced, -/obj/machinery/door/firedoor, -/obj/item/flashlight/lamp, -/obj/structure/window/reinforced/spawner, -/obj/machinery/door/poddoor/shutters/preopen{ - id = "HoPAft"; - name = "HoP Aft Desk Shutters" +/obj/effect/turf_decal/tile/yellow, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 }, -/turf/open/floor/plasteel/dark, -/area/security/checkpoint/customs) +/obj/effect/turf_decal/tile/yellow{ + dir = 1 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/machinery/door/window/southleft{ + name = "Primary Tool Storage Desk"; + req_access_txt = "11" + }, +/obj/item/folder/yellow, +/obj/machinery/door/firedoor/border_only{ + name = "south facing firelock" + }, +/turf/open/floor/plasteel, +/area/storage/primary) "cwb" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -60704,6 +60670,7 @@ pixel_y = 24 }, /obj/machinery/power/apc{ + areastring = "/area/crew_quarters/toilet/restrooms"; dir = 4; name = "Restrooms APC"; pixel_x = 24 @@ -61860,7 +61827,7 @@ /obj/effect/turf_decal/tile/green{ dir = 8 }, -/obj/item/caution, +/obj/item/clothing/suit/caution, /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 4 }, @@ -62959,7 +62926,7 @@ /obj/effect/turf_decal/tile/green{ dir = 4 }, -/obj/item/caution, +/obj/item/clothing/suit/caution, /obj/machinery/atmospherics/pipe/manifold4w/orange/hidden, /obj/structure/cable{ icon_state = "4-8" @@ -67102,8 +67069,8 @@ /turf/open/floor/plasteel, /area/engine/gravity_generator) "cJH" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 9 +/obj/machinery/atmospherics/pipe/manifold/orange/visible{ + dir = 4 }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -67708,11 +67675,6 @@ /obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plating, /area/engine/atmos) -"cLc" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/yellow/visible, -/turf/open/floor/plating, -/area/engine/atmos) "cLd" = ( /obj/effect/turf_decal/tile/green{ dir = 4 @@ -68133,14 +68095,14 @@ /turf/open/floor/plating, /area/engine/storage) "cMa" = ( -/obj/machinery/light/small{ - dir = 1; - light_color = "#ffc1c1" - }, /obj/machinery/atmospherics/pipe/simple/orange/visible, /obj/machinery/atmospherics/components/binary/pump/on{ dir = 4 }, +/obj/machinery/airlock_sensor/incinerator_atmos{ + pixel_x = -8; + pixel_y = 24 + }, /turf/open/floor/engine/vacuum, /area/engine/atmos) "cMb" = ( @@ -68280,17 +68242,22 @@ pixel_x = -40; pixel_y = 8 }, -/obj/machinery/atmospherics/pipe/simple/cyan/visible, /obj/machinery/atmospherics/pipe/simple/dark/visible{ dir = 4 }, +/obj/machinery/button/ignition/incinerator/atmos{ + pixel_x = -24; + pixel_y = -9 + }, /turf/open/floor/plasteel, /area/engine/atmos) "cMw" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible, /obj/machinery/atmospherics/pipe/simple/dark/visible{ dir = 4 }, +/obj/machinery/atmospherics/components/binary/valve/digital{ + name = "Waste Release" + }, /turf/open/floor/plasteel, /area/engine/atmos) "cMx" = ( @@ -68408,10 +68375,13 @@ /turf/open/floor/plasteel/dark, /area/engine/atmos) "cMI" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 9 +/obj/machinery/atmospherics/pipe/simple/supplymain/visible{ + dir = 4 }, -/turf/closed/wall/r_wall, +/obj/structure/extinguisher_cabinet{ + pixel_x = 27 + }, +/turf/open/floor/plasteel, /area/engine/atmos) "cMJ" = ( /obj/machinery/atmospherics/pipe/simple/cyan/visible{ @@ -68449,10 +68419,8 @@ /turf/open/floor/plating, /area/engine/atmos) "cMO" = ( +/obj/machinery/atmospherics/pipe/layer_manifold, /obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/manifold/cyan/visible{ - dir = 4 - }, /turf/open/floor/plating, /area/engine/atmos) "cMP" = ( @@ -68681,6 +68649,30 @@ /obj/machinery/light, /turf/open/floor/plasteel, /area/router/air) +"cNm" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/yellow, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 1 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/machinery/door/window/southright{ + name = "Primary Tool Storage Desk"; + req_access_txt = "11" + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/door/firedoor/border_only{ + name = "south facing firelock" + }, +/turf/open/floor/plasteel, +/area/storage/primary) "cNn" = ( /obj/machinery/conveyor/auto{ dir = 8; @@ -68693,26 +68685,28 @@ /area/engine/workshop) "cNp" = ( /obj/structure/table/reinforced, -/obj/machinery/door/firedoor, -/obj/machinery/door/window/southleft{ - name = "Workshop Desk"; - req_access_txt = "11" +/obj/effect/turf_decal/tile/red, +/obj/effect/turf_decal/tile/red{ + dir = 8 }, -/obj/item/paper_bin, -/obj/item/pen, -/obj/structure/disposalpipe/segment, -/turf/open/floor/plasteel, -/area/engine/workshop) -"cNq" = ( -/obj/structure/table/reinforced, -/obj/machinery/door/firedoor, -/obj/machinery/door/window/southright{ - name = "Workshop Desk"; - req_access_txt = "11" +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/item/folder/red, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/obj/machinery/door/window/northright{ + name = "Security Checkpoint"; + req_access_txt = "1" + }, +/obj/machinery/door/firedoor/border_only{ + dir = 1; + name = "north facing firelock" }, -/obj/item/folder/yellow, /turf/open/floor/plasteel, -/area/engine/workshop) +/area/security/checkpoint/supply) "cNr" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -70777,6 +70771,13 @@ /obj/effect/landmark/start/atmospheric_technician, /turf/open/floor/plasteel, /area/engine/atmos) +"dnN" = ( +/obj/structure/lattice, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 5 + }, +/turf/open/space/basic, +/area/space/nearstation) "dpO" = ( /obj/machinery/atmospherics/components/unary/thermomachine/heater/on{ dir = 4 @@ -70796,6 +70797,14 @@ }, /turf/open/floor/plating, /area/router) +"dSZ" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/layer_manifold, +/turf/open/floor/plating, +/area/engine/atmos) "dVR" = ( /obj/machinery/atmospherics/pipe/simple/violet/visible, /turf/open/floor/plasteel, @@ -70807,13 +70816,19 @@ }, /turf/open/floor/engine, /area/science/storage) +"ebG" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/turf/open/floor/plating, +/area/science/mixing) "eCy" = ( -/obj/structure/extinguisher_cabinet{ - pixel_x = -27 - }, /obj/machinery/atmospherics/pipe/simple/general/visible{ dir = 9 }, +/obj/machinery/embedded_controller/radio/airlock_controller/incinerator_atmos{ + pixel_x = -25; + pixel_y = 7 + }, /turf/open/floor/plasteel, /area/engine/atmos) "eIh" = ( @@ -70831,6 +70846,10 @@ dir = 1 }, /area/engine/atmos) +"eJy" = ( +/obj/machinery/rnd/experimentor, +/turf/open/floor/engine, +/area/science/explab) "eKM" = ( /obj/machinery/atmospherics/pipe/manifold/supplymain/visible, /turf/open/floor/plasteel, @@ -70991,6 +71010,13 @@ /obj/machinery/atmospherics/pipe/manifold/orange/visible, /turf/open/space/basic, /area/space/nearstation) +"iCa" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 5 + }, +/turf/open/floor/plating, +/area/science/mixing) "iQY" = ( /obj/machinery/atmospherics/pipe/manifold/yellow/visible{ dir = 4 @@ -71016,6 +71042,13 @@ }, /turf/open/space/basic, /area/space/nearstation) +"jAv" = ( +/obj/structure/lattice, +/obj/machinery/atmospherics/pipe/manifold/cyan/visible{ + dir = 4 + }, +/turf/open/space/basic, +/area/space/nearstation) "kzb" = ( /obj/machinery/atmospherics/pipe/manifold/orange/hidden{ dir = 4 @@ -71052,6 +71085,10 @@ }, /turf/open/floor/plasteel, /area/engine/atmos) +"mqE" = ( +/obj/machinery/atmospherics/pipe/manifold/cyan/visible, +/turf/closed/wall/r_wall, +/area/engine/atmos) "mxW" = ( /obj/structure/lattice, /obj/machinery/atmospherics/pipe/simple/supplymain/visible{ @@ -71059,6 +71096,13 @@ }, /turf/open/space/basic, /area/space/nearstation) +"mDW" = ( +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 10 + }, +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/engine/atmos) "mEa" = ( /obj/machinery/atmospherics/components/binary/pump/on{ dir = 8; @@ -71201,8 +71245,8 @@ /turf/open/space/basic, /area/space/nearstation) "rUl" = ( -/obj/machinery/atmospherics/pipe/manifold/orange/visible{ - dir = 8 +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 6 }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -71213,6 +71257,13 @@ }, /turf/open/floor/plating/airless, /area/router/aux) +"stP" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/item/kirbyplants/random, +/turf/open/floor/plasteel, +/area/quartermaster/office) "sAm" = ( /obj/structure/plasticflaps, /obj/machinery/door/poddoor{ @@ -71230,6 +71281,10 @@ /obj/machinery/portable_atmospherics/canister, /turf/open/floor/plasteel, /area/engine/atmos) +"sSg" = ( +/obj/machinery/rnd/bepis, +/turf/open/floor/engine, +/area/science/explab) "sVC" = ( /obj/structure/lattice/catwalk, /obj/structure/cable{ @@ -71278,8 +71333,8 @@ /turf/open/floor/plasteel, /area/engine/atmos) "tZC" = ( -/obj/machinery/atmospherics/pipe/manifold/orange/visible{ - dir = 1 +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 4 }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -71305,6 +71360,14 @@ }, /turf/open/floor/plasteel, /area/engine/atmos) +"uYy" = ( +/obj/structure/grille, +/obj/structure/cable{ + icon_state = "0-2" + }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/turf/open/floor/plating/airless, +/area/space/nearstation) "vcb" = ( /obj/machinery/atmospherics/pipe/simple/brown/visible, /obj/machinery/atmospherics/pipe/simple/green/visible{ @@ -90809,10 +90872,10 @@ bOv bfo blI bfo -bWS -bcw -bcw -bcw +bXg +ebG +ebG +iCa bcy cbu csR @@ -91321,9 +91384,9 @@ boJ fuR bzX bAl -boL +bdf bAG -cnT +bdf boQ cKJ bAP @@ -91576,11 +91639,11 @@ bcy bcy bcy bcy -bcy +bWS bgC bdf boR -bDL +bdf boQ cKJ bAP @@ -91833,11 +91896,11 @@ bQe aaU aaU aaU -bcw +boL bdf bdf bpM -bFp +bvj bvj cKK bAU @@ -92090,7 +92153,7 @@ aye aaU aaU aaU -bcw +bDL cnL bdf bpR @@ -92116,7 +92179,7 @@ cHj cqS cav cav -ccL +ctb caX caX caX @@ -92349,8 +92412,8 @@ abp abp bcy biK -bdf -bpR +bFp +cnT bJT bLl cKM @@ -92370,13 +92433,13 @@ aVF caw caA cHk -caP +ccL caT caX -caX +eJy caX cbh -caX +sSg caX cbx cav @@ -94872,11 +94935,11 @@ aUV aYB bbg bcH -bnZ +aYW bqi bIl bcJ -bOY +bod bdr beJ beJ @@ -95129,11 +95192,11 @@ bcN aYJ aNL aVJ -aYW +aYX baF bIr bcx -cvZ +bOY bdr beJ beT @@ -95386,11 +95449,11 @@ bcQ aUC aNL aVJ -aYX +bnZ baD bIV bKg -cwa +bVY bdr beJ bfd @@ -105699,7 +105762,7 @@ cgD cdV chy chN -bWQ +uYy bWQ cdo aPg @@ -107000,7 +107063,7 @@ cvb cvd cvd cNa -cNp +ctE ber cIQ cgB @@ -107257,7 +107320,7 @@ cuV cyv cuV cNb -cNq +cvZ beW cIM cgB @@ -108022,7 +108085,7 @@ cqs cqG crt cdm -ctl +cmT cuL cvd cAp @@ -108279,7 +108342,7 @@ bxz bwP cBn cBH -ctE +ctl cuM cvg cBa @@ -111626,7 +111689,7 @@ ciL cLr cwQ bPx -bod +cwa beW bXX cIM @@ -111883,7 +111946,7 @@ con coo cwR bPy -bVY +cNm bWn bYO cJc @@ -114200,7 +114263,7 @@ ckq bgf beB cxC -bgq +stP cjA biy bjN @@ -117286,7 +117349,7 @@ bdM cNA bhb ciE -cmT +cNp cnB csh cHV @@ -118800,7 +118863,7 @@ bNE cww cpO bYP -cRg +cMI cMH cww cMb @@ -119577,7 +119640,7 @@ chn eCy chL cMv -cMI +cMJ anr aaa aaa @@ -119834,7 +119897,7 @@ chp chx chM gDY -jiZ +mqE anr aaa aaa @@ -120088,7 +120151,7 @@ uVD mqB dpO tZC -qWY +cwB rUl cMw cfs @@ -120602,8 +120665,8 @@ sRD nAF cgz cJH -cwB -cMl +qWY +cJH cMx cMJ cxc @@ -121366,7 +121429,7 @@ bSb cKS cKY bQO -cLc +cMO eIh bYd tXV @@ -121376,7 +121439,7 @@ cwB cMc cMm cMy -cML +dSZ cLa cKY cLu @@ -122394,7 +122457,7 @@ bTH cKU cKY cLa -cLc +cMO fgS car cwB @@ -122404,7 +122467,7 @@ cwB cMg cMq cMB -cML +dSZ cMQ cKY cLw @@ -123175,8 +123238,8 @@ cLs cLs cMs cME -cMN -aaU +mDW +dnN bZR caJ bpq @@ -123422,7 +123485,7 @@ bTK cKW cKY bQV -cLc +cMO cLk ctk prx @@ -123433,7 +123496,7 @@ prx iQY cMF cMO -cMS +jAv cMT cLy blM diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index e907602d59..07902b28b1 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -3535,9 +3535,7 @@ dir = 4 }, /obj/effect/turf_decal/delivery, -/obj/item/kirbyplants{ - icon_state = "plant-21" - }, +/obj/machinery/gear_painter, /turf/open/floor/plasteel, /area/hallway/secondary/entry) "ajL" = ( @@ -3823,6 +3821,9 @@ /obj/effect/turf_decal/tile/blue{ dir = 8 }, +/obj/item/kirbyplants{ + icon_state = "plant-21" + }, /turf/open/floor/plasteel/white/corner, /area/hallway/secondary/entry) "akn" = ( @@ -79384,6 +79385,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/gear_painter, /turf/open/floor/plasteel{ heat_capacity = 1e+006 }, diff --git a/_maps/map_files/KiloStation/KiloStation.dmm b/_maps/map_files/KiloStation/KiloStation.dmm index 3ff364fa5c..408efad32f 100644 --- a/_maps/map_files/KiloStation/KiloStation.dmm +++ b/_maps/map_files/KiloStation/KiloStation.dmm @@ -48007,8 +48007,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/structure/closet/wardrobe/mixed, /obj/machinery/light/small, +/obj/effect/turf_decal/delivery, +/obj/machinery/gear_painter, /turf/open/floor/plasteel/dark, /area/crew_quarters/locker) "bzo" = ( @@ -48767,7 +48768,6 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/fitness/recreation) "bAA" = ( -/obj/structure/table, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -48777,11 +48777,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/item/storage/backpack{ - pixel_x = 4; - pixel_y = 4 - }, -/obj/item/storage/backpack, /obj/machinery/firealarm{ dir = 8; pixel_x = 26 @@ -49398,6 +49393,7 @@ dir = 1; name = "recreation camera" }, +/obj/structure/closet/wardrobe/mixed, /turf/open/floor/plasteel, /area/crew_quarters/fitness/recreation) "bBy" = ( @@ -54797,11 +54793,6 @@ /area/hallway/secondary/exit/departure_lounge) "bKn" = ( /obj/structure/table, -/obj/item/paper_bin{ - pixel_x = -4; - pixel_y = 4 - }, -/obj/item/pen, /obj/effect/decal/cleanable/cobweb/cobweb2, /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -54810,6 +54801,11 @@ /obj/machinery/airalarm{ pixel_y = 22 }, +/obj/item/storage/backpack{ + pixel_x = 4; + pixel_y = 4 + }, +/obj/item/storage/backpack, /turf/open/floor/plasteel/dark, /area/crew_quarters/fitness/recreation) "bKo" = ( @@ -55425,6 +55421,12 @@ pixel_x = 28; pixel_y = 22 }, +/obj/structure/table, +/obj/item/paper_bin{ + pixel_x = -4; + pixel_y = 4 + }, +/obj/item/pen, /turf/open/floor/plasteel, /area/crew_quarters/fitness/recreation) "bLd" = ( @@ -60844,6 +60846,11 @@ /obj/effect/turf_decal/tile/red{ dir = 1 }, +/obj/structure/table, +/obj/item/toy/figure/assistant{ + pixel_x = 8; + pixel_y = 6 + }, /turf/open/floor/plasteel, /area/hallway/secondary/entry) "bTD" = ( @@ -61021,6 +61028,12 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{ dir = 10 }, +/obj/structure/table, +/obj/item/paper_bin{ + pixel_x = -4; + pixel_y = 4 + }, +/obj/item/pen, /turf/open/floor/plasteel, /area/hallway/secondary/entry) "bTO" = ( @@ -61259,19 +61272,8 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/structure/table, -/obj/item/paper_bin{ - pixel_x = -4; - pixel_y = 4 - }, -/obj/item/pen, -/obj/item/toy/figure/assistant{ - pixel_x = 8; - pixel_y = 6 - }, -/obj/effect/turf_decal/loading_area{ - dir = 1 - }, +/obj/effect/turf_decal/delivery, +/obj/machinery/gear_painter, /turf/open/floor/plasteel/dark, /area/hallway/secondary/entry) "bUi" = ( @@ -71325,15 +71327,16 @@ icon_gib = "magicarp_gib"; icon_living = "magicarp"; icon_state = "magicarp"; - maxHealth = 200; max_co2 = 5; max_tox = 2; + maxHealth = 200; melee_damage_lower = 15; melee_damage_upper = 20; min_oxy = 5; name = "Lia"; real_name = "Lia"; - response_help = "pets"; + response_help_continuous = "pets"; + response_help_simple = "pet"; turns_per_move = 10 }, /turf/open/floor/plasteel/dark, diff --git a/_maps/map_files/LambdaStation/dorms.dmm b/_maps/map_files/LambdaStation/dorms.dmm index a38d2b9e1d..0ed1b0203c 100644 --- a/_maps/map_files/LambdaStation/dorms.dmm +++ b/_maps/map_files/LambdaStation/dorms.dmm @@ -10679,7 +10679,7 @@ light_color = "#e8eaff" }, /obj/machinery/vending/wardrobe/jani_wardrobe{ - products = list(/obj/item/clothing/under/rank/civilian/janitor = 2, /obj/item/cartridge/janitor = 2, /obj/item/clothing/gloves/color/black = 2, /obj/item/clothing/head/soft/purple = 2, /obj/item/paint/paint_remover = 2, /obj/item/melee/flyswatter = 2, /obj/item/flashlight = 2, /obj/item/caution = 10, /obj/item/holosign_creator = 2, /obj/item/lightreplacer = 2, /obj/item/soap/nanotrasen = 2, /obj/item/storage/bag/trash = 2, /obj/item/clothing/shoes/galoshes = 2, /obj/item/watertank/janitor = 2, /obj/item/storage/belt/janitor = 2) + products = list(/obj/item/clothing/under/rank/civilian/janitor = 2, /obj/item/cartridge/janitor = 2, /obj/item/clothing/gloves/color/black = 2, /obj/item/clothing/head/soft/purple = 2, /obj/item/paint/paint_remover = 2, /obj/item/melee/flyswatter = 2, /obj/item/flashlight = 2, /obj/item/clothing/suit/caution = 10, /obj/item/holosign_creator = 2, /obj/item/lightreplacer = 2, /obj/item/soap/nanotrasen = 2, /obj/item/storage/bag/trash = 2, /obj/item/clothing/shoes/galoshes = 2, /obj/item/watertank/janitor = 2, /obj/item/storage/belt/janitor = 2) }, /turf/open/floor/plating, /area/janitor) @@ -13637,7 +13637,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "IX" = ( -/obj/item/caution, +/obj/item/clothing/suit/caution, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{ @@ -13764,6 +13764,7 @@ /obj/effect/turf_decal/trimline/neutral/filled/corner{ dir = 4 }, +/obj/machinery/gear_painter, /turf/open/floor/plasteel, /area/crew_quarters/locker) "Jp" = ( diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 3c160180da..958ab2dc5a 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -4826,6 +4826,7 @@ /obj/machinery/light{ dir = 4 }, +/obj/machinery/gear_painter, /turf/open/floor/plasteel/white/corner, /area/hallway/secondary/entry) "aiU" = ( @@ -12681,7 +12682,7 @@ /turf/open/floor/wood, /area/crew_quarters/dorms) "axL" = ( -/obj/item/caution, +/obj/item/clothing/suit/caution, /obj/effect/turf_decal/stripes/line{ dir = 1 }, @@ -23177,6 +23178,9 @@ }, /obj/machinery/light, /obj/effect/turf_decal/tile/neutral, +/obj/machinery/newscaster{ + pixel_y = -32 + }, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aTy" = ( @@ -23190,17 +23194,6 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel, /area/crew_quarters/locker) -"aTz" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/machinery/light, -/obj/machinery/newscaster{ - pixel_y = -32 - }, -/obj/effect/turf_decal/tile/neutral, -/turf/open/floor/plasteel, -/area/crew_quarters/locker) "aTA" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 9 @@ -39921,9 +39914,6 @@ /turf/open/floor/plasteel/dark, /area/bridge) "bzU" = ( -/obj/structure/chair/comfy/teal{ - dir = 4 - }, /obj/structure/chair/comfy/black{ dir = 4 }, @@ -52010,19 +52000,23 @@ /turf/open/floor/plating, /area/maintenance/port/aft) "bZV" = ( -/obj/item/storage/toolbox/emergency, -/obj/item/hand_labeler, -/obj/effect/spawner/lootdrop/maintenance, +/obj/item/storage/box/lights/mixed, /turf/open/floor/plating, /area/maintenance/port/aft) "bZW" = ( -/obj/item/cigbutt, +/obj/item/cigbutt{ + pixel_x = 6; + pixel_y = -6 + }, /obj/structure/disposalpipe/segment{ dir = 6 }, /obj/effect/turf_decal/stripes/line{ dir = 4 }, +/obj/item/storage/toolbox/emergency, +/obj/item/hand_labeler, +/obj/effect/spawner/lootdrop/maintenance, /turf/open/floor/plating, /area/maintenance/port/aft) "bZX" = ( @@ -53085,7 +53079,6 @@ }, /area/maintenance/port/aft) "cbG" = ( -/obj/item/storage/box/lights/mixed, /obj/structure/disposalpipe/segment{ dir = 4 }, @@ -53178,8 +53171,6 @@ network = list("ss13","medbay") }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/structure/closet/crate/freezer/surplus_limbs, -/obj/item/reagent_containers/glass/beaker/synthflesh, /obj/effect/turf_decal/tile/blue, /obj/effect/turf_decal/tile/blue{ dir = 4 @@ -55173,7 +55164,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/machinery/bloodbankgen, +/obj/vehicle/ridden/wheelchair, /turf/open/floor/plasteel/dark, /area/medical/sleeper) "cfL" = ( @@ -55715,7 +55706,6 @@ icon_state = "4-8" }, /obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/obj/effect/turf_decal/stripes/line, /turf/open/floor/plating, /area/maintenance/port/aft) "cgM" = ( @@ -56421,35 +56411,29 @@ /turf/closed/wall, /area/medical/surgery) "cib" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 6 - }, -/turf/closed/wall, +/obj/structure/closet/secure_closet/medical2, +/turf/open/floor/plasteel/white/corner, /area/medical/surgery) "cic" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 + dir = 10 }, -/turf/closed/wall, -/area/medical/surgery) -"cid" = ( -/obj/machinery/door/airlock/maintenance{ - name = "Medbay Maintenance"; - req_access_txt = "5" - }, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ +/turf/open/floor/plasteel/white/side{ dir = 1 }, -/turf/open/floor/plating, -/area/maintenance/port/aft) +/area/medical/surgery) +"cid" = ( +/obj/structure/curtain{ + icon_state = "closed" + }, +/obj/machinery/door/firedoor, +/turf/open/floor/plasteel/white, +/area/medical/surgery) "cie" = ( /obj/machinery/firealarm{ dir = 4; pixel_x = -24 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 10 - }, /obj/effect/turf_decal/tile/blue{ dir = 1 }, @@ -57093,56 +57077,65 @@ /turf/open/floor/plating, /area/maintenance/port/aft) "cjw" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 4 +/obj/structure/table, +/obj/item/storage/backpack/duffelbag/med/surgery{ + pixel_y = 5 }, -/turf/open/floor/plasteel/dark, -/area/medical/surgery) -"cjx" = ( -/obj/structure/chair, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 4 +/obj/machinery/light_switch{ + pixel_x = -26 }, -/turf/open/floor/plasteel/dark, -/area/medical/surgery) -"cjy" = ( -/obj/item/cigbutt, -/obj/machinery/light/small{ - dir = 1 +/obj/machinery/vending/wallmed{ + pixel_y = 29 }, -/turf/open/floor/plasteel/dark, +/turf/open/floor/plasteel/white/corner, /area/medical/surgery) "cjz" = ( -/obj/structure/chair, -/obj/machinery/airalarm{ - pixel_y = 23 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 6 - }, -/turf/open/floor/plasteel/dark, -/area/medical/surgery) -"cjA" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ +/obj/structure/closet/secure_closet/medical2, +/turf/open/floor/plasteel/white/corner{ dir = 8 }, -/turf/open/floor/plasteel/dark, +/area/medical/surgery) +"cjA" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plasteel/white/corner{ + dir = 4 + }, /area/medical/surgery) "cjB" = ( -/obj/item/cigbutt, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/open/floor/plasteel/dark, +/obj/machinery/iv_drip, +/obj/machinery/atmospherics/components/unary/vent_pump/on, +/obj/machinery/firealarm{ + pixel_y = 28 + }, +/turf/open/floor/plasteel/white/side, /area/medical/surgery) "cjC" = ( -/obj/structure/chair, -/turf/open/floor/plasteel/dark, +/obj/structure/table, +/obj/item/radio/intercom{ + broadcasting = 1; + frequency = 1485; + listening = 0; + name = "Station Intercom (Medbay)"; + pixel_y = 22 + }, +/obj/item/clothing/gloves/color/latex, +/obj/item/clothing/suit/apron/surgical, +/turf/open/floor/plasteel/white/side, /area/medical/surgery) "cjD" = ( -/obj/structure/chair, -/obj/machinery/light/small{ - dir = 1 +/obj/structure/table, +/obj/item/storage/backpack/duffelbag/med/surgery{ + pixel_y = 5 + }, +/obj/machinery/light_switch{ + pixel_x = 28 + }, +/obj/machinery/vending/wallmed{ + pixel_y = 29 + }, +/turf/open/floor/plasteel/white/corner{ + dir = 8 }, -/turf/open/floor/plasteel/dark, /area/medical/surgery) "cjE" = ( /obj/structure/bed/roller, @@ -57153,9 +57146,6 @@ name = "Station Intercom (Medbay)"; pixel_x = -30 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 5 - }, /obj/machinery/camera{ c_tag = "Medbay Sleepers"; dir = 4; @@ -57171,12 +57161,7 @@ /turf/open/floor/plasteel/white, /area/medical/sleeper) "cjF" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel/white, /area/medical/sleeper) "cjG" = ( @@ -57188,7 +57173,6 @@ /area/medical/sleeper) "cjH" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/obj/effect/turf_decal/tile/blue, /turf/open/floor/plasteel/white, /area/medical/sleeper) "cjI" = ( @@ -57790,71 +57774,66 @@ /turf/open/floor/plasteel/dark, /area/aisat) "ckU" = ( -/obj/structure/chair, -/obj/structure/sign/warning/nosmoking{ - pixel_x = -28 +/obj/machinery/computer/operating{ + dir = 4 + }, +/obj/machinery/light{ + dir = 8 + }, +/turf/open/floor/plasteel/white/side{ + dir = 4 }, -/turf/open/floor/plasteel/dark, -/area/medical/surgery) -"ckV" = ( -/obj/structure/chair, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/open/floor/plasteel/dark, -/area/medical/surgery) -"ckW" = ( -/obj/machinery/holopad, -/turf/open/floor/plasteel/dark, /area/medical/surgery) "ckX" = ( -/obj/structure/chair, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ +/obj/structure/sink{ + dir = 4; + pixel_x = 11 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 10 + }, +/turf/open/floor/plasteel/white/side{ dir = 8 }, -/turf/open/floor/plasteel/dark, /area/medical/surgery) "ckY" = ( -/obj/structure/chair, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 6 + }, +/turf/open/floor/plasteel/white/side{ + dir = 1 }, -/turf/open/floor/plasteel/dark, /area/medical/surgery) "ckZ" = ( -/obj/structure/disposalpipe/segment, +/obj/structure/sink{ + dir = 8; + pixel_x = -12; + pixel_y = 2 + }, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 6 + }, +/turf/open/floor/plasteel/white/side{ dir = 4 }, -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/medical{ - name = "Observation" - }, -/turf/open/floor/plasteel/dark, /area/medical/surgery) "cla" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 1 - }, -/turf/open/floor/plasteel/dark, +/turf/open/floor/plasteel/white, /area/medical/surgery) "clb" = ( -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 1 - }, -/turf/open/floor/plasteel/dark, +/obj/effect/landmark/start/medical_doctor, +/turf/open/floor/plasteel/white, /area/medical/surgery) "clc" = ( -/obj/item/cigbutt, -/obj/machinery/atmospherics/components/unary/vent_pump/on{ +/obj/machinery/computer/operating{ dir = 8 }, -/obj/structure/sign/warning/nosmoking{ - pixel_x = 28 +/obj/machinery/light{ + dir = 4 + }, +/turf/open/floor/plasteel/white/side{ + dir = 8 }, -/obj/effect/landmark/blobstart, -/turf/open/floor/plasteel/dark, /area/medical/surgery) "cld" = ( /obj/machinery/sleeper{ @@ -57894,6 +57873,7 @@ /obj/effect/turf_decal/tile/blue{ dir = 8 }, +/obj/effect/landmark/start/paramedic, /turf/open/floor/plasteel/white, /area/medical/sleeper) "clg" = ( @@ -57974,6 +57954,9 @@ /area/medical/medbay/central) "cln" = ( /obj/effect/turf_decal/tile/blue, +/obj/vehicle/ridden/wheelchair{ + dir = 1 + }, /turf/open/floor/plasteel/white, /area/medical/medbay/central) "clo" = ( @@ -58441,26 +58424,32 @@ /turf/open/floor/wood, /area/maintenance/port/aft) "cmk" = ( -/obj/effect/spawner/structure/window, -/turf/open/floor/plating, +/obj/structure/table/optable, +/turf/open/floor/plasteel/white/corner{ + dir = 4 + }, /area/medical/surgery) "cml" = ( -/obj/effect/spawner/structure/window, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/open/floor/plating, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 4 + }, +/turf/open/floor/plasteel/white/side{ + dir = 1 + }, /area/medical/surgery) "cmm" = ( -/obj/effect/spawner/structure/window, /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/plating, +/turf/open/floor/plasteel/white/corner{ + dir = 1 + }, /area/medical/surgery) "cmn" = ( -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/medical{ - name = "Observation" +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 8 + }, +/turf/open/floor/plasteel/white/side{ + dir = 1 }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/plasteel, /area/medical/surgery) "cmo" = ( /obj/effect/spawner/structure/window, @@ -58903,78 +58892,30 @@ /turf/open/floor/wood, /area/maintenance/port/aft) "cnm" = ( -/obj/structure/table, -/obj/item/hemostat, -/obj/structure/extinguisher_cabinet{ - pixel_x = -27 - }, -/turf/open/floor/plasteel, -/area/medical/surgery) -"cnn" = ( -/obj/structure/table, -/obj/item/surgicaldrill, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/open/floor/plasteel/white/side, -/area/medical/surgery) -"cno" = ( -/obj/structure/table, -/obj/item/scalpel{ - pixel_y = 12 - }, -/obj/item/circular_saw, -/turf/open/floor/plasteel/white/side, +/obj/structure/sign/poster/official/cleanliness, +/turf/closed/wall, /area/medical/surgery) "cnp" = ( -/obj/structure/table, -/obj/item/cautery{ - pixel_x = 4 - }, /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/item/razor{ - pixel_y = 5 +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/medical/glass{ + name = "Operating Theatre"; + req_access_txt = "45" }, -/turf/open/floor/plasteel/white/side, +/turf/open/floor/plasteel/white, /area/medical/surgery) "cnq" = ( -/obj/structure/table, -/obj/item/retractor, -/turf/open/floor/plasteel, +/obj/machinery/smartfridge/organ/preloaded, +/turf/closed/wall, /area/medical/surgery) "cnr" = ( -/obj/machinery/computer/med_data{ - dir = 4 - }, -/obj/structure/extinguisher_cabinet{ - pixel_x = -27 - }, -/turf/open/floor/plasteel/white/side, -/area/medical/surgery) -"cns" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/plasteel/white/side, +/obj/effect/spawner/structure/window, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/plating, /area/medical/surgery) "cnt" = ( -/obj/structure/table/reinforced, -/obj/item/radio/intercom{ - broadcasting = 1; - frequency = 1485; - listening = 0; - name = "Station Intercom (Medbay)"; - pixel_x = 30 - }, -/obj/structure/bedsheetbin{ - pixel_x = 2 - }, -/obj/item/clothing/suit/straight_jacket, -/obj/item/clothing/mask/muzzle, -/obj/item/clothing/glasses/eyepatch, -/obj/item/clothing/glasses/sunglasses/blindfold, -/obj/item/clothing/ears/earmuffs, -/obj/item/storage/belt/medical{ - pixel_y = 2 - }, -/obj/item/gun/syringe/dart, -/turf/open/floor/plasteel/white/side, +/obj/effect/spawner/structure/window, +/turf/open/floor/plating, /area/medical/surgery) "cnu" = ( /obj/machinery/power/apc{ @@ -59637,89 +59578,96 @@ }, /area/maintenance/port/aft) "coy" = ( -/obj/structure/table, -/obj/item/clothing/gloves/color/latex, -/obj/item/clothing/mask/surgical, -/obj/item/clothing/suit/apron/surgical, -/obj/machinery/airalarm{ - dir = 4; - pixel_x = -22 - }, -/turf/open/floor/plasteel/white/side{ - dir = 4 +/obj/structure/chair{ + dir = 1 }, +/turf/open/floor/plasteel/dark, /area/medical/surgery) "coz" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/open/floor/plasteel/white, +/obj/structure/chair{ + dir = 1 + }, +/obj/effect/decal/cleanable/vomit/old{ + pixel_x = -2; + pixel_y = 7 + }, +/turf/open/floor/plasteel/dark, /area/medical/surgery) "coA" = ( -/obj/effect/landmark/start/medical_doctor, -/turf/open/floor/plasteel/white, +/obj/structure/chair{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 5 + }, +/turf/open/floor/plasteel/dark, /area/medical/surgery) "coB" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/plasteel/white, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, /area/medical/surgery) "coC" = ( -/obj/machinery/power/apc{ - areastring = "/area/medical/surgery"; - dir = 4; - name = "Surgery APC"; - pixel_x = 26 - }, -/obj/structure/cable/yellow{ - icon_state = "0-2" - }, -/obj/structure/table, -/obj/item/surgical_drapes, -/turf/open/floor/plasteel/white/side{ - dir = 8 +/obj/effect/landmark/start/medical_doctor, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 }, +/turf/open/floor/plasteel/dark, /area/medical/surgery) "coD" = ( -/obj/structure/bed/roller, -/obj/machinery/light/small{ - dir = 8 +/obj/item/cigbutt{ + pixel_x = -8; + pixel_y = 12 }, -/obj/machinery/iv_drip, -/turf/open/floor/plasteel/white, +/obj/structure/chair{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, +/turf/open/floor/plasteel/dark, /area/medical/surgery) "coE" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 4 +/obj/structure/chair{ + dir = 1 }, -/turf/open/floor/plasteel/white, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 10 + }, +/turf/open/floor/plasteel/dark, /area/medical/surgery) "coF" = ( -/obj/structure/bed, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 +/obj/item/trash/popcorn{ + pixel_x = -5; + pixel_y = -4 }, -/obj/item/bedsheet/medical, -/turf/open/floor/plasteel/white, +/obj/structure/chair{ + dir = 1 + }, +/obj/machinery/firealarm{ + dir = 8; + pixel_x = 24 + }, +/turf/open/floor/plasteel/dark, /area/medical/surgery) "coG" = ( -/obj/effect/spawner/structure/window, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 +/obj/structure/table/optable, +/obj/effect/decal/cleanable/blood/old, +/turf/open/floor/plasteel/white/corner{ + dir = 1 }, -/turf/open/floor/plating, /area/medical/surgery) "coH" = ( /obj/structure/cable/yellow{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 9 - }, /obj/effect/turf_decal/tile/blue{ dir = 1 }, /obj/effect/turf_decal/tile/blue{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel/white, /area/medical/cryo) "coI" = ( @@ -60439,96 +60387,90 @@ /obj/structure/cable/yellow{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/disposalpipe/segment, /obj/effect/turf_decal/stripes/line{ dir = 4 }, -/turf/open/floor/plating, -/area/maintenance/port/aft) -"cpT" = ( -/obj/machinery/door/airlock/maintenance{ - name = "Surgery Maintenance"; - req_access_txt = "45" - }, -/turf/open/floor/plating, -/area/maintenance/port/aft) -"cpU" = ( -/turf/open/floor/plasteel/white, -/area/medical/surgery) -"cpW" = ( -/obj/structure/cable/yellow{ - icon_state = "1-4" - }, -/turf/open/floor/plasteel/white, -/area/medical/surgery) -"cpX" = ( -/obj/structure/cable/yellow{ - icon_state = "4-8" - }, -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/medical{ - name = "Operating Theatre"; - req_access_txt = "45" - }, -/turf/open/floor/plasteel/white, -/area/medical/surgery) -"cpY" = ( -/obj/structure/cable/yellow{ - icon_state = "4-8" - }, -/obj/effect/landmark/event_spawn, -/turf/open/floor/plasteel/white, -/area/medical/surgery) -"cpZ" = ( -/obj/structure/cable/yellow{ - icon_state = "4-8" - }, /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ dir = 8 }, -/obj/effect/landmark/start/medical_doctor, -/obj/machinery/holopad, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"cpT" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 5 + }, /turf/open/floor/plasteel/white, /area/medical/surgery) +"cpW" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/holopad, +/turf/open/floor/plasteel/dark/side{ + dir = 1 + }, +/area/medical/surgery) +"cpX" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 9 + }, +/obj/structure/extinguisher_cabinet{ + pixel_y = -30 + }, +/turf/open/floor/plasteel/dark/side{ + dir = 1 + }, +/area/medical/surgery) +"cpZ" = ( +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 8 + }, +/turf/open/floor/plasteel/dark/side{ + dir = 1 + }, +/area/medical/surgery) "cqa" = ( -/obj/structure/cable/yellow{ - icon_state = "4-8" +/turf/open/floor/plasteel/dark/side{ + dir = 1 }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/turf/open/floor/plasteel/white, /area/medical/surgery) "cqb" = ( -/obj/structure/cable/yellow{ - icon_state = "4-8" +/obj/machinery/door/firedoor, +/obj/effect/turf_decal/tile/blue{ + dir = 8 }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ dir = 4 }, -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/medical/glass{ +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/machinery/door/airlock/medical{ name = "Surgery Observation" }, /turf/open/floor/plasteel/white, /area/medical/surgery) "cqc" = ( -/obj/structure/cable/yellow{ - icon_state = "4-8" - }, /obj/structure/cable/yellow{ icon_state = "1-4" }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 1 - }, /obj/effect/turf_decal/tile/blue{ dir = 1 }, /obj/effect/turf_decal/tile/blue{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 6 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 9 + }, /turf/open/floor/plasteel/white, /area/medical/cryo) "cqd" = ( @@ -61165,66 +61107,36 @@ }, /area/maintenance/port/aft) "crj" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 4 - }, -/obj/structure/sink{ - dir = 8; - pixel_x = -12; - pixel_y = 2 - }, /obj/machinery/light_switch{ - pixel_x = -28 + pixel_x = -26 }, -/turf/open/floor/plasteel/white/side{ +/turf/open/floor/plasteel/white/corner, +/area/medical/surgery) +"crl" = ( +/turf/open/floor/plasteel/white/side, +/area/medical/surgery) +"crm" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, +/turf/open/floor/plasteel/white/side, +/area/medical/surgery) +"crn" = ( +/obj/machinery/light{ dir = 4 }, +/turf/open/floor/plasteel/white/side, /area/medical/surgery) -"crk" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ +"cro" = ( +/obj/effect/landmark/blobstart, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 9 }, /turf/open/floor/plasteel/white, /area/medical/surgery) -"crl" = ( -/obj/machinery/computer/operating{ - dir = 1 - }, -/turf/open/floor/plasteel/white, -/area/medical/surgery) -"crm" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 5 - }, -/turf/open/floor/plasteel/white, -/area/medical/surgery) -"crn" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 8 - }, -/obj/machinery/firealarm{ - dir = 8; - pixel_x = 24 - }, -/turf/open/floor/plasteel/white/side{ - dir = 8 - }, -/area/medical/surgery) -"cro" = ( -/obj/structure/bed/roller, -/obj/machinery/iv_drip, -/obj/structure/sign/warning/nosmoking{ - pixel_x = -28 - }, -/turf/open/floor/plasteel/white, -/area/medical/surgery) "crq" = ( -/obj/structure/bed, -/obj/item/bedsheet/medical, -/obj/machinery/light_switch{ - pixel_x = 26 - }, -/turf/open/floor/plasteel/white, +/obj/effect/landmark/event_spawn, +/turf/open/floor/plasteel/white/side, /area/medical/surgery) "crr" = ( /obj/machinery/airalarm{ @@ -61669,23 +61581,46 @@ /turf/open/floor/plating, /area/maintenance/port/aft) "csj" = ( -/obj/structure/closet/secure_closet/medical2, /obj/structure/sign/warning/nosmoking{ pixel_x = -28 }, -/turf/open/floor/plasteel, +/obj/machinery/limbgrower, +/turf/open/floor/plasteel/white/side{ + dir = 4 + }, /area/medical/surgery) "csk" = ( +/obj/machinery/light, +/obj/machinery/bloodbankgen, +/turf/open/floor/plasteel/white, +/area/medical/surgery) +"csl" = ( /obj/machinery/airalarm{ dir = 1; pixel_y = -22 }, -/turf/open/floor/plasteel/white/side{ - dir = 1 +/obj/structure/window/reinforced{ + dir = 8 }, +/obj/structure/closet/crate/freezer/blood, +/obj/machinery/door/window/northleft{ + name = "Surgery Supplies"; + red_alert_access = 1; + req_access_txt = "5" + }, +/turf/open/floor/plasteel/white, /area/medical/surgery) -"csl" = ( -/obj/machinery/light, +"csm" = ( +/obj/structure/window/reinforced{ + dir = 4 + }, +/obj/structure/closet/crate/freezer/surplus_limbs, +/obj/item/reagent_containers/glass/beaker/synthflesh, +/obj/machinery/door/window/northright{ + name = "Surgery Supplies"; + red_alert_access = 1; + req_access_txt = "5" + }, /obj/machinery/camera{ c_tag = "Medbay Surgery"; dir = 1; @@ -61693,72 +61628,38 @@ }, /turf/open/floor/plasteel/white, /area/medical/surgery) -"csm" = ( -/obj/machinery/firealarm{ - dir = 1; - pixel_y = -24 - }, -/turf/open/floor/plasteel/white/side{ - dir = 1 - }, -/area/medical/surgery) "csn" = ( -/obj/item/radio/intercom{ - broadcasting = 1; - frequency = 1485; - listening = 0; - name = "Station Intercom (Medbay)"; - pixel_y = -30 - }, -/obj/structure/closet/crate/freezer/blood, -/turf/open/floor/plasteel, -/area/medical/surgery) -"cso" = ( -/obj/structure/bed/roller, -/obj/machinery/light/small{ - dir = 8 - }, -/obj/machinery/airalarm{ - dir = 1; - pixel_y = -22 - }, -/obj/machinery/iv_drip, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 8 +/obj/structure/chair/office/light{ + dir = 4 }, /turf/open/floor/plasteel/white, /area/medical/surgery) -"csp" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ +"cso" = ( +/obj/item/bedsheet/medical{ dir = 1 }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 8 +/obj/structure/bed{ + dir = 1 + }, +/turf/open/floor/plasteel/white/side{ + dir = 4 + }, +/area/medical/surgery) +"csp" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 1 }, /turf/open/floor/plasteel/white, /area/medical/surgery) "csq" = ( /obj/structure/bed, -/obj/machinery/firealarm{ - dir = 8; - pixel_x = 24 - }, /obj/item/bedsheet/medical, -/obj/machinery/newscaster{ - pixel_y = -32 +/obj/structure/sign/warning/nosmoking{ + pixel_x = 28 }, -/obj/machinery/camera{ - c_tag = "Medbay Recovery Room"; - dir = 1; - network = list("ss13","medbay") - }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ +/turf/open/floor/plasteel/white/side{ dir = 8 }, -/turf/open/floor/plasteel/white, /area/medical/surgery) "csr" = ( /obj/machinery/door/airlock/maintenance{ @@ -62325,8 +62226,12 @@ /turf/open/floor/plating, /area/maintenance/aft) "ctr" = ( -/obj/structure/bed, -/obj/item/bedsheet/medical, +/obj/structure/bed{ + dir = 1 + }, +/obj/item/bedsheet/medical{ + dir = 1 + }, /obj/machinery/atmospherics/components/unary/vent_scrubber/on, /obj/machinery/airalarm{ dir = 4; @@ -62376,6 +62281,16 @@ /obj/structure/cable/yellow{ icon_state = "4-8" }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue, /turf/open/floor/plasteel/white, /area/medical/patients_rooms/room_a) "ctv" = ( @@ -62458,7 +62373,7 @@ "ctD" = ( /obj/structure/sign/directions/evac, /turf/closed/wall, -/area/medical/genetics) +/area/medical/paramedic) "ctE" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/door/firedoor, @@ -62728,29 +62643,38 @@ /turf/open/floor/plating, /area/maintenance/port/aft) "cui" = ( -/obj/structure/closet/crate, -/obj/item/coin/silver, -/obj/item/reagent_containers/spray/weedspray, -/obj/item/paper, -/obj/effect/spawner/lootdrop/maintenance{ - lootcount = 2; - name = "2maintenance loot spawner" +/obj/structure/table/reinforced, +/obj/structure/bedsheetbin{ + pixel_x = 2 }, -/turf/open/floor/plating, -/area/maintenance/port/aft) +/obj/item/clothing/suit/straight_jacket, +/obj/item/clothing/ears/earmuffs, +/obj/item/clothing/glasses/sunglasses/blindfold, +/obj/item/clothing/mask/muzzle, +/obj/item/clothing/glasses/eyepatch, +/obj/item/gun/syringe/dart, +/obj/item/storage/belt/medical{ + pixel_y = 2 + }, +/turf/open/floor/plasteel/white/side{ + dir = 1 + }, +/area/medical/surgery) "cuj" = ( -/obj/effect/decal/cleanable/cobweb, -/obj/structure/cable/yellow{ - icon_state = "0-2" +/obj/structure/sign/poster/official/medical_green_cross{ + pixel_y = -32 }, -/obj/machinery/power/apc{ - areastring = "/area/maintenance/port/aft"; - dir = 1; - name = "Port Quarter Maintenance APC"; - pixel_y = 24 +/obj/structure/bed{ + dir = 1 }, -/turf/open/floor/plating, -/area/maintenance/port/aft) +/obj/item/bedsheet/medical{ + dir = 1 + }, +/obj/machinery/light/small, +/turf/open/floor/plasteel/white/corner{ + dir = 4 + }, +/area/medical/surgery) "cuk" = ( /obj/structure/table, /obj/item/folder/white{ @@ -62936,14 +62860,16 @@ }, /obj/item/folder/white{ pixel_x = 4; - pixel_y = -3 + pixel_y = 4 }, /obj/item/folder/white{ pixel_x = 4; - pixel_y = -3 + pixel_y = 4 }, /obj/item/storage/pill_bottle/mutadone, -/obj/item/storage/pill_bottle/mannitol, +/obj/item/storage/pill_bottle/mannitol{ + pixel_x = 5 + }, /obj/structure/table/glass, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -62981,10 +62907,12 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/item/reagent_containers/spray/cleaner{ + pixel_x = -5 + }, /turf/open/floor/plasteel/dark, /area/medical/genetics) "cuw" = ( -/obj/structure/filingcabinet/chestdrawer, /obj/effect/turf_decal/tile/blue{ dir = 1 }, @@ -62994,51 +62922,41 @@ /obj/effect/turf_decal/tile/blue{ dir = 8 }, -/turf/open/floor/plasteel, -/area/medical/genetics) -"cux" = ( -/obj/structure/noticeboard{ - desc = "A board for pinning important notices upon. Probably helpful for keeping track of requests."; - name = "requests board"; - pixel_x = -32; - pixel_y = 32 +/obj/machinery/computer/crew, +/obj/machinery/vending/wallmed{ + pixel_x = -25 }, +/turf/open/floor/plasteel, +/area/medical/paramedic) +"cux" = ( /obj/structure/disposalpipe/segment, /obj/effect/turf_decal/tile/blue{ dir = 1 }, -/obj/effect/turf_decal/tile/blue, /obj/effect/turf_decal/tile/blue{ dir = 4 }, /turf/open/floor/plasteel, -/area/medical/genetics) +/area/medical/paramedic) "cuy" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/door/poddoor/shutters/preopen{ - id = "genetics_shutters"; - name = "genetics shutters" +/obj/structure/table/glass, +/obj/item/flashlight/lamp{ + pixel_x = -1; + pixel_y = 11 }, -/turf/open/floor/plating, -/area/medical/genetics) -"cuz" = ( -/obj/structure/table/reinforced, -/obj/item/paper_bin{ - pixel_x = -2; - pixel_y = 6 +/obj/effect/spawner/lootdrop/cig_packs{ + pixel_x = 5; + pixel_y = -4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 }, /obj/effect/turf_decal/tile/blue{ dir = 1 }, /obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, /turf/open/floor/plasteel, -/area/medical/genetics) +/area/medical/paramedic) "cuA" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/turf_decal/tile/blue{ @@ -63047,6 +62965,9 @@ /obj/effect/turf_decal/tile/blue{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/hallway/primary/aft) "cuB" = ( @@ -63346,8 +63267,8 @@ /turf/open/floor/plating, /area/maintenance/port/aft) "cvn" = ( -/obj/structure/chair{ - dir = 8 +/obj/structure/sign/poster/contraband/random{ + pixel_x = 32 }, /turf/open/floor/plating, /area/maintenance/port/aft) @@ -63528,72 +63449,61 @@ /turf/open/floor/plasteel/white, /area/medical/genetics) "cvC" = ( -/obj/machinery/firealarm{ - dir = 4; +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/structure/chair/office/light{ + dir = 1 + }, +/obj/machinery/power/apc{ + areastring = "/area/medical/paramedic"; + dir = 8; + name = "Paramedic Station APC"; pixel_x = -24 }, -/obj/item/storage/box/syringes, -/obj/item/storage/box/beakers{ - pixel_x = 2; - pixel_y = 2 - }, -/obj/structure/table/glass, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 +/obj/structure/cable/yellow{ + icon_state = "0-4" }, /turf/open/floor/plasteel, -/area/medical/genetics) +/area/medical/paramedic) "cvD" = ( -/obj/structure/chair/office/light{ - dir = 4 - }, /obj/structure/disposalpipe/segment, -/obj/effect/landmark/start/geneticist, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 4 +/obj/structure/cable/yellow{ + icon_state = "2-8" }, +/obj/item/cigbutt{ + pixel_x = -15; + pixel_y = 14 + }, +/obj/effect/landmark/start/paramedic, /turf/open/floor/plasteel, -/area/medical/genetics) +/area/medical/paramedic) "cvE" = ( -/obj/structure/table/reinforced, +/obj/structure/table/glass, /obj/item/folder/white{ pixel_x = 4; - pixel_y = -3 + pixel_y = 4 }, -/obj/item/pen, -/obj/machinery/door/firedoor, -/obj/machinery/door/window/eastright{ - dir = 8; - name = "Genetics Desk"; - req_access_txt = "5;9" +/obj/item/pen/blue{ + pixel_x = 5; + pixel_y = 3 }, -/obj/machinery/door/window/southleft{ - dir = 4; - name = "Outer Window" - }, -/obj/machinery/door/poddoor/shutters/preopen{ - id = "genetics_shutters"; - name = "genetics shutters" - }, -/turf/open/floor/plating, -/area/medical/genetics) -"cvF" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue, /obj/effect/turf_decal/tile/blue{ dir = 4 }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 +/obj/effect/turf_decal/tile/blue, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 4 }, /turf/open/floor/plasteel, -/area/medical/genetics) +/area/medical/paramedic) +"cvF" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/medical/paramedic) "cvG" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/structure/extinguisher_cabinet{ @@ -63853,7 +63763,14 @@ /turf/open/floor/plating, /area/maintenance/port/aft) "cwj" = ( -/obj/item/cigbutt, +/obj/structure/closet/crate, +/obj/item/coin/silver, +/obj/item/reagent_containers/spray/weedspray, +/obj/item/paper, +/obj/effect/spawner/lootdrop/maintenance{ + lootcount = 2; + name = "2maintenance loot spawner" + }, /turf/open/floor/plating, /area/maintenance/port/aft) "cwm" = ( @@ -63865,12 +63782,10 @@ /turf/open/floor/plating, /area/maintenance/port/aft) "cwn" = ( -/obj/structure/rack, -/obj/item/clothing/glasses/sunglasses, -/obj/item/flashlight/pen, -/obj/effect/spawner/lootdrop/maintenance, -/turf/open/floor/plating, -/area/maintenance/port/aft) +/turf/open/floor/plasteel/white/side{ + dir = 1 + }, +/area/medical/surgery) "cwo" = ( /obj/machinery/light/small{ dir = 8 @@ -64061,20 +63976,15 @@ /turf/open/floor/plasteel/white, /area/medical/genetics) "cwD" = ( -/obj/item/storage/box/disks{ - pixel_x = 2; - pixel_y = 2 - }, /obj/item/radio/intercom{ name = "Station Intercom (General)"; pixel_x = -29 }, /obj/machinery/camera{ - c_tag = "Genetics Desk"; + c_tag = "Paramedics Office"; dir = 4; network = list("ss13","medbay") }, -/obj/structure/table/glass, /obj/effect/turf_decal/tile/blue{ dir = 1 }, @@ -64082,26 +63992,15 @@ dir = 8 }, /turf/open/floor/plasteel, -/area/medical/genetics) +/area/medical/paramedic) "cwE" = ( -/obj/machinery/light{ - dir = 4 - }, /obj/structure/disposalpipe/segment, -/obj/machinery/button/door{ - id = "genetics_shutters"; - name = "genetics shutters control"; - pixel_x = 28; - req_access_txt = "9" - }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 4 +/obj/structure/cable/yellow{ + icon_state = "1-2" }, /turf/open/floor/plasteel, -/area/medical/genetics) +/area/medical/paramedic) "cwF" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/firealarm{ dir = 4; pixel_x = -24 @@ -64109,6 +64008,7 @@ /obj/effect/turf_decal/tile/blue{ dir = 1 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel, /area/hallway/primary/aft) "cwG" = ( @@ -64333,11 +64233,28 @@ }, /area/maintenance/port/aft) "cxc" = ( -/obj/item/trash/chips, -/turf/open/floor/plating, -/area/maintenance/port/aft) +/obj/machinery/newscaster{ + pixel_y = -32 + }, +/obj/machinery/camera{ + c_tag = "Medbay Recovery Room"; + dir = 1; + network = list("ss13","medbay") + }, +/obj/structure/bed, +/obj/item/bedsheet/medical, +/obj/structure/sign/poster/official/love_ian{ + pixel_x = 32 + }, +/turf/open/floor/plasteel/white/corner{ + dir = 1 + }, +/area/medical/surgery) "cxd" = ( -/obj/structure/reagent_dispensers/watertank, +/obj/structure/rack, +/obj/item/clothing/glasses/sunglasses, +/obj/item/flashlight/pen, +/obj/effect/spawner/lootdrop/maintenance, /obj/effect/landmark/blobstart, /turf/open/floor/plating, /area/maintenance/port/aft) @@ -64383,6 +64300,16 @@ req_access_txt = "5" }, /obj/machinery/door/firedoor, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, /turf/open/floor/plasteel/white, /area/medical/medbay/aft) "cxi" = ( @@ -64491,12 +64418,12 @@ /obj/structure/cable/yellow{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, /obj/effect/turf_decal/tile/blue{ dir = 4 }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 1 + }, /turf/open/floor/plasteel/white, /area/medical/genetics) "cxu" = ( @@ -64513,57 +64440,62 @@ /turf/open/floor/plasteel/white, /area/medical/genetics) "cxv" = ( -/obj/effect/spawner/structure/window, -/turf/open/floor/plating, -/area/medical/genetics) -"cxw" = ( -/obj/item/folder/white{ - pixel_x = 4; - pixel_y = -3 - }, -/obj/item/stack/packageWrap, -/obj/item/pen, -/obj/item/reagent_containers/spray/cleaner, -/obj/structure/table/glass, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/medical/genetics) -"cxx" = ( -/obj/structure/disposalpipe/segment{ - dir = 5 +/obj/machinery/firealarm{ + dir = 8; + pixel_x = 24 }, +/obj/effect/landmark/start/paramedic, /obj/effect/turf_decal/tile/blue{ dir = 4 }, +/obj/effect/turf_decal/tile/blue, /turf/open/floor/plasteel, -/area/medical/genetics) -"cxy" = ( -/obj/structure/sign/warning/nosmoking{ - pixel_x = 28 - }, -/obj/machinery/disposal/bin, -/obj/structure/disposalpipe/trunk{ - dir = 8 - }, +/area/medical/paramedic) +"cxw" = ( /obj/effect/turf_decal/tile/blue{ dir = 1 }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/machinery/suit_storage_unit/paramedic, +/obj/effect/turf_decal/tile/blue, +/turf/open/floor/plasteel, +/area/medical/paramedic) +"cxx" = ( +/obj/structure/disposalpipe/segment, +/obj/machinery/light, +/obj/structure/closet/secure_closet/paramedic, +/obj/structure/cable/yellow{ + icon_state = "1-4" + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/medical/paramedic) +"cxy" = ( /obj/effect/turf_decal/tile/blue, /obj/effect/turf_decal/tile/blue{ dir = 4 }, -/turf/open/floor/plasteel, -/area/medical/genetics) -"cxz" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/machinery/light{ +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/machinery/airalarm{ + dir = 1; + pixel_y = -22 + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ dir = 8 }, +/turf/open/floor/plasteel, +/area/medical/paramedic) +"cxz" = ( /obj/machinery/navbeacon{ codes_txt = "patrol;next_patrol=10.1-Central-from-Aft"; location = "10-Aft-To-Central" @@ -64571,6 +64503,12 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/hallway/primary/aft) "cxA" = ( @@ -64580,6 +64518,9 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 4 }, +/obj/structure/cable/yellow{ + icon_state = "1-8" + }, /turf/open/floor/plasteel, /area/hallway/primary/aft) "cxB" = ( @@ -64710,17 +64651,36 @@ }, /area/maintenance/port/aft) "cxR" = ( -/obj/structure/rack, -/obj/item/clothing/mask/gas, -/obj/effect/spawner/lootdrop/maintenance, +/obj/item/trash/chips, /turf/open/floor/plating, /area/maintenance/port/aft) "cxS" = ( -/obj/item/latexballon, +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 6 + }, +/obj/structure/cable/yellow{ + icon_state = "2-4" + }, +/obj/structure/reagent_dispensers/fueltank, +/obj/effect/decal/cleanable/oil/streak, /turf/open/floor/plating, /area/maintenance/port/aft) "cxT" = ( -/obj/item/clothing/suit/ianshirt, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, /turf/open/floor/plating, /area/maintenance/port/aft) "cxU" = ( @@ -64885,6 +64845,7 @@ /obj/structure/cable/yellow{ icon_state = "1-8" }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel/white, /area/medical/genetics) "cyh" = ( @@ -64892,67 +64853,74 @@ /obj/effect/turf_decal/tile/blue{ dir = 4 }, +/obj/structure/sink{ + dir = 4; + pixel_x = 11 + }, +/obj/structure/mirror{ + pixel_x = 28 + }, /turf/open/floor/plasteel/white, /area/medical/genetics) "cyi" = ( -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/research{ - id_tag = "AuxGenetics"; - name = "Genetics Lab"; - req_access_txt = "9" +/obj/machinery/door/airlock/medical/glass{ + id_tag = "MedbayFoyer"; + name = "Medbay"; + req_access_txt = "5" }, +/obj/machinery/door/firedoor, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/medical/paramedic) +"cyk" = ( +/obj/structure/disposalpipe/segment, +/turf/closed/wall, +/area/medical/paramedic) +"cyl" = ( +/turf/closed/wall, +/area/medical/paramedic) +"cym" = ( +/obj/machinery/door/firedoor, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 4 }, -/turf/open/floor/plasteel, -/area/medical/genetics) -"cyj" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/medical/genetics) -"cyk" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/medical/genetics) -"cyl" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/medical/genetics) -"cym" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/machinery/door/firedoor, /obj/machinery/door/airlock/research{ id_tag = "AuxGenetics"; name = "Genetics Access"; req_access_txt = "9" }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/medical/genetics) "cyn" = ( -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 4 - }, /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/light{ + dir = 8 + }, +/obj/item/radio/intercom{ + name = "Station Intercom (General)"; + pixel_x = -26 + }, /turf/open/floor/plasteel, /area/hallway/primary/aft) "cyo" = ( @@ -65278,13 +65246,6 @@ /turf/open/floor/plasteel/white, /area/medical/genetics) "cza" = ( -/obj/structure/sink{ - dir = 4; - pixel_x = 11 - }, -/obj/structure/mirror{ - pixel_x = 28 - }, /obj/effect/turf_decal/tile/blue, /obj/effect/turf_decal/tile/blue{ dir = 4 @@ -65292,65 +65253,66 @@ /obj/effect/turf_decal/tile/blue{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, /turf/open/floor/plasteel/white, /area/medical/genetics) "czb" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 6 - }, /obj/effect/turf_decal/tile/blue{ dir = 1 }, -/obj/effect/turf_decal/tile/blue, /obj/effect/turf_decal/tile/blue{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 10 + }, +/obj/machinery/camera{ + c_tag = "Genetics Lab"; + dir = 6; + network = list("ss13","medbay") + }, /turf/open/floor/plasteel, /area/medical/genetics) "czc" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 4 }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 8 +/obj/machinery/light/small{ + dir = 1 }, /turf/open/floor/plasteel, /area/medical/genetics) "czd" = ( -/obj/machinery/light_switch{ - pixel_x = 23 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, /turf/open/floor/plasteel, /area/medical/genetics) "cze" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ +/obj/machinery/door/firedoor, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/turf/closed/wall, +/obj/machinery/door/airlock/research{ + id_tag = "AuxGenetics"; + name = "Genetics Access"; + req_access_txt = "9" + }, +/turf/open/floor/plasteel, /area/medical/genetics) "czf" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/item/radio/intercom{ - name = "Station Intercom (General)"; - pixel_x = -26 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/hallway/primary/aft) "czg" = ( @@ -65363,9 +65325,6 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "czh" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 4 - }, /obj/machinery/button/door{ id = "Skynet_launch"; name = "Mech Bay Door Control"; @@ -65374,6 +65333,7 @@ req_one_access_txt = "29" }, /obj/effect/turf_decal/tile/neutral, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel, /area/hallway/primary/aft) "czi" = ( @@ -65928,6 +65888,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, /turf/open/floor/plasteel/dark, /area/medical/genetics) "cAh" = ( @@ -67855,9 +67818,7 @@ /obj/structure/cable/yellow{ icon_state = "4-8" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 5 - }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel/dark, /area/medical/morgue) "cEd" = ( @@ -67876,28 +67837,21 @@ pixel_y = -3 }, /obj/item/clothing/gloves/color/latex, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, /turf/open/floor/plasteel/dark, /area/medical/morgue) "cEe" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/turf/closed/wall, -/area/medical/morgue) -"cEf" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 +/turf/open/floor/plasteel/dark/side{ + dir = 1 }, +/area/medical/surgery) +"cEf" = ( /turf/closed/wall, /area/hallway/primary/aft) "cEg" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, /obj/machinery/firealarm{ dir = 4; pixel_x = -24 @@ -67908,13 +67862,11 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "cEh" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 4 - }, /obj/effect/turf_decal/tile/purple, /obj/effect/turf_decal/tile/purple{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel, /area/hallway/primary/aft) "cEi" = ( @@ -68343,12 +68295,18 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 5 + }, /turf/open/floor/plasteel/dark, /area/medical/morgue) "cEX" = ( /obj/structure/disposalpipe/segment{ dir = 10 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/medical/morgue) "cEY" = ( @@ -68357,9 +68315,15 @@ name = "Morgue"; req_access_txt = "6" }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/medical/morgue) "cEZ" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 10 + }, /turf/open/floor/plasteel/dark, /area/hallway/primary/aft) "cFa" = ( @@ -68840,6 +68804,9 @@ /area/medical/morgue) "cFY" = ( /obj/structure/closet, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 5 + }, /turf/open/floor/plasteel/dark, /area/hallway/primary/aft) "cFZ" = ( @@ -68848,6 +68815,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/hallway/primary/aft) "cGa" = ( @@ -72322,17 +72292,14 @@ /turf/open/floor/plating, /area/maintenance/port/aft) "cMo" = ( -/obj/structure/disposalpipe/segment{ - dir = 9 +/obj/machinery/power/apc{ + areastring = "/area/maintenance/port/aft"; + dir = 1; + name = "Port Quarter Maintenance APC"; + pixel_y = 24 }, /obj/structure/cable/yellow{ - icon_state = "1-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 9 - }, -/obj/structure/extinguisher_cabinet{ - pixel_y = -30 + icon_state = "0-8" }, /turf/open/floor/plating, /area/maintenance/port/aft) @@ -72899,10 +72866,16 @@ /turf/open/floor/plating, /area/maintenance/port/aft) "cNg" = ( -/obj/structure/rack, -/obj/item/flashlight, -/obj/effect/spawner/lootdrop/maintenance, -/obj/machinery/light/small, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/item/cigbutt, /turf/open/floor/plating, /area/maintenance/port/aft) "cNh" = ( @@ -75895,8 +75868,12 @@ /turf/closed/wall/r_wall, /area/science/xenobiology) "cUH" = ( -/obj/structure/table/optable, -/turf/open/floor/plasteel/white, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel/dark/side{ + dir = 1 + }, /area/medical/surgery) "cUL" = ( /obj/docking_port/stationary/random{ @@ -79639,9 +79616,6 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 10 }, -/obj/structure/sign/poster/contraband/random{ - pixel_y = 32 - }, /obj/structure/cable/yellow{ icon_state = "2-4" }, @@ -80246,6 +80220,14 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, +/obj/machinery/power/apc{ + areastring = "/area/medical/surgery"; + name = "Surgery APC"; + pixel_y = -26 + }, +/obj/structure/cable/yellow{ + icon_state = "0-8" + }, /turf/open/floor/plating, /area/maintenance/port/aft) "dwj" = ( @@ -81359,6 +81341,27 @@ /obj/structure/closet/firecloset, /turf/open/floor/plating, /area/engine/engineering) +"foN" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/light, +/obj/machinery/gear_painter, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/locker) +"fpa" = ( +/obj/structure/extinguisher_cabinet{ + pixel_y = -30 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) "fpY" = ( /turf/closed/wall, /area/crew_quarters/cryopod) @@ -81457,6 +81460,32 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/aft) +"gtn" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/disposal/bin, +/obj/structure/disposalpipe/trunk{ + dir = 8 + }, +/obj/structure/sign/warning/nosmoking{ + pixel_x = 28 + }, +/turf/open/floor/plasteel/dark, +/area/medical/genetics) +"gwW" = ( +/obj/structure/chair{ + dir = 1 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) "gEk" = ( /obj/structure/cable/yellow{ icon_state = "2-8" @@ -81519,6 +81548,11 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/wood, /area/security/vacantoffice) +"hny" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/structure/curtain, +/turf/open/floor/plasteel/white/side, +/area/medical/surgery) "hyP" = ( /obj/machinery/door/airlock/external{ name = "Escape Pod Two" @@ -81766,6 +81800,15 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel/white, /area/science/circuit) +"kgN" = ( +/obj/machinery/door/firedoor, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/door/airlock/medical/glass{ + name = "Operating Theatre"; + req_access_txt = "45" + }, +/turf/open/floor/plasteel/white, +/area/medical/surgery) "krD" = ( /turf/closed/wall, /area/science/circuit) @@ -81939,6 +81982,16 @@ }, /turf/open/floor/plasteel/dark, /area/crew_quarters/cryopod) +"lFR" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/machinery/light{ + dir = 4 + }, +/obj/machinery/vending/clothing, +/turf/open/floor/plasteel/white/corner, +/area/hallway/secondary/entry) "lGS" = ( /obj/docking_port/stationary/public_mining_dock, /turf/open/floor/plating, @@ -81982,8 +82035,22 @@ /turf/open/floor/plasteel/white, /area/science/circuit) "lWL" = ( -/obj/machinery/smartfridge/organ/preloaded, -/turf/closed/wall, +/obj/machinery/computer/med_data{ + dir = 8 + }, +/obj/structure/window{ + dir = 4 + }, +/obj/item/radio/intercom{ + broadcasting = 1; + frequency = 1485; + listening = 0; + name = "Station Intercom (Medbay)"; + pixel_y = -30 + }, +/turf/open/floor/plasteel/white/side{ + dir = 8 + }, /area/medical/surgery) "lWY" = ( /obj/machinery/door/airlock/hatch{ @@ -82057,6 +82124,10 @@ }, /turf/open/floor/wood, /area/security/vacantoffice) +"mqC" = ( +/obj/structure/lattice, +/turf/closed/wall, +/area/maintenance/port/aft) "mvj" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -82110,6 +82181,10 @@ icon_state = "panelscorched" }, /area/maintenance/port/aft) +"nho" = ( +/obj/item/latexballon, +/turf/open/floor/plating, +/area/maintenance/port/aft) "nhy" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 @@ -82265,6 +82340,12 @@ }, /turf/open/floor/plasteel/white, /area/science/circuit) +"oeQ" = ( +/obj/structure/rack, +/obj/item/clothing/mask/gas, +/obj/effect/spawner/lootdrop/maintenance, +/turf/open/floor/plating, +/area/maintenance/port/aft) "ohj" = ( /obj/item/integrated_electronics/analyzer, /obj/item/integrated_electronics/debugger, @@ -82519,6 +82600,16 @@ }, /turf/open/floor/plasteel/white, /area/science/circuit) +"qee" = ( +/obj/structure/extinguisher_cabinet{ + pixel_x = 27 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/aft) "qhe" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -82627,6 +82718,16 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel, /area/hallway/primary/port) +"reM" = ( +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 5 + }, +/turf/open/floor/plasteel/white, +/area/medical/genetics) "roa" = ( /obj/structure/chair/stool, /obj/machinery/light/small{ @@ -82650,6 +82751,13 @@ }, /turf/open/floor/plating, /area/hallway/secondary/entry) +"rvd" = ( +/obj/structure/rack, +/obj/item/flashlight, +/obj/effect/spawner/lootdrop/maintenance, +/obj/machinery/light/small, +/turf/open/floor/plating, +/area/maintenance/port/aft) "rzX" = ( /obj/structure/chair/office/light{ dir = 1; @@ -82759,6 +82867,10 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel, /area/crew_quarters/fitness/recreation) +"sos" = ( +/obj/structure/mirror, +/turf/closed/wall, +/area/medical/surgery) "sqe" = ( /obj/machinery/atmospherics/pipe/heat_exchanging/simple, /turf/open/space/basic, @@ -82780,6 +82892,17 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel, /area/hallway/primary/port) +"sBC" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plating, +/area/medical/paramedic) +"sCN" = ( +/obj/item/clothing/suit/ianshirt, +/turf/open/floor/plating, +/area/maintenance/port/aft) "sFv" = ( /obj/structure/cable/yellow{ icon_state = "4-8" @@ -82954,6 +83077,13 @@ /obj/item/flashlight, /turf/open/floor/plasteel, /area/hallway/secondary/entry) +"umv" = ( +/obj/effect/turf_decal/tile/neutral, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/aft) "upN" = ( /obj/effect/turf_decal/stripes/line{ dir = 5 @@ -83074,6 +83204,14 @@ }, /turf/open/floor/wood, /area/security/vacantoffice) +"vwZ" = ( +/obj/machinery/atmospherics/pipe/manifold4w/general{ + color = "#0000ff" + }, +/turf/open/floor/plasteel/dark/side{ + dir = 1 + }, +/area/medical/surgery) "vxG" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -97423,7 +97561,7 @@ blU aiT bEs bHJ -aiT +lFR iSt mcS alK @@ -100807,7 +100945,7 @@ cwi dux dux dux -aaa +dux aaa cBR cCK @@ -101062,10 +101200,10 @@ cuf cvk cwh bXE +bXE dvq dux aaa -aaa cBR cBR cDE @@ -101318,10 +101456,10 @@ chZ chZ cvl cbx +cfD ceu dux -dux -aaf +mqC aaa aaa cBR @@ -101568,7 +101706,7 @@ cia cia cia cia -cpT +cDP cia cia cia @@ -101576,11 +101714,11 @@ ceu dyg dvt bXE +bXE dvE dux aaf aaf -aaf dBN cDG cEJ @@ -101823,21 +101961,21 @@ cia cjw ckU cmk -cnm +cnt coy -cpU +cUH crj csj cia cug dyg +bXE dDw bXE -cNg +rvd dux aaa aaa -aaa cBR cDH cEK @@ -102076,25 +102214,25 @@ bXE cer dux dwb -cib -cjx -ckV +cia +cjC +cla cml -cnn +cnt coz -coz -crk +cUH +crq csk cia cuh cvm cDK -cxc +ceu cxR +oeQ dux aaa aaa -aaa dBN cDI cEL @@ -102333,11 +102471,11 @@ bXE bYJ dux dwe +cia +cjB +cpT cic -cjy -ckW -cmk -cno +cnr coA cUH crl @@ -102346,12 +102484,12 @@ cia ceu ceu dyg +ceu dux dux dux aaa aaa -aaa cBR cDJ cEM @@ -102590,25 +102728,25 @@ dvt dux dux dwb -cic +cia cjz ckX cmm cnp coB -coB +vwZ crm csm cia -cui +dux cwj -dyg +cNg +ceu dux -cxS +nho dux aaf aaf -aaf cBR cBR cBR @@ -102847,23 +102985,23 @@ cdi dux cdl dwb -cic -cjA -ckY -cmk +cia +cnm +sos +cid cnq coC cpW crn csn -cia -cdl -cMm -cMo +cui dux -cxT +cxS +cNf +fpa +dux +sCN dux -aaa aaa aaa aaf @@ -103104,25 +103242,25 @@ dux dux cfD dwb -cic cia +cib ckZ -cia -cia -cia +cjA +kgN +coB cpX cia lWL cia -ceu +cia dyg +bXE dyw dux -cxS +nho dux aaa aaa -aaa aaf aaa aaa @@ -103361,20 +103499,20 @@ cdj cse cdj cgL -cid +cia cjB -cla -cmk +cro +ckY cnr coD -cpY -cro +cqa +cnt cso +cuj cia -cfD dyj ceu -dux +ceu dux dux dux @@ -103618,18 +103756,18 @@ cdk ceu cfE dwi -cic +cia cjC clb cmn -cns +cnt coE cpZ -coB +hny csp +cwn csr -duH -dyg +cxT ceu cMm cwm @@ -103875,17 +104013,17 @@ dux dux cfF dwj -cic +cia cjD clc -cmk +coG cnt coF -cqa -crq +cEe +cnt csq +cxc cia -dux diM cwm cNf @@ -104132,20 +104270,20 @@ cdl cev cev cgO -cic cia cia cia cia -coG +cia +cia cqb cia cia cia -cuj -cbx +cia +cMo dDw -bXE +gwW cxU cxU czN @@ -104401,7 +104539,7 @@ csr duH bXE cvn -cwn +dvE cxd cxU cyN @@ -104655,9 +104793,9 @@ coI cqd crs css -dux -dux -dux +cvp +cvp +cvp cxU cxU cxU @@ -108773,7 +108911,7 @@ cvA cwB cxt cyg -cyZ +reM cAd ctA dbr @@ -109285,10 +109423,10 @@ ctA ctA ctA ctA -cxv -cyi ctA ctA +cym +ctA ctA cCi cCW @@ -109538,12 +109676,12 @@ coV cqt cga cKJ -ctB +cyl cuw cvC cwD cxw -cyj +cyl czb cAf cBc @@ -110052,18 +110190,18 @@ coX cnL cga cbC -ctB +cyl cuy cvE -ctB +cxv cxy cyl czd -cAg +gtn ctB cCe cCe -cEe +cCe cEY cCe cCe @@ -110310,11 +110448,11 @@ coY cga csI ctD -cuz cvF -ctB -ctB -cym +sBC +cyl +cyi +cyl cze ctB cBd @@ -110825,18 +110963,18 @@ crG csK ctF car -car +czg car cxA car -czg +car cAi ctF car car -czg -cFb car +cFb +czg car cHO cIF @@ -111082,7 +111220,7 @@ crH csL ctG cgc -cvG +qee chh cxB cyo @@ -111093,7 +111231,7 @@ cCm cpa cEh cFc -chh +umv chh cvG cIG @@ -118481,8 +118619,8 @@ aOD aPK aQV aOu -aTz -aUM +aTt +foN aUM aYe dnh diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm index 74f7f95c2c..f4d798511f 100644 --- a/_maps/map_files/OmegaStation/OmegaStation.dmm +++ b/_maps/map_files/OmegaStation/OmegaStation.dmm @@ -15268,6 +15268,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/item/kirbyplants{ + icon_state = "plant-21" + }, /turf/open/floor/plasteel/dark, /area/crew_quarters/dorms) "axG" = ( @@ -19618,9 +19621,6 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/dorms) "aEL" = ( -/obj/item/kirbyplants{ - icon_state = "plant-21" - }, /obj/machinery/status_display{ pixel_y = -32 }, @@ -19635,6 +19635,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/gear_painter, /turf/open/floor/plasteel/dark, /area/crew_quarters/dorms) "aEM" = ( diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm index 0356dd1d07..12ae0092f0 100644 --- a/_maps/map_files/PubbyStation/PubbyStation.dmm +++ b/_maps/map_files/PubbyStation/PubbyStation.dmm @@ -511,10 +511,10 @@ /turf/open/floor/plasteel, /area/crew_quarters/fitness/recreation) "abi" = ( -/obj/machinery/disposal/bin, -/obj/structure/disposalpipe/trunk{ - dir = 8 +/obj/structure/disposalpipe/segment{ + dir = 10 }, +/obj/machinery/gear_painter, /turf/open/floor/plasteel, /area/crew_quarters/fitness/recreation) "abj" = ( @@ -2337,9 +2337,12 @@ /turf/open/floor/plasteel/dark, /area/security/prison) "afJ" = ( -/obj/effect/landmark/carpspawn, -/turf/open/space/basic, -/area/space/nearstation) +/obj/effect/turf_decal/tile/neutral, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) "afK" = ( /obj/machinery/atmospherics/components/unary/tank/air{ dir = 1 @@ -20027,9 +20030,7 @@ /obj/structure/cable{ icon_state = "1-8" }, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 4 - }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, /turf/open/floor/plating, /area/maintenance/department/crew_quarters/bar) "aUQ" = ( @@ -20044,6 +20045,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 10 + }, /turf/open/floor/plasteel/dark, /area/hydroponics) "aUR" = ( @@ -20485,8 +20489,16 @@ /turf/closed/wall, /area/janitor) "aVT" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/closed/wall, +/obj/machinery/door/firedoor, +/obj/machinery/door/poddoor/shutters{ + id = "jangarage"; + name = "Custodial Closet Shutters" + }, +/obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, /area/janitor) "aVU" = ( /obj/machinery/door/window/eastright{ @@ -20510,6 +20522,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel/dark, /area/janitor) "aVV" = ( @@ -20892,9 +20905,6 @@ /obj/machinery/camera{ c_tag = "Custodial Quarters" }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 1 - }, /obj/machinery/light/small{ dir = 1 }, @@ -20915,6 +20925,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/janitor) "aWO" = ( @@ -20934,6 +20947,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 9 + }, /turf/open/floor/plasteel/dark, /area/janitor) "aWP" = ( @@ -23004,9 +23020,6 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "baW" = ( -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 8 - }, /obj/machinery/button/door{ id = "jangarage"; name = "Custodial Closet Shutters Control"; @@ -23014,14 +23027,12 @@ req_access_txt = "26" }, /obj/effect/turf_decal/tile/neutral, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel, /area/hallway/primary/central) "baX" = ( /obj/vehicle/ridden/janicart, /obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, /obj/machinery/light{ dir = 8 }, @@ -23034,6 +23045,9 @@ /obj/structure/cable{ icon_state = "2-4" }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 6 + }, /turf/open/floor/plasteel, /area/janitor) "baY" = ( @@ -23398,6 +23412,9 @@ /obj/structure/cable{ icon_state = "1-2" }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 9 + }, /turf/open/floor/plasteel, /area/janitor) "bbY" = ( @@ -24603,7 +24620,7 @@ /turf/open/floor/plating, /area/maintenance/department/cargo) "beS" = ( -/obj/item/caution, +/obj/item/clothing/suit/caution, /turf/open/floor/plating, /area/maintenance/department/cargo) "beU" = ( @@ -31173,17 +31190,26 @@ "bup" = ( /obj/machinery/rnd/destructive_analyzer, /obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/science/lab) "buq" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/effect/turf_decal/bot, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/science/lab) "bur" = ( /obj/effect/turf_decal/delivery, /obj/machinery/rnd/production/protolathe/department/science, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/science/lab) "bus" = ( @@ -31202,6 +31228,9 @@ /obj/machinery/light{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 10 + }, /turf/open/floor/plasteel/white, /area/science/lab) "but" = ( @@ -31664,6 +31693,7 @@ /obj/structure/cable{ icon_state = "1-2" }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel/white, /area/science/lab) "bvA" = ( @@ -32372,6 +32402,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel/white, /area/science/lab) "bxh" = ( @@ -33056,12 +33087,6 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "byD" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 6 - }, -/obj/structure/cable{ - icon_state = "2-4" - }, /obj/machinery/door/airlock/research{ name = "R&D Lab"; req_one_access_txt = "7;29;30" @@ -33070,6 +33095,12 @@ /obj/structure/disposalpipe/segment{ dir = 6 }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/science/lab) "byE" = ( @@ -33091,7 +33122,6 @@ /turf/open/floor/plasteel/white, /area/science/lab) "byG" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on, /obj/structure/cable{ icon_state = "1-2" }, @@ -33919,10 +33949,6 @@ /area/hallway/primary/aft) "bAm" = ( /obj/structure/disposalpipe/segment, -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall/r_wall, /area/hallway/primary/aft) "bAo" = ( @@ -33952,7 +33978,6 @@ /obj/structure/cable{ icon_state = "1-4" }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/turf_decal/tile/purple{ dir = 1 }, @@ -34404,17 +34429,14 @@ name = "RD Office APC"; pixel_x = -25 }, -/obj/structure/cable{ - icon_state = "0-4" - }, /obj/effect/turf_decal/tile/purple{ dir = 1 }, /obj/effect/turf_decal/tile/purple{ dir = 8 }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 +/obj/structure/cable{ + icon_state = "4-8" }, /turf/open/floor/plasteel/dark, /area/crew_quarters/heads/hor) @@ -34425,8 +34447,8 @@ /obj/structure/disposalpipe/segment{ dir = 5 }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 4 +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 6 }, /turf/open/floor/plasteel/dark, /area/crew_quarters/heads/hor) @@ -34434,6 +34456,9 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/crew_quarters/heads/hor) "bBt" = ( @@ -34441,6 +34466,9 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/crew_quarters/heads/hor) "bBu" = ( @@ -34478,6 +34506,9 @@ /obj/effect/turf_decal/tile/purple{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 9 + }, /turf/open/floor/plasteel/dark, /area/crew_quarters/heads/hor) "bBw" = ( @@ -35240,6 +35271,7 @@ /obj/structure/cable{ icon_state = "0-8" }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plating, /area/crew_quarters/heads/hor) "bCK" = ( @@ -44248,9 +44280,11 @@ /turf/open/floor/engine/co2, /area/engine/atmos) "bWh" = ( -/obj/effect/turf_decal/sand, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 8 + }, /turf/open/floor/plasteel, -/area/chapel/office) +/area/hallway/primary/aft) "bWi" = ( /obj/structure/flora/ausbushes/leafybush, /obj/structure/flora/ausbushes/reedbush, @@ -52824,6 +52858,9 @@ /turf/closed/wall/r_wall, /area/science/lab) "cCt" = ( +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 1 + }, /turf/open/floor/plasteel/white, /area/science/lab) "cCB" = ( @@ -53058,6 +53095,9 @@ freq = 1400; location = "Research Division" }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/science/lab) "cXW" = ( @@ -53151,10 +53191,6 @@ /area/maintenance/department/security/brig) "dhz" = ( /obj/structure/disposalpipe/segment, -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/structure/chair{ dir = 8; name = "Defense" @@ -53163,9 +53199,6 @@ /obj/effect/turf_decal/tile/purple{ dir = 8 }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, /turf/open/floor/plasteel, /area/hallway/primary/aft) "dir" = ( @@ -53960,11 +53993,11 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/structure/cable{ - icon_state = "4-8" - }, /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 1 + dir = 4 + }, +/obj/structure/cable{ + icon_state = "1-8" }, /turf/open/floor/plasteel, /area/hallway/primary/aft) @@ -55488,6 +55521,12 @@ /obj/effect/turf_decal/tile/purple{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 6 + }, +/obj/structure/cable{ + icon_state = "2-4" + }, /turf/open/floor/plasteel, /area/hallway/primary/aft) "ioj" = ( @@ -55591,6 +55630,9 @@ /obj/effect/turf_decal/tile/blue{ dir = 8 }, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/plasteel, /area/hallway/primary/aft) "iyg" = ( @@ -56345,9 +56387,13 @@ /turf/open/floor/plasteel/white, /area/science/mixing) "koz" = ( -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/purple{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/hallway/primary/aft) "kpK" = ( @@ -56634,10 +56680,14 @@ /turf/open/floor/plasteel/dark, /area/science/xenobiology) "kSb" = ( -/obj/structure/lattice, -/obj/structure/grille, -/turf/open/space/basic, -/area/space) +/obj/structure/chair/office/light{ + dir = 8 + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, +/turf/open/floor/plasteel/white, +/area/science/lab) "kSF" = ( /obj/structure/cable{ icon_state = "1-4" @@ -56711,6 +56761,10 @@ /obj/effect/turf_decal/tile/purple{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plasteel, /area/hallway/primary/aft) "lcU" = ( @@ -57121,6 +57175,7 @@ /obj/effect/turf_decal/tile/purple{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel/white, /area/science/lab) "meF" = ( @@ -57128,8 +57183,9 @@ /turf/closed/wall/r_wall, /area/engine/supermatter) "mfC" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/structure/cable{ + icon_state = "1-2" }, /turf/open/floor/plasteel, /area/hallway/primary/aft) @@ -59138,6 +59194,13 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plating, /area/maintenance/department/engine) +"qAx" = ( +/obj/structure/disposalpipe/trunk{ + dir = 1 + }, +/obj/machinery/disposal/bin, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/recreation) "qAM" = ( /obj/effect/spawner/lootdrop/maintenance, /obj/item/cigbutt, @@ -59336,6 +59399,7 @@ /area/hallway/secondary/exit/departure_lounge) "qVk" = ( /obj/machinery/door/poddoor/incinerator_atmos_aux, +/obj/structure/lattice/catwalk, /turf/open/space/basic, /area/maintenance/disposal/incinerator) "qVP" = ( @@ -60486,6 +60550,9 @@ id = "research_shutters_2"; name = "research shutters" }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/science/lab) "tLP" = ( @@ -60808,12 +60875,6 @@ /obj/structure/disposalpipe/segment{ dir = 9 }, -/obj/structure/cable{ - icon_state = "1-8" - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 9 - }, /obj/structure/chair{ dir = 8; name = "Defense" @@ -60933,6 +60994,10 @@ /obj/effect/turf_decal/plaque, /turf/open/floor/plating, /area/maintenance/department/engine) +"uNA" = ( +/obj/structure/disposalpipe/segment, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/recreation) "uQR" = ( /obj/item/ammo_casing/shotgun/beanbag, /turf/open/floor/plating, @@ -61489,12 +61554,6 @@ }, /turf/open/floor/plasteel, /area/science/xenobiology) -"wfG" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/turf/closed/wall/r_wall, -/area/crew_quarters/heads/hor) "wfO" = ( /mob/living/simple_animal/hostile/retaliate/poison/snake, /turf/open/floor/plating, @@ -76958,7 +77017,7 @@ aaa bOv bNs bNs -bWh +bQg bQg bQg bQg @@ -84165,7 +84224,7 @@ bIZ cbb bDi ccO -bIZ +bva cjm cjm xgh @@ -84425,8 +84484,8 @@ bva bva aht aht -kSb -kSb +fon +fon aht aht mau @@ -86680,7 +86739,7 @@ aXL aYL aZN baW -aKI +afJ aKI beb aKI @@ -86936,8 +86995,8 @@ aVS aXM aVS aVS -aXM -bbW +aVS +aVT bbW aVS aVS @@ -87138,7 +87197,7 @@ aaa aaa aaa aaa -afJ +cFB aby aaa agQ @@ -87445,7 +87504,7 @@ aRJ aSz aSz aUP -aVT +aVS aWN aXO aYM @@ -89457,7 +89516,7 @@ aaa aaa aaa aaa -afJ +cFB aaa aaa abI @@ -94921,12 +94980,12 @@ jcT xje tTl tTl -tTl +bWh gkS tTl tTl tTl -koz +tTl dgg phJ phJ @@ -95178,7 +95237,7 @@ bjm mhn cqi cqi -cqi +koz cqi cqi imE @@ -95697,7 +95756,7 @@ duF bxa byE bBp -wfG +bBp bBp bBp bBp @@ -95950,7 +96009,7 @@ cCl brq byF cCt -byF +kSb bxc nIU bAo @@ -104126,8 +104185,8 @@ aaY awB abe abi -axw -axw +uNA +qAx axw axw aBX diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm index bf0e1dc797..7506fbdca3 100644 --- a/_maps/map_files/generic/CentCom.dmm +++ b/_maps/map_files/generic/CentCom.dmm @@ -10524,6 +10524,10 @@ }, /turf/open/floor/plasteel, /area/centcom/control) +"yl" = ( +/obj/machinery/gear_painter, +/turf/open/indestructible/hotelwood, +/area/centcom/holding) "yn" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/sign/warning/vacuum, @@ -43992,7 +43996,7 @@ NS Nd ZL NS -NS +yl Nd CU NS diff --git a/_maps/shuttles/emergency_nature.dmm b/_maps/shuttles/emergency_nature.dmm index 9639e37852..51a14594fb 100644 --- a/_maps/shuttles/emergency_nature.dmm +++ b/_maps/shuttles/emergency_nature.dmm @@ -33,8 +33,8 @@ "bg" = ( /obj/structure/table/reinforced, /obj/item/storage/toolbox/mechanical{ - pixel_y = 8; - pixel_x = -2 + pixel_x = -2; + pixel_y = 8 }, /obj/item/storage/toolbox/electrical, /obj/effect/turf_decal/stripes/line, @@ -43,8 +43,8 @@ "bS" = ( /obj/structure/table/reinforced, /obj/item/storage/box/lights/mixed{ - pixel_y = 9; - pixel_x = -5 + pixel_x = -5; + pixel_y = 9 }, /obj/item/storage/box/matches{ pixel_y = 5 @@ -413,8 +413,8 @@ pixel_y = 4 }, /obj/item/reagent_containers/food/drinks/soda_cans/monkey_energy{ - pixel_y = 5; - pixel_x = 6 + pixel_x = 6; + pixel_y = 5 }, /turf/open/floor/plasteel/white, /area/shuttle/escape) @@ -494,8 +494,8 @@ /area/shuttle/escape) "rg" = ( /obj/item/clothing/glasses/welding{ - pixel_y = 8; - pixel_x = 3 + pixel_x = 3; + pixel_y = 8 }, /obj/item/weldingtool/largetank{ pixel_x = -3 @@ -882,8 +882,8 @@ }, /obj/structure/table/glass, /obj/item/storage/box/monkeycubes{ - pixel_y = 10; - pixel_x = 5 + pixel_x = 5; + pixel_y = 10 }, /obj/item/reagent_containers/food/snacks/cube/monkey{ pixel_x = 5 @@ -1156,8 +1156,8 @@ }, /obj/structure/table/glass, /obj/item/clothing/suit/monkeysuit{ - pixel_y = 4; - pixel_x = -2 + pixel_x = -2; + pixel_y = 4 }, /obj/item/clothing/mask/gas/monkeymask{ pixel_x = 5; @@ -1169,6 +1169,7 @@ /obj/machinery/door/airlock/titanium{ name = "Emergency Shuttle Airlock" }, +/obj/structure/fans/tiny, /turf/open/floor/plasteel/white, /area/shuttle/escape) "ST" = ( @@ -1319,6 +1320,7 @@ name = "Emergency Shuttle Airlock" }, /obj/docking_port/mobile/emergency, +/obj/structure/fans/tiny, /turf/open/floor/plasteel/white, /area/shuttle/escape) "Yu" = ( diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index c9decee834..0000000000 --- a/appveyor.yml +++ /dev/null @@ -1,15 +0,0 @@ -version: '{build}' -skip_branch_with_pr: true -shallow_clone: true -branches: - except: - - ___TGS3TempBranch - - ___TGSTempBranch -cache: - - C:\byond\ -> dependencies.sh -build_script: - - ps: tools/appveyor/build.ps1 - - ps: "$deployPath = $env:APPVEYOR_BUILD_FOLDER + '/deploy'; bash tools/deploy.sh $deployPath" - - ps: "[System.IO.Compression.ZipFile]::CreateFromDirectory($env:APPVEYOR_BUILD_FOLDER + '/deploy', $env:APPVEYOR_BUILD_FOLDER + '/deploy.zip')" -artifacts: - - path: deploy.zip diff --git a/code/__DEFINES/MC.dm b/code/__DEFINES/MC.dm index bad64846d6..cad75fbfe4 100644 --- a/code/__DEFINES/MC.dm +++ b/code/__DEFINES/MC.dm @@ -22,49 +22,45 @@ #define START_PROCESSING(Processor, Datum) if (!(Datum.datum_flags & DF_ISPROCESSING)) {Datum.datum_flags |= DF_ISPROCESSING;Processor.processing += Datum} #define STOP_PROCESSING(Processor, Datum) Datum.datum_flags &= ~DF_ISPROCESSING;Processor.processing -= Datum;Processor.currentrun -= Datum -//SubSystem flags (Please design any new flags so that the default is off, to make adding flags to subsystems easier) +//! SubSystem flags (Please design any new flags so that the default is off, to make adding flags to subsystems easier) -//subsystem does not initialize. -#define SS_NO_INIT (1<<0) +/// subsystem does not initialize. +#define SS_NO_INIT 1 -//subsystem does not fire. -// (like can_fire = 0, but keeps it from getting added to the processing subsystems list) -// (Requires a MC restart to change) -#define SS_NO_FIRE (1<<1) +/** subsystem does not fire. */ +/// (like can_fire = 0, but keeps it from getting added to the processing subsystems list) +/// (Requires a MC restart to change) +#define SS_NO_FIRE 2 -//subsystem only runs on spare cpu (after all non-background subsystems have ran that tick) -// SS_BACKGROUND has its own priority bracket -#define SS_BACKGROUND (1<<2) +/** Subsystem only runs on spare cpu (after all non-background subsystems have ran that tick) */ +/// SS_BACKGROUND has its own priority bracket, this overrides SS_TICKER's priority bump +#define SS_BACKGROUND 4 -//subsystem does not tick check, and should not run unless there is enough time (or its running behind (unless background)) -#define SS_NO_TICK_CHECK (1<<3) +/// subsystem does not tick check, and should not run unless there is enough time (or its running behind (unless background)) +#define SS_NO_TICK_CHECK 8 -//Treat wait as a tick count, not DS, run every wait ticks. -// (also forces it to run first in the tick, above even SS_NO_TICK_CHECK subsystems) -// (implies all runlevels because of how it works) -// (overrides SS_BACKGROUND) -// This is designed for basically anything that works as a mini-mc (like SStimer) -#define SS_TICKER (1<<4) +/** Treat wait as a tick count, not DS, run every wait ticks. */ +/// (also forces it to run first in the tick (unless SS_BACKGROUND)) +/// (implies all runlevels because of how it works) +/// This is designed for basically anything that works as a mini-mc (like SStimer) +#define SS_TICKER 16 -//keep the subsystem's timing on point by firing early if it fired late last fire because of lag -// ie: if a 20ds subsystem fires say 5 ds late due to lag or what not, its next fire would be in 15ds, not 20ds. -#define SS_KEEP_TIMING (1<<5) +/** keep the subsystem's timing on point by firing early if it fired late last fire because of lag */ +/// ie: if a 20ds subsystem fires say 5 ds late due to lag or what not, its next fire would be in 15ds, not 20ds. +#define SS_KEEP_TIMING 32 -//Calculate its next fire after its fired. -// (IE: if a 5ds wait SS takes 2ds to run, its next fire should be 5ds away, not 3ds like it normally would be) -// This flag overrides SS_KEEP_TIMING -#define SS_POST_FIRE_TIMING (1<<6) +/** Calculate its next fire after its fired. */ +/// (IE: if a 5ds wait SS takes 2ds to run, its next fire should be 5ds away, not 3ds like it normally would be) +/// This flag overrides SS_KEEP_TIMING +#define SS_POST_FIRE_TIMING 64 -/// Show in stat() by default even if SS_NO_FIRE -#define SS_ALWAYS_SHOW_STAT (1<<7) - -//SUBSYSTEM STATES -#define SS_IDLE 0 //aint doing shit. -#define SS_QUEUED 1 //queued to run -#define SS_RUNNING 2 //actively running -#define SS_PAUSED 3 //paused by mc_tick_check -#define SS_SLEEPING 4 //fire() slept. -#define SS_PAUSING 5 //in the middle of pausing +//! SUBSYSTEM STATES +#define SS_IDLE 0 /// ain't doing shit. +#define SS_QUEUED 1 /// queued to run +#define SS_RUNNING 2 /// actively running +#define SS_PAUSED 3 /// paused by mc_tick_check +#define SS_SLEEPING 4 /// fire() slept. +#define SS_PAUSING 5 /// in the middle of pausing #define SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/##X);\ /datum/controller/subsystem/##X/New(){\ diff --git a/code/__DEFINES/_extools.dm b/code/__DEFINES/_extools.dm index 4513243aae..e01e09a3d3 100644 --- a/code/__DEFINES/_extools.dm +++ b/code/__DEFINES/_extools.dm @@ -1 +1,38 @@ -#define EXTOOLS (world.system_type == MS_WINDOWS ? "byond-extools.dll" : "libbyond-extools.so") +// _extools_api.dm - DM API for extools extension library +// (blatently stolen from rust_g) +// +// To configure, create a `extools.config.dm` and set what you care about from +// the following options: +// +// #define EXTOOLS "path/to/extools" +// Override the .dll/.so detection logic with a fixed path or with detection +// logic of your own. + +#ifndef EXTOOLS +// Default automatic EXTOOLS detection. +// On Windows, looks in the standard places for `byond-extools.dll`. +// On Linux, looks in the standard places for`libbyond-extools.so`. + +/* This comment bypasses grep checks */ /var/__extools + +/proc/__detect_extools() + if (world.system_type == UNIX) + if (fexists("./libbyond-extools.so")) + // No need for LD_LIBRARY_PATH badness. + return __extools = "./libbyond-extools.so" + else + // It's not in the current directory, so try others + return __extools = "libbyond-extools.so" + else + return __extools = "byond-extools.dll" + +#define EXTOOLS (__extools || __detect_extools()) +#endif + +#ifndef UNIT_TESTS // use default logging as extools is broken on travis +#define EXTOOLS_LOGGING // rust_g is used as a fallback if this is undefined +#endif + +/proc/extools_log_write() + +/proc/extools_finalize_logging() diff --git a/code/__DEFINES/_flags/_flags.dm b/code/__DEFINES/_flags/_flags.dm index 6e018b1eeb..f12e3618f7 100644 --- a/code/__DEFINES/_flags/_flags.dm +++ b/code/__DEFINES/_flags/_flags.dm @@ -163,5 +163,19 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 else if(!HAS_TRAIT(x, TRAIT_KEEP_TOGETHER))\ x.appearance_flags &= ~KEEP_TOGETHER +//dir macros +///Returns true if the dir is diagonal, false otherwise +#define ISDIAGONALDIR(d) (d&(d-1)) +///True if the dir is north or south, false therwise +#define NSCOMPONENT(d) (d&(NORTH|SOUTH)) +///True if the dir is east/west, false otherwise +#define EWCOMPONENT(d) (d&(EAST|WEST)) +///Flips the dir for north/south directions +#define NSDIRFLIP(d) (d^(NORTH|SOUTH)) +///Flips the dir for east/west directions +#define EWDIRFLIP(d) (d^(EAST|WEST)) +///Turns the dir by 180 degrees +#define DIRFLIP(d) turn(d, 180) + /// 33554431 (2^24 - 1) is the maximum value our bitflags can reach. #define MAX_BITFLAG_DIGITS 8 diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index 143063b4e9..f6293454ee 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -91,3 +91,6 @@ #define SPAM_TRIGGER_WARNING 5 //Number of identical messages required before the spam-prevention will warn you to stfu #define SPAM_TRIGGER_AUTOMUTE 10 //Number of identical messages required before the spam-prevention will automute you + +#define STICKYBAN_DB_CACHE_TIME 10 SECONDS +#define STICKYBAN_ROGUE_CHECK_TIME 5 diff --git a/code/__DEFINES/dcs/helpers.dm b/code/__DEFINES/dcs/helpers.dm index 182035db9b..ba2b9a704a 100644 --- a/code/__DEFINES/dcs/helpers.dm +++ b/code/__DEFINES/dcs/helpers.dm @@ -6,9 +6,16 @@ #define SEND_GLOBAL_SIGNAL(sigtype, arguments...) ( SEND_SIGNAL(SSdcs, sigtype, ##arguments) ) +/// Signifies that this proc is used to handle signals. +/// Every proc you pass to RegisterSignal must have this. +#define SIGNAL_HANDLER SHOULD_NOT_SLEEP(TRUE) + +/// Signifies that this proc is used to handle signals, but also sleeps. +/// Do not use this for new work. +#define SIGNAL_HANDLER_DOES_SLEEP + /// A wrapper for _AddElement that allows us to pretend we're using normal named arguments #define AddElement(arguments...) _AddElement(list(##arguments)) - /// A wrapper for _RemoveElement that allows us to pretend we're using normal named arguments #define RemoveElement(arguments...) _RemoveElement(list(##arguments)) diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 51a5fb3ece..a084f2ae34 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -136,11 +136,15 @@ #define COMSIG_ATOM_ATTACK_HAND "atom_attack_hand" //from base of atom/attack_hand(): (mob/user) #define COMSIG_ATOM_ATTACK_PAW "atom_attack_paw" //from base of atom/attack_paw(): (mob/user) #define COMPONENT_NO_ATTACK_HAND 1 //works on all 3. +///////////////// + //This signal return value bitflags can be found in __DEFINES/misc.dm #define COMSIG_ATOM_INTERCEPT_Z_FALL "movable_intercept_z_impact" //called for each movable in a turf contents on /turf/zImpact(): (atom/movable/A, levels) - -///////////////// +/// Called from orbit component: (atom/movable/orbiter, radius, clockwise, rotation_speed, rotation_segments, pre_rotation) +#define COMSIG_ATOM_ORBIT_BEGIN "atom_orbit_begin" +/// Called from orbit component: (atom/movable/orbiter, refreshing) +#define COMSIG_ATOM_ORBIT_END "atom_orbit_end" #define COMSIG_ENTER_AREA "enter_area" //from base of area/Entered(): (/area) #define COMSIG_EXIT_AREA "exit_area" //from base of area/Exited(): (/area) @@ -536,3 +540,7 @@ #define COMSIG_XENO_TURF_CLICK_SHIFT "xeno_turf_click_shift" //from turf ShiftClickOn(): (/mob) #define COMSIG_XENO_TURF_CLICK_CTRL "xeno_turf_click_alt" //from turf AltClickOn(): (/mob) #define COMSIG_XENO_MONKEY_CLICK_CTRL "xeno_monkey_click_ctrl" //from monkey CtrlClickOn(): (/mob) + +// twitch plays +/// Returns direction: (wipe_votes) +#define COMSIG_TWITCH_PLAYS_MOVEMENT_DATA "twitch_plays_movement_data" diff --git a/code/__DEFINES/loadout.dm b/code/__DEFINES/loadout.dm index 7fe5fa4876..ecd043a66a 100644 --- a/code/__DEFINES/loadout.dm +++ b/code/__DEFINES/loadout.dm @@ -55,6 +55,9 @@ //donator items #define LOADOUT_CATEGORY_DONATOR "Donator" +//unlockable items +#define LOADOUT_CATEGORY_UNLOCKABLE "Unlockable" + //how many prosthetics can we have #define MAXIMUM_LOADOUT_PROSTHETICS 2 diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 153a82ad5e..8e7cf8763b 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -61,7 +61,7 @@ #define BODYPART_NANITES 4 #define HYBRID_BODYPART_DAMAGE_THRESHHOLD 25 //How much damage has to be suffered until the damage threshhold counts as passed -#define HYBRID_BODYPART_THESHHOLD_MINDAMAGE 15 //Which damage value this limb cannot be healed out of via easy nonsurgical means if the threshhold has been passed, state resets if damage value goes below mindamage. +#define HYBRID_BODYPART_THESHHOLD_MINDAMAGE 10 //Which damage value this limb cannot be healed out of via easy nonsurgical means if the threshhold has been passed, state resets if damage value goes below mindamage. #define BODYPART_NOT_DISABLED 0 #define BODYPART_DISABLED_DAMAGE 1 diff --git a/code/__DEFINES/movement.dm b/code/__DEFINES/movement.dm new file mode 100644 index 0000000000..5bf7de8647 --- /dev/null +++ b/code/__DEFINES/movement.dm @@ -0,0 +1,26 @@ +/// The minimum for glide_size to be clamped to. +#define MIN_GLIDE_SIZE 1 +/// 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 32 + +/// Compensating for time dialation +GLOBAL_VAR_INIT(glide_size_multiplier, 1.0) + +///Broken down, here's what this does: +/// divides the world icon_size (32) by delay divided by ticklag to get the number of pixels something should be moving each tick. +/// The division result is given a min value of 1 to prevent obscenely slow glide sizes from being set +/// 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(((32 / max((delay) / world.tick_lag, 1)) * GLOB.glide_size_multiplier), MIN_GLIDE_SIZE, MAX_GLIDE_SIZE)) + +/// Enables smooth movement +// #define SMOOTH_MOVEMENT + +/// Set appearance flags in vars +#ifdef SMOOTH_MOVEMENT + #define SET_APPEARANCE_FLAGS(_flags) appearance_flags = (_flags | LONG_GLIDE) +#else + #define SET_APPEARANCE_FLAGS(_flags) appearance_flags = _flags +#endif diff --git a/code/__DEFINES/sound.dm b/code/__DEFINES/sound.dm index 73781154c5..1098a07b39 100644 --- a/code/__DEFINES/sound.dm +++ b/code/__DEFINES/sound.dm @@ -3,6 +3,7 @@ #define CHANNEL_ADMIN 1023 #define CHANNEL_VOX 1022 #define CHANNEL_JUKEBOX 1021 + #define CHANNEL_JUKEBOX_START 1016 //The gap between this and CHANNEL_JUKEBOX determines the amount of free jukebox channels. This currently allows 6 jukebox channels to exist. #define CHANNEL_JUSTICAR_ARK 1015 #define CHANNEL_HEARTBEAT 1014 //sound channel for heartbeats @@ -15,6 +16,17 @@ #define CHANNEL_DIGEST 1009 #define CHANNEL_PREYLOOP 1008 +///Default range of a sound. +#define SOUND_RANGE 17 +///default extra range for sounds considered to be quieter +#define SHORT_RANGE_SOUND_EXTRARANGE -9 +///The range deducted from sound range for things that are considered silent / sneaky +#define SILENCED_SOUND_EXTRARANGE -11 +///Percentage of sound's range where no falloff is applied +#define SOUND_DEFAULT_FALLOFF_DISTANCE 1 //For a normal sound this would be 1 tile of no falloff +///The default exponent of sound falloff +#define SOUND_FALLOFF_EXPONENT 6 + //THIS SHOULD ALWAYS BE THE LOWEST ONE! //KEEP IT UPDATED @@ -23,6 +35,7 @@ #define MAX_INSTRUMENT_CHANNELS (128 * 6) #define SOUND_MINIMUM_PRESSURE 10 +/// remove #define FALLOFF_SOUNDS 1 @@ -53,7 +66,8 @@ #define MINING list('sound/ambience/ambimine.ogg', 'sound/ambience/ambicave.ogg', 'sound/ambience/ambiruin.ogg',\ 'sound/ambience/ambiruin2.ogg', 'sound/ambience/ambiruin3.ogg', 'sound/ambience/ambiruin4.ogg',\ 'sound/ambience/ambiruin5.ogg', 'sound/ambience/ambiruin6.ogg', 'sound/ambience/ambiruin7.ogg',\ - 'sound/ambience/ambidanger.ogg', 'sound/ambience/ambidanger2.ogg', 'sound/ambience/ambimaint1.ogg', 'sound/ambience/ambilava.ogg') + 'sound/ambience/ambidanger.ogg', 'sound/ambience/ambidanger2.ogg', 'sound/ambience/ambimaint1.ogg',\ + 'sound/ambience/ambilava.ogg') #define MEDICAL list('sound/ambience/ambinice.ogg') @@ -80,3 +94,55 @@ 'sound/hallucinations/growl3.ogg', 'sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg', 'sound/hallucinations/i_see_you1.ogg', 'sound/hallucinations/i_see_you2.ogg',\ 'sound/hallucinations/look_up1.ogg', 'sound/hallucinations/look_up2.ogg', 'sound/hallucinations/over_here1.ogg', 'sound/hallucinations/over_here2.ogg', 'sound/hallucinations/over_here3.ogg',\ 'sound/hallucinations/turn_around1.ogg', 'sound/hallucinations/turn_around2.ogg', 'sound/hallucinations/veryfar_noise.ogg', 'sound/hallucinations/wail.ogg') + + +#define INTERACTION_SOUND_RANGE_MODIFIER -3 +#define EQUIP_SOUND_VOLUME 30 +#define PICKUP_SOUND_VOLUME 15 +#define DROP_SOUND_VOLUME 20 +#define YEET_SOUND_VOLUME 90 + + +//default byond sound environments +#define SOUND_ENVIRONMENT_NONE -1 +#define SOUND_ENVIRONMENT_GENERIC 0 +#define SOUND_ENVIRONMENT_PADDED_CELL 1 +#define SOUND_ENVIRONMENT_ROOM 2 +#define SOUND_ENVIRONMENT_BATHROOM 3 +#define SOUND_ENVIRONMENT_LIVINGROOM 4 +#define SOUND_ENVIRONMENT_STONEROOM 5 +#define SOUND_ENVIRONMENT_AUDITORIUM 6 +#define SOUND_ENVIRONMENT_CONCERT_HALL 7 +#define SOUND_ENVIRONMENT_CAVE 8 +#define SOUND_ENVIRONMENT_ARENA 9 +#define SOUND_ENVIRONMENT_HANGAR 10 +#define SOUND_ENVIRONMENT_CARPETED_HALLWAY 11 +#define SOUND_ENVIRONMENT_HALLWAY 12 +#define SOUND_ENVIRONMENT_STONE_CORRIDOR 13 +#define SOUND_ENVIRONMENT_ALLEY 14 +#define SOUND_ENVIRONMENT_FOREST 15 +#define SOUND_ENVIRONMENT_CITY 16 +#define SOUND_ENVIRONMENT_MOUNTAINS 17 +#define SOUND_ENVIRONMENT_QUARRY 18 +#define SOUND_ENVIRONMENT_PLAIN 19 +#define SOUND_ENVIRONMENT_PARKING_LOT 20 +#define SOUND_ENVIRONMENT_SEWER_PIPE 21 +#define SOUND_ENVIRONMENT_UNDERWATER 22 +#define SOUND_ENVIRONMENT_DRUGGED 23 +#define SOUND_ENVIRONMENT_DIZZY 24 +#define SOUND_ENVIRONMENT_PSYCHOTIC 25 +//If we ever make custom ones add them here + +//"sound areas": easy way of keeping different types of areas consistent. +#define SOUND_AREA_STANDARD_STATION SOUND_ENVIRONMENT_PARKING_LOT +#define SOUND_AREA_LARGE_ENCLOSED SOUND_ENVIRONMENT_QUARRY +#define SOUND_AREA_SMALL_ENCLOSED SOUND_ENVIRONMENT_BATHROOM +#define SOUND_AREA_TUNNEL_ENCLOSED SOUND_ENVIRONMENT_STONEROOM +#define SOUND_AREA_LARGE_SOFTFLOOR SOUND_ENVIRONMENT_CARPETED_HALLWAY +#define SOUND_AREA_MEDIUM_SOFTFLOOR SOUND_ENVIRONMENT_LIVINGROOM +#define SOUND_AREA_SMALL_SOFTFLOOR SOUND_ENVIRONMENT_ROOM +#define SOUND_AREA_ASTEROID SOUND_ENVIRONMENT_CAVE +#define SOUND_AREA_SPACE SOUND_ENVIRONMENT_UNDERWATER +#define SOUND_AREA_LAVALAND SOUND_ENVIRONMENT_MOUNTAINS +#define SOUND_AREA_ICEMOON SOUND_ENVIRONMENT_CAVE +#define SOUND_AREA_WOODFLOOR SOUND_ENVIRONMENT_CITY diff --git a/code/__DEFINES/spaceman_dmm.dm b/code/__DEFINES/spaceman_dmm.dm index e21f3dc1c1..087fa5e6e6 100644 --- a/code/__DEFINES/spaceman_dmm.dm +++ b/code/__DEFINES/spaceman_dmm.dm @@ -29,5 +29,5 @@ #endif /world/proc/enable_debugger() - if (fexists(EXTOOLS)) - call(EXTOOLS, "debug_initialize")() + if (fexists(EXTOOLS)) + call(EXTOOLS, "debug_initialize")() diff --git a/code/__DEFINES/species.dm b/code/__DEFINES/species.dm index efd715b85a..74ca459fa1 100644 --- a/code/__DEFINES/species.dm +++ b/code/__DEFINES/species.dm @@ -5,6 +5,7 @@ #define SPECIES_ANDROID "android" #define SPECIES_ANGEL "angel" #define SPECIES_MAMMAL "mammal" + #define SPECIES_MAMMAL_SYNTHETIC "mammal_synthetic" #define SPECIES_ARACHNID "arachnid" #define SPECIES_INSECT "insect" #define SPECIES_DULLAHAN "dullahan" diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index d6db35e68d..e2ace84156 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -40,6 +40,9 @@ #define STATUS_EFFECT_DETERMINED /datum/status_effect/determined //currently in a combat high from being seriously wounded +#define STATUS_EFFECT_MANTRA /datum/status_effect/mantra // a toggled self buff that makes you stronger and more resilient, but drains stamina over time +#define STATUS_EFFECT_ASURA /datum/status_effect/asura // like a weaker version of mantra, drains HP instead of stamina and has no armor + ///////////// // DEBUFFS // ///////////// @@ -102,10 +105,6 @@ #define STATUS_EFFECT_FAKE_VIRUS /datum/status_effect/fake_virus //gives you fluff messages for cough, sneeze, headache, etc but without an actual virus -#define STATUS_EFFECT_BREASTS_ENLARGEMENT /datum/status_effect/chem/breast_enlarger //Applied slowdown due to the ominous bulk. - -#define STATUS_EFFECT_PENIS_ENLARGEMENT /datum/status_effect/chem/penis_enlarger //More applied slowdown, just like the above. - #define STATUS_EFFECT_NO_COMBAT_MODE /datum/status_effect/no_combat_mode //Wont allow combat mode and will disable it #define STATUS_EFFECT_MESMERIZE /datum/status_effect/mesmerize //Just reskinned no_combat_mode diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index b405db83b0..cbf701e1d3 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -1,40 +1,90 @@ -//Update this whenever the db schema changes -//make sure you add an update to the schema_version stable in the db changelog +//! Defines for subsystems and overlays +//! +//! Lots of important stuff in here, make sure you have your brain switched on +//! when editing this file + +//! ## DB defines +/** + * DB major schema version + * + * Update this whenever the db schema changes + * + * make sure you add an update to the schema_version stable in the db changelog + */ #define DB_MAJOR_VERSION 4 + +/** + * DB minor schema version + * + * Update this whenever the db schema changes + * + * make sure you add an update to the schema_version stable in the db changelog + */ #define DB_MINOR_VERSION 7 -//Timing subsystem -//Don't run if there is an identical unique timer active -//if the arguments to addtimer are the same as an existing timer, it doesn't create a new timer, and returns the id of the existing timer +//! ## Timing subsystem +/** + * Don't run if there is an identical unique timer active + * + * if the arguments to addtimer are the same as an existing timer, it doesn't create a new timer, + * and returns the id of the existing timer + */ #define TIMER_UNIQUE (1<<0) -//For unique timers: Replace the old timer rather then not start this one + +///For unique timers: Replace the old timer rather then not start this one #define TIMER_OVERRIDE (1<<1) -//Timing should be based on how timing progresses on clients, not the sever. -// tracking this is more expensive, -// should only be used in conjuction with things that have to progress client side, such as animate() or sound() + +/** + * Timing should be based on how timing progresses on clients, not the server. + * + * Tracking this is more expensive, + * should only be used in conjuction with things that have to progress client side, such as + * animate() or sound() + */ #define TIMER_CLIENT_TIME (1<<2) -//Timer can be stopped using deltimer() + +///Timer can be stopped using deltimer() #define TIMER_STOPPABLE (1<<3) -//To be used with TIMER_UNIQUE -//prevents distinguishing identical timers with the wait variable + +///prevents distinguishing identical timers with the wait variable +/// +///To be used with TIMER_UNIQUE #define TIMER_NO_HASH_WAIT (1<<4) -//Loops the timer repeatedly until qdeleted -//In most cases you want a subsystem instead + +///Loops the timer repeatedly until qdeleted +/// +///In most cases you want a subsystem instead, so don't use this unless you have a good reason #define TIMER_LOOP (1<<5) -#define TIMER_NO_INVOKE_WARNING 600 //number of byond ticks that are allowed to pass before the timer subsystem thinks it hung on something - +///Empty ID define #define TIMER_ID_NULL -1 -#define INITIALIZATION_INSSATOMS 0 //New should not call Initialize -#define INITIALIZATION_INNEW_MAPLOAD 2 //New should call Initialize(TRUE) -#define INITIALIZATION_INNEW_REGULAR 1 //New should call Initialize(FALSE) +//! ## Initialization subsystem -#define INITIALIZE_HINT_NORMAL 0 //Nothing happens -#define INITIALIZE_HINT_LATELOAD 1 //Call LateInitialize -#define INITIALIZE_HINT_QDEL 2 //Call qdel on the atom +///New should not call Initialize +#define INITIALIZATION_INSSATOMS 0 +///New should call Initialize(TRUE) +#define INITIALIZATION_INNEW_MAPLOAD 2 +///New should call Initialize(FALSE) +#define INITIALIZATION_INNEW_REGULAR 1 -//type and all subtypes should always call Initialize in New() +//! ### Initialization hints + +///Nothing happens +#define INITIALIZE_HINT_NORMAL 0 +/** + * call LateInitialize at the end of all atom Initalization + * + * The item will be added to the late_loaders list, this is iterated over after + * initalization of subsystems is complete and calls LateInitalize on the atom + * see [this file for the LateIntialize proc](atom.html#proc/LateInitialize) + */ +#define INITIALIZE_HINT_LATELOAD 1 + +///Call qdel on the atom after intialization +#define INITIALIZE_HINT_QDEL 2 + +///type and all subtypes should always immediately call Initialize in New() #define INITIALIZE_IMMEDIATE(X) ##X/New(loc, ...){\ ..();\ if(!(flags_1 & INITIALIZED_1)) {\ @@ -47,35 +97,40 @@ // Subsystems shutdown in the reverse of the order they initialize in // The numbers just define the ordering, they are meaningless otherwise. -#define INIT_ORDER_PROFILER 100 -#define INIT_ORDER_FAIL2TOPIC 99 -#define INIT_ORDER_TITLE 98 -#define INIT_ORDER_GARBAGE 95 -#define INIT_ORDER_DBCORE 94 -#define INIT_ORDER_STATPANELS 93 -#define INIT_ORDER_BLACKBOX 92 -#define INIT_ORDER_SERVER_MAINT 91 -#define INIT_ORDER_INPUT 90 -#define INIT_ORDER_SOUNDS 85 +#define INIT_ORDER_PROFILER 102 +#define INIT_ORDER_FAIL2TOPIC 101 +#define INIT_ORDER_TITLE 100 +#define INIT_ORDER_GARBAGE 99 +#define INIT_ORDER_DBCORE 95 +#define INIT_ORDER_BLACKBOX 94 +#define INIT_ORDER_SERVER_MAINT 93 +#define INIT_ORDER_INPUT 85 +#define INIT_ORDER_SOUNDS 83 +#define INIT_ORDER_INSTRUMENTS 82 #define INIT_ORDER_VIS 80 +// #define INIT_ORDER_ACHIEVEMENTS 77 #define INIT_ORDER_RESEARCH 75 #define INIT_ORDER_EVENTS 70 #define INIT_ORDER_JOBS 65 #define INIT_ORDER_QUIRKS 60 #define INIT_ORDER_TICKER 55 -#define INIT_ORDER_INSTRUMENTS 53 +// #define INIT_ORDER_TCG 55 #define INIT_ORDER_MAPPING 50 -#define INIT_ORDER_ECONOMY 45 -#define INIT_ORDER_NETWORKS 40 +#define INIT_ORDER_TIMETRACK 47 +#define INIT_ORDER_NETWORKS 45 +#define INIT_ORDER_ECONOMY 40 #define INIT_ORDER_HOLODECK 35 +// #define INIT_ORDER_OUTPUTS 35 #define INIT_ORDER_ATOMS 30 #define INIT_ORDER_LANGUAGE 25 #define INIT_ORDER_MACHINES 20 #define INIT_ORDER_CIRCUIT 15 +// #define INIT_ORDER_SKILLS 15 #define INIT_ORDER_TIMER 1 #define INIT_ORDER_DEFAULT 0 #define INIT_ORDER_AIR -1 #define INIT_ORDER_AIR_TURFS -2 +#define INIT_ORDER_PERSISTENCE -2 //before assets because some assets take data from SSPersistence #define INIT_ORDER_MINIMAP -3 #define INIT_ORDER_ASSETS -4 #define INIT_ORDER_ICON_SMOOTHING -5 @@ -86,7 +141,9 @@ #define INIT_ORDER_SHUTTLE -21 #define INIT_ORDER_MINOR_MAPPING -40 #define INIT_ORDER_PATH -50 -#define INIT_ORDER_PERSISTENCE -95 +// #define INIT_ORDER_DISCORD -60 +// #define INIT_ORDER_EXPLOSIONS -69 +#define INIT_ORDER_STATPANELS -98 #define INIT_ORDER_DEMO -99 // o avoid a bunch of changes related to initialization being written, do this last #define INIT_ORDER_CHAT -100 //Should be last to ensure chat remains smooth during init. @@ -102,6 +159,7 @@ #define FIRE_PRIORITY_GARBAGE 15 #define FIRE_PRIORITY_WET_FLOORS 20 #define FIRE_PRIORITY_AIR 20 +#define FIRE_PRIORITY_NPC 20 #define FIRE_PRIORITY_PROCESS 25 #define FIRE_PRIORITY_THROWING 25 #define FIRE_PRIORITY_SPACEDRIFT 30 @@ -116,7 +174,6 @@ #define FIRE_PRIORITY_AIR_TURFS 40 #define FIRE_PRIORITY_DEFAULT 50 #define FIRE_PRIORITY_PARALLAX 65 -#define FIRE_PRIORITY_NPC 80 #define FIRE_PRIORITY_MOBS 100 #define FIRE_PRIORITY_TGUI 110 #define FIRE_PRIORITY_PROJECTILES 200 @@ -126,6 +183,8 @@ #define FIRE_PRIORITY_CHAT 400 #define FIRE_PRIORITY_RUNECHAT 410 #define FIRE_PRIORITY_OVERLAYS 500 +// #define FIRE_PRIORITY_EXPLOSIONS 666 +#define FIRE_PRIORITY_TIMER 700 #define FIRE_PRIORITY_INPUT 1000 // This must always always be the max highest priority. Player input must never be lost. // SS runlevels @@ -138,6 +197,37 @@ #define RUNLEVELS_DEFAULT (RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME) + + +//! ## Overlays subsystem + +///Compile all the overlays for an atom from the cache lists +// |= on overlays is not actually guaranteed to not add same appearances but we're optimistically using it anyway. +#define COMPILE_OVERLAYS(A)\ + if (TRUE) {\ + var/list/ad = A.add_overlays;\ + var/list/rm = A.remove_overlays;\ + if(LAZYLEN(rm)){\ + A.overlays -= rm;\ + rm.Cut();\ + }\ + if(LAZYLEN(ad)){\ + A.overlays |= ad;\ + ad.Cut();\ + }\ + A.flags_1 &= ~OVERLAY_QUEUED_1;\ + } + + +/** + Create a new timer and add it to the queue. + * Arguments: + * * callback the callback to call on timer finish + * * wait deciseconds to run the timer for + * * flags flags for this timer, see: code\__DEFINES\subsystems.dm +*/ +#define addtimer(args...) _addtimer(args, file = __FILE__, line = __LINE__) + // SSair run section #define SSAIR_PIPENETS 1 #define SSAIR_ATMOSMACHINERY 2 @@ -148,19 +238,3 @@ #define SSAIR_REBUILD_PIPENETS 7 #define SSAIR_EQUALIZE 8 #define SSAIR_ACTIVETURFS 9 - -// |= on overlays is not actually guaranteed to not add same appearances but we're optimistically using it anyway. -#define COMPILE_OVERLAYS(A)\ - if (TRUE) {\ - var/list/ad = A.add_overlays;\ - var/list/rm = A.remove_overlays;\ - if(LAZYLEN(rm)){\ - A.overlays -= rm;\ - A.remove_overlays = null;\ - }\ - if(LAZYLEN(ad)){\ - A.overlays |= ad;\ - A.add_overlays = null;\ - }\ - A.flags_1 &= ~OVERLAY_QUEUED_1;\ - } diff --git a/code/__DEFINES/vote.dm b/code/__DEFINES/vote.dm index a3617e21d0..88e70b884e 100644 --- a/code/__DEFINES/vote.dm +++ b/code/__DEFINES/vote.dm @@ -2,7 +2,7 @@ #define APPROVAL_VOTING "APPROVAL" #define SCHULZE_VOTING "SCHULZE" #define SCORE_VOTING "SCORE" -#define MAJORITY_JUDGEMENT_VOTING "MAJORITY_JUDGEMENT" +#define HIGHEST_MEDIAN_VOTING "HIGHEST_MEDIAN" #define INSTANT_RUNOFF_VOTING "IRV" #define SHOW_RESULTS (1<<0) @@ -18,7 +18,7 @@ GLOBAL_LIST_INIT(vote_type_names,list(\ "IRV (single winner ranked choice)" = INSTANT_RUNOFF_VOTING,\ "Schulze (ranked choice, higher result=better)" = SCHULZE_VOTING,\ "Raw Score (returns results from 0 to 1, winner is 1)" = SCORE_VOTING,\ -"Majority Judgement (single-winner score voting)" = MAJORITY_JUDGEMENT_VOTING,\ +"Highest Median (single-winner score voting)" = HIGHEST_MEDIAN_VOTING,\ )) GLOBAL_LIST_INIT(display_vote_settings, list(\ diff --git a/code/__HELPERS/_extools_api.dm b/code/__HELPERS/_extools_api.dm deleted file mode 100644 index af348dc939..0000000000 --- a/code/__HELPERS/_extools_api.dm +++ /dev/null @@ -1,5 +0,0 @@ -#define EXTOOLS_LOGGING // rust_g is used as a fallback if this is undefined - -/proc/extools_log_write() - -/proc/extools_finalize_logging() diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index 3efb50ef65..8d25fb8e03 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -37,7 +37,7 @@ * TYPECONT: The typepath of the contents of the list * COMPARE: The object to compare against, usualy the same as INPUT * COMPARISON: The variable on the objects to compare - * COMPTYPE: How the current bin item to compare against COMPARE is fetched. By key or value. + * COMPTYPE: How should the values be compared? Either COMPARE_KEY or COMPARE_VALUE. */ #define BINARY_INSERT(INPUT, LIST, TYPECONT, COMPARE, COMPARISON, COMPTYPE) \ do {\ @@ -49,7 +49,7 @@ var/__BIN_LEFT = 1;\ var/__BIN_RIGHT = __BIN_CTTL;\ var/__BIN_MID = (__BIN_LEFT + __BIN_RIGHT) >> 1;\ - var/##TYPECONT/__BIN_ITEM;\ + var ##TYPECONT/__BIN_ITEM;\ while(__BIN_LEFT < __BIN_RIGHT) {\ __BIN_ITEM = COMPTYPE;\ if(__BIN_ITEM.##COMPARISON <= COMPARE.##COMPARISON) {\ diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm index 583427cab7..18d02229dd 100644 --- a/code/__HELPERS/_logging.dm +++ b/code/__HELPERS/_logging.dm @@ -32,7 +32,7 @@ #define testing(msg) #endif -#ifdef UNIT_TESTS +#if defined(UNIT_TESTS) || defined(SPACEMAN_DMM) /proc/log_test(text) WRITE_LOG(GLOB.test_log, text) SEND_TEXT(world.log, text) @@ -86,10 +86,6 @@ if (CONFIG_GET(flag/log_attack)) WRITE_LOG(GLOB.world_attack_log, "ATTACK: [text]") -/proc/log_wounded(text) - if (CONFIG_GET(flag/log_attack)) - WRITE_LOG(GLOB.world_attack_log, "WOUND: [text]") - /proc/log_manifest(ckey, datum/mind/mind,mob/body, latejoin = FALSE) if (CONFIG_GET(flag/log_manifest)) WRITE_LOG(GLOB.world_manifest_log, "[ckey] \\ [body.real_name] \\ [mind.assigned_role] \\ [mind.special_role ? mind.special_role : "NONE"] \\ [latejoin ? "LATEJOIN":"ROUNDSTART"]") @@ -195,6 +191,10 @@ /proc/log_mapping(text) WRITE_LOG(GLOB.world_map_error_log, text) +/proc/log_perf(list/perf_info) + . = "[perf_info.Join(",")]\n" + WRITE_LOG_NO_FORMAT(GLOB.perf_log, .) + /proc/log_reagent(text) WRITE_LOG(GLOB.reagent_log, text) diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 2263ac2e27..40ae43b281 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -238,8 +238,11 @@ CHECK_TICK SSdbcore.SetRoundEnd() //Collects persistence features - if(mode.allow_persistence_save) - SSpersistence.CollectData() + if(mode.station_was_nuked) + SSpersistence.station_was_destroyed = TRUE + if(!mode.allow_persistence_save) + SSpersistence.station_persistence_save_disabled = TRUE + SSpersistence.CollectData() //stop collecting feedback during grifftime SSblackbox.Seal() diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index babcd5de54..08bf5e709a 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -271,7 +271,7 @@ Turf and target are separate in case you want to teleport some distance from a t if(skip_mindless && (!M.mind && !M.ckey)) if(!isbot(M) && !iscameramob(M) && !ismegafauna(M)) continue - if(M.client && M.client.holder && M.client.holder.fakekey) //stealthmins + if(M.client?.holder?.fakekey && isobserver(M)) continue var/name = avoid_assoc_duplicate_keys(M.name, namecounts) @@ -1202,7 +1202,7 @@ GLOBAL_REAL_VAR(list/stack_trace_storage) GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) //Version of view() which ignores darkness, because BYOND doesn't have it (I actually suggested it but it was tagged redundant, BUT HEARERS IS A T- /rant). -/proc/dview(var/range = world.view, var/center, var/invis_flags = 0) +/proc/dview(range = world.view, center, invis_flags = 0) if(!center) return @@ -1222,6 +1222,10 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) var/ready_to_die = FALSE /mob/dview/Initialize() //Properly prevents this mob from gaining huds or joining any global lists + SHOULD_CALL_PARENT(FALSE) + if(flags_1 & INITIALIZED_1) + stack_trace("Warning: [src]([type]) initialized multiple times!") + flags_1 |= INITIALIZED_1 return INITIALIZE_HINT_NORMAL /mob/dview/Destroy(force = FALSE) diff --git a/code/_compile_options.dm b/code/_compile_options.dm index 0e0bd4ffaa..64b4129024 100644 --- a/code/_compile_options.dm +++ b/code/_compile_options.dm @@ -46,11 +46,11 @@ //Update this whenever you need to take advantage of more recent byond features #define MIN_COMPILER_VERSION 513 -#define MIN_COMPILER_BUILD 1508 +#define MIN_COMPILER_BUILD 1514 #if DM_VERSION < MIN_COMPILER_VERSION || DM_BUILD < MIN_COMPILER_BUILD //Don't forget to update this part #error Your version of BYOND is too out-of-date to compile this project. Go to https://secure.byond.com/download and update. -#error You need version 513.1508 or higher +#error You need version 513.1514 or higher #endif //Additional code for the above flags. @@ -62,10 +62,14 @@ #define FIND_REF_NO_CHECK_TICK #endif -#ifdef TRAVISBUILDING +#ifdef CIBUILDING #define UNIT_TESTS #endif -#ifdef TRAVISTESTING +#ifdef CITESTING #define TESTING #endif + +// A reasonable number of maximum overlays an object needs +// If you think you need more, rethink it +#define MAX_ATOM_OVERLAYS 100 diff --git a/code/_globalvars/admin.dm b/code/_globalvars/admin.dm new file mode 100644 index 0000000000..81037ff3dd --- /dev/null +++ b/code/_globalvars/admin.dm @@ -0,0 +1,12 @@ +GLOBAL_LIST_EMPTY(stickybanadminexemptions) //stores a list of ckeys exempted from a stickyban (workaround for a bug) +GLOBAL_LIST_EMPTY(stickybanadmintexts) //stores the entire stickyban list temporarily +GLOBAL_VAR(stickbanadminexemptiontimerid) //stores the timerid of the callback that restores all stickybans after an admin joins + +// /proc/init_smites() //todo: add on the second wave +// var/list/smites = list() +// for (var/_smite_path in subtypesof(/datum/smite)) +// var/datum/smite/smite_path = _smite_path +// smites[initial(smite_path.name)] = smite_path +// return smites + +// GLOBAL_LIST_INIT_TYPED(smites, /datum/smite, init_smites()) diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm index 0444e42e91..7fad1690e6 100644 --- a/code/_globalvars/lists/flavor_misc.dm +++ b/code/_globalvars/lists/flavor_misc.dm @@ -275,7 +275,7 @@ GLOBAL_LIST_INIT(wisdoms, world.file2list("strings/wisdoms.txt")) //LANGUAGE CHARACTER CUSTOMIZATION GLOBAL_LIST_INIT(speech_verbs, list("default","says","gibbers", "states", "chitters", "chimpers", "declares", "bellows", "buzzes" ,"beeps", "chirps", "clicks", "hisses" ,"poofs" , "puffs", "rattles", "mewls" ,"barks", "blorbles", "squeaks", "squawks", "flutters", "warbles")) -GLOBAL_LIST_INIT(roundstart_tongues, list("default","human tongue" = /obj/item/organ/tongue, "lizard tongue" = /obj/item/organ/tongue/lizard, "skeleton tongue" = /obj/item/organ/tongue/bone, "fly tongue" = /obj/item/organ/tongue/fly, "ipc tongue" = /obj/item/organ/tongue/robot/ipc)) +GLOBAL_LIST_INIT(roundstart_tongues, list("default","human tongue" = /obj/item/organ/tongue, "lizard tongue" = /obj/item/organ/tongue/lizard, "skeleton tongue" = /obj/item/organ/tongue/bone, "fly tongue" = /obj/item/organ/tongue/fly, "ipc tongue" = /obj/item/organ/tongue/robot/ipc, "xeno tongue" = /obj/item/organ/tongue/alien)) //SPECIES BODYPART LISTS //locked parts are those that your picked species requires to have diff --git a/code/_globalvars/lists/loadout_categories.dm b/code/_globalvars/lists/loadout_categories.dm index 0f0ac52214..4a61a94dc7 100644 --- a/code/_globalvars/lists/loadout_categories.dm +++ b/code/_globalvars/lists/loadout_categories.dm @@ -9,5 +9,6 @@ GLOBAL_LIST_INIT(loadout_categories, list( LOADOUT_CATEGORY_SHOES = LOADOUT_SUBCATEGORIES_NONE, LOADOUT_CATEGORY_GLOVES = LOADOUT_SUBCATEGORIES_NONE, LOADOUT_CATEGORY_GLASSES = LOADOUT_SUBCATEGORIES_NONE, - LOADOUT_CATEGORY_DONATOR = LOADOUT_SUBCATEGORIES_NONE + LOADOUT_CATEGORY_DONATOR = LOADOUT_SUBCATEGORIES_NONE, + LOADOUT_CATEGORY_UNLOCKABLE = LOADOUT_SUBCATEGORIES_NONE )) diff --git a/code/_globalvars/lists/maintenance_loot.dm b/code/_globalvars/lists/maintenance_loot.dm index 694e913d53..b41b7356a8 100644 --- a/code/_globalvars/lists/maintenance_loot.dm +++ b/code/_globalvars/lists/maintenance_loot.dm @@ -89,7 +89,7 @@ GLOBAL_LIST_INIT(maintenance_loot, list( /obj/effect/spawner/lootdrop/welder_tools = 3, /obj/effect/spawner/lootdrop/low_tools = 5, /obj/item/relic = 3, - /obj/item/weaponcrafting/improvised_parts/shotgun_receiver = 2, + /obj/item/weaponcrafting/receiver = 2, /obj/item/clothing/head/cone = 2, /obj/item/grenade/smokebomb = 2, /obj/item/geiger_counter = 3, diff --git a/code/_globalvars/logging.dm b/code/_globalvars/logging.dm index e9f98f836e..78d802dbbf 100644 --- a/code/_globalvars/logging.dm +++ b/code/_globalvars/logging.dm @@ -8,6 +8,8 @@ GLOBAL_VAR(world_qdel_log) GLOBAL_PROTECT(world_qdel_log) GLOBAL_VAR(world_attack_log) GLOBAL_PROTECT(world_attack_log) +// GLOBAL_VAR(world_econ_log) +// GLOBAL_PROTECT(world_econ_log) GLOBAL_VAR(world_href_log) GLOBAL_PROTECT(world_href_log) GLOBAL_VAR(round_id) @@ -26,22 +28,28 @@ GLOBAL_VAR(query_debug_log) GLOBAL_PROTECT(query_debug_log) GLOBAL_VAR(world_job_debug_log) GLOBAL_PROTECT(world_job_debug_log) +// GLOBAL_VAR(world_mecha_log) +// GLOBAL_PROTECT(world_mecha_log) GLOBAL_VAR(world_virus_log) GLOBAL_PROTECT(world_virus_log) GLOBAL_VAR(world_asset_log) GLOBAL_PROTECT(world_asset_log) +// GLOBAL_VAR(world_cloning_log) +// GLOBAL_PROTECT(world_cloning_log) GLOBAL_VAR(world_map_error_log) GLOBAL_PROTECT(world_map_error_log) GLOBAL_VAR(world_paper_log) GLOBAL_PROTECT(world_paper_log) -GLOBAL_VAR(subsystem_log) -GLOBAL_PROTECT(subsystem_log) -GLOBAL_VAR(reagent_log) -GLOBAL_PROTECT(reagent_log) -GLOBAL_VAR(world_crafting_log) -GLOBAL_PROTECT(world_crafting_log) -GLOBAL_VAR(click_log) -GLOBAL_PROTECT(click_log) +GLOBAL_VAR(tgui_log) +GLOBAL_PROTECT(tgui_log) +GLOBAL_VAR(world_shuttle_log) +GLOBAL_PROTECT(world_shuttle_log) + +GLOBAL_VAR(perf_log) +GLOBAL_PROTECT(perf_log) + +// GLOBAL_VAR(demo_log) +// GLOBAL_PROTECT(demo_log) GLOBAL_LIST_EMPTY(bombers) GLOBAL_PROTECT(bombers) @@ -51,10 +59,7 @@ GLOBAL_LIST_EMPTY(lastsignalers) //keeps last 100 signals here in format: "[src] GLOBAL_PROTECT(lastsignalers) GLOBAL_LIST_EMPTY(lawchanges) //Stores who uploaded laws to which silicon-based lifeform, and what the law was GLOBAL_PROTECT(lawchanges) -GLOBAL_VAR(tgui_log) -GLOBAL_PROTECT(tgui_log) -GLOBAL_VAR(world_shuttle_log) -GLOBAL_PROTECT(world_shuttle_log) + GLOBAL_LIST_EMPTY(combatlog) GLOBAL_PROTECT(combatlog) GLOBAL_LIST_EMPTY(IClog) @@ -75,3 +80,13 @@ GLOBAL_PROTECT(picture_logging_id) GLOBAL_VAR(picture_logging_prefix) GLOBAL_PROTECT(picture_logging_prefix) ///// + +//// cit logging +GLOBAL_VAR(subsystem_log) +GLOBAL_PROTECT(subsystem_log) +GLOBAL_VAR(reagent_log) +GLOBAL_PROTECT(reagent_log) +GLOBAL_VAR(world_crafting_log) +GLOBAL_PROTECT(world_crafting_log) +GLOBAL_VAR(click_log) +GLOBAL_PROTECT(click_log) diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm index d82f3e7cf5..076c949f8e 100644 --- a/code/_onclick/hud/fullscreen.dm +++ b/code/_onclick/hud/fullscreen.dm @@ -149,6 +149,15 @@ /obj/screen/fullscreen/color_vision/blue color = "#0000ff" +/obj/screen/fullscreen/cinematic_backdrop + icon = 'icons/mob/screen_gen.dmi' + screen_loc = "WEST,SOUTH to EAST,NORTH" + icon_state = "flash" + plane = SPLASHSCREEN_PLANE + layer = SPLASHSCREEN_LAYER - 1 + color = "#000000" + show_when_dead = TRUE + /obj/screen/fullscreen/lighting_backdrop icon = 'icons/mob/screen_gen.dmi' icon_state = "flash" diff --git a/code/_onclick/hud/parallax.dm b/code/_onclick/hud/parallax.dm index 9050bcb5f0..5d48f430d7 100755 --- a/code/_onclick/hud/parallax.dm +++ b/code/_onclick/hud/parallax.dm @@ -10,6 +10,8 @@ C.parallax_layers_cached += new /obj/screen/parallax_layer/layer_1(null, C.view) C.parallax_layers_cached += new /obj/screen/parallax_layer/layer_2(null, C.view) C.parallax_layers_cached += new /obj/screen/parallax_layer/planet(null, C.view) + if(SSparallax.random_layer) + C.parallax_layers_cached += new SSparallax.random_layer C.parallax_layers_cached += new /obj/screen/parallax_layer/layer_3(null, C.view) C.parallax_layers = C.parallax_layers_cached.Copy() @@ -52,12 +54,12 @@ switch(C.prefs.parallax) if (PARALLAX_INSANE) C.parallax_throttle = FALSE - C.parallax_layers_max = 4 + C.parallax_layers_max = 5 return TRUE if (PARALLAX_MED) C.parallax_throttle = PARALLAX_DELAY_MED - C.parallax_layers_max = 2 + C.parallax_layers_max = 3 return TRUE if (PARALLAX_LOW) @@ -68,8 +70,9 @@ if (PARALLAX_DISABLE) return FALSE + //This is high parallax. C.parallax_throttle = PARALLAX_DELAY_DEFAULT - C.parallax_layers_max = 3 + C.parallax_layers_max = 4 return TRUE /datum/hud/proc/update_parallax_pref(mob/viewmob) @@ -219,15 +222,14 @@ L.screen_loc = "CENTER-7:[round(L.offset_x,1)],CENTER-7:[round(L.offset_y,1)]" /atom/movable/proc/update_parallax_contents() - set waitfor = FALSE if(length(client_mobs_in_contents)) for(var/thing in client_mobs_in_contents) var/mob/M = thing - if(M && M.client && M.hud_used && length(M.client.parallax_layers)) + if(M?.client && M.hud_used && length(M.client.parallax_layers)) M.hud_used.update_parallax() /mob/proc/update_parallax_teleport() //used for arrivals shuttle - if(client && client.eye && hud_used && length(client.parallax_layers)) + if(client?.eye && hud_used && length(client.parallax_layers)) var/area/areaobj = get_area(client.eye) hud_used.set_parallax_movedir(areaobj.parallax_movedir, TRUE) @@ -287,6 +289,21 @@ speed = 1.4 layer = 3 +/obj/screen/parallax_layer/random + blend_mode = BLEND_OVERLAY + speed = 3 + layer = 3 + +/obj/screen/parallax_layer/random/space_gas + icon_state = "space_gas" + +/obj/screen/parallax_layer/random/space_gas/Initialize(mapload, view) + . = ..() + src.add_atom_colour(SSparallax.random_parallax_color, ADMIN_COLOUR_PRIORITY) + +/obj/screen/parallax_layer/random/asteroids + icon_state = "asteroids" + /obj/screen/parallax_layer/planet icon_state = "planet" blend_mode = BLEND_OVERLAY @@ -295,11 +312,11 @@ layer = 30 /obj/screen/parallax_layer/planet/update_status(mob/M) - var/turf/T = get_turf(M) - if(is_station_level(T.z)) - invisibility = 0 - else - invisibility = INVISIBILITY_ABSTRACT + var/client/C = M.client + var/turf/posobj = get_turf(C.eye) + if(!posobj) + return + invisibility = is_station_level(posobj.z) ? 0 : INVISIBILITY_ABSTRACT /obj/screen/parallax_layer/planet/update_o() - return //Shit wont move + return //Shit won't move diff --git a/code/_onclick/hud/plane_master.dm b/code/_onclick/hud/plane_master.dm index 7a8b0a1121..f5b8991e20 100644 --- a/code/_onclick/hud/plane_master.dm +++ b/code/_onclick/hud/plane_master.dm @@ -28,8 +28,6 @@ . = ..() filters += filter(type="alpha", render_source=FIELD_OF_VISION_RENDER_TARGET, flags=MASK_INVERSE) -/obj/screen/plane_master/openspace/backdrop(mob/mymob) - filters = list() filters += filter(type = "drop_shadow", color = "#04080FAA", size = -10) filters += filter(type = "drop_shadow", color = "#04080FAA", size = -15) filters += filter(type = "drop_shadow", color = "#04080FAA", size = -20) @@ -93,13 +91,6 @@ else remove_filter("ambient_occlusion") -//Reserved to chat messages, so they are still displayed above the field of vision masking. -/obj/screen/plane_master/chat_messages - name = "chat messages plane master" - plane = CHAT_PLANE - appearance_flags = PLANE_MASTER - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - ///Contains all shadow cone masks, whose image overrides are displayed only to their respective owners. /obj/screen/plane_master/field_of_vision name = "field of vision mask plane master" @@ -135,10 +126,14 @@ blend_mode = BLEND_MULTIPLY mouse_opacity = MOUSE_OPACITY_TRANSPARENT +/obj/screen/plane_master/lighting/backdrop(mob/mymob) + mymob.overlay_fullscreen("lighting_backdrop_lit", /obj/screen/fullscreen/lighting_backdrop/lit) + mymob.overlay_fullscreen("lighting_backdrop_unlit", /obj/screen/fullscreen/lighting_backdrop/unlit) + /obj/screen/plane_master/lighting/Initialize() . = ..() - filters += filter(type="alpha", render_source=EMISSIVE_RENDER_TARGET, flags=MASK_INVERSE) - filters += filter(type="alpha", render_source=EMISSIVE_UNBLOCKABLE_RENDER_TARGET, flags=MASK_INVERSE) + filters += filter(type="alpha", render_source = EMISSIVE_RENDER_TARGET, flags = MASK_INVERSE) + filters += filter(type="alpha", render_source = EMISSIVE_UNBLOCKABLE_RENDER_TARGET, flags = MASK_INVERSE) /** * Things placed on this mask the lighting plane. Doesn't render directly. @@ -186,7 +181,6 @@ render_target = EMISSIVE_BLOCKER_RENDER_TARGET ///Contains space parallax - /obj/screen/plane_master/parallax name = "parallax plane master" plane = PLANE_SPACE_PARALLAX @@ -197,12 +191,16 @@ name = "parallax whitifier plane master" plane = PLANE_SPACE -/obj/screen/plane_master/lighting/backdrop(mob/mymob) - mymob.overlay_fullscreen("lighting_backdrop_lit", /obj/screen/fullscreen/lighting_backdrop/lit) - mymob.overlay_fullscreen("lighting_backdrop_unlit", /obj/screen/fullscreen/lighting_backdrop/unlit) - /obj/screen/plane_master/camera_static name = "camera static plane master" plane = CAMERA_STATIC_PLANE appearance_flags = PLANE_MASTER blend_mode = BLEND_OVERLAY + + +//Reserved to chat messages, so they are still displayed above the field of vision masking. +/obj/screen/plane_master/chat_messages + name = "runechat plane master" + plane = CHAT_PLANE + appearance_flags = PLANE_MASTER + blend_mode = BLEND_OVERLAY diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 2ed8c81ba2..53915ff42b 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -12,9 +12,14 @@ layer = HUD_LAYER plane = HUD_PLANE resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + animate_movement = SLIDE_STEPS + speech_span = SPAN_ROBOT + vis_flags = VIS_INHERIT_PLANE appearance_flags = APPEARANCE_UI - var/obj/master = null //A reference to the object in the slot. Grabs or items, generally. - var/datum/hud/hud = null // A reference to the owner HUD, if any. + /// A reference to the object in the slot. Grabs or items, generally. + var/obj/master = null + /// A reference to the owner HUD, if any. + var/datum/hud/hud = null /** * Map name assigned to this object. * Automatically set by /client/proc/add_obj_to_map. @@ -60,7 +65,17 @@ name = "swap hand" /obj/screen/swap_hand/Click() - usr.swap_hand() + // At this point in client Click() code we have passed the 1/10 sec check and little else + // We don't even know if it's a middle click + // if(world.time <= usr.next_move) + // return 1 + + if(usr.incapacitated()) + return 1 + + if(ismob(usr)) + var/mob/M = usr + M.swap_hand() return 1 /obj/screen/craft @@ -96,17 +111,27 @@ H.open_language_menu(usr) /obj/screen/inventory - var/slot_id // The indentifier for the slot. It has nothing to do with ID cards. - var/icon_empty // Icon when empty. For now used only by humans. - var/icon_full // Icon when contains an item. For now used only by humans. + /// The identifier for the slot. It has nothing to do with ID cards. + var/slot_id + /// Icon when empty. For now used only by humans. + var/icon_empty + /// Icon when contains an item. For now used only by humans. + var/icon_full + /// The overlay when hovering over with an item in your hand var/list/object_overlays = list() layer = HUD_LAYER plane = HUD_PLANE /obj/screen/inventory/Click(location, control, params) - if(hud?.mymob && (hud.mymob != usr)) - return - // just redirect clicks + // At this point in client Click() code we have passed the 1/10 sec check and little else + // We don't even know if it's a middle click + // if(world.time <= usr.next_move) + // return TRUE + + if(usr.incapacitated()) // ignore_stasis = TRUE + return TRUE + if(ismecha(usr.loc)) // stops inventory actions in a mech + return TRUE if(hud?.mymob && slot_id) var/obj/item/inv_item = hud.mymob.get_item_by_slot(slot_id) @@ -150,12 +175,13 @@ var/image/item_overlay = image(holding) item_overlay.alpha = 92 - if(!user.can_equip(holding, slot_id, TRUE, TRUE, TRUE)) + if(!user.can_equip(holding, slot_id, TRUE)) item_overlay.color = "#FF0000" else item_overlay.color = "#00ff00" - object_overlays += item_overlay + cut_overlay(object_overlays) + // object_overlay = item_overlay add_overlay(object_overlays) /obj/screen/inventory/hand @@ -187,10 +213,17 @@ /obj/screen/inventory/hand/Click(location, control, params) - if(hud?.mymob && (hud.mymob != usr)) - return - var/mob/user = hud.mymob - // just redirect clicks + // At this point in client Click() code we have passed the 1/10 sec check and little else + // We don't even know if it's a middle click + var/mob/user = hud?.mymob + if(usr != user) + return TRUE + // if(world.time <= user.next_move) + // return TRUE + if(user.incapacitated()) + return TRUE + if (ismecha(user.loc)) // stops inventory actions in a mech + return TRUE if(user.active_hand_index == held_index) var/obj/item/I = user.get_active_held_item() diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index cd1ee56848..7a614da07b 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -85,7 +85,7 @@ if(force && damtype != STAMINA && HAS_TRAIT(user, TRAIT_PACIFISM)) to_chat(user, "You don't want to harm other living beings!") return - + if(!UseStaminaBufferStandard(user, STAM_COST_ATTACK_MOB_MULT, null, TRUE)) return DISCARD_LAST_ACTION diff --git a/code/controllers/admin.dm b/code/controllers/admin.dm index 3782d8be94..19fef28597 100644 --- a/code/controllers/admin.dm +++ b/code/controllers/admin.dm @@ -3,7 +3,7 @@ name = "Initializing..." var/target -INITIALIZE_IMMEDIATE(/obj/effect/statclick) //it's new, but rebranded. +INITIALIZE_IMMEDIATE(/obj/effect/statclick) /obj/effect/statclick/Initialize(mapload, text, target) //Don't port this to Initialize it's too critical . = ..() @@ -33,14 +33,6 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick) //it's new, but rebranded. usr.client.debug_variables(target) message_admins("Admin [key_name_admin(usr)] is debugging the [target] [class].") -/obj/effect/statclick/misc_subsystems/Click() - if(!usr.client.holder) - return - var/subsystem = input(usr, "Debug which subsystem?", "Debug nonprocessing subsystem") as null|anything in (Master.subsystems - Master.statworthy_subsystems) - if(!subsystem) - return - usr.client.debug_variables(subsystem) - message_admins("Admin [key_name_admin(usr)] is debugging the [subsystem] subsystem.") // Debug verbs. /client/proc/restart_controller(controller in list("Master", "Failsafe")) diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index 67e4a97894..dc8e9e1859 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -566,3 +566,20 @@ config_entry_value = 0.333 min_val = 0 integer = FALSE + +/// Amount of dirtyness tiles need to spawn dirt. +/datum/config_entry/number/turf_dirt_threshold + config_entry_value = 100 + min_val = 1 + integer = TRUE + +/// Alpha dirt starts at +/datum/config_entry/number/dirt_alpha_starting + config_entry_value = 127 + max_val = 255 + min_val = 0 + integer = TRUE + +/// Dirtyness multiplier for making turfs dirty +/datum/config_entry/number/turf_dirty_multiplier + config_entry_value = 1 diff --git a/code/controllers/configuration/entries/persistence.dm b/code/controllers/configuration/entries/persistence.dm new file mode 100644 index 0000000000..2444034b86 --- /dev/null +++ b/code/controllers/configuration/entries/persistence.dm @@ -0,0 +1,20 @@ +/// Whether or not to use the persistence system for cleanable objects +/datum/config_entry/flag/persistent_debris + config_entry_value = FALSE + +/// Whether or not to nuke all roundstart debris that isn't due to persistence if the above is true +/datum/config_entry/flag/persistent_debris_only + config_entry_value = TRUE + +/// Max amount of objects to store, total +/datum/config_entry/number/persistent_debris_global_max + config_entry_value = 10000 + integer = TRUE + +/// Max amount of objects to store per type +/datum/config_entry/number/persistent_debris_type_max + config_entry_value = 2000 + integer = TRUE + +/// Wipe dirty stuff on nuke +/datum/config_entry/flag/persistent_debris_wipe_on_nuke diff --git a/code/controllers/failsafe.dm b/code/controllers/failsafe.dm index fdce9a1287..a15056e442 100644 --- a/code/controllers/failsafe.dm +++ b/code/controllers/failsafe.dm @@ -1,7 +1,7 @@ /** - * Failsafe - * - * Pretty much pokes the MC to make sure it's still alive. + * Failsafe + * + * Pretty much pokes the MC to make sure it's still alive. **/ GLOBAL_REAL(Failsafe, /datum/controller/failsafe) diff --git a/code/controllers/master.dm b/code/controllers/master.dm index 1b5c7e5e83..59ac68960c 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -1,10 +1,10 @@ - /** - * StonedMC - * - * Designed to properly split up a given tick among subsystems - * Note: if you read parts of this code and think "why is it doing it that way" - * Odds are, there is a reason - * +/** + * StonedMC + * + * Designed to properly split up a given tick among subsystems + * Note: if you read parts of this code and think "why is it doing it that way" + * Odds are, there is a reason + * **/ //This is the ABSOLUTE ONLY THING that should init globally like this @@ -28,8 +28,6 @@ GLOBAL_REAL(Master, /datum/controller/master) = new // List of subsystems to process(). var/list/subsystems - /// List of subsystems to include in the MC stat panel. - var/list/statworthy_subsystems // Vars for keeping track of tick drift. var/init_timeofday @@ -41,7 +39,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new ///Only run ticker subsystems for the next n ticks. var/skip_ticks = 0 - var/make_runtime = 0 + var/make_runtime = FALSE var/initializations_finished_with_no_players_logged_in //I wonder what this could be? @@ -67,9 +65,6 @@ GLOBAL_REAL(Master, /datum/controller/master) = new //used by CHECK_TICK as well so that the procs subsystems call can obey that SS's tick limits var/static/current_ticklimit = TICK_LIMIT_RUNNING - /// Statclick for misc subsystems - var/obj/effect/statclick/misc_subsystems/misc_statclick - /datum/controller/master/New() if(!config) config = new @@ -96,11 +91,6 @@ GLOBAL_REAL(Master, /datum/controller/master) = new _subsystems += new I Master = src - // We want to see all subsystems during init. - statworthy_subsystems = subsystems.Copy() - - misc_statclick = new(null, "Debug") - if(!GLOB) new /datum/controller/global_vars @@ -217,7 +207,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new // Sort subsystems by display setting for easy access. sortTim(subsystems, /proc/cmp_subsystem_display) // Set world options. - world.fps = CONFIG_GET(number/fps) + world.change_fps(CONFIG_GET(number/fps)) var/initialized_tod = REALTIMEOFDAY if(tgs_prime) @@ -271,14 +261,10 @@ GLOBAL_REAL(Master, /datum/controller/master) = new var/list/tickersubsystems = list() var/list/runlevel_sorted_subsystems = list(list()) //ensure we always have at least one runlevel var/timer = world.time - statworthy_subsystems = list() for (var/thing in subsystems) var/datum/controller/subsystem/SS = thing if (SS.flags & SS_NO_FIRE) - if(SS.flags & SS_ALWAYS_SHOW_STAT) - statworthy_subsystems += SS continue - statworthy_subsystems += SS SS.queued_time = 0 SS.queue_next = null SS.queue_prev = null diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm index e49da32557..12798f3863 100644 --- a/code/controllers/subsystem.dm +++ b/code/controllers/subsystem.dm @@ -23,7 +23,7 @@ var/priority = FIRE_PRIORITY_DEFAULT /// [Subsystem Flags][SS_NO_INIT] to control binary behavior. Flags must be set at compile time or before preinit finishes to take full effect. (You can also restart the mc to force them to process again) - var/flags = 0 + var/flags = NONE /// This var is set to TRUE after the subsystem has been initialized. var/initialized = FALSE @@ -114,7 +114,7 @@ //previously, this would have been named 'process()' but that name is used everywhere for different things! //fire() seems more suitable. This is the procedure that gets called every 'wait' deciseconds. //Sleeping in here prevents future fires until returned. -/datum/controller/subsystem/proc/fire(resumed = 0) +/datum/controller/subsystem/proc/fire(resumed = FALSE) flags |= SS_NO_FIRE CRASH("Subsystem [src]([type]) does not fire() but did not set the SS_NO_FIRE flag. Please add the SS_NO_FIRE flag to any subsystem that doesn't fire so it doesn't get added to the processing list and waste cpu.") diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm index f777c967ae..3c58c90452 100644 --- a/code/controllers/subsystem/air.dm +++ b/code/controllers/subsystem/air.dm @@ -241,7 +241,8 @@ SUBSYSTEM_DEF(air) return /datum/controller/subsystem/air/proc/process_turf_equalize(resumed = 0) - return process_turf_equalize_extools(resumed, (Master.current_ticklimit - TICK_USAGE) * 0.01 * world.tick_lag) + if(process_turf_equalize_extools(resumed, (Master.current_ticklimit - TICK_USAGE) * 0.01 * world.tick_lag)) + pause() /* //cache for sanic speed var/fire_count = times_fired @@ -260,7 +261,8 @@ SUBSYSTEM_DEF(air) */ /datum/controller/subsystem/air/proc/process_active_turfs(resumed = 0) - return process_active_turfs_extools(resumed, (Master.current_ticklimit - TICK_USAGE) * 0.01 * world.tick_lag) + if(process_active_turfs_extools(resumed, (Master.current_ticklimit - TICK_USAGE) * 0.01 * world.tick_lag)) + pause() /* //cache for sanic speed var/fire_count = times_fired @@ -278,7 +280,8 @@ SUBSYSTEM_DEF(air) */ /datum/controller/subsystem/air/proc/process_excited_groups(resumed = 0) - return process_excited_groups_extools(resumed, (Master.current_ticklimit - TICK_USAGE) * 0.01 * world.tick_lag) + if(process_excited_groups_extools(resumed, (Master.current_ticklimit - TICK_USAGE) * 0.01 * world.tick_lag)) + pause() /* if (!resumed) src.currentrun = excited_groups.Copy() diff --git a/code/controllers/subsystem/assets.dm b/code/controllers/subsystem/assets.dm index 4f02d32ad0..4b43f98290 100644 --- a/code/controllers/subsystem/assets.dm +++ b/code/controllers/subsystem/assets.dm @@ -11,7 +11,7 @@ SUBSYSTEM_DEF(assets) switch (CONFIG_GET(string/asset_transport)) if ("webroot") newtransporttype = /datum/asset_transport/webroot - + if (newtransporttype == transport.type) return diff --git a/code/controllers/subsystem/atoms.dm b/code/controllers/subsystem/atoms.dm index b9a4785f49..02aad6dec3 100644 --- a/code/controllers/subsystem/atoms.dm +++ b/code/controllers/subsystem/atoms.dm @@ -10,33 +10,37 @@ SUBSYSTEM_DEF(atoms) var/old_initialized - var/list/late_loaders + var/list/late_loaders = list() var/list/BadInitializeCalls = list() + initialized = INITIALIZATION_INSSATOMS + /datum/controller/subsystem/atoms/Initialize(timeofday) GLOB.fire_overlay.appearance_flags = RESET_COLOR - setupGenetics() + setupGenetics() //to set the mutations' sequence + initialized = INITIALIZATION_INNEW_MAPLOAD InitializeAtoms() + initialized = INITIALIZATION_INNEW_REGULAR return ..() /datum/controller/subsystem/atoms/proc/InitializeAtoms(list/atoms) if(initialized == INITIALIZATION_INSSATOMS) return + old_initialized = initialized initialized = INITIALIZATION_INNEW_MAPLOAD - LAZYINITLIST(late_loaders) - var/count var/list/mapload_arg = list(TRUE) + if(atoms) count = atoms.len - for(var/I in atoms) - var/atom/A = I + for(var/I in 1 to count) + var/atom/A = atoms[I] if(!(A.flags_1 & INITIALIZED_1)) - InitAtom(I, mapload_arg) + InitAtom(A, mapload_arg) CHECK_TICK else count = 0 @@ -49,15 +53,16 @@ SUBSYSTEM_DEF(atoms) testing("Initialized [count] atoms") pass(count) - initialized = INITIALIZATION_INNEW_REGULAR + initialized = old_initialized if(late_loaders.len) - for(var/I in late_loaders) - var/atom/A = I + for(var/I in 1 to late_loaders.len) + var/atom/A = late_loaders[I] A.LateInitialize() testing("Late initialized [late_loaders.len] atoms") late_loaders.Cut() +/// Init this specific atom /datum/controller/subsystem/atoms/proc/InitAtom(atom/A, list/arguments) var/the_type = A.type if(QDELING(A)) @@ -150,8 +155,3 @@ SUBSYSTEM_DEF(atoms) var/initlog = InitLog() if(initlog) text2file(initlog, "[GLOB.log_directory]/initialize.log") - -#undef BAD_INIT_QDEL_BEFORE -#undef BAD_INIT_DIDNT_INIT -#undef BAD_INIT_SLEPT -#undef BAD_INIT_NO_HINT diff --git a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm index a343f4c578..84f63cf47d 100644 --- a/code/controllers/subsystem/blackbox.dm +++ b/code/controllers/subsystem/blackbox.dm @@ -115,7 +115,6 @@ SUBSYSTEM_DEF(blackbox) SSdbcore.MassInsert(format_table_name("feedback"), sqlrowlist, ignore_errors = TRUE, delayed = TRUE, special_columns = special_columns) - /datum/controller/subsystem/blackbox/proc/Seal() if(sealed) return FALSE @@ -285,6 +284,18 @@ Versioning /datum/feedback_variable/New(new_key, new_key_type) key = new_key key_type = new_key_type +/* +/datum/controller/subsystem/blackbox/proc/LogAhelp(ticket, action, message, recipient, sender) + if(!SSdbcore.Connect()) + return + + var/datum/db_query/query_log_ahelp = SSdbcore.NewQuery({" + INSERT INTO [format_table_name("ticket")] (ticket, action, message, recipient, sender, server_ip, server_port, round_id, timestamp) + VALUES (:ticket, :action, :message, :recipient, :sender, INET_ATON(:server_ip), :server_port, :round_id, :time) + "}, list("ticket" = ticket, "action" = action, "message" = message, "recipient" = recipient, "sender" = sender, "server_ip" = world.internet_address || "0", "server_port" = world.port, "round_id" = GLOB.round_id, "time" = SQLtime())) + query_log_ahelp.Execute() + qdel(query_log_ahelp) +*/ /datum/controller/subsystem/blackbox/proc/LogAhelp(ticket, action, message, recipient, sender) if(!SSdbcore.Connect()) diff --git a/code/controllers/subsystem/chat.dm b/code/controllers/subsystem/chat.dm index f2e9da704f..0e4f8ecad2 100644 --- a/code/controllers/subsystem/chat.dm +++ b/code/controllers/subsystem/chat.dm @@ -1,4 +1,4 @@ -/** +/*! * Copyright (c) 2020 Aleksej Komarov * SPDX-License-Identifier: MIT */ diff --git a/code/controllers/subsystem/dbcore.dm b/code/controllers/subsystem/dbcore.dm index b6b750fbf4..c298460b2c 100644 --- a/code/controllers/subsystem/dbcore.dm +++ b/code/controllers/subsystem/dbcore.dm @@ -202,6 +202,25 @@ SUBSYSTEM_DEF(dbcore) +/datum/controller/subsystem/dbcore/proc/QuerySelect(list/querys, warn = FALSE, qdel = FALSE) + if (!islist(querys)) + if (!istype(querys, /datum/DBQuery)) + CRASH("Invalid query passed to QuerySelect: [querys]") + querys = list(querys) + + for (var/thing in querys) + var/datum/DBQuery/query = thing + if (warn) + INVOKE_ASYNC(query, /datum/DBQuery.proc/warn_execute) + else + INVOKE_ASYNC(query, /datum/DBQuery.proc/Execute) + + for (var/thing in querys) + var/datum/DBQuery/query = thing + UNTIL(!query.in_progress) + if (qdel) + qdel(query) + /* Takes a list of rows (each row being an associated list of column => value) and inserts them via a single mass query. Rows missing columns present in other rows will resolve to SQL NULL diff --git a/code/controllers/subsystem/events.dm b/code/controllers/subsystem/events.dm index 9bc8a631c1..3660770596 100644 --- a/code/controllers/subsystem/events.dm +++ b/code/controllers/subsystem/events.dm @@ -25,7 +25,7 @@ SUBSYSTEM_DEF(events) return ..() -/datum/controller/subsystem/events/fire(resumed = 0) +/datum/controller/subsystem/events/fire(resumed = FALSE) if(!resumed) checkEvent() //only check these if we aren't resuming a paused fire src.currentrun = running.Copy() @@ -37,7 +37,7 @@ SUBSYSTEM_DEF(events) var/datum/thing = currentrun[currentrun.len] currentrun.len-- if(thing) - thing.process() + thing.process(wait * 0.1) else running.Remove(thing) if (MC_TICK_CHECK) @@ -91,13 +91,13 @@ SUBSYSTEM_DEF(events) if(. == EVENT_CANT_RUN)//we couldn't run this event for some reason, set its max_occurrences to 0 E.max_occurrences = 0 else if(. == EVENT_READY) - E.random = TRUE - E.runEvent(TRUE) + E.runEvent(random = TRUE) //allows a client to trigger an event //aka Badmin Central // > Not in modules/admin // REEEEEEEEE +// Why the heck is this here! Took me so damn long to find! /client/proc/forceEvent() set name = "Trigger Event" set category = "Admin.Events" diff --git a/code/controllers/subsystem/fire_burning.dm b/code/controllers/subsystem/fire_burning.dm index 3251285ade..f81c23d186 100644 --- a/code/controllers/subsystem/fire_burning.dm +++ b/code/controllers/subsystem/fire_burning.dm @@ -18,6 +18,7 @@ SUBSYSTEM_DEF(fire_burning) //cache for sanic speed (lists are references anyways) var/list/currentrun = src.currentrun + var/delta_time = wait * 0.1 while(currentrun.len) var/obj/O = currentrun[currentrun.len] @@ -28,10 +29,12 @@ SUBSYSTEM_DEF(fire_burning) return continue - if(O.resistance_flags & ON_FIRE) - O.take_damage(20, BURN, "fire", 0) - else - processing -= O + + if(O.resistance_flags & ON_FIRE) //in case an object is extinguished while still in currentrun + if(!(O.resistance_flags & FIRE_PROOF)) + O.take_damage(10 * delta_time, BURN, "fire", 0) + else + O.extinguish() if (MC_TICK_CHECK) return diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index 51d56545b6..2d2fac1d13 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -1,3 +1,26 @@ +/*! +## Debugging GC issues + +In order to debug `qdel()` failures, there are several tools available. +To enable these tools, define `TESTING` in [_compile_options.dm](https://github.com/tgstation/-tg-station/blob/master/code/_compile_options.dm). + +First is a verb called "Find References", which lists **every** refererence to an object in the world. This allows you to track down any indirect or obfuscated references that you might have missed. + +Complementing this is another verb, "qdel() then Find References". +This does exactly what you'd expect; it calls `qdel()` on the object and then it finds all references remaining. +This is great, because it means that `Destroy()` will have been called before it starts to find references, +so the only references you'll find will be the ones preventing the object from `qdel()`ing gracefully. + +If you have a datum or something you are not destroying directly (say via the singulo), +the next tool is `QDEL_HINT_FINDREFERENCE`. You can return this in `Destroy()` (where you would normally `return ..()`), +to print a list of references once it enters the GC queue. + +Finally is a verb, "Show qdel() Log", which shows the deletion log that the garbage subsystem keeps. This is helpful if you are having race conditions or need to review the order of deletions. + +Note that for any of these tools to work `TESTING` must be defined. +By using these methods of finding references, you can make your life far, far easier when dealing with `qdel()` failures. +*/ + SUBSYSTEM_DEF(garbage) name = "Garbage" priority = FIRE_PRIORITY_GARBAGE @@ -6,7 +29,7 @@ SUBSYSTEM_DEF(garbage) runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY init_order = INIT_ORDER_GARBAGE - var/list/collection_timeout = list(15 SECONDS, 30 SECONDS) // deciseconds to wait before moving something up in the queue to the next level + var/list/collection_timeout = list(2 MINUTES, 10 SECONDS) // deciseconds to wait before moving something up in the queue to the next level //Stat tracking var/delslasttick = 0 // number of del()'s we've done this tick @@ -24,10 +47,8 @@ SUBSYSTEM_DEF(garbage) //Queue var/list/queues - #ifdef LEGACY_REFERENCE_TRACKING var/list/reference_find_on_fail = list() - var/list/reference_find_on_fail_types = list() #endif @@ -99,6 +120,9 @@ SUBSYSTEM_DEF(garbage) state = SS_RUNNING break + + + /datum/controller/subsystem/garbage/proc/HandleQueue(level = GC_QUEUE_CHECK) if (level == GC_QUEUE_CHECK) delslasttick = 0 @@ -115,18 +139,22 @@ SUBSYSTEM_DEF(garbage) lastlevel = level - for (var/refID in queue) - if (!refID) + //We do this rather then for(var/refID in queue) because that sort of for loop copies the whole list. + //Normally this isn't expensive, but the gc queue can grow to 40k items, and that gets costly/causes overrun. + for (var/i in 1 to length(queue)) + var/list/L = queue[i] + if (length(L) < 2) count++ if (MC_TICK_CHECK) return continue - var/GCd_at_time = queue[refID] + var/GCd_at_time = L[1] if(GCd_at_time > cut_off_time) break // Everything else is newer, skip them count++ + var/refID = L[2] var/datum/D D = locate(refID) @@ -135,7 +163,7 @@ SUBSYSTEM_DEF(garbage) ++totalgcs pass_counts[level]++ #ifdef LEGACY_REFERENCE_TRACKING - reference_find_on_fail -= refID //It's deleted we don't care anymore. + reference_find_on_fail -= refID //It's deleted we don't care anymore. #endif if (MC_TICK_CHECK) return @@ -149,10 +177,10 @@ SUBSYSTEM_DEF(garbage) D.find_references() #elif defined(LEGACY_REFERENCE_TRACKING) if(reference_find_on_fail[refID]) - D.find_references() + D.find_references_legacy() #ifdef GC_FAILURE_HARD_LOOKUP else - D.find_references() + D.find_references_legacy() #endif reference_find_on_fail -= refID #endif @@ -186,27 +214,6 @@ SUBSYSTEM_DEF(garbage) queue.Cut(1,count+1) count = 0 -/datum/controller/subsystem/garbage/proc/Queue(datum/D, level = GC_QUEUE_CHECK) - if (isnull(D)) - return - if (level > GC_QUEUE_COUNT) - HardDelete(D) - return - var/gctime = world.time - var/refid = "\ref[D]" - -#ifdef LEGACY_REFERENCE_TRACKING - if(reference_find_on_fail_types[D.type]) - reference_find_on_fail["\ref[D]"] = TRUE -#endif - - D.gc_destroyed = gctime - var/list/queue = queues[level] - if (queue[refid]) - queue -= refid // Removing any previous references that were GC'd so that the current object will be at the end of the list. - - queue[refid] = gctime - #ifdef LEGACY_REFERENCE_TRACKING /datum/controller/subsystem/garbage/proc/add_type_to_findref(type) if(!ispath(type)) @@ -222,6 +229,24 @@ SUBSYSTEM_DEF(garbage) reference_find_on_fail_types = list() #endif +/datum/controller/subsystem/garbage/proc/Queue(datum/D, level = GC_QUEUE_CHECK) + if (isnull(D)) + return + if (level > GC_QUEUE_COUNT) + HardDelete(D) + return + var/gctime = world.time + var/refid = "\ref[D]" + +#ifdef LEGACY_REFERENCE_TRACKING + if(reference_find_on_fail_types[D.type]) + SSgarbage.reference_find_on_fail[REF(D)] = TRUE +#endif + + D.gc_destroyed = gctime + var/list/queue = queues[level] + queue[++queue.len] = list(gctime, refid) // not += for byond reasons + //this is mainly to separate things profile wise. /datum/controller/subsystem/garbage/proc/HardDelete(datum/D) var/time = world.timeofday @@ -274,8 +299,10 @@ SUBSYSTEM_DEF(garbage) /datum/qdel_item/New(mytype) name = "[mytype]" -// Should be treated as a replacement for the 'del' keyword. -// Datums passed to this will be given a chance to clean up references to allow the GC to collect them. + +/// Should be treated as a replacement for the 'del' keyword. +/// +/// Datums passed to this will be given a chance to clean up references to allow the GC to collect them. /proc/qdel(datum/D, force=FALSE, ...) if(!istype(D)) del(D) @@ -330,9 +357,10 @@ SUBSYSTEM_DEF(garbage) #ifdef LEGACY_REFERENCE_TRACKING if (QDEL_HINT_FINDREFERENCE) //qdel will, if LEGACY_REFERENCE_TRACKING is enabled, display all references to this object, then queue the object for deletion. SSgarbage.Queue(D) + D.find_references_legacy() if (QDEL_HINT_IFFAIL_FINDREFERENCE) SSgarbage.Queue(D) - SSgarbage.reference_find_on_fail["\ref[D]"] = TRUE + SSgarbage.reference_find_on_fail[REF(D)] = TRUE #endif else #ifdef TESTING diff --git a/code/controllers/subsystem/idlenpcpool.dm b/code/controllers/subsystem/idlenpcpool.dm index 03b7931d82..ccdaa555a2 100644 --- a/code/controllers/subsystem/idlenpcpool.dm +++ b/code/controllers/subsystem/idlenpcpool.dm @@ -33,8 +33,9 @@ SUBSYSTEM_DEF(idlenpcpool) while(currentrun.len) var/mob/living/simple_animal/SA = currentrun[currentrun.len] --currentrun.len - if (!SA) + if (QDELETED(SA)) GLOB.simple_animals[AI_IDLE] -= SA + log_world("Found a null in simple_animals list!") continue if(!SA.ckey) diff --git a/code/controllers/subsystem/ipintel.dm b/code/controllers/subsystem/ipintel.dm index fca394924d..fb0ddead09 100644 --- a/code/controllers/subsystem/ipintel.dm +++ b/code/controllers/subsystem/ipintel.dm @@ -2,13 +2,13 @@ SUBSYSTEM_DEF(ipintel) name = "XKeyScore" init_order = INIT_ORDER_XKEYSCORE flags = SS_NO_FIRE - var/enabled = 0 //disable at round start to avoid checking reconnects + var/enabled = FALSE //disable at round start to avoid checking reconnects var/throttle = 0 var/errors = 0 var/list/cache = list() /datum/controller/subsystem/ipintel/Initialize(timeofday, zlevel) - enabled = 1 + enabled = TRUE . = ..() diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index 4963e33cc3..779ee2fbac 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -698,6 +698,8 @@ SUBSYSTEM_DEF(job) if(polychromic && istype(polychromic)) var/list/polychromic_entry = polychromic.colors_by_atom[I] if(polychromic_entry) + if(polychromic.suits_with_helmet_typecache[I.type]) //is this one of those toggleable hood/helmet things? + polychromic.connect_helmet(I,i[LOADOUT_COLOR]) polychromic.colors_by_atom[I] = i[LOADOUT_COLOR] I.update_icon() else diff --git a/code/controllers/subsystem/jukeboxes.dm b/code/controllers/subsystem/jukeboxes.dm index 3ebeaf71ea..7be6d44a7f 100644 --- a/code/controllers/subsystem/jukeboxes.dm +++ b/code/controllers/subsystem/jukeboxes.dm @@ -94,8 +94,8 @@ SUBSYSTEM_DEF(jukeboxes) stack_trace("Nonexistant or invalid object associated with jukebox.") continue var/sound/song_played = sound(juketrack.song_path) - var/area/currentarea = get_area(jukebox) var/turf/currentturf = get_turf(jukebox) + var/area/currentarea = get_area(jukebox) var/list/hearerscache = hearers(7, jukebox) song_played.falloff = jukeinfo[4] @@ -116,7 +116,6 @@ SUBSYSTEM_DEF(jukeboxes) inrange = TRUE else song_played.status = SOUND_MUTE | SOUND_UPDATE //Setting volume = 0 doesn't let the sound properties update at all, which is lame. - M.playsound_local(currentturf, null, 100, channel = jukeinfo[2], S = song_played, envwet = (inrange ? -250 : 0), envdry = (inrange ? 0 : -10000)) CHECK_TICK return diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm index e193c68536..19345f3c8d 100644 --- a/code/controllers/subsystem/lighting.dm +++ b/code/controllers/subsystem/lighting.dm @@ -6,6 +6,7 @@ SUBSYSTEM_DEF(lighting) name = "Lighting" wait = 2 init_order = INIT_ORDER_LIGHTING + flags = SS_TICKER /datum/controller/subsystem/lighting/stat_entry(msg) msg = "L:[length(GLOB.lighting_update_lights)]|C:[length(GLOB.lighting_update_corners)]|O:[length(GLOB.lighting_update_objects)]" diff --git a/code/controllers/subsystem/machines.dm b/code/controllers/subsystem/machines.dm index f356009569..23190574d8 100644 --- a/code/controllers/subsystem/machines.dm +++ b/code/controllers/subsystem/machines.dm @@ -2,6 +2,7 @@ SUBSYSTEM_DEF(machines) name = "Machines" init_order = INIT_ORDER_MACHINES flags = SS_KEEP_TIMING + wait = 2 SECONDS var/list/processing = list() var/list/currentrun = list() var/list/powernets = list() @@ -27,7 +28,7 @@ SUBSYSTEM_DEF(machines) return ..() -/datum/controller/subsystem/machines/fire(resumed = 0) +/datum/controller/subsystem/machines/fire(resumed = FALSE) if (!resumed) for(var/datum/powernet/Powernet in powernets) Powernet.reset() //reset the power state. @@ -36,11 +37,10 @@ SUBSYSTEM_DEF(machines) //cache for sanic speed (lists are references anyways) var/list/currentrun = src.currentrun - var/seconds = wait * 0.1 while(currentrun.len) var/obj/machinery/thing = currentrun[currentrun.len] currentrun.len-- - if(!QDELETED(thing) && thing.process(seconds) != PROCESS_KILL) + if(!QDELETED(thing) && thing.process(wait * 0.1) != PROCESS_KILL) if(thing.use_power) thing.auto_use_power() //add back the power state else diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index 36347c9a43..b5dfec3c44 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -41,6 +41,8 @@ SUBSYSTEM_DEF(mapping) var/datum/space_level/transit var/datum/space_level/empty_space var/num_of_res_levels = 1 + /// Lookup for zlevel to station z. text = num. + var/list/z_to_station_z_index var/stat_map_name = "Loading..." @@ -259,6 +261,16 @@ SUBSYSTEM_DEF(mapping) INIT_ANNOUNCE("Loaded [name] in [(REALTIMEOFDAY - start_time)/10]s!") return parsed_maps +/datum/controller/subsystem/mapping/proc/setup_station_z_index() + z_to_station_z_index = list() + var/sz = 1 + var/cz = station_start + if(islist(config.map_file)) + for(var/map in config.map_file) + z_to_station_z_index["[cz++]"] = sz++ + else + z_to_station_z_index["[station_start]"] = 1 + /datum/controller/subsystem/mapping/proc/loadWorld() //if any of these fail, something has gone horribly, HORRIBLY, wrong var/list/FailedZs = list() @@ -271,6 +283,8 @@ SUBSYSTEM_DEF(mapping) INIT_ANNOUNCE("Loading [config.map_name]...") LoadGroup(FailedZs, "Station", config.map_path, config.map_file, config.traits, ZTRAITS_STATION, FALSE, config.orientation) + setup_station_z_index() + if(SSdbcore.Connect()) var/datum/db_query/query_round_map_name = SSdbcore.NewQuery({" UPDATE [format_table_name("round")] SET map_name = :map_name WHERE id = :round_id diff --git a/code/controllers/subsystem/minimum_spawns.dm b/code/controllers/subsystem/minimum_spawns.dm index caab2b1949..b9d19b6cd2 100644 --- a/code/controllers/subsystem/minimum_spawns.dm +++ b/code/controllers/subsystem/minimum_spawns.dm @@ -1,7 +1,7 @@ SUBSYSTEM_DEF(min_spawns) name = "Minimum Spawns" /// this hot steaming pile of garbage makes sure theres a minimum of tendrils scattered around init_order = INIT_ORDER_DEFAULT - flags = SS_BACKGROUND | SS_NO_FIRE | SS_ALWAYS_SHOW_STAT + flags = SS_BACKGROUND | SS_NO_FIRE wait = 2 var/where_we_droppin_boys_iterations = 0 var/snaxi_snowflake_check = FALSE @@ -71,7 +71,7 @@ GLOBAL_LIST_INIT(minimum_snow_under_spawns, list( continue if(typesof(/turf/open/lava) in orange(9, TT)) continue - valid_mining_turfs_2.Add(TT) + valid_mining_turfs_2.Add(TT) else for(var/z_level in SSmapping.levels_by_trait(ZTRAIT_LAVA_RUINS)) for(var/turf/TT in Z_TURFS(z_level)) @@ -103,14 +103,14 @@ GLOBAL_LIST_INIT(minimum_snow_under_spawns, list( for(var/mob/living/simple_animal/hostile/megafauna/H in urange(70,RT)) //prevents mob clumps if((istype(MS_tospawn, /mob/living/simple_animal/hostile/megafauna)) && get_dist(RT, H) <= 70) active_spawns.Add(MS_tospawn) - continue //let's try not to dump megas too close to each other? + continue //let's try not to dump megas too close to each other? if((istype(MS_tospawn, /obj/structure/spawner)) && get_dist(RT, H) <= 40) active_spawns.Add(MS_tospawn) continue //let's at least /try/ to space these out? for(var/obj/structure/spawner/LT in urange(70,RT)) //prevents tendril/mega clumps if((istype(MS_tospawn, /mob/living/simple_animal/hostile/megafauna)) && get_dist(RT, LT) <= 70) active_spawns.Add(MS_tospawn) - continue //let's try not to dump megas too close to each other? + continue //let's try not to dump megas too close to each other? if((istype(MS_tospawn, /obj/structure/spawner)) && get_dist(RT, LT) <= 40) active_spawns.Add(MS_tospawn) continue //let's at least /try/ to space these out? @@ -127,7 +127,7 @@ GLOBAL_LIST_INIT(minimum_snow_under_spawns, list( for(var/mob/living/simple_animal/hostile/H in urange(70,RT2)) //prevents mob clumps if((istype(MS2_tospawn, /mob/living/simple_animal/hostile/megafauna) || ismegafauna(H)) && get_dist(RT2, H) <= 70) active_spawns_2.Add(MS2_tospawn) - continue //let's try not to dump megas too close to each other? + continue //let's try not to dump megas too close to each other? if((istype(MS2_tospawn, /obj/structure/spawner)) && get_dist(RT2, H) <= 40) active_spawns_2.Add(MS2_tospawn) continue //let's at least /try/ to space these out? diff --git a/code/controllers/subsystem/minor_mapping.dm b/code/controllers/subsystem/minor_mapping.dm index bd950e453e..d6cbf99f97 100644 --- a/code/controllers/subsystem/minor_mapping.dm +++ b/code/controllers/subsystem/minor_mapping.dm @@ -1,3 +1,5 @@ +#define PROB_MOUSE_SPAWN 98 + SUBSYSTEM_DEF(minor_mapping) name = "Minor Mapping" init_order = INIT_ORDER_MINOR_MAPPING @@ -5,29 +7,43 @@ SUBSYSTEM_DEF(minor_mapping) /datum/controller/subsystem/minor_mapping/Initialize(timeofday) trigger_migration(CONFIG_GET(number/mice_roundstart)) + // place_satchels() return ..() /datum/controller/subsystem/minor_mapping/proc/trigger_migration(num_mice=10) var/list/exposed_wires = find_exposed_wires() - var/mob/living/simple_animal/mouse/M + var/mob/living/simple_animal/mouse/mouse var/turf/proposed_turf while((num_mice > 0) && exposed_wires.len) proposed_turf = pick_n_take(exposed_wires) - if(!M) - M = new(proposed_turf) - else - M.forceMove(proposed_turf) - if(M.environment_is_safe()) - num_mice -= 1 - M = null + if(prob(PROB_MOUSE_SPAWN)) + if(!mouse) + mouse = new(proposed_turf) + else + mouse.forceMove(proposed_turf) + // else + // mouse = new /mob/living/simple_animal/hostile/regalrat/controlled(proposed_turf) + if(mouse.environment_is_safe()) + num_mice -= 1 + mouse = null + +// /datum/controller/subsystem/minor_mapping/proc/place_satchels(amount=10) +// var/list/turfs = find_satchel_suitable_turfs() + +// while(turfs.len && amount > 0) +// var/turf/T = pick_n_take(turfs) +// var/obj/item/storage/backpack/satchel/flat/F = new(T) + +// SEND_SIGNAL(F, COMSIG_OBJ_HIDE, T.intact) +// amount-- /proc/find_exposed_wires() var/list/exposed_wires = list() - exposed_wires.Cut() + var/list/all_turfs - for (var/z in SSmapping.levels_by_trait(ZTRAIT_STATION)) + for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION)) all_turfs += block(locate(1,1,z), locate(world.maxx,world.maxy,z)) for(var/turf/open/floor/plating/T in all_turfs) if(is_blocked_turf(T)) @@ -36,3 +52,15 @@ SUBSYSTEM_DEF(minor_mapping) exposed_wires += T return shuffle(exposed_wires) + +// /proc/find_satchel_suitable_turfs() +// var/list/suitable = list() + +// for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION)) +// for(var/t in block(locate(1,1,z), locate(world.maxx,world.maxy,z))) +// if(isfloorturf(t) && !isplatingturf(t)) +// suitable += t + +// return shuffle(suitable) + +#undef PROB_MOUSE_SPAWN diff --git a/code/controllers/subsystem/overlays.dm b/code/controllers/subsystem/overlays.dm index b42a1e6b7e..74b60783c3 100644 --- a/code/controllers/subsystem/overlays.dm +++ b/code/controllers/subsystem/overlays.dm @@ -48,9 +48,16 @@ SUBSYSTEM_DEF(overlays) for (var/thing in queue) count++ if(thing) - STAT_START_STOPWATCH var/atom/A = thing + if(A.overlays.len >= MAX_ATOM_OVERLAYS) + //Break it real GOOD + stack_trace("Too many overlays on [A.type] - [A.overlays.len], refusing to update and cutting") + A.overlays.Cut() + continue + STAT_START_STOPWATCH COMPILE_OVERLAYS(A) + UNSETEMPTY(A.add_overlays) + UNSETEMPTY(A.remove_overlays) STAT_STOP_STOPWATCH STAT_LOG_ENTRY(stats, A.type) if(mc_check) @@ -117,9 +124,8 @@ SUBSYSTEM_DEF(overlays) #define QUEUE_FOR_COMPILE flags_1 |= OVERLAY_QUEUED_1; SSoverlays.queue += src; /atom/proc/cut_overlays() LAZYINITLIST(remove_overlays) - LAZYINITLIST(add_overlays) remove_overlays = overlays.Copy() - add_overlays.Cut() + add_overlays = null //If not already queued for work and there are overlays to remove if(NOT_QUEUED_ALREADY && remove_overlays.len) @@ -129,7 +135,7 @@ SUBSYSTEM_DEF(overlays) if(!overlays) return overlays = build_appearance_list(overlays) - LAZYINITLIST(add_overlays) //always initialized after this point + LAZYINITLIST(add_overlays) LAZYINITLIST(remove_overlays) var/a_len = add_overlays.len var/r_len = remove_overlays.len @@ -140,8 +146,9 @@ SUBSYSTEM_DEF(overlays) var/fr_len = remove_overlays.len //If not already queued and there is work to be done - if(NOT_QUEUED_ALREADY && (fa_len != a_len || fr_len != r_len)) + if(NOT_QUEUED_ALREADY && (fa_len != a_len || fr_len != r_len )) QUEUE_FOR_COMPILE + UNSETEMPTY(add_overlays) /atom/proc/add_overlay(list/overlays) if(!overlays) diff --git a/code/controllers/subsystem/parallax.dm b/code/controllers/subsystem/parallax.dm index 64299fda38..7096c667e1 100644 --- a/code/controllers/subsystem/parallax.dm +++ b/code/controllers/subsystem/parallax.dm @@ -7,13 +7,21 @@ SUBSYSTEM_DEF(parallax) var/list/currentrun var/planet_x_offset = 128 var/planet_y_offset = 128 + var/random_layer + var/random_parallax_color -/datum/controller/subsystem/parallax/Initialize(timeofday) + +//These are cached per client so needs to be done asap so people joining at roundstart do not miss these. +/datum/controller/subsystem/parallax/PreInit() . = ..() + if(prob(70)) //70% chance to pick a special extra layer + random_layer = pick(/obj/screen/parallax_layer/random/space_gas, /obj/screen/parallax_layer/random/asteroids) + random_parallax_color = pick(COLOR_TEAL, COLOR_GREEN, COLOR_YELLOW, COLOR_CYAN, COLOR_ORANGE, COLOR_PURPLE)//Special color for random_layer1. Has to be done here so everyone sees the same color. [COLOR_SILVER] planet_y_offset = rand(100, 160) planet_x_offset = rand(100, 160) -/datum/controller/subsystem/parallax/fire(resumed = 0) + +/datum/controller/subsystem/parallax/fire(resumed = FALSE) if (!resumed) src.currentrun = GLOB.clients.Copy() @@ -21,24 +29,27 @@ SUBSYSTEM_DEF(parallax) var/list/currentrun = src.currentrun while(length(currentrun)) - var/client/C = currentrun[currentrun.len] + var/client/processing_client = currentrun[currentrun.len] currentrun.len-- - if (!C || !C.eye) + if (QDELETED(processing_client) || !processing_client.eye) if (MC_TICK_CHECK) return continue - var/atom/movable/A = C.eye - if(!istype(A)) - continue - for (A; isloc(A.loc) && !isturf(A.loc); A = A.loc); - if(A != C.movingmob) - if(C.movingmob != null) - C.movingmob.client_mobs_in_contents -= C.mob - UNSETEMPTY(C.movingmob.client_mobs_in_contents) - LAZYINITLIST(A.client_mobs_in_contents) - A.client_mobs_in_contents += C.mob - C.movingmob = A + var/atom/movable/movable_eye = processing_client.eye + if(!istype(movable_eye)) + continue + + for (movable_eye; isloc(movable_eye.loc) && !isturf(movable_eye.loc); movable_eye = movable_eye.loc); + + if(movable_eye == processing_client.movingmob) + if (MC_TICK_CHECK) + return + continue + if(!isnull(processing_client.movingmob)) + LAZYREMOVE(processing_client.movingmob.client_mobs_in_contents, processing_client.mob) + LAZYADD(movable_eye.client_mobs_in_contents, processing_client.mob) + processing_client.movingmob = movable_eye if (MC_TICK_CHECK) return currentrun = null diff --git a/code/controllers/subsystem/pathfinder.dm b/code/controllers/subsystem/pathfinder.dm index 8e1cf946ae..ccbea79306 100644 --- a/code/controllers/subsystem/pathfinder.dm +++ b/code/controllers/subsystem/pathfinder.dm @@ -18,7 +18,7 @@ SUBSYSTEM_DEF(pathfinder) var/free var/list/flow -/datum/flowcache/New(var/n) +/datum/flowcache/New(n) . = ..() lcount = n run = 0 diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence/_persistence.dm similarity index 51% rename from code/controllers/subsystem/persistence.dm rename to code/controllers/subsystem/persistence/_persistence.dm index e39242aac3..e8faf80e5d 100644 --- a/code/controllers/subsystem/persistence.dm +++ b/code/controllers/subsystem/persistence/_persistence.dm @@ -5,18 +5,14 @@ SUBSYSTEM_DEF(persistence) name = "Persistence" init_order = INIT_ORDER_PERSISTENCE flags = SS_NO_FIRE - var/list/satchel_blacklist = list() //this is a typecache - var/list/new_secret_satchels = list() //these are objects - var/list/old_secret_satchels = list() + + /// Marks if the station got horribly destroyed + var/station_was_destroyed = FALSE + /// Marks if persistence save should be disabled + var/station_persistence_save_disabled = FALSE var/list/obj/structure/chisel_message/chisel_messages = list() var/list/saved_messages = list() - var/list/saved_modes = list(1,2,3) - var/list/saved_dynamic_rules = list(list(),list(),list()) - var/list/saved_storytellers = list("foo","bar","baz") - var/list/average_dynamic_threat = 50 - var/list/saved_maps - var/list/saved_trophies = list() var/list/spawned_objects = list() var/list/antag_rep = list() var/list/antag_rep_change = list() @@ -28,62 +24,82 @@ SUBSYSTEM_DEF(persistence) var/list/paintings = list() /datum/controller/subsystem/persistence/Initialize() - LoadSatchels() - LoadPoly() - LoadChiselMessages() - LoadTrophies() - LoadRecentModes() - LoadRecentStorytellers() - LoadRecentRulesets() - LoadRecentMaps() - LoadPhotoPersistence() + LoadServerPersistence() + LoadGamePersistence() + var/map_persistence_path = get_map_persistence_path() + if(map_persistence_path) + LoadMapPersistence() + return ..() + +/** + * Gets the persistence path of the current map. + */ +/datum/controller/subsystem/persistence/proc/get_map_persistence_path() + ASSERT(SSmapping.config) + if(!SSmapping.config.persistence_key || (SSmapping.config.persistence_key == "NO_PERSIST")) + return null + return "data/persistence/[ckey(SSmapping.config.persistence_key)]" + +/datum/controller/subsystem/persistence/proc/CollectData() + SaveServerPersistence() + if(station_persistence_save_disabled) + return + SaveGamePersistence() + var/map_persistence_path = get_map_persistence_path() + if(map_persistence_path) + SaveMapPersistence() + +/** + * Loads persistent data relevant to the server: Configurations, past gamemodes, votes, antag rep, etc + */ +/datum/controller/subsystem/persistence/proc/LoadServerPersistence() for(var/client/C in GLOB.clients) LoadSavedVote(C.ckey) if(CONFIG_GET(flag/use_antag_rep)) LoadAntagReputation() LoadRandomizedRecipes() - LoadPanicBunker() - return ..() + LoadPaintings() -/datum/controller/subsystem/persistence/proc/LoadSatchels() - var/placed_satchel = 0 - var/path +/** + * Saves persistent data relevant to the server: Configurations, past gamemodes, votes, antag rep, etc + */ +/datum/controller/subsystem/persistence/proc/SaveServerPersistence() + if(CONFIG_GET(flag/use_antag_rep)) + CollectAntagReputation() + SaveRandomizedRecipes() - var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json") - var/list/json = list() - if(fexists(json_file)) - json = json_decode(file2text(json_file)) +/** + * Loads persistent data relevant to the game in general: Photos, etc + * + * Legacy map persistence systems also use this. + */ +/datum/controller/subsystem/persistence/proc/LoadGamePersistence() + LoadChiselMessages() + LoadPhotoPersistence() + LoadPaintings() - old_secret_satchels = json["data"] - var/obj/item/storage/backpack/satchel/flat/F - if(old_secret_satchels && old_secret_satchels.len >= 10) //guards against low drop pools assuring that one player cannot reliably find his own gear. - var/pos = rand(1, old_secret_satchels.len) - F = new() - old_secret_satchels.Cut(pos, pos+1 % old_secret_satchels.len) - F.x = old_secret_satchels[pos]["x"] - F.y = old_secret_satchels[pos]["y"] - F.z = SSmapping.station_start - path = text2path(old_secret_satchels[pos]["saved_obj"]) +/** + * Saves persistent data relevant to the game in general: Photos, etc + * + * Legacy map persistence systems also use this. + */ +/datum/controller/subsystem/persistence/proc/SaveGamePersistence() + CollectChiselMessages() + SavePhotoPersistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION. + SavePaintings() + SaveScars() - if(F) - if(isfloorturf(F.loc) && !isplatingturf(F.loc)) - F.hide(1) - if(ispath(path)) - var/spawned_item = new path(F) - spawned_objects[spawned_item] = TRUE - placed_satchel++ - var/free_satchels = 0 - for(var/turf/T in shuffle(block(locate(TRANSITIONEDGE,TRANSITIONEDGE,SSmapping.station_start), locate(world.maxx-TRANSITIONEDGE,world.maxy-TRANSITIONEDGE,SSmapping.station_start)))) //Nontrivially expensive but it's roundstart only - if(isfloorturf(T) && !isplatingturf(T)) - new /obj/item/storage/backpack/satchel/flat/secret(T) - free_satchels++ - if((free_satchels + placed_satchel) == 10) //ten tiles, more than enough to kill anything that moves - break +/** + * Loads persistent data relevant to the current map: Objects, etc. + */ +/datum/controller/subsystem/persistence/proc/LoadMapPersistence() + return -/datum/controller/subsystem/persistence/proc/LoadPoly() - for(var/mob/living/simple_animal/parrot/Poly/P in GLOB.alive_mob_list) - twitterize(P.speech_buffer, "polytalk") - break //Who's been duping the bird?! +/** + * Saves persistent data relevant to the current map: Objects, etc. + */ +/datum/controller/subsystem/persistence/proc/SaveMapPersistence() + return /datum/controller/subsystem/persistence/proc/LoadChiselMessages() var/list/saved_messages = list() @@ -130,63 +146,6 @@ SUBSYSTEM_DEF(persistence) log_world("Loaded [saved_messages.len] engraved messages on map [SSmapping.config.map_name]") -/datum/controller/subsystem/persistence/proc/LoadTrophies() - if(fexists("data/npc_saves/TrophyItems.sav")) //legacy compatability to convert old format to new - var/savefile/S = new /savefile("data/npc_saves/TrophyItems.sav") - var/saved_json - S >> saved_json - if(!saved_json) - return - saved_trophies = json_decode(saved_json) - fdel("data/npc_saves/TrophyItems.sav") - else - var/json_file = file("data/npc_saves/TrophyItems.json") - if(!fexists(json_file)) - return - var/list/json = json_decode(file2text(json_file)) - if(!json) - return - saved_trophies = json["data"] - SetUpTrophies(saved_trophies.Copy()) - -/datum/controller/subsystem/persistence/proc/LoadRecentModes() - var/json_file = file("data/RecentModes.json") - if(!fexists(json_file)) - return - var/list/json = json_decode(file2text(json_file)) - if(!json) - return - saved_modes = json["data"] - -/datum/controller/subsystem/persistence/proc/LoadRecentRulesets() - var/json_file = file("data/RecentRulesets.json") - if(!fexists(json_file)) - return - var/list/json = json_decode(file2text(json_file)) - if(!json) - return - saved_dynamic_rules = json["data"] - -/datum/controller/subsystem/persistence/proc/LoadRecentStorytellers() - var/json_file = file("data/RecentStorytellers.json") - if(!fexists(json_file)) - return - var/list/json = json_decode(file2text(json_file)) - if(!json) - return - saved_storytellers = json["data"] - if(saved_storytellers.len > 3) - average_dynamic_threat = saved_storytellers[4] - saved_storytellers.len = 3 - -/datum/controller/subsystem/persistence/proc/LoadRecentMaps() - var/json_file = file("data/RecentMaps.json") - if(!fexists(json_file)) - return - var/list/json = json_decode(file2text(json_file)) - if(!json) - return - saved_maps = json["maps"] /datum/controller/subsystem/persistence/proc/LoadAntagReputation() var/json = file2text(FILE_ANTAG_REP) @@ -207,59 +166,6 @@ SUBSYSTEM_DEF(persistence) return saved_votes[ckey] = json["data"] -/datum/controller/subsystem/persistence/proc/SetUpTrophies(list/trophy_items) - for(var/A in GLOB.trophy_cases) - var/obj/structure/displaycase/trophy/T = A - if (T.showpiece) - continue - T.added_roundstart = TRUE - - var/trophy_data = pick_n_take(trophy_items) - - if(!islist(trophy_data)) - continue - - var/list/chosen_trophy = trophy_data - - if(!chosen_trophy || isemptylist(chosen_trophy)) //Malformed - continue - - var/path = text2path(chosen_trophy["path"]) //If the item no longer exist, this returns null - if(!path) - continue - - T.showpiece = new /obj/item/showpiece_dummy(T, path) - T.trophy_message = chosen_trophy["message"] - T.placer_key = chosen_trophy["placer_key"] - T.update_icon() - -/datum/controller/subsystem/persistence/proc/CollectData() - CollectChiselMessages() - CollectSecretSatchels() - CollectTrophies() - CollectRoundtype() - if(istype(SSticker.mode, /datum/game_mode/dynamic)) - var/datum/game_mode/dynamic/mode = SSticker.mode - CollectStoryteller(mode) - CollectRulesets(mode) - RecordMaps() - SavePhotoPersistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION. - if(CONFIG_GET(flag/use_antag_rep)) - CollectAntagReputation() - SaveRandomizedRecipes() - SavePanicBunker() - SavePaintings() - SaveScars() - -/datum/controller/subsystem/persistence/proc/LoadPanicBunker() - var/bunker_path = file("data/bunker_passthrough.json") - if(fexists(bunker_path)) - var/list/json = json_decode(file2text(bunker_path)) - GLOB.bunker_passthrough = json["data"] - for(var/ckey in GLOB.bunker_passthrough) - if(daysSince(GLOB.bunker_passthrough[ckey]) >= CONFIG_GET(number/max_bunker_days)) - GLOB.bunker_passthrough -= ckey - /datum/controller/subsystem/persistence/proc/GetPhotoAlbums() var/album_path = file("data/photo_albums.json") if(fexists(album_path)) @@ -329,35 +235,6 @@ SUBSYSTEM_DEF(persistence) WRITE_FILE(frame_path, frame_json) -/datum/controller/subsystem/persistence/proc/CollectSecretSatchels() - satchel_blacklist = typecacheof(list(/obj/item/stack/tile/plasteel, /obj/item/crowbar)) - var/list/satchels_to_add = list() - for(var/A in new_secret_satchels) - var/obj/item/storage/backpack/satchel/flat/F = A - if(QDELETED(F) || F.z != SSmapping.station_start || F.invisibility != INVISIBILITY_MAXIMUM) - continue - var/list/savable_obj = list() - for(var/obj/O in F) - if(is_type_in_typecache(O, satchel_blacklist) || (O.flags_1 & ADMIN_SPAWNED_1)) - continue - if(O.persistence_replacement) - savable_obj += O.persistence_replacement - else - savable_obj += O.type - if(isemptylist(savable_obj)) - continue - var/list/data = list() - data["x"] = F.x - data["y"] = F.y - data["saved_obj"] = pick(savable_obj) - satchels_to_add += list(data) - - var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json") - var/list/file_data = list() - fdel(json_file) - file_data["data"] = old_secret_satchels + satchels_to_add - WRITE_FILE(json_file, json_encode(file_data)) - /datum/controller/subsystem/persistence/proc/CollectChiselMessages() var/json_file = file("data/npc_saves/ChiselMessages[SSmapping.config.map_name].json") @@ -373,84 +250,6 @@ SUBSYSTEM_DEF(persistence) /datum/controller/subsystem/persistence/proc/SaveChiselMessage(obj/structure/chisel_message/M) saved_messages += list(M.pack()) // dm eats one list - -/datum/controller/subsystem/persistence/proc/CollectTrophies() - var/json_file = file("data/npc_saves/TrophyItems.json") - var/list/file_data = list() - file_data["data"] = remove_duplicate_trophies(saved_trophies) - fdel(json_file) - WRITE_FILE(json_file, json_encode(file_data)) - -/datum/controller/subsystem/persistence/proc/SavePanicBunker() - var/json_file = file("data/bunker_passthrough.json") - var/list/file_data = list() - file_data["data"] = GLOB.bunker_passthrough - fdel(json_file) - WRITE_FILE(json_file,json_encode(file_data)) - -/datum/controller/subsystem/persistence/proc/remove_duplicate_trophies(list/trophies) - var/list/ukeys = list() - . = list() - for(var/trophy in trophies) - var/tkey = "[trophy["path"]]-[trophy["message"]]" - if(ukeys[tkey]) - continue - else - . += list(trophy) - ukeys[tkey] = TRUE - -/datum/controller/subsystem/persistence/proc/SaveTrophy(obj/structure/displaycase/trophy/T) - if(!T.added_roundstart && T.showpiece) - var/list/data = list() - data["path"] = T.showpiece.type - data["message"] = T.trophy_message - data["placer_key"] = T.placer_key - saved_trophies += list(data) - -/datum/controller/subsystem/persistence/proc/CollectRoundtype() - saved_modes[3] = saved_modes[2] - saved_modes[2] = saved_modes[1] - saved_modes[1] = SSticker.mode.config_tag - var/json_file = file("data/RecentModes.json") - var/list/file_data = list() - file_data["data"] = saved_modes - fdel(json_file) - WRITE_FILE(json_file, json_encode(file_data)) - -/datum/controller/subsystem/persistence/proc/CollectStoryteller(var/datum/game_mode/dynamic/mode) - saved_storytellers.len = 3 - saved_storytellers[3] = saved_storytellers[2] - saved_storytellers[2] = saved_storytellers[1] - saved_storytellers[1] = mode.storyteller.name - average_dynamic_threat = (mode.max_threat + average_dynamic_threat) / 2 - var/json_file = file("data/RecentStorytellers.json") - var/list/file_data = list() - file_data["data"] = saved_storytellers + average_dynamic_threat - fdel(json_file) - WRITE_FILE(json_file, json_encode(file_data)) - -/datum/controller/subsystem/persistence/proc/CollectRulesets(var/datum/game_mode/dynamic/mode) - saved_dynamic_rules[3] = saved_dynamic_rules[2] - saved_dynamic_rules[2] = saved_dynamic_rules[1] - saved_dynamic_rules[1] = list() - for(var/r in mode.executed_rules) - var/datum/dynamic_ruleset/rule = r - saved_dynamic_rules[1] += rule.config_tag - var/json_file = file("data/RecentRulesets.json") - var/list/file_data = list() - file_data["data"] = saved_dynamic_rules - fdel(json_file) - WRITE_FILE(json_file, json_encode(file_data)) - -/datum/controller/subsystem/persistence/proc/RecordMaps() - saved_maps = saved_maps?.len ? list("[SSmapping.config.map_name]") | saved_maps : list("[SSmapping.config.map_name]") - var/json_file = file("data/RecentMaps.json") - var/list/file_data = list() - file_data["maps"] = saved_maps - fdel(json_file) - WRITE_FILE(json_file, json_encode(file_data)) - - /datum/controller/subsystem/persistence/proc/CollectAntagReputation() var/ANTAG_REP_MAXIMUM = CONFIG_GET(number/antag_rep_maximum) diff --git a/code/controllers/subsystem/persistence/cleanable_debris.dm b/code/controllers/subsystem/persistence/cleanable_debris.dm new file mode 100644 index 0000000000..a0817c460b --- /dev/null +++ b/code/controllers/subsystem/persistence/cleanable_debris.dm @@ -0,0 +1,177 @@ +/** + * Persistence for cleanable debris. + */ +/datum/controller/subsystem/persistence + /// tracks if we already loaded debris. Unlike everything else, this can actually be a major problem if some badmin procs it twice. + var/loaded_debris = FALSE + +/datum/controller/subsystem/persistence/LoadMapPersistence() + . = ..() + if(CONFIG_GET(flag/persistent_debris)) + LoadMapDebris() + +/datum/controller/subsystem/persistence/SaveMapPersistence() + . = ..() + if(CONFIG_GET(flag/persistent_debris)) + SaveMapDebris() + +/datum/controller/subsystem/persistence/proc/LoadMapDebris() + if(CONFIG_GET(flag/persistent_debris_only)) + wipe_existing_debris() + if(!fexists("[get_map_persistence_path()]/debris.json")) + return + if(loaded_debris) + return + loaded_debris = TRUE + var/list/allowed_turf_typecache = typecacheof(/turf/open) - typecacheof(/turf/open/space) + var/list/allowed_z_cache = list() + for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION)) + allowed_z_cache[num2text(z)] = TRUE + var/list/data = json_decode(file2text("[get_map_persistence_path()]/debris.json")) + var/list/z_lookup = list() + var/loaded = 0 + var/list/loaded_by_type = list() + var/nopath = 0 + var/badloc = 0 + var/noturf = 0 + /// reverse it + for(var/z in SSmapping.z_to_station_z_index) + var/sz = SSmapping.z_to_station_z_index[z] + z_lookup[num2text(sz)] = text2num(z) + for(var/z in data) + var/actual_z = z_lookup[z] + var/list/L1 = data[z] + for(var/x in L1) + var/list/L2 = data[z][x] + for(var/y in L2) + var/turf/tile = locate(text2num(x), text2num(y), actual_z) + if(!tile) + noturf++ + continue + var/list/objects = data[z][x][y] + for(var/_L in objects) + var/list/objdata + var/path + if(islist(_L)) + objdata = _L + path = text2path(objdata["__PATH__"]) + else + path = text2path(_L) + objdata = objects[_L] + if(!path) + nopath++ + continue + if(!IsValidDebrisLocation(tile, allowed_turf_typecache, allowed_z_cache, path, TRUE)) + badloc++ + continue + var/obj/effect/decal/cleanable/instantiated = new path(tile) + loaded_by_type[path] += 1 + loaded++ + if(objdata) + instantiated.PersistenceLoad(objdata) + var/list/bytype = list() + for(var/path in loaded_by_type) + bytype += "[path] - [loaded_by_type[path]]" + subsystem_log( + {"Debris loading completed: + Errors: + No path: [nopath] + Invalid location: [badloc] + No turf on map: [noturf] + Total loaded: [loaded] + By type: + [bytype.Join("\n")]"} + ) + +/datum/controller/subsystem/persistence/proc/SaveMapDebris() + if(fexists("[get_map_persistence_path()]/debris.json")) + fdel("[get_map_persistence_path()]/debris.json") + if(CONFIG_GET(flag/persistent_debris_wipe_on_nuke) && station_was_destroyed) + return // local janitor cheers on nukeop team to save some work + var/list/data = list() + var/list/z_lookup = SSmapping.z_to_station_z_index + var/list/debris = RelevantPersistentDebris() + var/obj/effect/decal/cleanable/saving + var/global_max = CONFIG_GET(number/persistent_debris_global_max) + var/type_max = CONFIG_GET(number/persistent_debris_type_max) + var/stored = 0 + var/list/stored_by_type = list() + for(var/i in debris) + saving = i + var/list/serializing = list() + var/path = saving.PersistenceSave(serializing) + if(!path) + continue + if(stored_by_type[path] > type_max) + continue + var/text_z = num2text(z_lookup[num2text(saving.z)]) + var/text_y = num2text(saving.y) + var/text_x = num2text(saving.x) + LAZYINITLIST(data[text_z]) + LAZYINITLIST(data[text_z][text_x]) + LAZYINITLIST(data[text_z][text_x][text_y]) + if(saving.persistence_allow_stacking) + serializing["__PATH__"] = path + data[text_z][text_x][text_y] += list(serializing) + else + data[text_z][text_x][text_y][path] = serializing + stored++ + if(stored > global_max) + var/w = "Persistent debris saving globally aborted due to global max >= [global_max]. Either janitors never do their jobs or something is wrong." + message_admins(w) + subsystem_log(w) + return + stored_by_type[path] = stored_by_type[path]? stored_by_type[path] + 1 : 1 + if(stored_by_type[path] > type_max) + var/w = "Persistent debris saving aborted for type [path] due to type max >= [global_max]. Either janitors never do their jobs or something is wrong." + message_admins(w) + subsystem_log(w) + + var/list/bytype = list() + for(var/path in stored_by_type) + bytype += "[path] - [stored_by_type[path]]" + subsystem_log( + {"Debris saving completed: + Total: [stored] + By type: + [bytype.Join("\n")]"} + ) + WRITE_FILE(file("[get_map_persistence_path()]/debris.json"), json_encode(data)) + +/datum/controller/subsystem/persistence/proc/IsValidDebrisLocation(turf/tile, list/allowed_typecache, list/allowed_zcache, obj/effect/decal/cleanable/type, loading = FALSE) + if(!allowed_typecache[tile.type]) + return FALSE + var/area/A = tile.loc + if(!A.persistent_debris_allowed) + return FALSE + if(!allowed_zcache[num2text(tile.z)]) + return FALSE + if(loading) + if(!initial(type.persistence_allow_stacking)) + var/obj/effect/decal/cleanable/C = locate(type) in tile + if(!QDELETED(C)) + return FALSE + // Saving verifies allow stacking in the save proc. + for(var/obj/structure/window/W in tile) + if(W.fulltile) + return FALSE + return TRUE + +/datum/controller/subsystem/persistence/proc/wipe_existing_debris() + var/list/existing = RelevantPersistentDebris() + QDEL_LIST(existing) + +/datum/controller/subsystem/persistence/proc/RelevantPersistentDebris() + var/list/allowed_turf_typecache = typecacheof(/turf/open) - typecacheof(/turf/open/space) + var/list/allowed_z_cache = list() + for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION)) + allowed_z_cache[num2text(z)] = TRUE + . = list() + for(var/obj/effect/decal/cleanable/C in world) + if(!C.loc || QDELETED(C)) + continue + if(!C.persistent) + continue + if(!IsValidDebrisLocation(C.loc, allowed_turf_typecache, allowed_z_cache, C.type, FALSE)) + continue + . += C diff --git a/code/controllers/subsystem/persistence/panic_bunker.dm b/code/controllers/subsystem/persistence/panic_bunker.dm new file mode 100644 index 0000000000..93ada2835c --- /dev/null +++ b/code/controllers/subsystem/persistence/panic_bunker.dm @@ -0,0 +1,26 @@ +/** + * Persists panic bunker whitelisting for a configured period of time + */ +/datum/controller/subsystem/persistence/LoadServerPersistence() + . = ..() + LoadPanicBunker() + +/datum/controller/subsystem/persistence/SaveServerPersistence() + . = ..() + SavePanicBunker() + +/datum/controller/subsystem/persistence/proc/LoadPanicBunker() + var/bunker_path = file("data/bunker_passthrough.json") + if(fexists(bunker_path)) + var/list/json = json_decode(file2text(bunker_path)) + GLOB.bunker_passthrough = json["data"] + for(var/ckey in GLOB.bunker_passthrough) + if(daysSince(GLOB.bunker_passthrough[ckey]) >= CONFIG_GET(number/max_bunker_days)) + GLOB.bunker_passthrough -= ckey + +/datum/controller/subsystem/persistence/proc/SavePanicBunker() + var/json_file = file("data/bunker_passthrough.json") + var/list/file_data = list() + file_data["data"] = GLOB.bunker_passthrough + fdel(json_file) + WRITE_FILE(json_file,json_encode(file_data)) diff --git a/code/controllers/subsystem/persistence/poly_parrot.dm b/code/controllers/subsystem/persistence/poly_parrot.dm new file mode 100644 index 0000000000..64743e9623 --- /dev/null +++ b/code/controllers/subsystem/persistence/poly_parrot.dm @@ -0,0 +1,11 @@ +/** + * Persists poly messages across rounds + */ +/datum/controller/subsystem/persistence/LoadGamePersistence() + . = ..() + LoadPoly() + +/datum/controller/subsystem/persistence/proc/LoadPoly() + for(var/mob/living/simple_animal/parrot/Poly/P in GLOB.alive_mob_list) + twitterize(P.speech_buffer, "polytalk") + break //Who's been duping the bird?! diff --git a/code/controllers/subsystem/persistence/recent_votes_etc.dm b/code/controllers/subsystem/persistence/recent_votes_etc.dm new file mode 100644 index 0000000000..f1b902d6ab --- /dev/null +++ b/code/controllers/subsystem/persistence/recent_votes_etc.dm @@ -0,0 +1,107 @@ +/** + * Stores recently played gamemodes, maps, etc. + */ +/datum/controller/subsystem/persistence + var/list/saved_modes = list(1,2,3) + var/list/saved_dynamic_rules = list(list(),list(),list()) + var/list/saved_storytellers = list("foo","bar","baz") + var/list/average_dynamic_threat = 50 + var/list/saved_maps + +/datum/controller/subsystem/persistence/SaveServerPersistence() + . = ..() + CollectRoundtype() + if(istype(SSticker.mode, /datum/game_mode/dynamic)) + var/datum/game_mode/dynamic/mode = SSticker.mode + CollectStoryteller(mode) + CollectRulesets(mode) + RecordMaps() + +/datum/controller/subsystem/persistence/LoadServerPersistence() + . = ..() + LoadRecentModes() + LoadRecentStorytellers() + LoadRecentRulesets() + LoadRecentMaps() + +/datum/controller/subsystem/persistence/proc/CollectRoundtype() + saved_modes[3] = saved_modes[2] + saved_modes[2] = saved_modes[1] + saved_modes[1] = SSticker.mode.config_tag + var/json_file = file("data/RecentModes.json") + var/list/file_data = list() + file_data["data"] = saved_modes + fdel(json_file) + WRITE_FILE(json_file, json_encode(file_data)) + +/datum/controller/subsystem/persistence/proc/CollectStoryteller(var/datum/game_mode/dynamic/mode) + saved_storytellers.len = 3 + saved_storytellers[3] = saved_storytellers[2] + saved_storytellers[2] = saved_storytellers[1] + saved_storytellers[1] = mode.storyteller.name + average_dynamic_threat = (mode.max_threat + average_dynamic_threat) / 2 + var/json_file = file("data/RecentStorytellers.json") + var/list/file_data = list() + file_data["data"] = saved_storytellers + average_dynamic_threat + fdel(json_file) + WRITE_FILE(json_file, json_encode(file_data)) + +/datum/controller/subsystem/persistence/proc/CollectRulesets(var/datum/game_mode/dynamic/mode) + saved_dynamic_rules[3] = saved_dynamic_rules[2] + saved_dynamic_rules[2] = saved_dynamic_rules[1] + saved_dynamic_rules[1] = list() + for(var/r in mode.executed_rules) + var/datum/dynamic_ruleset/rule = r + saved_dynamic_rules[1] += rule.config_tag + var/json_file = file("data/RecentRulesets.json") + var/list/file_data = list() + file_data["data"] = saved_dynamic_rules + fdel(json_file) + WRITE_FILE(json_file, json_encode(file_data)) + +/datum/controller/subsystem/persistence/proc/RecordMaps() + saved_maps = saved_maps?.len ? list("[SSmapping.config.map_name]") | saved_maps : list("[SSmapping.config.map_name]") + var/json_file = file("data/RecentMaps.json") + var/list/file_data = list() + file_data["maps"] = saved_maps + fdel(json_file) + WRITE_FILE(json_file, json_encode(file_data)) + +/datum/controller/subsystem/persistence/proc/LoadRecentModes() + var/json_file = file("data/RecentModes.json") + if(!fexists(json_file)) + return + var/list/json = json_decode(file2text(json_file)) + if(!json) + return + saved_modes = json["data"] + +/datum/controller/subsystem/persistence/proc/LoadRecentRulesets() + var/json_file = file("data/RecentRulesets.json") + if(!fexists(json_file)) + return + var/list/json = json_decode(file2text(json_file)) + if(!json) + return + saved_dynamic_rules = json["data"] + +/datum/controller/subsystem/persistence/proc/LoadRecentStorytellers() + var/json_file = file("data/RecentStorytellers.json") + if(!fexists(json_file)) + return + var/list/json = json_decode(file2text(json_file)) + if(!json) + return + saved_storytellers = json["data"] + if(saved_storytellers.len > 3) + average_dynamic_threat = saved_storytellers[4] + saved_storytellers.len = 3 + +/datum/controller/subsystem/persistence/proc/LoadRecentMaps() + var/json_file = file("data/RecentMaps.json") + if(!fexists(json_file)) + return + var/list/json = json_decode(file2text(json_file)) + if(!json) + return + saved_maps = json["maps"] diff --git a/code/controllers/subsystem/persistence/secret_satchels.dm b/code/controllers/subsystem/persistence/secret_satchels.dm new file mode 100644 index 0000000000..fa2a445317 --- /dev/null +++ b/code/controllers/subsystem/persistence/secret_satchels.dm @@ -0,0 +1,79 @@ +/** + * Secret satchel persistence - allows storing of items in underfloor satchels that's loaded later. + */ +/datum/controller/subsystem/persistence + var/list/satchel_blacklist = list() //this is a typecache + var/list/new_secret_satchels = list() //these are objects + var/list/old_secret_satchels = list() + +/datum/controller/subsystem/persistence/LoadGamePersistence() + . = ..() + LoadSatchels() + +/datum/controller/subsystem/persistence/SaveGamePersistence() + . = ..() + CollectSecretSatchels() + +/datum/controller/subsystem/persistence/proc/LoadSatchels() + var/placed_satchel = 0 + var/path + + var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json") + var/list/json = list() + if(fexists(json_file)) + json = json_decode(file2text(json_file)) + + old_secret_satchels = json["data"] + var/obj/item/storage/backpack/satchel/flat/F + if(old_secret_satchels && old_secret_satchels.len >= 10) //guards against low drop pools assuring that one player cannot reliably find his own gear. + var/pos = rand(1, old_secret_satchels.len) + F = new() + old_secret_satchels.Cut(pos, pos+1 % old_secret_satchels.len) + F.x = old_secret_satchels[pos]["x"] + F.y = old_secret_satchels[pos]["y"] + F.z = SSmapping.station_start + path = text2path(old_secret_satchels[pos]["saved_obj"]) + + if(F) + if(isfloorturf(F.loc) && !isplatingturf(F.loc)) + F.hide(1) + if(ispath(path)) + var/spawned_item = new path(F) + spawned_objects[spawned_item] = TRUE + placed_satchel++ + var/free_satchels = 0 + for(var/turf/T in shuffle(block(locate(TRANSITIONEDGE,TRANSITIONEDGE,SSmapping.station_start), locate(world.maxx-TRANSITIONEDGE,world.maxy-TRANSITIONEDGE,SSmapping.station_start)))) //Nontrivially expensive but it's roundstart only + if(isfloorturf(T) && !isplatingturf(T)) + new /obj/item/storage/backpack/satchel/flat/secret(T) + free_satchels++ + if((free_satchels + placed_satchel) == 10) //ten tiles, more than enough to kill anything that moves + break + +/datum/controller/subsystem/persistence/proc/CollectSecretSatchels() + satchel_blacklist = typecacheof(list(/obj/item/stack/tile/plasteel, /obj/item/crowbar)) + var/list/satchels_to_add = list() + for(var/A in new_secret_satchels) + var/obj/item/storage/backpack/satchel/flat/F = A + if(QDELETED(F) || F.z != SSmapping.station_start || F.invisibility != INVISIBILITY_MAXIMUM) + continue + var/list/savable_obj = list() + for(var/obj/O in F) + if(is_type_in_typecache(O, satchel_blacklist) || (O.flags_1 & ADMIN_SPAWNED_1)) + continue + if(O.persistence_replacement) + savable_obj += O.persistence_replacement + else + savable_obj += O.type + if(isemptylist(savable_obj)) + continue + var/list/data = list() + data["x"] = F.x + data["y"] = F.y + data["saved_obj"] = pick(savable_obj) + satchels_to_add += list(data) + + var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json") + var/list/file_data = list() + fdel(json_file) + file_data["data"] = old_secret_satchels + satchels_to_add + WRITE_FILE(json_file, json_encode(file_data)) diff --git a/code/controllers/subsystem/persistence/trophies.dm b/code/controllers/subsystem/persistence/trophies.dm new file mode 100644 index 0000000000..770ca99125 --- /dev/null +++ b/code/controllers/subsystem/persistence/trophies.dm @@ -0,0 +1,84 @@ +/** + * Stores trophies in curator display cases + */ +/datum/controller/subsystem/persistence + var/list/saved_trophies = list() + +/datum/controller/subsystem/persistence/LoadGamePersistence() + . = ..() + LoadTrophies() + +/datum/controller/subsystem/persistence/SaveGamePersistence() + . = ..() + CollectTrophies() + +/datum/controller/subsystem/persistence/proc/LoadTrophies() + if(fexists("data/npc_saves/TrophyItems.sav")) //legacy compatability to convert old format to new + var/savefile/S = new /savefile("data/npc_saves/TrophyItems.sav") + var/saved_json + S >> saved_json + if(!saved_json) + return + saved_trophies = json_decode(saved_json) + fdel("data/npc_saves/TrophyItems.sav") + else + var/json_file = file("data/npc_saves/TrophyItems.json") + if(!fexists(json_file)) + return + var/list/json = json_decode(file2text(json_file)) + if(!json) + return + saved_trophies = json["data"] + SetUpTrophies(saved_trophies.Copy()) + +/datum/controller/subsystem/persistence/proc/SetUpTrophies(list/trophy_items) + for(var/A in GLOB.trophy_cases) + var/obj/structure/displaycase/trophy/T = A + if (T.showpiece) + continue + T.added_roundstart = TRUE + + var/trophy_data = pick_n_take(trophy_items) + + if(!islist(trophy_data)) + continue + + var/list/chosen_trophy = trophy_data + + if(!chosen_trophy || isemptylist(chosen_trophy)) //Malformed + continue + + var/path = text2path(chosen_trophy["path"]) //If the item no longer exist, this returns null + if(!path) + continue + + T.showpiece = new /obj/item/showpiece_dummy(T, path) + T.trophy_message = chosen_trophy["message"] + T.placer_key = chosen_trophy["placer_key"] + T.update_icon() + +/datum/controller/subsystem/persistence/proc/CollectTrophies() + var/json_file = file("data/npc_saves/TrophyItems.json") + var/list/file_data = list() + file_data["data"] = remove_duplicate_trophies(saved_trophies) + fdel(json_file) + WRITE_FILE(json_file, json_encode(file_data)) + +/datum/controller/subsystem/persistence/proc/remove_duplicate_trophies(list/trophies) + var/list/ukeys = list() + . = list() + for(var/trophy in trophies) + var/tkey = "[trophy["path"]]-[trophy["message"]]" + if(ukeys[tkey]) + continue + else + . += list(trophy) + ukeys[tkey] = TRUE + +/datum/controller/subsystem/persistence/proc/SaveTrophy(obj/structure/displaycase/trophy/T) + if(!T.added_roundstart && T.showpiece) + var/list/data = list() + data["path"] = T.showpiece.type + data["message"] = T.trophy_message + data["placer_key"] = T.placer_key + saved_trophies += list(data) diff --git a/code/controllers/subsystem/processing/fastprocess.dm b/code/controllers/subsystem/processing/fastprocess.dm index 9622e02146..1b30ca44c2 100644 --- a/code/controllers/subsystem/processing/fastprocess.dm +++ b/code/controllers/subsystem/processing/fastprocess.dm @@ -1,6 +1,4 @@ -//Fires five times every second. - PROCESSING_SUBSYSTEM_DEF(fastprocess) name = "Fast Processing" - wait = 2 + wait = 0.2 SECONDS stat_tag = "FP" diff --git a/code/controllers/subsystem/processing/nanites.dm b/code/controllers/subsystem/processing/nanites.dm index c34e7f7806..8a55491f5f 100644 --- a/code/controllers/subsystem/processing/nanites.dm +++ b/code/controllers/subsystem/processing/nanites.dm @@ -1,7 +1,7 @@ PROCESSING_SUBSYSTEM_DEF(nanites) name = "Nanites" flags = SS_BACKGROUND|SS_POST_FIRE_TIMING|SS_NO_INIT - wait = 10 + wait = 1 SECONDS var/list/datum/nanite_cloud_backup/cloud_backups = list() var/list/mob/living/nanite_monitored_mobs = list() diff --git a/code/controllers/subsystem/processing/obj.dm b/code/controllers/subsystem/processing/obj.dm index 26021fb267..3566e8a4dc 100644 --- a/code/controllers/subsystem/processing/obj.dm +++ b/code/controllers/subsystem/processing/obj.dm @@ -2,4 +2,4 @@ PROCESSING_SUBSYSTEM_DEF(obj) name = "Objects" priority = FIRE_PRIORITY_OBJ flags = SS_NO_INIT - wait = 20 + wait = 2 SECONDS diff --git a/code/controllers/subsystem/processing/processing.dm b/code/controllers/subsystem/processing/processing.dm index 637b04993d..5cefd3a148 100644 --- a/code/controllers/subsystem/processing/processing.dm +++ b/code/controllers/subsystem/processing/processing.dm @@ -1,10 +1,10 @@ -//Used to process objects. Fires once every second. +//Used to process objects. SUBSYSTEM_DEF(processing) name = "Processing" priority = FIRE_PRIORITY_PROCESS flags = SS_BACKGROUND|SS_POST_FIRE_TIMING|SS_NO_INIT - wait = 10 + wait = 1 SECONDS var/stat_tag = "P" //Used for logging var/list/processing = list() @@ -14,9 +14,10 @@ SUBSYSTEM_DEF(processing) msg = "[stat_tag]:[length(processing)]" return ..() -/datum/controller/subsystem/processing/fire(resumed = 0) +/datum/controller/subsystem/processing/fire(resumed = FALSE) if (!resumed) currentrun = processing.Copy() + var/delta_time = (flags & SS_TICKER)? (wait * world.tick_lag * 0.1) : (wait * 0.1) //cache for sanic speed (lists are references anyways) var/list/current_run = currentrun @@ -25,12 +26,26 @@ SUBSYSTEM_DEF(processing) current_run.len-- if(QDELETED(thing)) processing -= thing - else if(thing.process(wait) == PROCESS_KILL) + else if(thing.process(delta_time) == PROCESS_KILL) // fully stop so that a future START_PROCESSING will work STOP_PROCESSING(src, thing) if (MC_TICK_CHECK) return -/datum/proc/process() - set waitfor = 0 + +/** + * This proc is called on a datum on every "cycle" if it is being processed by a subsystem. The time between each cycle is determined by the subsystem's "wait" setting. + * You can start and stop processing a datum using the START_PROCESSING and STOP_PROCESSING defines. + * + * Since the wait setting of a subsystem can be changed at any time, it is important that any rate-of-change that you implement in this proc is multiplied by the delta_time that is sent as a parameter, + * Additionally, any "prob" you use in this proc should instead use the DT_PROB define to make sure that the final probability per second stays the same even if the subsystem's wait is altered. + * Examples where this must be considered: + * - Implementing a cooldown timer, use `mytimer -= delta_time`, not `mytimer -= 1`. This way, `mytimer` will always have the unit of seconds + * - Damaging a mob, do `L.adjustFireLoss(20 * delta_time)`, not `L.adjustFireLoss(20)`. This way, the damage per second stays constant even if the wait of the subsystem is changed + * - Probability of something happening, do `if(DT_PROB(25, delta_time))`, not `if(prob(25))`. This way, if the subsystem wait is e.g. lowered, there won't be a higher chance of this event happening per second + * + * If you override this do not call parent, as it will return PROCESS_KILL. This is done to prevent objects that dont override process() from staying in the processing list + */ +/datum/proc/process(delta_time) + set waitfor = FALSE return PROCESS_KILL diff --git a/code/controllers/subsystem/processing/quirks.dm b/code/controllers/subsystem/processing/quirks.dm index c57bac5526..74cd53b0ae 100644 --- a/code/controllers/subsystem/processing/quirks.dm +++ b/code/controllers/subsystem/processing/quirks.dm @@ -5,8 +5,8 @@ PROCESSING_SUBSYSTEM_DEF(quirks) name = "Quirks" init_order = INIT_ORDER_QUIRKS flags = SS_BACKGROUND - wait = 10 runlevels = RUNLEVEL_GAME + wait = 1 SECONDS var/list/quirks = list() //Assoc. list of all roundstart quirk datum types; "name" = /path/ var/list/quirk_names_by_path = list() diff --git a/code/controllers/subsystem/profiler.dm b/code/controllers/subsystem/profiler.dm index 81fa77dc6c..7533e9663f 100644 --- a/code/controllers/subsystem/profiler.dm +++ b/code/controllers/subsystem/profiler.dm @@ -18,7 +18,7 @@ SUBSYSTEM_DEF(profiler) if(CONFIG_GET(flag/auto_profile)) StartProfiling() else - StopProfiling() //Stop the early start from world/New + StopProfiling() //Stop the early start profiler return ..() /datum/controller/subsystem/profiler/fire() @@ -31,12 +31,23 @@ SUBSYSTEM_DEF(profiler) return ..() /datum/controller/subsystem/profiler/proc/StartProfiling() +#if DM_BUILD < 1506 + stack_trace("Auto profiling unsupported on this byond version") + CONFIG_SET(flag/auto_profile, FALSE) +#else world.Profile(PROFILE_START) +#endif /datum/controller/subsystem/profiler/proc/StopProfiling() +#if DM_BUILD >= 1506 world.Profile(PROFILE_STOP) +#endif /datum/controller/subsystem/profiler/proc/DumpFile() +#if DM_BUILD < 1506 + stack_trace("Auto profiling unsupported on this byond version") + CONFIG_SET(flag/auto_profile, FALSE) +#else var/timer = TICK_USAGE_REAL var/current_profile_data = world.Profile(PROFILE_REFRESH,format="json") fetch_cost = MC_AVERAGE(fetch_cost, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer)) @@ -49,3 +60,4 @@ SUBSYSTEM_DEF(profiler) timer = TICK_USAGE_REAL WRITE_FILE(json_file, current_profile_data) write_cost = MC_AVERAGE(write_cost, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer)) +#endif diff --git a/code/controllers/subsystem/radiation.dm b/code/controllers/subsystem/radiation.dm index f29fe72e80..2d764d84dd 100644 --- a/code/controllers/subsystem/radiation.dm +++ b/code/controllers/subsystem/radiation.dm @@ -1,6 +1,7 @@ PROCESSING_SUBSYSTEM_DEF(radiation) name = "Radiation" flags = SS_NO_INIT | SS_BACKGROUND + wait = 1 SECONDS var/list/warned_atoms = list() @@ -13,5 +14,5 @@ PROCESSING_SUBSYSTEM_DEF(radiation) warned_atoms[ref] = TRUE var/atom/master = contamination.parent SSblackbox.record_feedback("tally", "contaminated", 1, master.type) - var/msg = "has become contamintaed with enough radiation to contaminate other objects. || Source: [contamination.source] || Strength: [contamination.strength]" + var/msg = "has become contaminated with enough radiation to contaminate other objects. || Source: [contamination.source] || Strength: [contamination.strength]" master.investigate_log(msg, INVESTIGATE_RADIATION) diff --git a/code/controllers/subsystem/runechat.dm b/code/controllers/subsystem/runechat.dm index ec296e7d32..9bd665e5ee 100644 --- a/code/controllers/subsystem/runechat.dm +++ b/code/controllers/subsystem/runechat.dm @@ -6,15 +6,15 @@ #define BUCKET_LIMIT (world.time + TICKS2DS(min(BUCKET_LEN - (SSrunechat.practical_offset - DS2TICKS(world.time - SSrunechat.head_offset)) - 1, BUCKET_LEN - 1))) /** - * # Runechat Subsystem - * - * Maintains a timer-like system to handle destruction of runechat messages. Much of this code is modeled - * after or adapted from the timer subsystem. - * - * Note that this has the same structure for storing and queueing messages as the timer subsystem does - * for handling timers: the bucket_list is a list of chatmessage datums, each of which are the head - * of a circularly linked list. Any given index in bucket_list could be null, representing an empty bucket. - */ + * # Runechat Subsystem + * + * Maintains a timer-like system to handle destruction of runechat messages. Much of this code is modeled + * after or adapted from the timer subsystem. + * + * Note that this has the same structure for storing and queueing messages as the timer subsystem does + * for handling timers: the bucket_list is a list of chatmessage datums, each of which are the head + * of a circularly linked list. Any given index in bucket_list could be null, representing an empty bucket. + */ SUBSYSTEM_DEF(runechat) name = "Runechat" flags = SS_TICKER | SS_NO_INIT @@ -131,14 +131,14 @@ SUBSYSTEM_DEF(runechat) bucket_resolution = world.tick_lag /** - * Enters the runechat subsystem with this chatmessage, inserting it into the end-of-life queue - * - * This will also account for a chatmessage already being registered, and in which case - * the position will be updated to remove it from the previous location if necessary - * - * Arguments: - * * new_sched_destruction Optional, when provided is used to update an existing message with the new specified time - */ + * Enters the runechat subsystem with this chatmessage, inserting it into the end-of-life queue + * + * This will also account for a chatmessage already being registered, and in which case + * the position will be updated to remove it from the previous location if necessary + * + * Arguments: + * * new_sched_destruction Optional, when provided is used to update an existing message with the new specified time + */ /datum/chatmessage/proc/enter_subsystem(new_sched_destruction = 0) // Get local references from subsystem as they are faster to access than the datum references var/list/bucket_list = SSrunechat.bucket_list @@ -169,7 +169,7 @@ SUBSYSTEM_DEF(runechat) // Handle insertion into the secondary queue if the required time is outside our tracked amounts if (scheduled_destruction >= BUCKET_LIMIT) - BINARY_INSERT(src, SSrunechat.second_queue, datum/chatmessage, src, scheduled_destruction, COMPARE_KEY) + BINARY_INSERT(src, SSrunechat.second_queue, /datum/chatmessage, src, scheduled_destruction, COMPARE_KEY) return // Get bucket position and a local reference to the datum var, it's faster to access this way @@ -194,8 +194,8 @@ SUBSYSTEM_DEF(runechat) /** - * Removes this chatmessage datum from the runechat subsystem - */ + * Removes this chatmessage datum from the runechat subsystem + */ /datum/chatmessage/proc/leave_subsystem() // Attempt to find the bucket that contains this chat message var/bucket_pos = BUCKET_POS(scheduled_destruction) diff --git a/code/controllers/subsystem/server_maint.dm b/code/controllers/subsystem/server_maint.dm index 2427fbd277..7eb81003f1 100644 --- a/code/controllers/subsystem/server_maint.dm +++ b/code/controllers/subsystem/server_maint.dm @@ -56,12 +56,13 @@ SUBSYSTEM_DEF(server_maint) for(var/I in currentrun) var/client/C = I //handle kicking inactive players - if(round_started && kick_inactive && C.is_afk(afk_period)) + if(round_started && kick_inactive && !C.holder && C.is_afk(afk_period)) var/cmob = C.mob - if(!(isobserver(cmob) || (isdead(cmob) && C.holder))) + if (!isnewplayer(cmob) || !SSticker.queued_players.Find(cmob)) log_access("AFK: [key_name(C)]") - to_chat(C, "You have been inactive for more than [DisplayTimeText(afk_period)] and have been disconnected.") - qdel(C) + to_chat(C, "You have been inactive for more than [DisplayTimeText(afk_period)] and have been disconnected.
You may reconnect via the button in the file menu or by clicking here to reconnect.") + QDEL_IN(C, 1) //to ensure they get our message before getting disconnected + continue if (!(!C || world.time - C.connection_time < PING_BUFFER_TIME || C.inactivity >= (wait-1))) winset(C, null, "command=.update_ping+[world.time+world.tick_lag*TICK_USAGE_REAL/100]") @@ -83,4 +84,15 @@ SUBSYSTEM_DEF(server_maint) if(tgsversion) SSblackbox.record_feedback("text", "server_tools", 1, tgsversion.raw_parameter) + +/datum/controller/subsystem/server_maint/proc/UpdateHubStatus() + // if(!CONFIG_GET(flag/hub) || !CONFIG_GET(number/max_hub_pop)) + // return FALSE //no point, hub / auto hub controls are disabled + + // var/max_pop = CONFIG_GET(number/max_hub_pop) + + // if(GLOB.clients.len > max_pop) + // world.update_hub_visibility(FALSE) + // else + // world.update_hub_visibility(TRUE) #undef PING_BUFFER_TIME diff --git a/code/controllers/subsystem/sounds.dm b/code/controllers/subsystem/sounds.dm index 5e7c5e6545..fa9ba3c472 100644 --- a/code/controllers/subsystem/sounds.dm +++ b/code/controllers/subsystem/sounds.dm @@ -5,34 +5,48 @@ SUBSYSTEM_DEF(sounds) flags = SS_NO_FIRE init_order = INIT_ORDER_SOUNDS var/static/using_channels_max = CHANNEL_HIGHEST_AVAILABLE //BYOND max channels + /// Amount of channels to reserve for random usage rather than reservations being allowed to reserve all channels. Also a nice safeguard for when someone screws up. + var/static/random_channels_min = 50 // Hey uh these two needs to be initialized fast because the whole "things get deleted before init" thing. - /// Assoc list, "[channel]" = either the datum using it or TRUE for an unsafe-reserved (datumless reservation) channel - var/list/using_channels = list() + /// Assoc list, `"[channel]" =` either the datum using it or TRUE for an unsafe-reserved (datumless reservation) channel + var/list/using_channels /// Assoc list datum = list(channel1, channel2, ...) for what channels something reserved. - var/list/using_channels_by_datum = list() - /// List of all available channels with associations set to TRUE for fast lookups/allocation. - var/list/available_channels + var/list/using_channels_by_datum + // Special datastructure for fast channel management + /// List of all channels as numbers + var/list/channel_list + /// Associative list of all reserved channels associated to their position. `"[channel_number]" =` index as number + var/list/reserved_channels + /// lower iteration position - Incremented and looped to get "random" sound channels for normal sounds. The channel at this index is returned when asking for a random channel. + var/channel_random_low + /// higher reserve position - decremented and incremented to reserve sound channels, anything above this is reserved. The channel at this index is the highest unreserved channel. + var/channel_reserve_high /datum/controller/subsystem/sounds/Initialize() setup_available_channels() return ..() /datum/controller/subsystem/sounds/proc/setup_available_channels() - available_channels = list() + channel_list = list() + reserved_channels = list() + using_channels = list() + using_channels_by_datum = list() for(var/i in 1 to using_channels_max) - available_channels[num2text(i)] = TRUE + channel_list += i + channel_random_low = 1 + channel_reserve_high = length(channel_list) /// Removes a channel from using list. /datum/controller/subsystem/sounds/proc/free_sound_channel(channel) - channel = num2text(channel) - var/using = using_channels[channel] - using_channels -= channel - if(using) + var/text_channel = num2text(channel) + var/using = using_channels[text_channel] + using_channels -= text_channel + if(using != TRUE) // datum channel using_channels_by_datum[using] -= channel if(!length(using_channels_by_datum[using])) using_channels_by_datum -= using - available_channels[channel] = TRUE + free_channel(channel) /// Frees all the channels a datum is using. /datum/controller/subsystem/sounds/proc/free_datum_channels(datum/D) @@ -40,8 +54,8 @@ SUBSYSTEM_DEF(sounds) if(!L) return for(var/channel in L) - using_channels -= channel - available_channels[channel] = TRUE + using_channels -= num2text(channel) + free_channel(channel) using_channels_by_datum -= D /// Frees all datumless channels @@ -50,42 +64,72 @@ SUBSYSTEM_DEF(sounds) /// NO AUTOMATIC CLEANUP - If you use this, you better manually free it later! Returns an integer for channel. /datum/controller/subsystem/sounds/proc/reserve_sound_channel_datumless() - var/channel = random_available_channel_text() - if(!channel) //oh no.. + . = reserve_channel() + if(!.) //oh no.. return FALSE - available_channels -= channel - using_channels[channel] = DATUMLESS + var/text_channel = num2text(.) + using_channels[text_channel] = DATUMLESS LAZYINITLIST(using_channels_by_datum[DATUMLESS]) - using_channels_by_datum[DATUMLESS] += channel - return text2num(channel) + using_channels_by_datum[DATUMLESS] += . /// Reserves a channel for a datum. Automatic cleanup only when the datum is deleted. Returns an integer for channel. /datum/controller/subsystem/sounds/proc/reserve_sound_channel(datum/D) if(!D) //i don't like typechecks but someone will fuck it up CRASH("Attempted to reserve sound channel without datum using the managed proc.") - var/channel = random_available_channel_text() - if(!channel) + .= reserve_channel() + if(!.) return FALSE - available_channels -= channel - using_channels[channel] = D + var/text_channel = num2text(.) + using_channels[text_channel] = D LAZYINITLIST(using_channels_by_datum[D]) - using_channels_by_datum[D] += channel - return text2num(channel) + using_channels_by_datum[D] += . + +/** + * Reserves a channel and updates the datastructure. Private proc. + */ +/datum/controller/subsystem/sounds/proc/reserve_channel() + PRIVATE_PROC(TRUE) + if(channel_reserve_high <= random_channels_min) // out of channels + return + var/channel = channel_list[channel_reserve_high] + reserved_channels[num2text(channel)] = channel_reserve_high-- + return channel + +/** + * Frees a channel and updates the datastructure. Private proc. + */ +/datum/controller/subsystem/sounds/proc/free_channel(number) + PRIVATE_PROC(TRUE) + var/text_channel = num2text(number) + var/index = reserved_channels[text_channel] + if(!index) + CRASH("Attempted to (internally) free a channel that wasn't reserved.") + reserved_channels -= text_channel + // push reserve index up, which makes it now on a channel that is reserved + channel_reserve_high++ + // swap the reserved channel wtih the unreserved channel so the reserve index is now on an unoccupied channel and the freed channel is next to be used. + channel_list.Swap(channel_reserve_high, index) + // now, an existing reserved channel will likely (exception: unreserving last reserved channel) be at index + // get it, and update position. + var/text_reserved = num2text(channel_list[index]) + if(!reserved_channels[text_reserved]) //if it isn't already reserved make sure we don't accidently mistakenly put it on reserved list! + return + reserved_channels[text_reserved] = index /// Random available channel, returns text. /datum/controller/subsystem/sounds/proc/random_available_channel_text() - return pick(available_channels) + if(channel_random_low > channel_reserve_high) + channel_random_low = 1 + . = "[channel_list[channel_random_low++]]" /// Random available channel, returns number /datum/controller/subsystem/sounds/proc/random_available_channel() - return text2num(pick(available_channels)) - -/// If a channel is available -/datum/controller/subsystem/sounds/proc/is_channel_available(channel) - return available_channels[num2text(channel)] + if(channel_random_low > channel_reserve_high) + channel_random_low = 1 + . = channel_list[channel_random_low++] /// How many channels we have left. /datum/controller/subsystem/sounds/proc/available_channels_left() - return length(available_channels) + return length(channel_list) - random_channels_min #undef DATUMLESS diff --git a/code/controllers/subsystem/spacedrift.dm b/code/controllers/subsystem/spacedrift.dm index c3261df304..e84a70a45f 100644 --- a/code/controllers/subsystem/spacedrift.dm +++ b/code/controllers/subsystem/spacedrift.dm @@ -13,7 +13,7 @@ SUBSYSTEM_DEF(spacedrift) return ..() -/datum/controller/subsystem/spacedrift/fire(resumed = 0) +/datum/controller/subsystem/spacedrift/fire(resumed = FALSE) if (!resumed) src.currentrun = processing.Copy() @@ -47,6 +47,7 @@ SUBSYSTEM_DEF(spacedrift) var/old_dir = AM.dir var/old_loc = AM.loc AM.inertia_moving = TRUE + AM.set_glide_size(DELAY_TO_GLIDE_SIZE(AM.inertia_move_delay), FALSE) step(AM, AM.inertia_dir) AM.inertia_moving = FALSE AM.inertia_next_move = world.time + AM.inertia_move_delay diff --git a/code/controllers/subsystem/statpanel.dm b/code/controllers/subsystem/statpanel.dm index 13e9ff50a2..d0d5579611 100644 --- a/code/controllers/subsystem/statpanel.dm +++ b/code/controllers/subsystem/statpanel.dm @@ -203,3 +203,4 @@ SUBSYSTEM_DEF(statpanels) set hidden = TRUE statbrowser_ready = TRUE + init_verbs() diff --git a/code/controllers/subsystem/stickyban.dm b/code/controllers/subsystem/stickyban.dm index 189efa99fe..0c71777bc0 100644 --- a/code/controllers/subsystem/stickyban.dm +++ b/code/controllers/subsystem/stickyban.dm @@ -1,34 +1,231 @@ SUBSYSTEM_DEF(stickyban) - name = "Sticky Ban" + name = "PRISM" init_order = INIT_ORDER_STICKY_BAN flags = SS_NO_FIRE var/list/cache = list() + var/list/dbcache = list() + var/list/confirmed_exempt = list() + var/dbcacheexpire = 0 + /datum/controller/subsystem/stickyban/Initialize(timeofday) - var/list/bannedkeys = world.GetConfig("ban") + if (length(GLOB.stickybanadminexemptions)) + restore_stickybans() + var/list/bannedkeys = sticky_banned_ckeys() //sanitize the sticky ban list + + //delete db bans that no longer exist in the database and add new legacy bans to the database + if (SSdbcore.Connect() || length(SSstickyban.dbcache)) + if (length(GLOB.stickybanadminexemptions)) + restore_stickybans() + for (var/oldban in (world.GetConfig("ban") - bannedkeys)) + var/ckey = ckey(oldban) + if (ckey != oldban && (ckey in bannedkeys)) + continue + + var/list/ban = params2list(world.GetConfig("ban", oldban)) + if (ban && !ban["fromdb"]) + if (!import_raw_stickyban_to_db(ckey, ban)) + log_world("Could not import stickyban on [oldban] into the database. Ignoring") + continue + dbcacheexpire = 0 + bannedkeys += ckey + world.SetConfig("ban", oldban, null) + + if (length(GLOB.stickybanadminexemptions)) //the previous loop can sleep + restore_stickybans() + for (var/bannedkey in bannedkeys) var/ckey = ckey(bannedkey) - var/list/ban = stickyban2list(world.GetConfig("ban", bannedkey)) + var/list/ban = get_stickyban_from_ckey(bannedkey) - //byond stores sticky bans by key, that can end up confusing things - //i also remove it here so that if any stickybans cause a runtime, they just stop existing - world.SetConfig("ban", bannedkey, null) + //byond stores sticky bans by key, that's lame + if (ckey != bannedkey) + world.SetConfig("ban", bannedkey, null) if (!ban["ckey"]) ban["ckey"] = ckey - //storing these can break things and isn't needed for sticky ban tracking - ban -= "IP" - ban -= "computer_id" - ban["matches_this_round"] = list() ban["existing_user_matches_this_round"] = list() ban["admin_matches_this_round"] = list() + ban["pending_matches_this_round"] = list() + cache[ckey] = ban - - for (var/bannedckey in cache) - world.SetConfig("ban", bannedckey, list2stickyban(cache[bannedckey])) + world.SetConfig("ban", ckey, list2stickyban(ban)) return ..() + +/datum/controller/subsystem/stickyban/proc/Populatedbcache() + var/newdbcache = list() //so if we runtime or the db connection dies we don't kill the existing cache + + // var/datum/db_query/query_stickybans = SSdbcore.NewQuery("SELECT ckey, reason, banning_admin, datetime FROM [format_table_name("stickyban")] ORDER BY ckey") + // var/datum/db_query/query_ckey_matches = SSdbcore.NewQuery("SELECT stickyban, matched_ckey, first_matched, last_matched, exempt FROM [format_table_name("stickyban_matched_ckey")] ORDER BY first_matched") + // var/datum/db_query/query_cid_matches = SSdbcore.NewQuery("SELECT stickyban, matched_cid, first_matched, last_matched FROM [format_table_name("stickyban_matched_cid")] ORDER BY first_matched") + // var/datum/db_query/query_ip_matches = SSdbcore.NewQuery("SELECT stickyban, INET_NTOA(matched_ip), first_matched, last_matched FROM [format_table_name("stickyban_matched_ip")] ORDER BY first_matched") + + var/datum/DBQuery/query_stickybans = SSdbcore.NewQuery("SELECT ckey, reason, banning_admin, datetime FROM [format_table_name("stickyban")] ORDER BY ckey") + var/datum/DBQuery/query_ckey_matches = SSdbcore.NewQuery("SELECT stickyban, matched_ckey, first_matched, last_matched, exempt FROM [format_table_name("stickyban_matched_ckey")] ORDER BY first_matched") + var/datum/DBQuery/query_cid_matches = SSdbcore.NewQuery("SELECT stickyban, matched_cid, first_matched, last_matched FROM [format_table_name("stickyban_matched_cid")] ORDER BY first_matched") + var/datum/DBQuery/query_ip_matches = SSdbcore.NewQuery("SELECT stickyban, INET_NTOA(matched_ip), first_matched, last_matched FROM [format_table_name("stickyban_matched_ip")] ORDER BY first_matched") + + SSdbcore.QuerySelect(list(query_stickybans, query_ckey_matches, query_cid_matches, query_ip_matches)) + + if (query_stickybans.last_error) + qdel(query_stickybans) + qdel(query_ckey_matches) + qdel(query_cid_matches) + qdel(query_ip_matches) + return + + while (query_stickybans.NextRow()) + var/list/ban = list() + + ban["ckey"] = query_stickybans.item[1] + ban["message"] = query_stickybans.item[2] + ban["reason"] = "(InGameBan)([query_stickybans.item[3]])" + ban["admin"] = query_stickybans.item[3] + ban["datetime"] = query_stickybans.item[4] + ban["type"] = list("sticky") + + newdbcache["[query_stickybans.item[1]]"] = ban + + + if (!query_ckey_matches.last_error) + while (query_ckey_matches.NextRow()) + var/list/match = list() + + match["stickyban"] = query_ckey_matches.item[1] + match["matched_ckey"] = query_ckey_matches.item[2] + match["first_matched"] = query_ckey_matches.item[3] + match["last_matched"] = query_ckey_matches.item[4] + match["exempt"] = text2num(query_ckey_matches.item[5]) + + var/ban = newdbcache[query_ckey_matches.item[1]] + if (!ban) + continue + var/keys = ban[text2num(query_ckey_matches.item[5]) ? "whitelist" : "keys"] + if (!keys) + keys = ban[text2num(query_ckey_matches.item[5]) ? "whitelist" : "keys"] = list() + keys[query_ckey_matches.item[2]] = match + + if (!query_cid_matches.last_error) + while (query_cid_matches.NextRow()) + var/list/match = list() + + match["stickyban"] = query_cid_matches.item[1] + match["matched_cid"] = query_cid_matches.item[2] + match["first_matched"] = query_cid_matches.item[3] + match["last_matched"] = query_cid_matches.item[4] + + var/ban = newdbcache[query_cid_matches.item[1]] + if (!ban) + continue + var/computer_ids = ban["computer_id"] + if (!computer_ids) + computer_ids = ban["computer_id"] = list() + computer_ids[query_cid_matches.item[2]] = match + + + if (!query_ip_matches.last_error) + while (query_ip_matches.NextRow()) + var/list/match = list() + + match["stickyban"] = query_ip_matches.item[1] + match["matched_ip"] = query_ip_matches.item[2] + match["first_matched"] = query_ip_matches.item[3] + match["last_matched"] = query_ip_matches.item[4] + + var/ban = newdbcache[query_ip_matches.item[1]] + if (!ban) + continue + var/IPs = ban["IP"] + if (!IPs) + IPs = ban["IP"] = list() + IPs[query_ip_matches.item[2]] = match + + dbcache = newdbcache + dbcacheexpire = world.time+STICKYBAN_DB_CACHE_TIME + + qdel(query_stickybans) + qdel(query_ckey_matches) + qdel(query_cid_matches) + qdel(query_ip_matches) + + +/datum/controller/subsystem/stickyban/proc/import_raw_stickyban_to_db(ckey, list/ban) + . = FALSE + if (!ban["admin"]) + ban["admin"] = "LEGACY" + if (!ban["message"]) + ban["message"] = "Evasion" + + // TODO: USE NEW DB IMPLEMENTATION + var/datum/DBQuery/query_create_stickyban = SSdbcore.NewQuery( + "INSERT IGNORE INTO [format_table_name("stickyban")] (ckey, reason, banning_admin) VALUES ([ckey], [ban["message"]], ban["admin"]))" + ) + + if (query_create_stickyban.warn_execute()) + qdel(query_create_stickyban) + return + qdel(query_create_stickyban) + + // var/datum/db_query/query_create_stickyban = SSdbcore.NewQuery( + // "INSERT IGNORE INTO [format_table_name("stickyban")] (ckey, reason, banning_admin) VALUES (:ckey, :message, :admin)", + // list("ckey" = ckey, "message" = ban["message"], "admin" = ban["admin"]) + // ) + // if (!query_create_stickyban.warn_execute()) + // qdel(query_create_stickyban) + // return + // qdel(query_create_stickyban) + + var/list/sqlckeys = list() + var/list/sqlcids = list() + var/list/sqlips = list() + + if (ban["keys"]) + var/list/keys = splittext(ban["keys"], ",") + for (var/key in keys) + var/list/sqlckey = list() + sqlckey["stickyban"] = ckey + sqlckey["matched_ckey"] = ckey(key) + sqlckey["exempt"] = FALSE + sqlckeys[++sqlckeys.len] = sqlckey + + if (ban["whitelist"]) + var/list/keys = splittext(ban["whitelist"], ",") + for (var/key in keys) + var/list/sqlckey = list() + sqlckey["stickyban"] = ckey + sqlckey["matched_ckey"] = ckey(key) + sqlckey["exempt"] = TRUE + sqlckeys[++sqlckeys.len] = sqlckey + + if (ban["computer_id"]) + var/list/cids = splittext(ban["computer_id"], ",") + for (var/cid in cids) + var/list/sqlcid = list() + sqlcid["stickyban"] = ckey + sqlcid["matched_cid"] = cid + sqlcids[++sqlcids.len] = sqlcid + + if (ban["IP"]) + var/list/ips = splittext(ban["IP"], ",") + for (var/ip in ips) + var/list/sqlip = list() + sqlip["stickyban"] = ckey + sqlip["matched_ip"] = ip + sqlips[++sqlips.len] = sqlip + + if (length(sqlckeys)) + SSdbcore.MassInsert(format_table_name("stickyban_matched_ckey"), sqlckeys, ignore_errors = TRUE) + + if (length(sqlcids)) + SSdbcore.MassInsert(format_table_name("stickyban_matched_cid"), sqlcids, ignore_errors = TRUE) + + if (length(sqlips)) + SSdbcore.MassInsert(format_table_name("stickyban_matched_ip"), sqlips, ignore_errors = TRUE) + + + return TRUE diff --git a/code/controllers/subsystem/throwing.dm b/code/controllers/subsystem/throwing.dm index 8c5abc5469..e5d6b0bbd0 100644 --- a/code/controllers/subsystem/throwing.dm +++ b/code/controllers/subsystem/throwing.dm @@ -57,6 +57,7 @@ SUBSYSTEM_DEF(throwing) var/dx var/dy var/force = MOVE_FORCE_DEFAULT + var/gentle = FALSE var/pure_diagonal var/diagonal_error var/datum/callback/callback @@ -64,15 +65,42 @@ SUBSYSTEM_DEF(throwing) var/delayed_time = 0 var/last_move = 0 + +/datum/thrownthing/New(thrownthing, target, target_turf, init_dir, maxrange, speed, thrower, diagonals_first, force, gentle, callback, target_zone) + . = ..() + src.thrownthing = thrownthing + RegisterSignal(thrownthing, COMSIG_PARENT_QDELETING, .proc/on_thrownthing_qdel) + src.target = target + src.target_turf = target_turf + src.init_dir = init_dir + src.maxrange = maxrange + src.speed = speed + src.thrower = thrower + src.diagonals_first = diagonals_first + src.force = force + src.gentle = gentle + src.callback = callback + src.target_zone = target_zone + + /datum/thrownthing/Destroy() SSthrowing.processing -= thrownthing thrownthing.throwing = null thrownthing = null target = null thrower = null - callback = null + if(callback) + QDEL_NULL(callback) //It stores a reference to the thrownthing, its source. Let's clean that. return ..() + +///Defines the datum behavior on the thrownthing's qdeletion event. +/datum/thrownthing/proc/on_thrownthing_qdel(atom/movable/source, force) + SIGNAL_HANDLER + + qdel(src) + + /datum/thrownthing/proc/tick() var/atom/movable/AM = thrownthing if (!isturf(AM.loc) || !AM.throwing) @@ -112,7 +140,7 @@ SUBSYSTEM_DEF(throwing) finalize() return - AM.Move(step, get_dir(AM, step)) + AM.Move(step, get_dir(AM, step), DELAY_TO_GLIDE_SIZE(1 / speed)) if (!AM.throwing) // we hit something during our move finalize(hit = TRUE) @@ -136,15 +164,21 @@ SUBSYSTEM_DEF(throwing) if (A == target) hit = TRUE thrownthing.throw_impact(A, src) + if(QDELETED(thrownthing)) //throw_impact can delete things, such as glasses smashing + return //deletion should already be handled by on_thrownthing_qdel() break if (!hit) thrownthing.throw_impact(get_turf(thrownthing), src) // we haven't hit something yet and we still must, let's hit the ground. + if(QDELETED(thrownthing)) //throw_impact can delete things, such as glasses smashing + return //deletion should already be handled by on_thrownthing_qdel() thrownthing.newtonian_move(init_dir) else thrownthing.newtonian_move(init_dir) if(target) thrownthing.throw_impact(target, src) + if(QDELETED(thrownthing)) //throw_impact can delete things, such as glasses smashing + return //deletion should already be handled by on_thrownthing_qdel() if (callback) callback.Invoke() diff --git a/code/controllers/subsystem/time_track.dm b/code/controllers/subsystem/time_track.dm index 2f4949fc1e..8a0a351d48 100644 --- a/code/controllers/subsystem/time_track.dm +++ b/code/controllers/subsystem/time_track.dm @@ -1,7 +1,8 @@ SUBSYSTEM_DEF(time_track) name = "Time Tracking" - wait = 1 SECONDS - flags = SS_NO_INIT|SS_NO_TICK_CHECK + wait = 10 + flags = SS_NO_TICK_CHECK + init_order = INIT_ORDER_TIMETRACK runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT var/time_dilation_current = 0 @@ -16,33 +17,81 @@ SUBSYSTEM_DEF(time_track) var/last_tick_byond_time = 0 var/last_tick_tickcount = 0 - var/last_measurement = 0 - var/measurement_delay = 60 - - var/stat_time_text - var/time_dilation_text +/datum/controller/subsystem/time_track/Initialize(start_timeofday) + . = ..() + GLOB.perf_log = "[GLOB.log_directory]/perf-[GLOB.round_id ? GLOB.round_id : "NULL"]-[SSmapping.config?.map_name].csv" + log_perf( + list( + "time", + "players", + "tidi", + "tidi_fastavg", + "tidi_avg", + "tidi_slowavg", + "maptick", + "num_timers", + "air_turf_cost", + "air_eg_cost", + "air_highpressure_cost", + "air_hotspots_cost", + "air_superconductivity_cost", + "air_pipenets_cost", + "air_rebuilds_cost", + "air_turf_count", + "air_eg_count", + "air_hotspot_count", + "air_network_count", + "air_delta_count", + "air_superconductive_count" + ) + ) /datum/controller/subsystem/time_track/fire() - stat_time_text = "Server Time: [time2text(world.timeofday, "YYYY-MM-DD hh:mm:ss")]\n\nRound Time: [DisplayTimeText(world.time - SSticker.round_start_time, 1)] \n\nStation Time: [STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]\n\n[time_dilation_text]" - if(++last_measurement == measurement_delay) - last_measurement = 0 - var/current_realtime = REALTIMEOFDAY - var/current_byondtime = world.time - var/current_tickcount = world.time/world.tick_lag + var/current_realtime = REALTIMEOFDAY + var/current_byondtime = world.time + var/current_tickcount = world.time/world.tick_lag + GLOB.glide_size_multiplier = (current_byondtime - last_tick_byond_time) / (current_realtime - last_tick_realtime) - if (!first_run) - var/tick_drift = max(0, (((current_realtime - last_tick_realtime) - (current_byondtime - last_tick_byond_time)) / world.tick_lag)) + if(times_fired % 10) // everything else is once every 10 seconds + return - time_dilation_current = tick_drift / (current_tickcount - last_tick_tickcount) * 100 + if (!first_run) + var/tick_drift = max(0, (((current_realtime - last_tick_realtime) - (current_byondtime - last_tick_byond_time)) / world.tick_lag)) - 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) - else - first_run = FALSE - last_tick_realtime = current_realtime - last_tick_byond_time = current_byondtime - last_tick_tickcount = current_tickcount - SSblackbox.record_feedback("associative", "time_dilation_current", 1, list("[SQLtime()]" = list("current" = "[time_dilation_current]", "avg_fast" = "[time_dilation_avg_fast]", "avg" = "[time_dilation_avg]", "avg_slow" = "[time_dilation_avg_slow]"))) - time_dilation_text = "Time Dilation: [round(time_dilation_current,1)]% AVG:([round(time_dilation_avg_fast,1)]%, [round(time_dilation_avg,1)]%, [round(time_dilation_avg_slow,1)]%)" + 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) + else + first_run = FALSE + last_tick_realtime = current_realtime + last_tick_byond_time = current_byondtime + last_tick_tickcount = current_tickcount + SSblackbox.record_feedback("associative", "time_dilation_current", 1, list("[SQLtime()]" = list("current" = "[time_dilation_current]", "avg_fast" = "[time_dilation_avg_fast]", "avg" = "[time_dilation_avg]", "avg_slow" = "[time_dilation_avg_slow]"))) + log_perf( + list( + world.time, + length(GLOB.clients), + time_dilation_current, + time_dilation_avg_fast, + time_dilation_avg, + time_dilation_avg_slow, + MAPTICK_LAST_INTERNAL_TICK_USAGE, + length(SStimer.timer_id_dict), + SSair.cost_turfs, + SSair.cost_groups, + SSair.cost_highpressure, + SSair.cost_hotspots, + SSair.cost_superconductivity, + SSair.cost_pipenets, + SSair.cost_rebuilds, + SSair.get_active_turfs(), //does not return a list, which is what we want + SSair.get_amt_excited_groups(), + length(SSair.hotspots), + length(SSair.networks), + length(SSair.high_pressure_delta), + length(SSair.active_super_conductivity) + ) + ) diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm index 398e23cdc1..48165be960 100644 --- a/code/controllers/subsystem/timer.dm +++ b/code/controllers/subsystem/timer.dm @@ -1,31 +1,51 @@ -#define BUCKET_LEN (world.fps*1*60) //how many ticks should we keep in the bucket. (1 minutes worth) +/// Controls how many buckets should be kept, each representing a tick. (1 minutes worth) +#define BUCKET_LEN (world.fps*1*60) +/// Helper for getting the correct bucket for a given timer #define BUCKET_POS(timer) (((round((timer.timeToRun - SStimer.head_offset) / world.tick_lag)+1) % BUCKET_LEN)||BUCKET_LEN) +/// Gets the maximum time at which timers will be invoked from buckets, used for deferring to secondary queue #define TIMER_MAX (world.time + TICKS2DS(min(BUCKET_LEN-(SStimer.practical_offset-DS2TICKS(world.time - SStimer.head_offset))-1, BUCKET_LEN-1))) -#define TIMER_ID_MAX (2**24) //max float with integer precision +/// Max float with integer precision +#define TIMER_ID_MAX (2**24) +/** + * # Timer Subsystem + * + * Handles creation, callbacks, and destruction of timed events. + * + * It is important to understand the buckets used in the timer subsystem are just a series of circular doubly-linked + * lists. The object at a given index in bucket_list is a /datum/timedevent, the head of a circular list, which has prev + * and next references for the respective elements in that bucket's circular list. + */ SUBSYSTEM_DEF(timer) name = "Timer" - wait = 1 //SS_TICKER subsystem, so wait is in ticks + wait = 1 // SS_TICKER subsystem, so wait is in ticks init_order = INIT_ORDER_TIMER - + priority = FIRE_PRIORITY_TIMER flags = SS_TICKER|SS_NO_INIT - var/list/datum/timedevent/second_queue = list() //awe, yes, you've had first queue, but what about second queue? + /// Queue used for storing timers that do not fit into the current buckets + var/list/datum/timedevent/second_queue = list() + /// A hashlist dictionary used for storing unique timers var/list/hashes = list() - - var/head_offset = 0 //world.time of the first entry in the the bucket. - var/practical_offset = 1 //index of the first non-empty item in the bucket. - var/bucket_resolution = 0 //world.tick_lag the bucket was designed for - var/bucket_count = 0 //how many timers are in the buckets - - var/list/bucket_list = list() //list of buckets, each bucket holds every timer that has to run that byond tick. - - var/list/timer_id_dict = list() //list of all active timers assoicated to their timer id (for easy lookup) - - var/list/clienttime_timers = list() //special snowflake timers that run on fancy pansy "client time" - + /// world.time of the first entry in the bucket list, effectively the 'start time' of the current buckets + var/head_offset = 0 + /// Index of the wrap around pivot for buckets. buckets before this are later running buckets wrapped around from the end of the bucket list. + var/practical_offset = 1 + /// world.tick_lag the bucket was designed for + var/bucket_resolution = 0 + /// How many timers are in the buckets + var/bucket_count = 0 + /// List of buckets, each bucket holds every timer that has to run that byond tick + var/list/bucket_list = list() + /// List of all active timers associated to their timer ID (for easy lookup) + var/list/timer_id_dict = list() + /// Special timers that run in real-time, not BYOND time; these are more expensive to run and maintain + var/list/clienttime_timers = list() + /// Contains the last time that a timer's callback was invoked, or the last tick the SS fired if no timers are being processed var/last_invoke_tick = 0 + /// Contains the last time that a warning was issued for not invoking callbacks var/static/last_invoke_warning = 0 + /// Boolean operator controlling if the timer SS will automatically reset buckets if it fails to invoke callbacks for an extended period of time var/static/bucket_auto_reset = TRUE /datum/controller/subsystem/timer/PreInit() @@ -38,44 +58,53 @@ SUBSYSTEM_DEF(timer) return ..() /datum/controller/subsystem/timer/fire(resumed = FALSE) + // Store local references to datum vars as it is faster to access them var/lit = last_invoke_tick - var/last_check = world.time - TICKS2DS(BUCKET_LEN*1.5) var/list/bucket_list = src.bucket_list + var/last_check = world.time - TICKS2DS(BUCKET_LEN * 1.5) + // If there are no timers being tracked, then consider now to be the last invoked time if(!bucket_count) last_invoke_tick = world.time + // Check that we have invoked a callback in the last 1.5 minutes of BYOND time, + // and throw a warning and reset buckets if this is true if(lit && lit < last_check && head_offset < last_check && last_invoke_warning < last_check) last_invoke_warning = world.time - var/msg = "No regular timers processed in the last [BUCKET_LEN*1.5] ticks[bucket_auto_reset ? ", resetting buckets" : ""]!" + var/msg = "No regular timers processed in the last [BUCKET_LEN * 1.5] ticks[bucket_auto_reset ? ", resetting buckets" : ""]!" message_admins(msg) WARNING(msg) if(bucket_auto_reset) bucket_resolution = 0 - log_world("Timer bucket reset. world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]") + var/list/to_log = list("Timer bucket reset. world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]") for (var/i in 1 to length(bucket_list)) var/datum/timedevent/bucket_head = bucket_list[i] if (!bucket_head) continue - log_world("Active timers at index [i]:") - + to_log += "Active timers at index [i]:" var/datum/timedevent/bucket_node = bucket_head var/anti_loop_check = 1000 do - log_world(get_timer_debug_string(bucket_node)) + to_log += get_timer_debug_string(bucket_node) bucket_node = bucket_node.next anti_loop_check-- while(bucket_node && bucket_node != bucket_head && anti_loop_check) - log_world("Active timers in the second_queue queue:") + + to_log += "Active timers in the second_queue queue:" for(var/I in second_queue) - log_world(get_timer_debug_string(I)) + to_log += get_timer_debug_string(I) - var/next_clienttime_timer_index = 0 - var/len = length(clienttime_timers) + // Dump all the logged data to the world log + log_world(to_log.Join("\n")) - for (next_clienttime_timer_index in 1 to len) + // Process client-time timers + var/static/next_clienttime_timer_index = 0 + if (next_clienttime_timer_index) + clienttime_timers.Cut(1, next_clienttime_timer_index+1) + next_clienttime_timer_index = 0 + for (next_clienttime_timer_index in 1 to length(clienttime_timers)) if (MC_TICK_CHECK) next_clienttime_timer_index-- break @@ -86,8 +115,8 @@ SUBSYSTEM_DEF(timer) var/datum/callback/callBack = ctime_timer.callBack if (!callBack) - clienttime_timers.Cut(next_clienttime_timer_index,next_clienttime_timer_index+1) - CRASH("Invalid timer: [get_timer_debug_string(ctime_timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset], REALTIMEOFDAY: [REALTIMEOFDAY]") + CRASH("Invalid timer: [get_timer_debug_string(ctime_timer)] world.time: [world.time], \ + head_offset: [head_offset], practical_offset: [practical_offset], REALTIMEOFDAY: [REALTIMEOFDAY]") ctime_timer.spent = REALTIMEOFDAY callBack.InvokeAsync() @@ -95,135 +124,93 @@ SUBSYSTEM_DEF(timer) if(ctime_timer.flags & TIMER_LOOP) ctime_timer.spent = 0 ctime_timer.timeToRun = REALTIMEOFDAY + ctime_timer.wait - BINARY_INSERT(ctime_timer, clienttime_timers, datum/timedevent, ctime_timer, timeToRun, COMPARE_KEY) + BINARY_INSERT(ctime_timer, clienttime_timers, /datum/timedevent, ctime_timer, timeToRun, COMPARE_KEY) else qdel(ctime_timer) - + // Remove invoked client-time timers if (next_clienttime_timer_index) clienttime_timers.Cut(1, next_clienttime_timer_index+1) + next_clienttime_timer_index = 0 if (MC_TICK_CHECK) return - var/static/list/spent = list() - var/static/datum/timedevent/timer + // Check for when we need to loop the buckets, this occurs when + // the head_offset is approaching BUCKET_LEN ticks in the past if (practical_offset > BUCKET_LEN) head_offset += TICKS2DS(BUCKET_LEN) practical_offset = 1 resumed = FALSE + // Check for when we have to reset buckets, typically from auto-reset if ((length(bucket_list) != BUCKET_LEN) || (world.tick_lag != bucket_resolution)) reset_buckets() bucket_list = src.bucket_list resumed = FALSE - if (!resumed) - timer = null - - while (practical_offset <= BUCKET_LEN && head_offset + ((practical_offset-1)*world.tick_lag) <= world.time) - var/datum/timedevent/head = bucket_list[practical_offset] - if (!timer || !head || timer == head) - head = bucket_list[practical_offset] - timer = head - while (timer) + // Iterate through each bucket starting from the practical offset + while (practical_offset <= BUCKET_LEN && head_offset + ((practical_offset - 1) * world.tick_lag) <= world.time) + var/datum/timedevent/timer + while ((timer = bucket_list[practical_offset])) var/datum/callback/callBack = timer.callBack if (!callBack) - bucket_resolution = null //force bucket recreation - CRASH("Invalid timer: [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]") + bucket_resolution = null // force bucket recreation + CRASH("Invalid timer: [get_timer_debug_string(timer)] world.time: [world.time], \ + head_offset: [head_offset], practical_offset: [practical_offset]") + timer.bucketEject() //pop the timer off of the bucket list. + + // Invoke callback if possible if (!timer.spent) - spent += timer timer.spent = world.time callBack.InvokeAsync() last_invoke_tick = world.time - if (MC_TICK_CHECK) - return - - timer = timer.next - if (timer == head) - break - - - bucket_list[practical_offset++] = null - - //we freed up a bucket, lets see if anything in second_queue needs to be shifted to that bucket. - var/i = 0 - var/L = length(second_queue) - for (i in 1 to L) - timer = second_queue[i] - if (timer.timeToRun >= TIMER_MAX) - i-- - break - - if (timer.timeToRun < head_offset) - bucket_resolution = null //force bucket recreation - stack_trace("[i] Invalid timer state: Timer in long run queue with a time to run less then head_offset. [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]") - - if (timer.callBack && !timer.spent) - timer.callBack.InvokeAsync() - spent += timer - bucket_count++ - else if(!QDELETED(timer)) - qdel(timer) - continue - - if (timer.timeToRun < head_offset + TICKS2DS(practical_offset-1)) - bucket_resolution = null //force bucket recreation - stack_trace("[i] Invalid timer state: Timer in long run queue that would require a backtrack to transfer to short run queue. [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]") - if (timer.callBack && !timer.spent) - timer.callBack.InvokeAsync() - spent += timer - bucket_count++ - else if(!QDELETED(timer)) - qdel(timer) - continue - - bucket_count++ - var/bucket_pos = max(1, BUCKET_POS(timer)) - - var/datum/timedevent/bucket_head = bucket_list[bucket_pos] - if (!bucket_head) - bucket_list[bucket_pos] = timer - timer.next = null - timer.prev = null - continue - - if (!bucket_head.prev) - bucket_head.prev = bucket_head - timer.next = bucket_head - timer.prev = bucket_head.prev - timer.next.prev = timer - timer.prev.next = timer - if (i) - second_queue.Cut(1, i+1) - - timer = null - - bucket_count -= length(spent) - - for (var/i in spent) - var/datum/timedevent/qtimer = i - if(QDELETED(qtimer)) - bucket_count++ - continue - if(!(qtimer.flags & TIMER_LOOP)) - qdel(qtimer) - else - bucket_count++ - qtimer.spent = 0 - qtimer.bucketEject() - if(qtimer.flags & TIMER_CLIENT_TIME) - qtimer.timeToRun = REALTIMEOFDAY + qtimer.wait + if (timer.flags & TIMER_LOOP) // Prepare looping timers to re-enter the queue + timer.spent = 0 + timer.timeToRun = world.time + timer.wait + timer.bucketJoin() else - qtimer.timeToRun = world.time + qtimer.wait - qtimer.bucketJoin() + qdel(timer) - spent.len = 0 + if (MC_TICK_CHECK) + break -//formated this way to be runtime resistant + if (!bucket_list[practical_offset]) + // Empty the bucket, check if anything in the secondary queue should be shifted to this bucket + bucket_list[practical_offset++] = null + var/i = 0 + for (i in 1 to length(second_queue)) + timer = second_queue[i] + if (timer.timeToRun >= TIMER_MAX) + i-- + break + + // Check for timers that are scheduled to run in the past + if (timer.timeToRun < head_offset) + bucket_resolution = null // force bucket recreation + stack_trace("[i] Invalid timer state: Timer in long run queue with a time to run less then head_offset. \ + [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]") + break + + // Check for timers that are not capable of being scheduled to run without rebuilding buckets + if (timer.timeToRun < head_offset + TICKS2DS(practical_offset - 1)) + bucket_resolution = null // force bucket recreation + stack_trace("[i] Invalid timer state: Timer in long run queue that would require a backtrack to transfer to \ + short run queue. [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]") + break + + timer.bucketJoin() + if (i) + second_queue.Cut(1, i+1) + if (MC_TICK_CHECK) + break + +/** + * Generates a string with details about the timed event for debugging purposes + */ /datum/controller/subsystem/timer/proc/get_timer_debug_string(datum/timedevent/TE) . = "Timer: [TE]" . += "Prev: [TE.prev ? TE.prev : "NULL"], Next: [TE.next ? TE.next : "NULL"]" @@ -234,12 +221,16 @@ SUBSYSTEM_DEF(timer) if(!TE.callBack) . += ", NO CALLBACK" +/** + * Destroys the existing buckets and creates new buckets from the existing timed events + */ /datum/controller/subsystem/timer/proc/reset_buckets() - var/list/bucket_list = src.bucket_list + var/list/bucket_list = src.bucket_list // Store local reference to datum var, this is faster var/list/alltimers = list() - //collect the timers currently in the bucket + + // Get all timers currently in the buckets for (var/bucket_head in bucket_list) - if (!bucket_head) + if (!bucket_head) // if bucket is empty for this tick continue var/datum/timedevent/bucket_node = bucket_head do @@ -247,25 +238,38 @@ SUBSYSTEM_DEF(timer) bucket_node = bucket_node.next while(bucket_node && bucket_node != bucket_head) + // Empty the list by zeroing and re-assigning the length bucket_list.len = 0 bucket_list.len = BUCKET_LEN + // Reset values for the subsystem to their initial values practical_offset = 1 bucket_count = 0 head_offset = world.time bucket_resolution = world.tick_lag + // Add all timed events from the secondary queue as well alltimers += second_queue + + // If there are no timers being tracked by the subsystem, + // there is no need to do any further rebuilding if (!length(alltimers)) return + // Sort all timers by time to run sortTim(alltimers, .proc/cmp_timer) + // Get the earliest timer, and if the TTR is earlier than the current world.time, + // then set the head offset appropriately to be the earliest time tracked by the + // current set of buckets var/datum/timedevent/head = alltimers[1] - if (head.timeToRun < head_offset) head_offset = head.timeToRun + // Iterate through each timed event and insert it into an appropriate bucket, + // up unto the point that we can no longer insert into buckets as the TTR + // is outside the range we are tracking, then insert the remainder into the + // secondary queue var/new_bucket_count var/i = 1 for (i in 1 to length(alltimers)) @@ -273,34 +277,38 @@ SUBSYSTEM_DEF(timer) if (!timer) continue - var/bucket_pos = BUCKET_POS(timer) + // Check that the TTR is within the range covered by buckets, when exceeded we've finished if (timer.timeToRun >= TIMER_MAX) i-- break - + // Check that timer has a valid callback and hasn't been invoked if (!timer.callBack || timer.spent) - WARNING("Invalid timer: [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]") + WARNING("Invalid timer: [get_timer_debug_string(timer)] world.time: [world.time], \ + head_offset: [head_offset], practical_offset: [practical_offset]") if (timer.callBack) qdel(timer) continue + // Insert the timer into the bucket, and perform necessary circular doubly-linked list operations new_bucket_count++ + var/bucket_pos = BUCKET_POS(timer) var/datum/timedevent/bucket_head = bucket_list[bucket_pos] if (!bucket_head) bucket_list[bucket_pos] = timer timer.next = null timer.prev = null continue - if (!bucket_head.prev) bucket_head.prev = bucket_head timer.next = bucket_head timer.prev = bucket_head.prev timer.next.prev = timer timer.prev.next = timer + + // Cut the timers that are tracked by the buckets from the secondary queue if (i) - alltimers.Cut(1, i+1) + alltimers.Cut(1, i + 1) second_queue = alltimers bucket_count = new_bucket_count @@ -311,45 +319,64 @@ SUBSYSTEM_DEF(timer) timer_id_dict |= SStimer.timer_id_dict bucket_list |= SStimer.bucket_list +/** + * # Timed Event + * + * This is the actual timer, it contains the callback and necessary data to maintain + * the timer. + * + * See the documentation for the timer subsystem for an explanation of the buckets referenced + * below in next and prev + */ /datum/timedevent + /// ID used for timers when the TIMER_STOPPABLE flag is present var/id + /// The callback to invoke after the timer completes var/datum/callback/callBack + /// The time at which the callback should be invoked at var/timeToRun + /// The length of the timer var/wait + /// Unique hash generated when TIMER_UNIQUE flag is present var/hash + /// The source of the timedevent, whatever called addtimer + var/source + /// Flags associated with the timer, see _DEFINES/subsystems.dm var/list/flags - var/spent = 0 //time we ran the timer. - var/name //for easy debugging. - //cicular doublely linked list + /// Time at which the timer was invoked or destroyed + var/spent = 0 + /// An informative name generated for the timer as its representation in strings, useful for debugging + var/name + /// Next timed event in the bucket var/datum/timedevent/next + /// Previous timed event in the bucket var/datum/timedevent/prev -/datum/timedevent/New(datum/callback/callBack, wait, flags, hash) +/datum/timedevent/New(datum/callback/callBack, wait, flags, hash, source) var/static/nextid = 1 id = TIMER_ID_NULL src.callBack = callBack src.wait = wait src.flags = flags src.hash = hash + src.source = source - if (flags & TIMER_CLIENT_TIME) - timeToRun = REALTIMEOFDAY + wait - else - timeToRun = world.time + wait + // Determine time at which the timer's callback should be invoked + timeToRun = (flags & TIMER_CLIENT_TIME ? REALTIMEOFDAY : world.time) + wait + // Include the timer in the hash table if the timer is unique if (flags & TIMER_UNIQUE) SStimer.hashes[hash] = src + // Generate ID for the timer if the timer is stoppable, include in the timer id dictionary if (flags & TIMER_STOPPABLE) id = num2text(nextid, 100) if (nextid >= SHORT_REAL_LIMIT) - nextid += min(1, 2**round(nextid/SHORT_REAL_LIMIT)) + nextid += min(1, 2 ** round(nextid / SHORT_REAL_LIMIT)) else nextid++ SStimer.timer_id_dict[id] = src - name = "Timer: [id] (\ref[src]), TTR: [timeToRun], Flags: [jointext(bitfield2list(flags, list("TIMER_UNIQUE", "TIMER_OVERRIDE", "TIMER_CLIENT_TIME", "TIMER_STOPPABLE", "TIMER_NO_HASH_WAIT", "TIMER_LOOP")), ", ")], callBack: \ref[callBack], callBack.object: [callBack.object]\ref[callBack.object]([getcallingtype()]), callBack.delegate:[callBack.delegate]([callBack.arguments ? callBack.arguments.Join(", ") : ""])" - if ((timeToRun < world.time || timeToRun < SStimer.head_offset) && !(flags & TIMER_CLIENT_TIME)) CRASH("Invalid timer state: Timer created that would require a backtrack to run (addtimer would never let this happen): [SStimer.get_timer_debug_string(src)]") @@ -390,23 +417,39 @@ SUBSYSTEM_DEF(timer) prev = null return QDEL_HINT_IWILLGC +/** + * Removes this timed event from any relevant buckets, or the secondary queue + */ /datum/timedevent/proc/bucketEject() + // Attempt to find bucket that contains this timed event var/bucketpos = BUCKET_POS(src) + + // Store local references for the bucket list and secondary queue + // This is faster than referencing them from the datum itself var/list/bucket_list = SStimer.bucket_list var/list/second_queue = SStimer.second_queue + + // Attempt to get the head of the bucket var/datum/timedevent/buckethead if(bucketpos > 0) buckethead = bucket_list[bucketpos] + + // Decrement the number of timers in buckets if the timed event is + // the head of the bucket, or has a TTR less than TIMER_MAX implying it fits + // into an existing bucket, or is otherwise not present in the secondary queue if(buckethead == src) bucket_list[bucketpos] = next SStimer.bucket_count-- - else if(timeToRun < TIMER_MAX || next || prev) + else if(timeToRun < TIMER_MAX) SStimer.bucket_count-- else var/l = length(second_queue) second_queue -= src if(l == length(second_queue)) SStimer.bucket_count-- + + // Remove the timed event from the bucket, ensuring to maintain + // the integrity of the bucket's list if relevant if(prev != next) prev.next = next next.prev = prev @@ -415,32 +458,47 @@ SUBSYSTEM_DEF(timer) next?.prev = null prev = next = null +/** + * Attempts to add this timed event to a bucket, will enter the secondary queue + * if there are no appropriate buckets at this time. + * + * Secondary queueing of timed events will occur when the timespan covered by the existing + * buckets is exceeded by the time at which this timed event is scheduled to be invoked. + * If the timed event is tracking client time, it will be added to a special bucket. + */ /datum/timedevent/proc/bucketJoin() - var/list/L + // Generate debug-friendly name for timer + var/static/list/bitfield_flags = list("TIMER_UNIQUE", "TIMER_OVERRIDE", "TIMER_CLIENT_TIME", "TIMER_STOPPABLE", "TIMER_NO_HASH_WAIT", "TIMER_LOOP") + name = "Timer: [id] (\ref[src]), TTR: [timeToRun], wait:[wait] Flags: [jointext(bitfield2list(flags, bitfield_flags), ", ")], \ + callBack: \ref[callBack], callBack.object: [callBack.object]\ref[callBack.object]([getcallingtype()]), \ + callBack.delegate:[callBack.delegate]([callBack.arguments ? callBack.arguments.Join(", ") : ""]), source: [source]" + // Check if this timed event should be diverted to the client time bucket, or the secondary queue + var/list/L if (flags & TIMER_CLIENT_TIME) L = SStimer.clienttime_timers else if (timeToRun >= TIMER_MAX) L = SStimer.second_queue - if(L) - BINARY_INSERT(src, L, datum/timedevent, src, timeToRun, COMPARE_KEY) + BINARY_INSERT(src, L, /datum/timedevent, src, timeToRun, COMPARE_KEY) return - //get the list of buckets + // Get a local reference to the bucket list, this is faster than referencing the datum var/list/bucket_list = SStimer.bucket_list - //calculate our place in the bucket list + // Find the correct bucket for this timed event var/bucket_pos = BUCKET_POS(src) - - //get the bucket for our tick var/datum/timedevent/bucket_head = bucket_list[bucket_pos] SStimer.bucket_count++ - //empty bucket, we will just add ourselves + + // If there is no timed event at this position, then the bucket is 'empty' + // and we can just set this event to that position if (!bucket_head) bucket_list[bucket_pos] = src return - //other wise, lets do a simplified linked list add. + + // Otherwise, we merely add this timed event into the bucket, which is a + // circularly doubly-linked list if (!bucket_head.prev) bucket_head.prev = bucket_head next = bucket_head @@ -448,7 +506,9 @@ SUBSYSTEM_DEF(timer) next.prev = src prev.next = src -///Returns a string of the type of the callback for this timer +/** + * Returns a string of the type of the callback for this timer + */ /datum/timedevent/proc/getcallingtype() . = "ERROR" if (callBack.object == GLOBAL_PROC) @@ -457,14 +517,15 @@ SUBSYSTEM_DEF(timer) . = "[callBack.object.type]" /** - * Create a new timer and insert it in the queue - * - * Arguments: - * * callback the callback to call on timer finish - * * wait deciseconds to run the timer for - * * flags flags for this timer, see: code\__DEFINES\subsystems.dm - */ -/proc/addtimer(datum/callback/callback, wait = 0, flags = 0) + * Create a new timer and insert it in the queue. + * You should not call this directly, and should instead use the addtimer macro, which includes source information. + * + * Arguments: + * * callback the callback to call on timer finish + * * wait deciseconds to run the timer for + * * flags flags for this timer, see: code\__DEFINES\subsystems.dm + */ +/proc/_addtimer(datum/callback/callback, wait = 0, flags = 0, file, line) if (!callback) CRASH("addtimer called without a callback") @@ -472,31 +533,30 @@ SUBSYSTEM_DEF(timer) stack_trace("addtimer called with a negative wait. Converting to [world.tick_lag]") if (callback.object != GLOBAL_PROC && QDELETED(callback.object) && !QDESTROYING(callback.object)) - stack_trace("addtimer called with a callback assigned to a qdeleted object. In the future such timers will not be supported and may refuse to run or run with a 0 wait") + stack_trace("addtimer called with a callback assigned to a qdeleted object. In the future such timers will not \ + be supported and may refuse to run or run with a 0 wait") wait = max(CEILING(wait, world.tick_lag), world.tick_lag) if(wait >= INFINITY) CRASH("Attempted to create timer with INFINITY delay") + // Generate hash if relevant for timed events with the TIMER_UNIQUE flag var/hash - if (flags & TIMER_UNIQUE) - var/list/hashlist - if(flags & TIMER_NO_HASH_WAIT) - hashlist = list(callback.object, "([REF(callback.object)])", callback.delegate, flags & TIMER_CLIENT_TIME) - else - hashlist = list(callback.object, "([REF(callback.object)])", callback.delegate, wait, flags & TIMER_CLIENT_TIME) + var/list/hashlist = list(callback.object, "([REF(callback.object)])", callback.delegate, flags & TIMER_CLIENT_TIME) + if(!(flags & TIMER_NO_HASH_WAIT)) + hashlist += wait hashlist += callback.arguments hash = hashlist.Join("|||||||") var/datum/timedevent/hash_timer = SStimer.hashes[hash] if(hash_timer) - if (hash_timer.spent) //it's pending deletion, pretend it doesn't exist. - hash_timer.hash = null //but keep it from accidentally deleting us + if (hash_timer.spent) // it's pending deletion, pretend it doesn't exist. + hash_timer.hash = null // but keep it from accidentally deleting us else if (flags & TIMER_OVERRIDE) - hash_timer.hash = null //no need having it delete it's hash if we are going to replace it + hash_timer.hash = null // no need having it delete it's hash if we are going to replace it qdel(hash_timer) else if (hash_timer.flags & TIMER_STOPPABLE) @@ -505,24 +565,23 @@ SUBSYSTEM_DEF(timer) else if(flags & TIMER_OVERRIDE) stack_trace("TIMER_OVERRIDE used without TIMER_UNIQUE") - var/datum/timedevent/timer = new(callback, wait, flags, hash) + var/datum/timedevent/timer = new(callback, wait, flags, hash, file && "[file]:[line]") return timer.id /** - * Delete a timer - * - * Arguments: - * * id a timerid or a /datum/timedevent - */ + * Delete a timer + * + * Arguments: + * * id a timerid or a /datum/timedevent + */ /proc/deltimer(id) if (!id) return FALSE if (id == TIMER_ID_NULL) CRASH("Tried to delete a null timerid. Use TIMER_STOPPABLE flag") - if (!istext(id)) - if (istype(id, /datum/timedevent)) - qdel(id) - return TRUE + if (istype(id, /datum/timedevent)) + qdel(id) + return TRUE //id is string var/datum/timedevent/timer = SStimer.timer_id_dict[id] if (timer && !timer.spent) @@ -531,25 +590,22 @@ SUBSYSTEM_DEF(timer) return FALSE /** - * Get the remaining deciseconds on a timer - * - * Arguments: - * * id a timerid or a /datum/timedevent - */ + * Get the remaining deciseconds on a timer + * + * Arguments: + * * id a timerid or a /datum/timedevent + */ /proc/timeleft(id) if (!id) return null if (id == TIMER_ID_NULL) CRASH("Tried to get timeleft of a null timerid. Use TIMER_STOPPABLE flag") - if (!istext(id)) - if (istype(id, /datum/timedevent)) - var/datum/timedevent/timer = id - return timer.timeToRun - world.time + if (istype(id, /datum/timedevent)) + var/datum/timedevent/timer = id + return timer.timeToRun - world.time //id is string var/datum/timedevent/timer = SStimer.timer_id_dict[id] - if (timer && !timer.spent) - return timer.timeToRun - world.time - return null + return (timer && !timer.spent) ? timer.timeToRun - world.time : null #undef BUCKET_LEN #undef BUCKET_POS diff --git a/code/controllers/subsystem/title.dm b/code/controllers/subsystem/title.dm index bd843f959d..996f73ccf6 100644 --- a/code/controllers/subsystem/title.dm +++ b/code/controllers/subsystem/title.dm @@ -25,12 +25,12 @@ SUBSYSTEM_DEF(title) SSmapping.HACK_LoadMapConfig() for(var/S in provisional_title_screens) var/list/L = splittext(S,"+") - if((L.len == 1 && L[1] != "blank.png")|| (L.len > 1 && ((use_rare_screens && lowertext(L[1]) == "rare") || (lowertext(L[1]) == lowertext(SSmapping.config.map_name))))) + if((L.len == 1 && (L[1] != "exclude" && L[1] != "blank.png"))|| (L.len > 1 && ((use_rare_screens && lowertext(L[1]) == "rare") || (lowertext(L[1]) == lowertext(SSmapping.config.map_name))))) title_screens += S if(length(title_screens)) file_path = "[global.config.directory]/title_screens/images/[pick(title_screens)]" - + if(!file_path) file_path = "icons/default_title.dmi" diff --git a/code/controllers/subsystem/vis_overlays.dm b/code/controllers/subsystem/vis_overlays.dm index 0635709074..b0e5d6c689 100644 --- a/code/controllers/subsystem/vis_overlays.dm +++ b/code/controllers/subsystem/vis_overlays.dm @@ -5,10 +5,12 @@ SUBSYSTEM_DEF(vis_overlays) init_order = INIT_ORDER_VIS var/list/vis_overlay_cache + var/list/unique_vis_overlays var/list/currentrun /datum/controller/subsystem/vis_overlays/Initialize() vis_overlay_cache = list() + unique_vis_overlays = list() return ..() /datum/controller/subsystem/vis_overlays/fire(resumed = FALSE) @@ -29,31 +31,45 @@ SUBSYSTEM_DEF(vis_overlays) return //the "thing" var can be anything with vis_contents which includes images -/datum/controller/subsystem/vis_overlays/proc/add_vis_overlay(atom/movable/thing, icon, iconstate, layer, plane, dir, alpha = 255, add_appearance_flags = NONE) - . = "[icon]|[iconstate]|[layer]|[plane]|[dir]|[alpha]|[add_appearance_flags]" - var/obj/effect/overlay/vis/overlay = vis_overlay_cache[.] - if(!overlay) - overlay = new - overlay.icon = icon - overlay.icon_state = iconstate - overlay.layer = layer - overlay.plane = plane - overlay.dir = dir - overlay.alpha = alpha - overlay.appearance_flags |= add_appearance_flags - vis_overlay_cache[.] = overlay +/datum/controller/subsystem/vis_overlays/proc/add_vis_overlay(atom/movable/thing, icon, iconstate, layer, plane, dir, alpha = 255, add_appearance_flags = NONE, unique = FALSE) + var/obj/effect/overlay/vis/overlay + if(!unique) + . = "[icon]|[iconstate]|[layer]|[plane]|[dir]|[alpha]|[add_appearance_flags]" + overlay = vis_overlay_cache[.] + if(!overlay) + overlay = _create_new_vis_overlay(icon, iconstate, layer, plane, dir, alpha, add_appearance_flags) + vis_overlay_cache[.] = overlay + else + overlay.unused = 0 else - overlay.unused = 0 + overlay = _create_new_vis_overlay(icon, iconstate, layer, plane, dir, alpha, add_appearance_flags) + overlay.cache_expiration = -1 + var/cache_id = "\ref[overlay]@{[world.time]}" + unique_vis_overlays += overlay + vis_overlay_cache[cache_id] = overlay + . = overlay thing.vis_contents += overlay if(!isatom(thing)) // Automatic rotation is not supported on non atoms - return + return overlay if(!thing.managed_vis_overlays) thing.managed_vis_overlays = list(overlay) - RegisterSignal(thing, COMSIG_ATOM_DIR_CHANGE, .proc/rotate_vis_overlay) else thing.managed_vis_overlays += overlay + return overlay + +/datum/controller/subsystem/vis_overlays/proc/_create_new_vis_overlay(icon, iconstate, layer, plane, dir, alpha, add_appearance_flags) + var/obj/effect/overlay/vis/overlay = new + overlay.icon = icon + overlay.icon_state = iconstate + overlay.layer = layer + overlay.plane = plane + overlay.dir = dir + overlay.alpha = alpha + overlay.appearance_flags |= add_appearance_flags + return overlay + /datum/controller/subsystem/vis_overlays/proc/remove_vis_overlay(atom/movable/thing, list/overlays) thing.vis_contents -= overlays @@ -62,15 +78,3 @@ SUBSYSTEM_DEF(vis_overlays) thing.managed_vis_overlays -= overlays if(!length(thing.managed_vis_overlays)) thing.managed_vis_overlays = null - UnregisterSignal(thing, COMSIG_ATOM_DIR_CHANGE) - -/datum/controller/subsystem/vis_overlays/proc/rotate_vis_overlay(atom/thing, old_dir, new_dir) - if(old_dir == new_dir) - return - var/rotation = dir2angle(old_dir) - dir2angle(new_dir) - var/list/overlays_to_remove = list() - for(var/i in thing.managed_vis_overlays) - var/obj/effect/overlay/vis/overlay = i - add_vis_overlay(thing, overlay.icon, overlay.icon_state, overlay.layer, overlay.plane, turn(overlay.dir, rotation), overlay.alpha, overlay.appearance_flags) - overlays_to_remove += overlay - remove_vis_overlay(thing, overlays_to_remove) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 880802fd5c..fb8299d108 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -141,8 +141,8 @@ SUBSYSTEM_DEF(vote) choices[choices[i]]++ // higher shortest path = better candidate, so we add to choices here // choices[choices[i]] is the schulze ranking, here, rather than raw vote numbers -/datum/controller/subsystem/vote/proc/calculate_majority_judgement_vote(var/blackbox_text) - // https://en.wikipedia.org/wiki/Majority_judgment +/datum/controller/subsystem/vote/proc/calculate_highest_median(var/blackbox_text) + // https://en.wikipedia.org/wiki/Highest_median_voting_rules var/list/scores_by_choice = list() for(var/choice in choices) scores_by_choice += "[choice]" @@ -161,33 +161,24 @@ SUBSYSTEM_DEF(vote) // END BALLOT GATHERING for(var/score_name in scores_by_choice) var/list/score = scores_by_choice[score_name] - for(var/indiv_score in score) - SSblackbox.record_feedback("nested tally","voting",1,list(blackbox_text,"Scores",score_name,GLOB.vote_score_options[indiv_score])) - if(score.len == 0) - scores_by_choice -= score_name - while(scores_by_choice.len > 1) - var/highest_median = 0 - for(var/score_name in scores_by_choice) // first get highest median - var/list/score = scores_by_choice[score_name] - if(!score.len) - scores_by_choice -= score_name - continue + if(!score.len) + choices[score_name] = 0 + else var/median = score[max(1,round(score.len/2))] - if(median >= highest_median) - highest_median = median - for(var/score_name in scores_by_choice) // then, remove - var/list/score = scores_by_choice[score_name] - var/median = score[max(1,round(score.len/2))] - if(median < highest_median) - scores_by_choice -= score_name - for(var/score_name in scores_by_choice) // after removals - var/list/score = scores_by_choice[score_name] - if(score.len == 0) - choices[score_name] += 100 // we're in a tie situation--just go with the first one - return - var/median_pos = max(1,round(score.len/2)) - score.Cut(median_pos,median_pos+1) - choices[score_name]++ + var/p = 0 // proponents (those with higher than median) + var/q = 0 // opponents (lower than median) + var/list/this_score_list = scores_by_choice[score_name] + for(var/indiv_score in score) + SSblackbox.record_feedback("nested tally","voting",1,list(blackbox_text,"Scores",score_name,GLOB.vote_score_options[indiv_score])) + if(indiv_score < median) // this is possible to do in O(logn) but n is never more than 200 so this is fine + q += 1 + else if(indiv_score > median) + p += 1 + p /= this_score_list.len + q /= this_score_list.len + choices[score_name] = median + (((p - q) / (1 - p - q)) * 0.5) // usual judgement + // choices[score_name] = median + p - q // typical judgement + // choices[score_name] = median + (((p - q) / (p + q)) * 0.5) // central judgement /datum/controller/subsystem/vote/proc/calculate_scores(var/blackbox_text) for(var/choice in choices) @@ -245,8 +236,8 @@ SUBSYSTEM_DEF(vote) calculate_condorcet_votes(vote_title_text) if(vote_system == SCORE_VOTING) calculate_scores(vote_title_text) - if(vote_system == MAJORITY_JUDGEMENT_VOTING) - calculate_majority_judgement_vote(vote_title_text) // nothing uses this at the moment + if(vote_system == HIGHEST_MEDIAN_VOTING) + calculate_highest_median(vote_title_text) // nothing uses this at the moment var/list/winners = vote_system == INSTANT_RUNOFF_VOTING ? get_runoff_results() : get_result() var/was_roundtype_vote = mode == "roundtype" || mode == "dynamic" if(winners.len > 0) @@ -255,8 +246,8 @@ SUBSYSTEM_DEF(vote) if(display_votes & SHOW_RESULTS) if(vote_system == SCHULZE_VOTING) text += "\nIt should be noted that this is not a raw tally of votes (impossible in ranked choice) but the score determined by the schulze method of voting, so the numbers will look weird!" - if(vote_system == MAJORITY_JUDGEMENT_VOTING) - text += "\nIt should be noted that this is not a raw tally of votes but the number of runoffs done by majority judgement!" + if(vote_system == HIGHEST_MEDIAN_VOTING) + text += "\nThis is the highest median score plus the tiebreaker!" for(var/i=1,i<=choices.len,i++) var/votes = choices[choices[i]] if(!votes) @@ -302,7 +293,7 @@ SUBSYSTEM_DEF(vote) if(vote_system != SCORE_VOTING) if(vote_system == SCHULZE_VOTING) admintext += "\nIt should be noted that this is not a raw tally of votes (impossible in ranked choice) but the score determined by the schulze method of voting, so the numbers will look weird!" - else if(vote_system == MAJORITY_JUDGEMENT_VOTING) + else if(vote_system == HIGHEST_MEDIAN_VOTING) admintext += "\nIt should be noted that this is not a raw tally of votes but the number of runoffs done by majority judgement!" for(var/i=1,i<=choices.len,i++) var/votes = choices[choices[i]] @@ -429,7 +420,7 @@ SUBSYSTEM_DEF(vote) voted[usr.ckey] = list() voted[usr.ckey] += vote saved -= usr.ckey - if(SCORE_VOTING,MAJORITY_JUDGEMENT_VOTING) + if(SCORE_VOTING,HIGHEST_MEDIAN_VOTING) if(!(usr.ckey in voted)) voted += usr.ckey voted[usr.ckey] = list() @@ -584,7 +575,7 @@ SUBSYSTEM_DEF(vote) . += "

Vote any number of choices.

" if(SCHULZE_VOTING,INSTANT_RUNOFF_VOTING) . += "

Vote by order of preference. Revoting will demote to the bottom. 1 is your favorite, and higher numbers are worse.

" - if(SCORE_VOTING,MAJORITY_JUDGEMENT_VOTING) + if(SCORE_VOTING,HIGHEST_MEDIAN_VOTING) . += "

Grade the candidates by how much you like them.

" . += "

No-votes have no power--your opinion is only heard if you vote!

" . += "Time Left: [DisplayTimeText(end_time-world.time)]